poe-code 4.0.57 → 4.0.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/program.js +2 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/index.js +1755 -2241
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safejs/dist/graph-depth.js +4 -0
- package/packages/safejs/dist/interp/arguments.d.ts +10 -0
- package/packages/safejs/dist/interp/arguments.js +44 -0
- package/packages/safejs/dist/interp/async.js +3 -1
- package/packages/safejs/dist/interp/values.d.ts +1 -1
- package/packages/safejs/dist/interp/values.js +27 -2
- package/packages/safejs/dist/lint/index.js +0 -4
- package/packages/safejs/dist/lint/rules/AS-async-not-needed.d.ts +1 -1
- package/packages/safejs/dist/lint/rules/AS-async-not-needed.js +15 -3
- package/packages/safejs/dist/lint/rules/AS-await-non-promise.js +10 -0
- package/packages/safejs/dist/lint/rules/AS-destructure-null-default.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-export-import-meta.js +17 -0
- package/packages/safejs/dist/lint/rules/AS-floating-promise.js +23 -2
- package/packages/safejs/dist/lint/rules/AS-frontmatter-field-unused.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-jsdoc-type.js +10 -0
- package/packages/safejs/dist/lint/rules/AS-large-literal.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-missing-async.d.ts +1 -1
- package/packages/safejs/dist/lint/rules/AS-missing-async.js +9 -1
- package/packages/safejs/dist/lint/rules/AS-mutating-frozen.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-needless-template.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-shadow-global.js +12 -0
- package/packages/safejs/dist/lint/rules/AS-unbounded-loop.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-unreachable.js +9 -1
- package/packages/safejs/dist/lint/rules/AS-unused-import.js +22 -0
- package/packages/safejs/dist/lint/rules/AS001.js +0 -6
- package/packages/safejs/dist/lint/rules/AS003.js +22 -0
- package/packages/safejs/dist/lint/rules/AS006-007.js +19 -0
- package/packages/safejs/dist/lint/rules/AS008.js +9 -0
- package/packages/safejs/dist/lint/rules/AS009.js +9 -0
- package/packages/safejs/dist/lint/rules/AS010.js +9 -0
- package/packages/safejs/dist/lint/rules/AS011.js +9 -0
- package/packages/safejs/dist/lint/rules/AS015.js +9 -0
- package/packages/safejs/dist/parse/parser.d.ts +1 -0
- package/packages/safejs/dist/parse/parser.js +4 -7
- package/packages/safejs/dist/snapshot/arguments.d.ts +17 -0
- package/packages/safejs/dist/snapshot/arguments.js +34 -0
- package/packages/safejs/dist/snapshot/dump-format.js +15 -3
- package/packages/safejs/dist/snapshot/restore.js +27 -1
- package/packages/safejs/dist/snapshot/serialize.d.ts +2 -1
- package/packages/safejs/dist/snapshot/serialize.js +20 -10
- package/packages/safejs/dist/snapshot/validation.js +50 -1
- package/packages/safejs/dist/lint/rules/AS002.d.ts +0 -13
- package/packages/safejs/dist/lint/rules/AS002.js +0 -525
- package/packages/safejs/dist/lint/rules/AS012.d.ts +0 -13
- package/packages/safejs/dist/lint/rules/AS012.js +0 -384
|
@@ -31,6 +31,9 @@ class ASUnreachableScanner {
|
|
|
31
31
|
}
|
|
32
32
|
visitStatement(node) {
|
|
33
33
|
switch (node.type) {
|
|
34
|
+
case "FunctionDeclaration":
|
|
35
|
+
this.visitArrowFunction(node);
|
|
36
|
+
return false;
|
|
34
37
|
case "BlockStatement":
|
|
35
38
|
return this.visitBlock(node);
|
|
36
39
|
case "ExpressionStatement":
|
|
@@ -75,7 +78,6 @@ class ASUnreachableScanner {
|
|
|
75
78
|
this.visitExpression(node.declaration);
|
|
76
79
|
return false;
|
|
77
80
|
case "ImportDeclaration":
|
|
78
|
-
case "FunctionDeclaration":
|
|
79
81
|
case "EmptyStatement":
|
|
80
82
|
return false;
|
|
81
83
|
}
|
|
@@ -156,6 +158,12 @@ class ASUnreachableScanner {
|
|
|
156
158
|
}
|
|
157
159
|
visitExpression(node) {
|
|
158
160
|
switch (node.type) {
|
|
161
|
+
case "YieldExpression":
|
|
162
|
+
if (node.argument !== undefined) {
|
|
163
|
+
this.visitExpression(node.argument);
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
case "FunctionExpression":
|
|
159
167
|
case "ArrowFunctionExpression":
|
|
160
168
|
this.visitArrowFunction(node);
|
|
161
169
|
return;
|
|
@@ -55,6 +55,9 @@ class ASUnusedImportScanner {
|
|
|
55
55
|
}
|
|
56
56
|
visitStatement(node) {
|
|
57
57
|
switch (node.type) {
|
|
58
|
+
case "FunctionDeclaration":
|
|
59
|
+
this.visitArrowFunction(node);
|
|
60
|
+
return;
|
|
58
61
|
case "ExportNamedDeclaration":
|
|
59
62
|
this.visitVariableDeclaration(node.declaration);
|
|
60
63
|
return;
|
|
@@ -182,9 +185,15 @@ class ASUnusedImportScanner {
|
|
|
182
185
|
}
|
|
183
186
|
visitExpression(node) {
|
|
184
187
|
switch (node.type) {
|
|
188
|
+
case "YieldExpression":
|
|
189
|
+
if (node.argument !== undefined) {
|
|
190
|
+
this.visitExpression(node.argument);
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
185
193
|
case "Identifier":
|
|
186
194
|
this.markRead(node);
|
|
187
195
|
return;
|
|
196
|
+
case "FunctionExpression":
|
|
188
197
|
case "ArrowFunctionExpression":
|
|
189
198
|
this.visitArrowFunction(node);
|
|
190
199
|
return;
|
|
@@ -417,6 +426,10 @@ class ASUnusedImportScanner {
|
|
|
417
426
|
bindings.push(...this.collectImportBindings(statement));
|
|
418
427
|
continue;
|
|
419
428
|
}
|
|
429
|
+
if (statement.type === "FunctionDeclaration") {
|
|
430
|
+
bindings.push({ kind: "let", name: statement.id.name });
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
420
433
|
if (statement.type === "VariableDeclaration") {
|
|
421
434
|
bindings.push(...this.collectDeclarationBindings(statement));
|
|
422
435
|
continue;
|
|
@@ -430,6 +443,9 @@ class ASUnusedImportScanner {
|
|
|
430
443
|
collectBlockBindings(body) {
|
|
431
444
|
const bindings = [];
|
|
432
445
|
for (const statement of body) {
|
|
446
|
+
if (statement.type === "FunctionDeclaration") {
|
|
447
|
+
bindings.push({ kind: "let", name: statement.id.name });
|
|
448
|
+
}
|
|
433
449
|
if (statement.type === "VariableDeclaration") {
|
|
434
450
|
bindings.push(...this.collectDeclarationBindings(statement));
|
|
435
451
|
}
|
|
@@ -438,6 +454,12 @@ class ASUnusedImportScanner {
|
|
|
438
454
|
}
|
|
439
455
|
collectParameterBindings(node) {
|
|
440
456
|
const bindings = [];
|
|
457
|
+
if (node.type !== "ArrowFunctionExpression") {
|
|
458
|
+
bindings.push({ kind: "param", name: "arguments" });
|
|
459
|
+
if (node.type === "FunctionExpression" && node.id !== undefined) {
|
|
460
|
+
bindings.push({ kind: "param", name: node.id.name });
|
|
461
|
+
}
|
|
462
|
+
}
|
|
441
463
|
for (const parameter of node.params) {
|
|
442
464
|
this.collectBindingNamesFromElement(parameter, "param", bindings);
|
|
443
465
|
}
|
|
@@ -165,11 +165,6 @@ class AS001Scanner {
|
|
|
165
165
|
pendingClassBody = true;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
if (token.value === "function" && nextSignificantChar === "*") {
|
|
169
|
-
const generatorStart = this.positionWithinSource(this.skipTriviaFrom(this.index));
|
|
170
|
-
const generatorEnd = this.positionWithinSource(this.skipTriviaFrom(this.index) + 1);
|
|
171
|
-
this.report("generator", generatorStart, generatorEnd);
|
|
172
|
-
}
|
|
173
168
|
}
|
|
174
169
|
const isStatementBrace = token.type === "punctuator" && token.value === "{" && canStartStatement;
|
|
175
170
|
if (token.type === "punctuator" && token.value === "{") {
|
|
@@ -218,7 +213,6 @@ class AS001Scanner {
|
|
|
218
213
|
switch (token.value) {
|
|
219
214
|
case "class":
|
|
220
215
|
case "eval":
|
|
221
|
-
case "function":
|
|
222
216
|
case "Function":
|
|
223
217
|
case "switch":
|
|
224
218
|
case "this":
|
|
@@ -26,6 +26,9 @@ class AS003Scanner {
|
|
|
26
26
|
}
|
|
27
27
|
visitStatement(node) {
|
|
28
28
|
switch (node.type) {
|
|
29
|
+
case "FunctionDeclaration":
|
|
30
|
+
this.visitArrowFunction(node);
|
|
31
|
+
return;
|
|
29
32
|
case "BlockStatement":
|
|
30
33
|
this.visitBlock(node);
|
|
31
34
|
return;
|
|
@@ -159,9 +162,15 @@ class AS003Scanner {
|
|
|
159
162
|
}
|
|
160
163
|
visitExpression(node) {
|
|
161
164
|
switch (node.type) {
|
|
165
|
+
case "YieldExpression":
|
|
166
|
+
if (node.argument !== undefined) {
|
|
167
|
+
this.visitExpression(node.argument);
|
|
168
|
+
}
|
|
169
|
+
return;
|
|
162
170
|
case "Identifier":
|
|
163
171
|
this.visitIdentifier(node);
|
|
164
172
|
return;
|
|
173
|
+
case "FunctionExpression":
|
|
165
174
|
case "ArrowFunctionExpression":
|
|
166
175
|
this.visitArrowFunction(node);
|
|
167
176
|
return;
|
|
@@ -438,6 +447,10 @@ class AS003Scanner {
|
|
|
438
447
|
bindings.push(...this.collectImportBindings(statement));
|
|
439
448
|
continue;
|
|
440
449
|
}
|
|
450
|
+
if (statement.type === "FunctionDeclaration") {
|
|
451
|
+
bindings.push({ kind: "let", name: statement.id.name });
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
441
454
|
if (statement.type === "VariableDeclaration") {
|
|
442
455
|
bindings.push(...this.collectDeclarationBindings(statement));
|
|
443
456
|
continue;
|
|
@@ -451,6 +464,9 @@ class AS003Scanner {
|
|
|
451
464
|
collectBlockBindings(body) {
|
|
452
465
|
const bindings = [];
|
|
453
466
|
for (const statement of body) {
|
|
467
|
+
if (statement.type === "FunctionDeclaration") {
|
|
468
|
+
bindings.push({ kind: "let", name: statement.id.name });
|
|
469
|
+
}
|
|
454
470
|
if (statement.type === "VariableDeclaration") {
|
|
455
471
|
bindings.push(...this.collectDeclarationBindings(statement));
|
|
456
472
|
}
|
|
@@ -459,6 +475,12 @@ class AS003Scanner {
|
|
|
459
475
|
}
|
|
460
476
|
collectParameterBindings(node) {
|
|
461
477
|
const bindings = [];
|
|
478
|
+
if (node.type !== "ArrowFunctionExpression") {
|
|
479
|
+
bindings.push({ kind: "let", name: "arguments" });
|
|
480
|
+
if (node.type === "FunctionExpression" && node.id !== undefined) {
|
|
481
|
+
bindings.push({ kind: "const", name: node.id.name });
|
|
482
|
+
}
|
|
483
|
+
}
|
|
462
484
|
for (const parameter of node.params) {
|
|
463
485
|
this.collectBindingNamesFromElement(parameter, "param", bindings);
|
|
464
486
|
}
|
|
@@ -26,6 +26,9 @@ class AS006007Scanner {
|
|
|
26
26
|
}
|
|
27
27
|
visitStatement(node) {
|
|
28
28
|
switch (node.type) {
|
|
29
|
+
case "FunctionDeclaration":
|
|
30
|
+
this.visitArrowFunction(node);
|
|
31
|
+
return;
|
|
29
32
|
case "ExportNamedDeclaration":
|
|
30
33
|
this.visitVariableDeclaration(node.declaration);
|
|
31
34
|
return;
|
|
@@ -159,9 +162,15 @@ class AS006007Scanner {
|
|
|
159
162
|
}
|
|
160
163
|
visitExpression(node) {
|
|
161
164
|
switch (node.type) {
|
|
165
|
+
case "YieldExpression":
|
|
166
|
+
if (node.argument !== undefined) {
|
|
167
|
+
this.visitExpression(node.argument);
|
|
168
|
+
}
|
|
169
|
+
return;
|
|
162
170
|
case "Identifier":
|
|
163
171
|
this.markRead(node);
|
|
164
172
|
return;
|
|
173
|
+
case "FunctionExpression":
|
|
165
174
|
case "ArrowFunctionExpression":
|
|
166
175
|
this.visitArrowFunction(node);
|
|
167
176
|
return;
|
|
@@ -432,6 +441,10 @@ class AS006007Scanner {
|
|
|
432
441
|
bindings.push(...this.collectImportBindings(statement));
|
|
433
442
|
continue;
|
|
434
443
|
}
|
|
444
|
+
if (statement.type === "FunctionDeclaration") {
|
|
445
|
+
bindings.push(this.createBinding(statement.id, "let"));
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
435
448
|
if (statement.type === "VariableDeclaration") {
|
|
436
449
|
bindings.push(...this.collectDeclarationBindings(statement));
|
|
437
450
|
continue;
|
|
@@ -445,6 +458,9 @@ class AS006007Scanner {
|
|
|
445
458
|
collectBlockBindings(body) {
|
|
446
459
|
const bindings = [];
|
|
447
460
|
for (const statement of body) {
|
|
461
|
+
if (statement.type === "FunctionDeclaration") {
|
|
462
|
+
bindings.push(this.createBinding(statement.id, "let"));
|
|
463
|
+
}
|
|
448
464
|
if (statement.type === "VariableDeclaration") {
|
|
449
465
|
bindings.push(...this.collectDeclarationBindings(statement));
|
|
450
466
|
}
|
|
@@ -453,6 +469,9 @@ class AS006007Scanner {
|
|
|
453
469
|
}
|
|
454
470
|
collectParameterBindings(node) {
|
|
455
471
|
const bindings = [];
|
|
472
|
+
if (node.type === "FunctionExpression" && node.id !== undefined) {
|
|
473
|
+
bindings.push(this.createBinding(node.id, "param"));
|
|
474
|
+
}
|
|
456
475
|
for (const parameter of node.params) {
|
|
457
476
|
this.collectBindingNamesFromElement(parameter, "param", bindings);
|
|
458
477
|
}
|
|
@@ -23,6 +23,9 @@ class AS008Scanner {
|
|
|
23
23
|
}
|
|
24
24
|
visitStatement(node) {
|
|
25
25
|
switch (node.type) {
|
|
26
|
+
case "FunctionDeclaration":
|
|
27
|
+
this.visitArrowFunction(node);
|
|
28
|
+
return;
|
|
26
29
|
case "BlockStatement":
|
|
27
30
|
this.withNestedScope(() => {
|
|
28
31
|
this.visitBlock(node);
|
|
@@ -141,6 +144,12 @@ class AS008Scanner {
|
|
|
141
144
|
}
|
|
142
145
|
visitExpression(node) {
|
|
143
146
|
switch (node.type) {
|
|
147
|
+
case "YieldExpression":
|
|
148
|
+
if (node.argument !== undefined) {
|
|
149
|
+
this.visitExpression(node.argument);
|
|
150
|
+
}
|
|
151
|
+
return;
|
|
152
|
+
case "FunctionExpression":
|
|
144
153
|
case "ArrowFunctionExpression":
|
|
145
154
|
this.visitArrowFunction(node);
|
|
146
155
|
return;
|
|
@@ -28,6 +28,9 @@ class AS009Scanner {
|
|
|
28
28
|
}
|
|
29
29
|
visitStatement(node) {
|
|
30
30
|
switch (node.type) {
|
|
31
|
+
case "FunctionDeclaration":
|
|
32
|
+
this.visitArrowFunction(node);
|
|
33
|
+
return;
|
|
31
34
|
case "BlockStatement":
|
|
32
35
|
this.visitBlockStatement(node.body);
|
|
33
36
|
return;
|
|
@@ -157,6 +160,12 @@ class AS009Scanner {
|
|
|
157
160
|
}
|
|
158
161
|
visitExpression(node) {
|
|
159
162
|
switch (node.type) {
|
|
163
|
+
case "YieldExpression":
|
|
164
|
+
if (node.argument !== undefined) {
|
|
165
|
+
this.visitExpression(node.argument);
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
case "FunctionExpression":
|
|
160
169
|
case "ArrowFunctionExpression":
|
|
161
170
|
this.visitArrowFunction(node);
|
|
162
171
|
return;
|
|
@@ -38,6 +38,9 @@ class AS010Scanner {
|
|
|
38
38
|
}
|
|
39
39
|
visitStatement(node) {
|
|
40
40
|
switch (node.type) {
|
|
41
|
+
case "FunctionDeclaration":
|
|
42
|
+
this.visitArrowFunction(node);
|
|
43
|
+
return;
|
|
41
44
|
case "BlockStatement":
|
|
42
45
|
this.visitBlock(node);
|
|
43
46
|
return;
|
|
@@ -176,9 +179,15 @@ class AS010Scanner {
|
|
|
176
179
|
}
|
|
177
180
|
visitExpression(node) {
|
|
178
181
|
switch (node.type) {
|
|
182
|
+
case "YieldExpression":
|
|
183
|
+
if (node.argument !== undefined) {
|
|
184
|
+
this.visitExpression(node.argument);
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
179
187
|
case "Identifier":
|
|
180
188
|
this.markRead(node);
|
|
181
189
|
return;
|
|
190
|
+
case "FunctionExpression":
|
|
182
191
|
case "ArrowFunctionExpression":
|
|
183
192
|
this.visitArrowFunction(node);
|
|
184
193
|
return;
|
|
@@ -21,6 +21,9 @@ class AS011Scanner {
|
|
|
21
21
|
}
|
|
22
22
|
visitStatement(node) {
|
|
23
23
|
switch (node.type) {
|
|
24
|
+
case "FunctionDeclaration":
|
|
25
|
+
this.visitArrowFunction(node);
|
|
26
|
+
return;
|
|
24
27
|
case "BlockStatement":
|
|
25
28
|
for (const statement of node.body) {
|
|
26
29
|
this.visitStatement(statement);
|
|
@@ -138,6 +141,12 @@ class AS011Scanner {
|
|
|
138
141
|
}
|
|
139
142
|
visitExpression(node) {
|
|
140
143
|
switch (node.type) {
|
|
144
|
+
case "YieldExpression":
|
|
145
|
+
if (node.argument !== undefined) {
|
|
146
|
+
this.visitExpression(node.argument);
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
case "FunctionExpression":
|
|
141
150
|
case "ArrowFunctionExpression":
|
|
142
151
|
this.visitArrowFunction(node);
|
|
143
152
|
return;
|
|
@@ -19,6 +19,9 @@ class AS015Scanner {
|
|
|
19
19
|
}
|
|
20
20
|
visitStatement(node) {
|
|
21
21
|
switch (node.type) {
|
|
22
|
+
case "FunctionDeclaration":
|
|
23
|
+
this.visitArrowFunction(node);
|
|
24
|
+
return;
|
|
22
25
|
case "BlockStatement":
|
|
23
26
|
for (const statement of node.body) {
|
|
24
27
|
this.visitStatement(statement);
|
|
@@ -136,6 +139,12 @@ class AS015Scanner {
|
|
|
136
139
|
}
|
|
137
140
|
visitExpression(node) {
|
|
138
141
|
switch (node.type) {
|
|
142
|
+
case "YieldExpression":
|
|
143
|
+
if (node.argument !== undefined) {
|
|
144
|
+
this.visitExpression(node.argument);
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
case "FunctionExpression":
|
|
139
148
|
case "ArrowFunctionExpression":
|
|
140
149
|
this.visitArrowFunction(node);
|
|
141
150
|
return;
|
|
@@ -346,6 +346,7 @@ export type ArrowFunctionExpression = BaseNode & {
|
|
|
346
346
|
expression: boolean;
|
|
347
347
|
params: Array<AssignmentPattern | ArrayPattern | Identifier | ObjectPattern | RestElement>;
|
|
348
348
|
};
|
|
349
|
+
export type FunctionNode = ArrowFunctionExpression | FunctionDeclaration | FunctionExpression;
|
|
349
350
|
export type Expression = ArrowFunctionExpression | AssignmentExpression | ArrayExpression | AwaitExpression | BinaryExpression | BooleanLiteral | CallExpression | ConditionalExpression | FunctionExpression | Identifier | LogicalExpression | MemberExpression | MetaProperty | NewExpression | NullLiteral | NumericLiteral | ObjectExpression | RegexLiteral | SequenceExpression | StringLiteral | TaggedTemplateExpression | TemplateLiteral | ThisExpression | UnaryExpression | UpdateExpression | UndefinedLiteral | YieldExpression;
|
|
350
351
|
export type ParseResult = Expression | Statement;
|
|
351
352
|
export declare function parse(source: string, filename?: string): ParseResult;
|
|
@@ -170,13 +170,13 @@ class Parser {
|
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
172
|
parseExpression(options = {}) {
|
|
173
|
-
const first = this.
|
|
173
|
+
const first = this.parseAssignmentExpression();
|
|
174
174
|
if (options.allowSequence !== true || this.consumePunctuator(",") === undefined) {
|
|
175
175
|
return first;
|
|
176
176
|
}
|
|
177
177
|
const expressions = [first.node];
|
|
178
178
|
do {
|
|
179
|
-
expressions.push(this.
|
|
179
|
+
expressions.push(this.parseAssignmentExpression().node);
|
|
180
180
|
} while (this.consumePunctuator(",") !== undefined);
|
|
181
181
|
return {
|
|
182
182
|
node: {
|
|
@@ -187,7 +187,7 @@ class Parser {
|
|
|
187
187
|
parenthesized: false
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
|
-
|
|
190
|
+
parseAssignmentExpression() {
|
|
191
191
|
const arrowFunction = this.tryParseArrowFunctionExpression();
|
|
192
192
|
if (arrowFunction !== undefined) {
|
|
193
193
|
return {
|
|
@@ -195,9 +195,6 @@ class Parser {
|
|
|
195
195
|
parenthesized: false
|
|
196
196
|
};
|
|
197
197
|
}
|
|
198
|
-
return this.parseAssignmentExpression();
|
|
199
|
-
}
|
|
200
|
-
parseAssignmentExpression() {
|
|
201
198
|
const patternAssignment = this.tryParsePatternAssignmentExpression();
|
|
202
199
|
if (patternAssignment !== undefined) {
|
|
203
200
|
return {
|
|
@@ -271,7 +268,7 @@ class Parser {
|
|
|
271
268
|
}
|
|
272
269
|
const consequent = this.parseExpression();
|
|
273
270
|
this.expectPunctuator(":");
|
|
274
|
-
const alternate = this.
|
|
271
|
+
const alternate = this.parseAssignmentExpression();
|
|
275
272
|
return {
|
|
276
273
|
node: {
|
|
277
274
|
type: "ConditionalExpression",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SandboxObject, SandboxValue } from "../interp/values.js";
|
|
2
|
+
type PropertyFlags = {
|
|
3
|
+
configurable: boolean;
|
|
4
|
+
enumerable: boolean;
|
|
5
|
+
writable: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type SerializedArguments<TValue> = {
|
|
8
|
+
kind: "arguments";
|
|
9
|
+
extensible: boolean;
|
|
10
|
+
lengthBeforeCallee: boolean;
|
|
11
|
+
iterator: PropertyFlags | null;
|
|
12
|
+
properties: Record<string, PropertyFlags & {
|
|
13
|
+
value: TValue;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
export declare function serializeArguments<TValue>(value: SandboxObject, serializeValue: (entry: SandboxValue, key: string) => TValue): SerializedArguments<TValue>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function serializeArguments(value, serializeValue) {
|
|
2
|
+
const properties = Object.create(null);
|
|
3
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
|
|
4
|
+
if (!("value" in descriptor)) {
|
|
5
|
+
if (key !== "callee")
|
|
6
|
+
throw new TypeError(`Cannot snapshot arguments accessor '${key}'.`);
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
properties[key] = {
|
|
10
|
+
value: serializeValue(descriptor.value, key),
|
|
11
|
+
configurable: descriptor.configurable === true,
|
|
12
|
+
enumerable: descriptor.enumerable === true,
|
|
13
|
+
writable: descriptor.writable === true
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const iterator = Object.getOwnPropertyDescriptor(value, Symbol.iterator);
|
|
17
|
+
if (iterator !== undefined && iterator.value !== Array.prototype.values) {
|
|
18
|
+
throw new TypeError("Cannot snapshot a replaced arguments iterator.");
|
|
19
|
+
}
|
|
20
|
+
const names = Object.getOwnPropertyNames(value);
|
|
21
|
+
return {
|
|
22
|
+
kind: "arguments",
|
|
23
|
+
extensible: Object.isExtensible(value),
|
|
24
|
+
lengthBeforeCallee: names.includes("length") && names.indexOf("length") < names.indexOf("callee"),
|
|
25
|
+
iterator: iterator === undefined
|
|
26
|
+
? null
|
|
27
|
+
: {
|
|
28
|
+
configurable: iterator.configurable === true,
|
|
29
|
+
enumerable: iterator.enumerable === true,
|
|
30
|
+
writable: iterator.writable === true
|
|
31
|
+
},
|
|
32
|
+
properties
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const DUMP_FORMAT_VERSION = 1;
|
|
2
2
|
import { assertSnapshotGraphDepth } from "../graph-depth.js";
|
|
3
|
+
import { getSandboxArgumentEntries, isSandboxArguments } from "../interp/arguments.js";
|
|
4
|
+
import { serializeArguments } from "./arguments.js";
|
|
3
5
|
const SKIP_VALUE = Symbol("SafeJS.skip-dump-value");
|
|
4
6
|
export function serializeSafeJSSnapshot(snapshot) {
|
|
5
7
|
for (const [key, value] of getEnumerableDataEntries(snapshot)) {
|
|
@@ -76,7 +78,13 @@ function serializeHeapReference(value, path, state) {
|
|
|
76
78
|
}
|
|
77
79
|
if (!state.serializedHeapIds.has(id)) {
|
|
78
80
|
state.serializedHeapIds.add(id);
|
|
79
|
-
if (
|
|
81
|
+
if (isSandboxArguments(value)) {
|
|
82
|
+
state.heap[String(id)] = serializeArguments(value, (entry, key) => {
|
|
83
|
+
const serialized = serializeDumpValue(entry, `${path}.${key}`, state);
|
|
84
|
+
return serialized === SKIP_VALUE ? { kind: "undefined" } : serialized;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else if (Array.isArray(value)) {
|
|
80
88
|
state.heap[String(id)] = {
|
|
81
89
|
kind: "array",
|
|
82
90
|
items: serializeArrayItems(value, path, state)
|
|
@@ -116,7 +124,7 @@ function indexHeapContainers(snapshot) {
|
|
|
116
124
|
const heapIds = new WeakMap();
|
|
117
125
|
let nextId = 1;
|
|
118
126
|
for (const [value, stat] of stats.entries()) {
|
|
119
|
-
if (stat.count > 1 || stat.cyclic) {
|
|
127
|
+
if (stat.count > 1 || stat.cyclic || isSandboxArguments(value)) {
|
|
120
128
|
heapIds.set(value, nextId);
|
|
121
129
|
nextId += 1;
|
|
122
130
|
}
|
|
@@ -149,7 +157,11 @@ function collectContainerStats(value, stats, ancestors) {
|
|
|
149
157
|
}
|
|
150
158
|
stat.expanded = true;
|
|
151
159
|
ancestors.add(value);
|
|
152
|
-
const entries =
|
|
160
|
+
const entries = isSandboxArguments(value)
|
|
161
|
+
? getSandboxArgumentEntries(value).map(([, entry]) => entry)
|
|
162
|
+
: Array.isArray(value)
|
|
163
|
+
? getArrayDataItems(value)
|
|
164
|
+
: getEnumerableDataValues(value);
|
|
153
165
|
for (const entry of entries) {
|
|
154
166
|
collectContainerStats(entry, stats, ancestors);
|
|
155
167
|
}
|
|
@@ -2,7 +2,7 @@ import { Budget } from "../interp/budget.js";
|
|
|
2
2
|
import { SnapshotMismatchError } from "../restore.js";
|
|
3
3
|
import { Scope } from "../interp/interpreter.js";
|
|
4
4
|
import { wrapCallerInjectedBindings } from "../interp/host-bridge.js";
|
|
5
|
-
import { createSandboxClosure, createSandboxGenerator, createSandboxMap, createSandboxPromise, createSandboxRegex, createSandboxSet, measureSandboxData } from "../interp/values.js";
|
|
5
|
+
import { createSandboxArguments, createSandboxClosure, createSandboxGenerator, createSandboxMap, createSandboxPromise, createSandboxRegex, createSandboxSet, measureSandboxData } from "../interp/values.js";
|
|
6
6
|
import { createGeneratorChannel, restoreGeneratorChannel } from "../interp/generator.js";
|
|
7
7
|
import { hashSource } from "../parse/hash.js";
|
|
8
8
|
import { parseModule } from "../parse/parser.js";
|
|
@@ -327,6 +327,30 @@ function restoreHeapValue(id, state) {
|
|
|
327
327
|
}
|
|
328
328
|
return array;
|
|
329
329
|
}
|
|
330
|
+
if (serialized.kind === "arguments") {
|
|
331
|
+
const args = createSandboxArguments([]);
|
|
332
|
+
if (!serialized.lengthBeforeCallee)
|
|
333
|
+
delete args.length;
|
|
334
|
+
state.heapValueById.set(id, args);
|
|
335
|
+
for (const [key, descriptor] of Object.entries(serialized.properties)) {
|
|
336
|
+
Object.defineProperty(args, key, {
|
|
337
|
+
...descriptor,
|
|
338
|
+
value: deserializeValue(descriptor.value, state)
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
if (serialized.iterator === null) {
|
|
342
|
+
Reflect.deleteProperty(args, Symbol.iterator);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
Object.defineProperty(args, Symbol.iterator, {
|
|
346
|
+
...serialized.iterator,
|
|
347
|
+
value: Array.prototype.values
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
if (!serialized.extensible)
|
|
351
|
+
Object.preventExtensions(args);
|
|
352
|
+
return args;
|
|
353
|
+
}
|
|
330
354
|
if (serialized.kind === "map") {
|
|
331
355
|
const map = createSandboxMap();
|
|
332
356
|
state.heapValueById.set(id, map);
|
|
@@ -399,6 +423,8 @@ async function executeRestoredClosure(node, capturedScopeId, closure, args, this
|
|
|
399
423
|
}
|
|
400
424
|
if (node.type !== "ArrowFunctionExpression") {
|
|
401
425
|
scope.declare("this", "const", thisValue);
|
|
426
|
+
state.budget.allocateArrayLength(args.length);
|
|
427
|
+
scope.declare("arguments", "let", createSandboxArguments(args));
|
|
402
428
|
}
|
|
403
429
|
for (let index = 0; index < node.params.length; index += 1) {
|
|
404
430
|
const param = node.params[index];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SerializedArguments } from "./arguments.js";
|
|
1
2
|
import { type SandboxMap, type SandboxGenerator, type SandboxRegex, type SandboxSet } from "../interp/values.js";
|
|
2
3
|
type SnapshotId = number | string;
|
|
3
4
|
type SerializedUndefinedValue = {
|
|
@@ -36,7 +37,7 @@ export type SerializedReferenceValue = {
|
|
|
36
37
|
kind: "ref";
|
|
37
38
|
id: number;
|
|
38
39
|
};
|
|
39
|
-
export type SerializedHeapValue = {
|
|
40
|
+
export type SerializedHeapValue = SerializedArguments<SerializedSnapshotValue> | {
|
|
40
41
|
kind: "array";
|
|
41
42
|
items: SerializedSnapshotValue[];
|
|
42
43
|
} | {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { hashSource } from "../parse/hash.js";
|
|
2
2
|
import { assertSnapshotGraphDepth } from "../graph-depth.js";
|
|
3
|
-
import {
|
|
3
|
+
import { serializeArguments } from "./arguments.js";
|
|
4
|
+
import { isSandboxArguments, isSandboxGenerator, isSandboxMap, isSandboxRegex, isSandboxSet } from "../interp/values.js";
|
|
4
5
|
export class UnsnapshotableValueError extends Error {
|
|
5
6
|
path;
|
|
6
7
|
constructor(path) {
|
|
@@ -180,7 +181,10 @@ function serializeHeapReference(value, path, state) {
|
|
|
180
181
|
}
|
|
181
182
|
if (!state.serializedHeapIds.has(id)) {
|
|
182
183
|
state.serializedHeapIds.add(id);
|
|
183
|
-
if (
|
|
184
|
+
if (isSandboxArguments(value)) {
|
|
185
|
+
state.heap[String(id)] = serializeArguments(value, (entry, key) => serializeValue(entry, `${path}.${key}`, state));
|
|
186
|
+
}
|
|
187
|
+
else if (isSandboxMap(value)) {
|
|
184
188
|
state.heap[String(id)] = {
|
|
185
189
|
kind: "map",
|
|
186
190
|
entries: [...value.entries].map(([key, entry], index) => [
|
|
@@ -273,7 +277,11 @@ function indexHeapContainers(input) {
|
|
|
273
277
|
const heapIds = new WeakMap();
|
|
274
278
|
let nextId = 1;
|
|
275
279
|
for (const [value, stat] of stats.entries()) {
|
|
276
|
-
if (stat.count > 1 ||
|
|
280
|
+
if (stat.count > 1 ||
|
|
281
|
+
stat.cyclic ||
|
|
282
|
+
isSandboxArguments(value) ||
|
|
283
|
+
isSandboxMap(value) ||
|
|
284
|
+
isSandboxSet(value)) {
|
|
277
285
|
heapIds.set(value, nextId);
|
|
278
286
|
nextId += 1;
|
|
279
287
|
}
|
|
@@ -313,13 +321,15 @@ function collectContainerStats(value, stats, ancestors) {
|
|
|
313
321
|
}
|
|
314
322
|
stat.expanded = true;
|
|
315
323
|
ancestors.add(value);
|
|
316
|
-
const entries =
|
|
317
|
-
?
|
|
318
|
-
:
|
|
319
|
-
? [...value.
|
|
320
|
-
:
|
|
321
|
-
? value
|
|
322
|
-
:
|
|
324
|
+
const entries = isSandboxArguments(value)
|
|
325
|
+
? Object.values(Object.getOwnPropertyDescriptors(value)).flatMap((descriptor) => "value" in descriptor ? [descriptor.value] : [])
|
|
326
|
+
: isSandboxMap(value)
|
|
327
|
+
? [...value.entries].flatMap(([key, entry]) => [key, entry])
|
|
328
|
+
: isSandboxSet(value)
|
|
329
|
+
? [...value.values]
|
|
330
|
+
: Array.isArray(value)
|
|
331
|
+
? value
|
|
332
|
+
: Object.values(value);
|
|
323
333
|
for (const entry of entries) {
|
|
324
334
|
collectContainerStats(entry, stats, ancestors);
|
|
325
335
|
}
|