@@ -150,6 +150,10 @@ function State(input, options) {
150150 this . lineStart = 0 ;
151151 this . lineIndent = 0 ;
152152
153+ // position of first leading tab in the current line,
154+ // used to make sure there are no tabs in the indentation
155+ this . firstTabInLine = - 1 ;
156+
153157 this . documents = [ ] ;
154158
155159 /*
@@ -389,6 +393,7 @@ function readLineBreak(state) {
389393
390394 state . line += 1 ;
391395 state . lineStart = state . position ;
396+ state . firstTabInLine = - 1 ;
392397}
393398
394399function skipSeparationSpace ( state , allowComments , checkIndent ) {
@@ -397,6 +402,9 @@ function skipSeparationSpace(state, allowComments, checkIndent) {
397402
398403 while ( ch !== 0 ) {
399404 while ( is_WHITE_SPACE ( ch ) ) {
405+ if ( ch === 0x09 /* Tab */ && state . firstTabInLine === - 1 ) {
406+ state . firstTabInLine = state . position ;
407+ }
400408 ch = state . input . charCodeAt ( ++ state . position ) ;
401409 }
402410
@@ -959,13 +967,21 @@ function readBlockSequence(state, nodeIndent) {
959967 detected = false ,
960968 ch ;
961969
970+ // there is a leading tab before this token, so it can't be a block sequence/mapping;
971+ // it can still be flow sequence/mapping or a scalar
972+ if ( state . firstTabInLine !== - 1 ) return false ;
973+
962974 if ( state . anchor !== null ) {
963975 state . anchorMap [ state . anchor ] = _result ;
964976 }
965977
966978 ch = state . input . charCodeAt ( state . position ) ;
967979
968980 while ( ch !== 0 ) {
981+ if ( state . firstTabInLine !== - 1 ) {
982+ state . position = state . firstTabInLine ;
983+ throwError ( state , 'tab characters must not be used in indentation' ) ;
984+ }
969985
970986 if ( ch !== 0x2D /* - */ ) {
971987 break ;
@@ -1030,13 +1046,22 @@ function readBlockMapping(state, nodeIndent, flowIndent) {
10301046 detected = false ,
10311047 ch ;
10321048
1049+ // there is a leading tab before this token, so it can't be a block sequence/mapping;
1050+ // it can still be flow sequence/mapping or a scalar
1051+ if ( state . firstTabInLine !== - 1 ) return false ;
1052+
10331053 if ( state . anchor !== null ) {
10341054 state . anchorMap [ state . anchor ] = _result ;
10351055 }
10361056
10371057 ch = state . input . charCodeAt ( state . position ) ;
10381058
10391059 while ( ch !== 0 ) {
1060+ if ( ! atExplicitKey && state . firstTabInLine !== - 1 ) {
1061+ state . position = state . firstTabInLine ;
1062+ throwError ( state , 'tab characters must not be used in indentation' ) ;
1063+ }
1064+
10401065 following = state . input . charCodeAt ( state . position + 1 ) ;
10411066 _line = state . line ; // Save the current line.
10421067
0 commit comments