@@ -62,7 +62,7 @@ export class JsonLdParser extends Transform implements RDF.Sink<EventEmitter, RD
6262 // A promise representing the last job
6363 private lastOnValueJob : Promise < void > ;
6464 // The keys inside of the JSON tree
65- private readonly jsonKeyStack : ( string | number ) [ ] ;
65+ private readonly jsonKeyStack : ( string | number | undefined ) [ ] ;
6666 // The value inside of the JSON tree
6767 private readonly jsonValueStack : any [ ] ;
6868
@@ -410,80 +410,72 @@ export class JsonLdParser extends Transform implements RDF.Sink<EventEmitter, RD
410410 * This should only be called once.
411411 */
412412 protected onJsonEvent ( event : JsonEvent ) {
413- let key : any ;
414- let value : any ;
415413 switch ( event . type ) {
416414 case 'open-object' :
417- this . insertInStack ( event . key , { } , true ) ;
418- return ;
415+ this . jsonKeyStack . push ( event . key ) ;
416+ this . insertContainerInValueStack ( event . key , { } ) ;
417+ break ;
419418 case 'open-array' :
420- this . insertInStack ( event . key , [ ] , true ) ;
421- return ;
419+ this . jsonKeyStack . push ( event . key ) ;
420+ this . insertContainerInValueStack ( event . key , [ ] ) ;
421+ break ;
422422 case 'value' :
423- this . insertInStack ( event . key , event . value , false ) ;
424- key = event . key ;
425- value = event . value ;
423+ if ( ! this . jsonKeyStack . includes ( '@context' ) ) { // Don't parse inner nodes inside @context
424+ this . onValue ( event . key , event . value , this . jsonKeyStack ) ;
425+ }
426+ if ( typeof event . key === 'string' ) {
427+ this . jsonValueStack [ this . jsonValueStack . length - 1 ] [ event . key ] = event . value ;
428+ } else if ( typeof event . key === 'number' ) {
429+ this . jsonValueStack [ this . jsonValueStack . length - 1 ] . push ( event . value ) ;
430+ }
426431 break ;
427432 case 'close-object' :
428433 case 'close-array' :
429- key = this . jsonKeyStack [ this . jsonKeyStack . length - 1 ] ;
430- value = this . jsonValueStack [ this . jsonValueStack . length - 1 ] ;
434+ const key = this . jsonKeyStack . pop ( ) ;
435+ const value = this . jsonValueStack . pop ( ) ;
436+ if ( ! this . jsonKeyStack . includes ( '@context' ) ) { // Don't parse inner nodes inside @context
437+ this . onValue ( key , value , this . jsonKeyStack ) ;
438+ }
431439 }
440+ }
432441
433- const depth = this . jsonKeyStack . length ;
434- const keys = < string [ ] > < any [ ] > [ undefined , ...this . jsonKeyStack ] ;
442+ protected onValue ( key : string | number | undefined , value : any , keyStack : ( string | number | undefined ) [ ] ) {
443+ const depth = keyStack . length ;
444+ const keys = < string [ ] > < any [ ] > [ ...keyStack , key ] ;
435445
436- if ( ! this . isParsingContextInner ( ) ) { // Don't parse inner nodes inside @context
437- const valueJobCb = ( ) => this . newOnValueJob ( keys , value , depth , true ) ;
438- if ( ! this . parsingContext . streamingProfile
446+ const valueJobCb = ( ) => this . newOnValueJob ( keys , value , depth , true ) ;
447+ if ( ! this . parsingContext . streamingProfile
439448 && ! this . parsingContext . contextTree . getContext ( keys . slice ( 0 , - 1 ) ) ) {
440- // If an out-of-order context is allowed,
441- // we have to buffer everything.
442- // We store jobs for @context 's and @type's separately,
443- // because at the end, we have to process them first.
444- // We also handle @type because these *could* introduce a type-scoped context.
445- if ( key === '@context' ) {
446- let jobs = this . contextJobs [ depth ] ;
447- if ( ! jobs ) {
448- jobs = this . contextJobs [ depth ] = [ ] ;
449- }
450- jobs . push ( valueJobCb ) ;
451- } else if ( key === '@type'
452- || typeof key === 'number' && this . jsonKeyStack [ this . jsonKeyStack . length - 2 ] === '@type' ) { // Also capture @type with array values
453- // Remove @type from keys, because we want it to apply to parent later on
454- this . typeJobs . push ( { job : valueJobCb , keys : keys . slice ( 0 , keys . length - 1 ) } ) ;
455- } else {
456- this . contextAwaitingJobs . push ( { job : valueJobCb , keys } ) ;
449+ // If an out-of-order context is allowed,
450+ // we have to buffer everything.
451+ // We store jobs for @context 's and @type's separately,
452+ // because at the end, we have to process them first.
453+ // We also handle @type because these *could* introduce a type-scoped context.
454+ if ( key === '@context' ) {
455+ let jobs = this . contextJobs [ depth ] ;
456+ if ( ! jobs ) {
457+ jobs = this . contextJobs [ depth ] = [ ] ;
457458 }
459+ jobs . push ( valueJobCb ) ;
460+ } else if ( key === '@type'
461+ || typeof key === 'number' && keys [ keys . length - 2 ] === '@type' ) { // Also capture @type with array values
462+ // Remove @type from keys, because we want it to apply to parent later on
463+ this . typeJobs . push ( { job : valueJobCb , keys : keys . slice ( 0 , keys . length - 1 ) } ) ;
458464 } else {
459- // Make sure that our value jobs are chained synchronously
460- this . lastOnValueJob = this . lastOnValueJob . then ( valueJobCb ) ;
461- }
462-
463- // Execute all buffered jobs on deeper levels
464- if ( ! this . parsingContext . streamingProfile && depth === 0 ) {
465- this . lastOnValueJob = this . lastOnValueJob
466- . then ( ( ) => this . executeBufferedJobs ( ) ) ;
465+ this . contextAwaitingJobs . push ( { job : valueJobCb , keys } ) ;
467466 }
467+ } else {
468+ // Make sure that our value jobs are chained synchronously
469+ this . lastOnValueJob = this . lastOnValueJob . then ( valueJobCb ) ;
468470 }
469471
470- switch ( event . type ) {
471- case 'close-object' :
472- case 'close-array' :
473- this . jsonValueStack . pop ( ) ;
474- case "value" :
475- this . jsonKeyStack . pop ( ) ;
472+ // Execute all buffered jobs on deeper levels
473+ if ( ! this . parsingContext . streamingProfile && depth === 0 ) {
474+ this . lastOnValueJob = this . lastOnValueJob
475+ . then ( ( ) => this . executeBufferedJobs ( ) ) ;
476476 }
477477 }
478478
479- /**
480- * Check if the parser is currently parsing an element that is part of an @context entry.
481- * @return {boolean } A boolean.
482- */
483- protected isParsingContextInner ( ) {
484- return this . jsonKeyStack . slice ( 0 , - 1 ) . includes ( '@context' ) ;
485- }
486-
487479 /**
488480 * Execute all buffered jobs.
489481 * @return {Promise<void> } A promise resolving if all jobs are finished.
@@ -537,17 +529,13 @@ export class JsonLdParser extends Transform implements RDF.Sink<EventEmitter, RD
537529 }
538530 }
539531
540- private insertInStack ( key : string | number | undefined , value : any , push : boolean ) : void {
532+ private insertContainerInValueStack ( key : string | number | undefined , value : any ) : void {
541533 if ( typeof key === 'string' ) {
542- this . jsonKeyStack . push ( key ) ;
543534 this . jsonValueStack [ this . jsonValueStack . length - 1 ] [ key ] = value ;
544535 } else if ( typeof key === 'number' ) {
545- this . jsonKeyStack . push ( key ) ;
546536 this . jsonValueStack [ this . jsonValueStack . length - 1 ] . push ( value ) ;
547537 }
548- if ( push ) {
549- this . jsonValueStack . push ( value ) ;
550- }
538+ this . jsonValueStack . push ( value ) ;
551539 }
552540}
553541
0 commit comments