@@ -264,7 +264,10 @@ export function createParser(
264264 return result ;
265265 }
266266
267- function parseIdentifier ( ) : string {
267+ function parseIdentifier ( ) : string | null {
268+ if ( ! isIdentStart ( chr ) ) {
269+ return null ;
270+ }
268271 let result = '' ;
269272 while ( pos < l ) {
270273 if ( isIdent ( chr ) ) {
@@ -334,23 +337,28 @@ export function createParser(
334337 if ( is ( '|' ) ) {
335338 assert ( namespaceEnabled , 'Namespaces are not enabled.' ) ;
336339 next ( ) ;
340+ const name = parseIdentifier ( ) ;
341+ assert ( name , 'Expected attribute name.' ) ;
337342 attr = {
338343 type : 'Attribute' ,
339- name : parseIdentifier ( ) ,
344+ name : name ,
340345 namespace : { type : 'NoNamespace' }
341346 } ;
342347 } else if ( is ( '*' ) ) {
343348 assert ( namespaceEnabled , 'Namespaces are not enabled.' ) ;
344349 assert ( namespaceWildcardEnabled , 'Wildcard namespace is not enabled.' ) ;
345350 next ( ) ;
346351 pass ( '|' ) ;
352+ const name = parseIdentifier ( ) ;
353+ assert ( name , 'Expected attribute name.' ) ;
347354 attr = {
348355 type : 'Attribute' ,
349- name : parseIdentifier ( ) ,
356+ name,
350357 namespace : { type : 'WildcardNamespace' }
351358 } ;
352359 } else {
353360 const identifier = parseIdentifier ( ) ;
361+ assert ( identifier , 'Expected attribute name.' ) ;
354362 attr = {
355363 type : 'Attribute' ,
356364 name : identifier
@@ -360,9 +368,11 @@ export function createParser(
360368 next ( ) ;
361369 if ( isIdentStart ( chr ) ) {
362370 assert ( namespaceEnabled , 'Namespaces are not enabled.' ) ;
371+ const name = parseIdentifier ( ) ;
372+ assert ( name , 'Expected attribute name.' ) ;
363373 attr = {
364374 type : 'Attribute' ,
365- name : parseIdentifier ( ) ,
375+ name,
366376 namespace : { type : 'NamespaceName' , name : identifier }
367377 } ;
368378 } else {
@@ -389,25 +399,28 @@ export function createParser(
389399 } ;
390400 } else if ( substitutesEnabled && is ( '$' ) ) {
391401 next ( ) ;
402+ const name = parseIdentifier ( ) ;
403+ assert ( name , 'Expected substitute name.' ) ;
392404 attr . value = {
393405 type : 'Substitution' ,
394- name : parseIdentifier ( )
406+ name
395407 } ;
396- assert ( attr . value . name , 'Expected substitute name.' ) ;
397408 } else {
409+ const value = parseIdentifier ( ) ;
410+ assert ( value , 'Expected attribute value.' ) ;
398411 attr . value = {
399412 type : 'String' ,
400- value : parseIdentifier ( )
413+ value
401414 } ;
402- assert ( attr . value . value , 'Expected attribute value.' ) ;
403415 }
404416 skipWhitespace ( ) ;
405417 if ( isEof ( ) && ! strict ) {
406418 return attr ;
407419 }
408420 if ( ! is ( ']' ) ) {
409- attr . caseSensitivityModifier = parseIdentifier ( ) ;
410- assert ( attr . caseSensitivityModifier , 'Expected end of attribute selector.' ) ;
421+ const caseSensitivityModifier = parseIdentifier ( ) ;
422+ assert ( caseSensitivityModifier , 'Expected end of attribute selector.' ) ;
423+ attr . caseSensitivityModifier = caseSensitivityModifier ;
411424 assert (
412425 attributesCaseSensitivityModifiersEnabled ,
413426 'Attribute case sensitivity modifiers are not enabled.'
@@ -505,11 +518,12 @@ export function createParser(
505518 skipWhitespace ( ) ;
506519 if ( substitutesEnabled && is ( '$' ) ) {
507520 next ( ) ;
521+ const name = parseIdentifier ( ) ;
522+ assert ( name , 'Expected substitute name.' ) ;
508523 argument = {
509524 type : 'Substitution' ,
510- name : parseIdentifier ( )
525+ name
511526 } ;
512- assert ( argument . name , 'Expected substitute name.' ) ;
513527 } else if ( signature . type === 'String' ) {
514528 argument = {
515529 type : 'String' ,
@@ -560,9 +574,11 @@ export function createParser(
560574 return { type : 'WildcardTag' } ;
561575 } else if ( isIdentStart ( chr ) ) {
562576 assert ( tagNameEnabled , 'Tag names are not enabled.' ) ;
577+ const name = parseIdentifier ( ) ;
578+ assert ( name , 'Expected tag name.' ) ;
563579 return {
564580 type : 'TagName' ,
565- name : parseIdentifier ( )
581+ name
566582 } ;
567583 } else {
568584 return fail ( 'Expected tag name.' ) ;
@@ -595,6 +611,7 @@ export function createParser(
595611 return tagName ;
596612 } else if ( isIdentStart ( chr ) ) {
597613 const identifier = parseIdentifier ( ) ;
614+ assert ( identifier , 'Expected tag name.' ) ;
598615 if ( ! is ( '|' ) ) {
599616 assert ( tagNameEnabled , 'Tag names are not enabled.' ) ;
600617 return {
@@ -677,6 +694,7 @@ export function createParser(
677694
678695 assert ( isDoubleColon || pseudoName , 'Expected pseudo-class name.' ) ;
679696 assert ( ! isDoubleColon || pseudoName , 'Expected pseudo-element name.' ) ;
697+ assert ( pseudoName , 'Expected pseudo-class name.' ) ;
680698 assert (
681699 ! isDoubleColon ||
682700 pseudoElementsAcceptUnknown ||
0 commit comments