@@ -670,34 +670,38 @@ export class Parser {
670670
671671 private addRawCode ( ctx : Context ) {
672672 ctx . pushCode ( 'var offset = 0;' ) ;
673-
674- if ( this . constructorFn ) {
675- ctx . pushCode ( 'var vars = new constructorFn();' ) ;
676- } else {
677- ctx . pushCode ( 'var vars = {};' ) ;
678- }
673+ ctx . pushCode (
674+ `var vars = ${ this . constructorFn ? 'new constructorFn()' : '{}' } ;`
675+ ) ;
676+ ctx . pushCode ( 'vars.$parent = null;' ) ;
677+ ctx . pushCode ( 'vars.$root = vars;' ) ;
679678
680679 this . generate ( ctx ) ;
681680
682681 this . resolveReferences ( ctx ) ;
683682
683+ ctx . pushCode ( 'delete vars.$parent;' ) ;
684+ ctx . pushCode ( 'delete vars.$root;' ) ;
684685 ctx . pushCode ( 'return vars;' ) ;
685686 }
686687
687688 private addAliasedCode ( ctx : Context ) {
688- ctx . pushCode ( `function ${ FUNCTION_PREFIX + this . alias } (offset) {` ) ;
689-
690- if ( this . constructorFn ) {
691- ctx . pushCode ( 'var vars = new constructorFn();' ) ;
692- } else {
693- ctx . pushCode ( 'var vars = {};' ) ;
694- }
689+ ctx . pushCode (
690+ `function ${ FUNCTION_PREFIX + this . alias } (offset, parent, root) {`
691+ ) ;
692+ ctx . pushCode (
693+ `var vars = ${ this . constructorFn ? 'new constructorFn()' : '{}' } ;`
694+ ) ;
695+ ctx . pushCode ( 'vars.$parent = parent || null;' ) ;
696+ ctx . pushCode ( 'vars.$root = root || vars;' ) ;
695697
696698 this . generate ( ctx ) ;
697699
698700 ctx . markResolved ( this . alias ) ;
699701 this . resolveReferences ( ctx ) ;
700702
703+ ctx . pushCode ( 'delete vars.$parent;' ) ;
704+ ctx . pushCode ( 'delete vars.$root;' ) ;
701705 ctx . pushCode ( 'return { offset: offset, result: vars };' ) ;
702706 ctx . pushCode ( '}' ) ;
703707
@@ -1088,18 +1092,28 @@ export class Parser {
10881092 ) ;
10891093 ctx . pushCode ( `offset += ${ PRIMITIVE_SIZES [ type as PrimitiveTypes ] } ;` ) ;
10901094 } else {
1095+ const parentVar = ctx . generateVariable ( ) ;
10911096 const tempVar = ctx . generateTmpVariable ( ) ;
1092- ctx . pushCode ( `var ${ tempVar } = ${ FUNCTION_PREFIX + type } (offset);` ) ;
1097+ ctx . pushCode (
1098+ `var ${ tempVar } = ${
1099+ FUNCTION_PREFIX + type
1100+ } (offset, ${ parentVar } , ${ parentVar } .$root);`
1101+ ) ;
10931102 ctx . pushCode (
10941103 `var ${ item } = ${ tempVar } .result; offset = ${ tempVar } .offset;`
10951104 ) ;
10961105 if ( type !== this . alias ) ctx . addReference ( type ) ;
10971106 }
10981107 } else if ( type instanceof Parser ) {
1108+ const parentVar = ctx . generateVariable ( ) ;
10991109 ctx . pushCode ( `var ${ item } = {};` ) ;
11001110
11011111 ctx . pushScope ( item ) ;
1112+ ctx . pushCode ( `${ item } .$parent = ${ parentVar } ;` ) ;
1113+ ctx . pushCode ( `${ item } .$root = ${ parentVar } .$root;` ) ;
11021114 type . generate ( ctx ) ;
1115+ ctx . pushCode ( `delete ${ item } .$parent` ) ;
1116+ ctx . pushCode ( `delete ${ item } .$root` ) ;
11031117 ctx . popScope ( ) ;
11041118 }
11051119
@@ -1136,7 +1150,11 @@ export class Parser {
11361150 ctx . pushCode ( `offset += ${ PRIMITIVE_SIZES [ type as PrimitiveTypes ] } ` ) ;
11371151 } else {
11381152 const tempVar = ctx . generateTmpVariable ( ) ;
1139- ctx . pushCode ( `var ${ tempVar } = ${ FUNCTION_PREFIX + type } (offset);` ) ;
1153+ ctx . pushCode (
1154+ `var ${ tempVar } = ${
1155+ FUNCTION_PREFIX + type
1156+ } (offset, ${ varName } .$parent, ${ varName } .$root);`
1157+ ) ;
11401158 ctx . pushCode (
11411159 `${ varName } = ${ tempVar } .result; offset = ${ tempVar } .offset;`
11421160 ) ;
@@ -1151,8 +1169,14 @@ export class Parser {
11511169
11521170 private generateChoice ( ctx : Context ) {
11531171 const tag = ctx . generateOption ( this . options . tag ) ;
1172+ const nestVar = ctx . generateVariable ( this . varName ) ;
1173+
11541174 if ( this . varName ) {
1155- ctx . pushCode ( `${ ctx . generateVariable ( this . varName ) } = {};` ) ;
1175+ ctx . pushCode ( `${ nestVar } = {};` ) ;
1176+
1177+ const parentVar = ctx . generateVariable ( ) ;
1178+ ctx . pushCode ( `${ nestVar } .$parent = ${ parentVar } ;` ) ;
1179+ ctx . pushCode ( `${ nestVar } .$root = ${ parentVar } .$root;` ) ;
11561180 }
11571181 ctx . pushCode ( `switch(${ tag } ) {` ) ;
11581182 Object . keys ( this . options . choices ) . forEach ( ( tag ) => {
@@ -1169,22 +1193,37 @@ export class Parser {
11691193 ctx . generateError ( `"Met undefined tag value " + ${ tag } + " at choice"` ) ;
11701194 }
11711195 ctx . pushCode ( '}' ) ;
1196+
1197+ if ( this . varName ) {
1198+ ctx . pushCode ( `delete ${ nestVar } .$parent` ) ;
1199+ ctx . pushCode ( `delete ${ nestVar } .$root` ) ;
1200+ }
11721201 }
11731202
11741203 private generateNest ( ctx : Context ) {
11751204 const nestVar = ctx . generateVariable ( this . varName ) ;
11761205
11771206 if ( this . options . type instanceof Parser ) {
11781207 if ( this . varName ) {
1208+ const parentVar = ctx . generateVariable ( ) ;
11791209 ctx . pushCode ( `${ nestVar } = {};` ) ;
1210+ ctx . pushCode ( `${ nestVar } .$parent = ${ parentVar } ;` ) ;
1211+ ctx . pushCode ( `${ nestVar } .$root = ${ parentVar } .$root;` ) ;
11801212 }
11811213 ctx . pushPath ( this . varName ) ;
11821214 this . options . type . generate ( ctx ) ;
11831215 ctx . popPath ( this . varName ) ;
1216+ if ( this . varName ) {
1217+ ctx . pushCode ( `delete ${ nestVar } .$parent` ) ;
1218+ ctx . pushCode ( `delete ${ nestVar } .$root` ) ;
1219+ }
11841220 } else if ( aliasRegistry [ this . options . type ] ) {
1221+ const parentVar = ctx . generateVariable ( ) ;
11851222 const tempVar = ctx . generateTmpVariable ( ) ;
11861223 ctx . pushCode (
1187- `var ${ tempVar } = ${ FUNCTION_PREFIX + this . options . type } (offset);`
1224+ `var ${ tempVar } = ${
1225+ FUNCTION_PREFIX + this . options . type
1226+ } (offset, ${ parentVar } , ${ parentVar } .$root);`
11881227 ) ;
11891228 ctx . pushCode (
11901229 `${ nestVar } = ${ tempVar } .result; offset = ${ tempVar } .offset;`
@@ -1283,14 +1322,22 @@ export class Parser {
12831322 ctx . pushCode ( `offset = ${ offset } ;` ) ;
12841323
12851324 if ( this . options . type instanceof Parser ) {
1325+ const parentVar = ctx . generateVariable ( ) ;
12861326 ctx . pushCode ( `${ nestVar } = {};` ) ;
1327+ ctx . pushCode ( `${ nestVar } .$parent = ${ parentVar } ;` ) ;
1328+ ctx . pushCode ( `${ nestVar } .$root = ${ parentVar } .$root;` ) ;
12871329 ctx . pushPath ( this . varName ) ;
12881330 this . options . type . generate ( ctx ) ;
12891331 ctx . popPath ( this . varName ) ;
1332+ ctx . pushCode ( `delete ${ nestVar } .$parent` ) ;
1333+ ctx . pushCode ( `delete ${ nestVar } .$root` ) ;
12901334 } else if ( aliasRegistry [ this . options . type ] ) {
1335+ const parentVar = ctx . generateVariable ( ) ;
12911336 const tempVar = ctx . generateTmpVariable ( ) ;
12921337 ctx . pushCode (
1293- `var ${ tempVar } = ${ FUNCTION_PREFIX + this . options . type } (offset);`
1338+ `var ${ tempVar } = ${
1339+ FUNCTION_PREFIX + this . options . type
1340+ } (offset, ${ parentVar } , ${ parentVar } .$root);`
12941341 ) ;
12951342 ctx . pushCode (
12961343 `${ nestVar } = ${ tempVar } .result; offset = ${ tempVar } .offset;`
0 commit comments