Skip to content

Commit e9d6c96

Browse files
committed
Disable context variables by default
1 parent 458484a commit e9d6c96

File tree

4 files changed

+97
-43
lines changed

4 files changed

+97
-43
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,13 +520,17 @@ These options can be used in all parsers.
520520
```
521521

522522
### Context variables
523-
You can use some special fields while parsing to traverse your structure. These
524-
context variables will be removed after the parsing process:
523+
You can use some special fields while parsing to traverse your structure.
524+
These context variables will be removed after the parsing process.
525+
Note that this feature is turned off by default for performance reasons, and
526+
you need to call `.useContextVars()` to enable it.
527+
525528
- `$parent` - This field references the parent structure. This variable will be
526529
`null` while parsing the root structure.
527530

528531
```javascript
529532
var parser = new Parser()
533+
.useContextVars()
530534
.nest("header", {
531535
type: new Parser().uint32("length"),
532536
})
@@ -542,6 +546,7 @@ context variables will be removed after the parsing process:
542546

543547
```javascript
544548
var parser = new Parser()
549+
.useContextVars()
545550
.nest("header", {
546551
type: new Parser().uint32("length"),
547552
})
@@ -562,6 +567,7 @@ context variables will be removed after the parsing process:
562567

563568
```javascript
564569
var parser = new Parser()
570+
.useContextVars()
565571
.nest("header", {
566572
type: new Parser().uint32("length"),
567573
})

lib/binary_parser.ts

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export class Parser {
178178
endian: Endianess = 'be';
179179
constructorFn: Function | null = null;
180180
alias: string | null = null;
181+
useContextVariables: boolean = false;
181182

182183
constructor() {}
183184

@@ -637,6 +638,12 @@ export class Parser {
637638
return this;
638639
}
639640

641+
useContextVars(useContextVariables: boolean = true) {
642+
this.useContextVariables = useContextVariables;
643+
644+
return this;
645+
}
646+
640647
create(constructorFn: Function) {
641648
if (!(constructorFn instanceof Function)) {
642649
throw new Error('Constructor must be a Function object.');
@@ -648,7 +655,7 @@ export class Parser {
648655
}
649656

650657
private getContext(importPath?: string) {
651-
const ctx = new Context(importPath);
658+
const ctx = new Context(importPath, this.useContextVariables);
652659

653660
ctx.pushCode(
654661
'var dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.length);'
@@ -673,15 +680,16 @@ export class Parser {
673680
ctx.pushCode(
674681
`var vars = ${this.constructorFn ? 'new constructorFn()' : '{}'};`
675682
);
683+
676684
ctx.pushCode('vars.$parent = null;');
677685
ctx.pushCode('vars.$root = vars;');
678686

679687
this.generate(ctx);
680-
681688
this.resolveReferences(ctx);
682689

683690
ctx.pushCode('delete vars.$parent;');
684691
ctx.pushCode('delete vars.$root;');
692+
685693
ctx.pushCode('return vars;');
686694
}
687695

@@ -691,7 +699,7 @@ export class Parser {
691699
`var vars = ${this.constructorFn ? 'new constructorFn()' : '{}'};`
692700
);
693701
ctx.pushCode(
694-
`var ctx = Object.assign({$parent: null, $root: vars}, context || {});`
702+
'var ctx = Object.assign({$parent: null, $root: vars}, context || {});'
695703
);
696704
ctx.pushCode(`vars = Object.assign(vars, ctx);`);
697705

@@ -1093,13 +1101,15 @@ export class Parser {
10931101
);
10941102
ctx.pushCode(`offset += ${PRIMITIVE_SIZES[type as PrimitiveTypes]};`);
10951103
} else {
1096-
const parentVar = ctx.generateVariable();
10971104
const tempVar = ctx.generateTmpVariable();
10981105
ctx.pushCode(`var ${tempVar} = ${FUNCTION_PREFIX + type}(offset, {`);
1099-
ctx.pushCode(`$parent: ${parentVar},`);
1100-
ctx.pushCode(`$root: ${parentVar}.$root,`);
1101-
if (!this.options.readUntil && lengthInBytes === undefined) {
1102-
ctx.pushCode(`$index: ${length} - ${counter},`);
1106+
if (ctx.useContextVariables) {
1107+
const parentVar = ctx.generateVariable();
1108+
ctx.pushCode(`$parent: ${parentVar},`);
1109+
ctx.pushCode(`$root: ${parentVar}.$root,`);
1110+
if (!this.options.readUntil && lengthInBytes === undefined) {
1111+
ctx.pushCode(`$index: ${length} - ${counter},`);
1112+
}
11031113
}
11041114
ctx.pushCode(`});`);
11051115
ctx.pushCode(
@@ -1108,19 +1118,25 @@ export class Parser {
11081118
if (type !== this.alias) ctx.addReference(type);
11091119
}
11101120
} else if (type instanceof Parser) {
1111-
const parentVar = ctx.generateVariable();
11121121
ctx.pushCode(`var ${item} = {};`);
1113-
1122+
const parentVar = ctx.generateVariable();
11141123
ctx.pushScope(item);
1115-
ctx.pushCode(`${item}.$parent = ${parentVar};`);
1116-
ctx.pushCode(`${item}.$root = ${parentVar}.$root;`);
1117-
if (!this.options.readUntil && lengthInBytes === undefined) {
1118-
ctx.pushCode(`${item}.$index = ${length} - ${counter};`);
1124+
1125+
if (ctx.useContextVariables) {
1126+
ctx.pushCode(`${item}.$parent = ${parentVar};`);
1127+
ctx.pushCode(`${item}.$root = ${parentVar}.$root;`);
1128+
if (!this.options.readUntil && lengthInBytes === undefined) {
1129+
ctx.pushCode(`${item}.$index = ${length} - ${counter};`);
1130+
}
11191131
}
1132+
11201133
type.generate(ctx);
1121-
ctx.pushCode(`delete ${item}.$parent;`);
1122-
ctx.pushCode(`delete ${item}.$root;`);
1123-
ctx.pushCode(`delete ${item}.$index;`);
1134+
1135+
if (ctx.useContextVariables) {
1136+
ctx.pushCode(`delete ${item}.$parent;`);
1137+
ctx.pushCode(`delete ${item}.$root;`);
1138+
ctx.pushCode(`delete ${item}.$index;`);
1139+
}
11241140
ctx.popScope();
11251141
}
11261142

@@ -1158,8 +1174,10 @@ export class Parser {
11581174
} else {
11591175
const tempVar = ctx.generateTmpVariable();
11601176
ctx.pushCode(`var ${tempVar} = ${FUNCTION_PREFIX + type}(offset, {`);
1161-
ctx.pushCode(`$parent: ${varName}.$parent,`);
1162-
ctx.pushCode(`$root: ${varName}.$root,`);
1177+
if (ctx.useContextVariables) {
1178+
ctx.pushCode(`$parent: ${varName}.$parent,`);
1179+
ctx.pushCode(`$root: ${varName}.$root,`);
1180+
}
11631181
ctx.pushCode(`});`);
11641182
ctx.pushCode(
11651183
`${varName} = ${tempVar}.result; offset = ${tempVar}.offset;`
@@ -1180,9 +1198,11 @@ export class Parser {
11801198
if (this.varName) {
11811199
ctx.pushCode(`${nestVar} = {};`);
11821200

1183-
const parentVar = ctx.generateVariable();
1184-
ctx.pushCode(`${nestVar}.$parent = ${parentVar};`);
1185-
ctx.pushCode(`${nestVar}.$root = ${parentVar}.$root;`);
1201+
if (ctx.useContextVariables) {
1202+
const parentVar = ctx.generateVariable();
1203+
ctx.pushCode(`${nestVar}.$parent = ${parentVar};`);
1204+
ctx.pushCode(`${nestVar}.$root = ${parentVar}.$root;`);
1205+
}
11861206
}
11871207
ctx.pushCode(`switch(${tag}) {`);
11881208
Object.keys(this.options.choices).forEach((tag) => {
@@ -1200,7 +1220,7 @@ export class Parser {
12001220
}
12011221
ctx.pushCode('}');
12021222

1203-
if (this.varName) {
1223+
if (this.varName && ctx.useContextVariables) {
12041224
ctx.pushCode(`delete ${nestVar}.$parent;`);
12051225
ctx.pushCode(`delete ${nestVar}.$root;`);
12061226
}
@@ -1211,26 +1231,35 @@ export class Parser {
12111231

12121232
if (this.options.type instanceof Parser) {
12131233
if (this.varName) {
1214-
const parentVar = ctx.generateVariable();
12151234
ctx.pushCode(`${nestVar} = {};`);
1216-
ctx.pushCode(`${nestVar}.$parent = ${parentVar};`);
1217-
ctx.pushCode(`${nestVar}.$root = ${parentVar}.$root;`);
1235+
1236+
if (ctx.useContextVariables) {
1237+
const parentVar = ctx.generateVariable();
1238+
ctx.pushCode(`${nestVar}.$parent = ${parentVar};`);
1239+
ctx.pushCode(`${nestVar}.$root = ${parentVar}.$root;`);
1240+
}
12181241
}
1242+
12191243
ctx.pushPath(this.varName);
12201244
this.options.type.generate(ctx);
12211245
ctx.popPath(this.varName);
1222-
if (this.varName) {
1223-
ctx.pushCode(`delete ${nestVar}.$parent;`);
1224-
ctx.pushCode(`delete ${nestVar}.$root;`);
1246+
1247+
if (this.varName && ctx.useContextVariables) {
1248+
if (ctx.useContextVariables) {
1249+
ctx.pushCode(`delete ${nestVar}.$parent;`);
1250+
ctx.pushCode(`delete ${nestVar}.$root;`);
1251+
}
12251252
}
12261253
} else if (aliasRegistry[this.options.type]) {
1227-
const parentVar = ctx.generateVariable();
12281254
const tempVar = ctx.generateTmpVariable();
12291255
ctx.pushCode(
12301256
`var ${tempVar} = ${FUNCTION_PREFIX + this.options.type}(offset, {`
12311257
);
1232-
ctx.pushCode(`$parent: ${parentVar},`);
1233-
ctx.pushCode(`$root: ${parentVar}.$root,`);
1258+
if (ctx.useContextVariables) {
1259+
const parentVar = ctx.generateVariable();
1260+
ctx.pushCode(`$parent: ${parentVar},`);
1261+
ctx.pushCode(`$root: ${parentVar}.$root,`);
1262+
}
12341263
ctx.pushCode(`});`);
12351264
ctx.pushCode(
12361265
`${nestVar} = ${tempVar}.result; offset = ${tempVar}.offset;`
@@ -1331,23 +1360,32 @@ export class Parser {
13311360
ctx.pushCode(`offset = ${offset};`);
13321361

13331362
if (this.options.type instanceof Parser) {
1334-
const parentVar = ctx.generateVariable();
13351363
ctx.pushCode(`${nestVar} = {};`);
1336-
ctx.pushCode(`${nestVar}.$parent = ${parentVar};`);
1337-
ctx.pushCode(`${nestVar}.$root = ${parentVar}.$root;`);
1364+
1365+
if (ctx.useContextVariables) {
1366+
const parentVar = ctx.generateVariable();
1367+
ctx.pushCode(`${nestVar}.$parent = ${parentVar};`);
1368+
ctx.pushCode(`${nestVar}.$root = ${parentVar}.$root;`);
1369+
}
1370+
13381371
ctx.pushPath(this.varName);
13391372
this.options.type.generate(ctx);
13401373
ctx.popPath(this.varName);
1341-
ctx.pushCode(`delete ${nestVar}.$parent;`);
1342-
ctx.pushCode(`delete ${nestVar}.$root;`);
1374+
1375+
if (ctx.useContextVariables) {
1376+
ctx.pushCode(`delete ${nestVar}.$parent;`);
1377+
ctx.pushCode(`delete ${nestVar}.$root;`);
1378+
}
13431379
} else if (aliasRegistry[this.options.type]) {
1344-
const parentVar = ctx.generateVariable();
13451380
const tempVar = ctx.generateTmpVariable();
13461381
ctx.pushCode(
13471382
`var ${tempVar} = ${FUNCTION_PREFIX + this.options.type}(offset, {`
13481383
);
1349-
ctx.pushCode(`$parent: ${parentVar},`);
1350-
ctx.pushCode(`$root: ${parentVar}.$root,`);
1384+
if (ctx.useContextVariables) {
1385+
const parentVar = ctx.generateVariable();
1386+
ctx.pushCode(`$parent: ${parentVar},`);
1387+
ctx.pushCode(`$root: ${parentVar}.$root,`);
1388+
}
13511389
ctx.pushCode(`});`);
13521390
ctx.pushCode(
13531391
`${nestVar} = ${tempVar}.result; offset = ${tempVar}.offset;`

lib/context.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ export class Context {
99
importPath: string;
1010
imports: any[] = [];
1111
reverseImports = new Map<any, number>();
12+
useContextVariables: boolean = false;
1213

13-
constructor(importPath?: string) {
14+
constructor(importPath?: string, useContextVariables?: boolean) {
1415
this.importPath = importPath;
16+
this.useContextVariables = useContextVariables;
1517
}
1618

1719
generateVariable(name?: string) {

test/composite_parser.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const suite = (Buffer) =>
7272
});
7373

7474
var parser = Parser.start()
75+
.useContextVars()
7576
.uint16le('length')
7677
.uint16le('valueLength')
7778
.array('message', {
@@ -109,6 +110,7 @@ const suite = (Buffer) =>
109110
});
110111

111112
var parser = Parser.start()
113+
.useContextVars()
112114
.uint16le('length')
113115
.uint16le('valueLength')
114116
.array('message', {
@@ -444,6 +446,7 @@ const suite = (Buffer) =>
444446
// /
445447
// 0
446448

449+
// prettier-ignore
447450
var buffer = Buffer.from([
448451
2,
449452
/* 0 */ 3,
@@ -523,6 +526,7 @@ const suite = (Buffer) =>
523526
});
524527

525528
var parser = Parser.start()
529+
.useContextVars()
526530
.uint16le('length')
527531
.uint16le('valueLength')
528532
.array('message', {
@@ -567,6 +571,7 @@ const suite = (Buffer) =>
567571
.namely('ArrayLengthIndexTest');
568572

569573
var parser = Parser.start()
574+
.useContextVars()
570575
.uint16le('length')
571576
.uint16le('valueLength')
572577
.array('message', {
@@ -845,6 +850,7 @@ const suite = (Buffer) =>
845850
// /
846851
// 0
847852

853+
// prettier-ignore
848854
var buffer = Buffer.from([
849855
2,
850856
/* left -> */ 3,
@@ -1009,6 +1015,7 @@ const suite = (Buffer) =>
10091015
});
10101016
it('should be able to use parsing context', function () {
10111017
var parser = Parser.start()
1018+
.useContextVars()
10121019
.uint8('tag')
10131020
.uint8('items')
10141021
.choice('data', {
@@ -1141,6 +1148,7 @@ const suite = (Buffer) =>
11411148

11421149
it('should be able to use parsing context', function () {
11431150
var parser = Parser.start()
1151+
.useContextVars()
11441152
.uint8('items')
11451153
.nest('data', {
11461154
type: Parser.start()

0 commit comments

Comments
 (0)