@nyariv/sandboxjs 0.8.23 → 0.8.24
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/.eslintignore +6 -0
- package/.eslintrc.js +22 -0
- package/.prettierrc +4 -0
- package/.vscode/settings.json +4 -0
- package/build/Sandbox.d.ts +11 -79
- package/build/Sandbox.js +21 -216
- package/build/SandboxExec.d.ts +25 -0
- package/build/SandboxExec.js +169 -0
- package/build/eval.d.ts +18 -0
- package/build/eval.js +43 -0
- package/build/executor.d.ts +29 -90
- package/build/executor.js +249 -328
- package/build/parser.d.ts +8 -239
- package/build/parser.js +342 -440
- package/build/unraw.js +13 -16
- package/build/utils.d.ts +242 -0
- package/build/utils.js +276 -0
- package/dist/Sandbox.d.ts +11 -79
- package/dist/Sandbox.js +106 -1
- package/dist/Sandbox.js.map +1 -1
- package/dist/Sandbox.min.js +2 -0
- package/dist/Sandbox.min.js.map +1 -0
- package/dist/SandboxExec.d.ts +25 -0
- package/dist/SandboxExec.js +173 -0
- package/dist/SandboxExec.js.map +1 -0
- package/dist/SandboxExec.min.js +2 -0
- package/dist/SandboxExec.min.js.map +1 -0
- package/dist/eval.d.ts +18 -0
- package/dist/executor.d.ts +29 -90
- package/dist/executor.js +1270 -0
- package/dist/executor.js.map +1 -0
- package/dist/node/Sandbox.d.ts +11 -79
- package/dist/node/Sandbox.js +36 -3150
- package/dist/node/SandboxExec.d.ts +25 -0
- package/dist/node/SandboxExec.js +176 -0
- package/dist/node/eval.d.ts +18 -0
- package/dist/node/executor.d.ts +29 -90
- package/dist/node/executor.js +1289 -0
- package/dist/node/parser.d.ts +8 -239
- package/dist/node/parser.js +1528 -0
- package/dist/node/utils.d.ts +242 -0
- package/dist/node/utils.js +290 -0
- package/dist/parser.d.ts +8 -239
- package/dist/parser.js +1514 -0
- package/dist/parser.js.map +1 -0
- package/dist/utils.d.ts +242 -0
- package/dist/utils.js +279 -0
- package/dist/utils.js.map +1 -0
- package/package.json +11 -3
- package/.github/workflows/npm-publish.yml +0 -34
- package/rollup.config.mjs +0 -33
package/build/executor.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CodeString, isLisp, LocalScope, Prop, SandboxError, Scope, } from './utils.js';
|
|
2
2
|
export class ExecReturn {
|
|
3
3
|
constructor(auditReport, result, returned, breakLoop = false, continueLoop = false) {
|
|
4
4
|
this.auditReport = auditReport;
|
|
@@ -8,154 +8,7 @@ export class ExecReturn {
|
|
|
8
8
|
this.continueLoop = continueLoop;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
export class Prop {
|
|
12
|
-
constructor(context, prop, isConst = false, isGlobal = false, isVariable = false) {
|
|
13
|
-
this.context = context;
|
|
14
|
-
this.prop = prop;
|
|
15
|
-
this.isConst = isConst;
|
|
16
|
-
this.isGlobal = isGlobal;
|
|
17
|
-
this.isVariable = isVariable;
|
|
18
|
-
}
|
|
19
|
-
get(context) {
|
|
20
|
-
if (this.context === undefined)
|
|
21
|
-
throw new ReferenceError(`${this.prop} is not defined`);
|
|
22
|
-
context.getSubscriptions.forEach((cb) => cb(this.context, this.prop));
|
|
23
|
-
return this.context[this.prop];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
11
|
const optional = {};
|
|
27
|
-
const reservedWords = new Set([
|
|
28
|
-
'instanceof',
|
|
29
|
-
'typeof',
|
|
30
|
-
'return',
|
|
31
|
-
'try',
|
|
32
|
-
'catch',
|
|
33
|
-
'if',
|
|
34
|
-
'finally',
|
|
35
|
-
'else',
|
|
36
|
-
'in',
|
|
37
|
-
'of',
|
|
38
|
-
'var',
|
|
39
|
-
'let',
|
|
40
|
-
'const',
|
|
41
|
-
'for',
|
|
42
|
-
'delete',
|
|
43
|
-
'false',
|
|
44
|
-
'true',
|
|
45
|
-
'while',
|
|
46
|
-
'do',
|
|
47
|
-
'break',
|
|
48
|
-
'continue',
|
|
49
|
-
'new',
|
|
50
|
-
'function',
|
|
51
|
-
'async',
|
|
52
|
-
'await',
|
|
53
|
-
'switch',
|
|
54
|
-
'case'
|
|
55
|
-
]);
|
|
56
|
-
var VarType;
|
|
57
|
-
(function (VarType) {
|
|
58
|
-
VarType["let"] = "let";
|
|
59
|
-
VarType["const"] = "const";
|
|
60
|
-
VarType["var"] = "var";
|
|
61
|
-
})(VarType || (VarType = {}));
|
|
62
|
-
function keysOnly(obj) {
|
|
63
|
-
const ret = Object.assign({}, obj);
|
|
64
|
-
for (let key in ret) {
|
|
65
|
-
ret[key] = true;
|
|
66
|
-
}
|
|
67
|
-
return ret;
|
|
68
|
-
}
|
|
69
|
-
export class Scope {
|
|
70
|
-
constructor(parent, vars = {}, functionThis) {
|
|
71
|
-
this.const = {};
|
|
72
|
-
this.let = {};
|
|
73
|
-
this.var = {};
|
|
74
|
-
const isFuncScope = functionThis !== undefined || parent === null;
|
|
75
|
-
this.parent = parent;
|
|
76
|
-
this.allVars = vars;
|
|
77
|
-
this.let = isFuncScope ? this.let : keysOnly(vars);
|
|
78
|
-
this.var = isFuncScope ? keysOnly(vars) : this.var;
|
|
79
|
-
this.globals = parent === null ? keysOnly(vars) : {};
|
|
80
|
-
this.functionThis = functionThis;
|
|
81
|
-
}
|
|
82
|
-
get(key, functionScope = false) {
|
|
83
|
-
if (key === 'this' && this.functionThis !== undefined) {
|
|
84
|
-
return new Prop({ this: this.functionThis }, key, true, false, true);
|
|
85
|
-
}
|
|
86
|
-
if (reservedWords.has(key))
|
|
87
|
-
throw new SyntaxError("Unexepected token '" + key + "'");
|
|
88
|
-
if (this.parent === null || !functionScope || this.functionThis !== undefined) {
|
|
89
|
-
if (this.globals.hasOwnProperty(key)) {
|
|
90
|
-
return new Prop(this.functionThis, key, false, true, true);
|
|
91
|
-
}
|
|
92
|
-
if (key in this.allVars && (!(key in {}) || this.allVars.hasOwnProperty(key))) {
|
|
93
|
-
return new Prop(this.allVars, key, this.const.hasOwnProperty(key), this.globals.hasOwnProperty(key), true);
|
|
94
|
-
}
|
|
95
|
-
if (this.parent === null) {
|
|
96
|
-
return new Prop(undefined, key);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return this.parent.get(key, functionScope);
|
|
100
|
-
}
|
|
101
|
-
set(key, val) {
|
|
102
|
-
if (key === 'this')
|
|
103
|
-
throw new SyntaxError('"this" cannot be assigned');
|
|
104
|
-
if (reservedWords.has(key))
|
|
105
|
-
throw new SyntaxError("Unexepected token '" + key + "'");
|
|
106
|
-
let prop = this.get(key);
|
|
107
|
-
if (prop.context === undefined) {
|
|
108
|
-
throw new ReferenceError(`Variable '${key}' was not declared.`);
|
|
109
|
-
}
|
|
110
|
-
if (prop.isConst) {
|
|
111
|
-
throw new TypeError(`Cannot assign to const variable '${key}'`);
|
|
112
|
-
}
|
|
113
|
-
if (prop.isGlobal) {
|
|
114
|
-
throw new SandboxError(`Cannot override global variable '${key}'`);
|
|
115
|
-
}
|
|
116
|
-
prop.context[prop.prop] = val;
|
|
117
|
-
return prop;
|
|
118
|
-
}
|
|
119
|
-
declare(key, type = null, value = undefined, isGlobal = false) {
|
|
120
|
-
if (key === 'this')
|
|
121
|
-
throw new SyntaxError('"this" cannot be declared');
|
|
122
|
-
if (reservedWords.has(key))
|
|
123
|
-
throw new SyntaxError("Unexepected token '" + key + "'");
|
|
124
|
-
if (type === 'var' && this.functionThis === undefined && this.parent !== null) {
|
|
125
|
-
return this.parent.declare(key, type, value, isGlobal);
|
|
126
|
-
}
|
|
127
|
-
else if ((this[type].hasOwnProperty(key) && type !== 'const' && !this.globals.hasOwnProperty(key)) || !(key in this.allVars)) {
|
|
128
|
-
if (isGlobal) {
|
|
129
|
-
this.globals[key] = true;
|
|
130
|
-
}
|
|
131
|
-
this[type][key] = true;
|
|
132
|
-
this.allVars[key] = value;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
throw new SandboxError(`Identifier '${key}' has already been declared`);
|
|
136
|
-
}
|
|
137
|
-
return new Prop(this.allVars, key, this.const.hasOwnProperty(key), isGlobal);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
export class FunctionScope {
|
|
141
|
-
}
|
|
142
|
-
export class LocalScope {
|
|
143
|
-
}
|
|
144
|
-
export class SandboxError extends Error {
|
|
145
|
-
}
|
|
146
|
-
let currentTicks;
|
|
147
|
-
export function sandboxFunction(context, ticks) {
|
|
148
|
-
return SandboxFunction;
|
|
149
|
-
function SandboxFunction(...params) {
|
|
150
|
-
let code = params.pop() || "";
|
|
151
|
-
let parsed = parse(code);
|
|
152
|
-
return createFunction(params, parsed.tree, ticks || currentTicks, {
|
|
153
|
-
...context,
|
|
154
|
-
constants: parsed.constants,
|
|
155
|
-
tree: parsed.tree
|
|
156
|
-
}, undefined, 'anonymous');
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
12
|
function generateArgs(argNames, args) {
|
|
160
13
|
const vars = {};
|
|
161
14
|
argNames.forEach((arg, i) => {
|
|
@@ -168,10 +21,10 @@ function generateArgs(argNames, args) {
|
|
|
168
21
|
});
|
|
169
22
|
return vars;
|
|
170
23
|
}
|
|
171
|
-
const sandboxedFunctions = new WeakSet();
|
|
24
|
+
export const sandboxedFunctions = new WeakSet();
|
|
172
25
|
export function createFunction(argNames, parsed, ticks, context, scope, name) {
|
|
173
26
|
if (context.ctx.options.forbidFunctionCreation) {
|
|
174
|
-
throw new SandboxError(
|
|
27
|
+
throw new SandboxError('Function creation is forbidden');
|
|
175
28
|
}
|
|
176
29
|
let func;
|
|
177
30
|
if (name === undefined) {
|
|
@@ -194,10 +47,10 @@ export function createFunction(argNames, parsed, ticks, context, scope, name) {
|
|
|
194
47
|
}
|
|
195
48
|
export function createFunctionAsync(argNames, parsed, ticks, context, scope, name) {
|
|
196
49
|
if (context.ctx.options.forbidFunctionCreation) {
|
|
197
|
-
throw new SandboxError(
|
|
50
|
+
throw new SandboxError('Function creation is forbidden');
|
|
198
51
|
}
|
|
199
52
|
if (!context.ctx.prototypeWhitelist?.has(Promise.prototype)) {
|
|
200
|
-
throw new SandboxError(
|
|
53
|
+
throw new SandboxError('Async/await not permitted');
|
|
201
54
|
}
|
|
202
55
|
let func;
|
|
203
56
|
if (name === undefined) {
|
|
@@ -218,26 +71,6 @@ export function createFunctionAsync(argNames, parsed, ticks, context, scope, nam
|
|
|
218
71
|
sandboxedFunctions.add(func);
|
|
219
72
|
return func;
|
|
220
73
|
}
|
|
221
|
-
export function sandboxedEval(func) {
|
|
222
|
-
return sandboxEval;
|
|
223
|
-
function sandboxEval(code) {
|
|
224
|
-
return func(code)();
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
export function sandboxedSetTimeout(func) {
|
|
228
|
-
return function sandboxSetTimeout(handler, ...args) {
|
|
229
|
-
if (typeof handler !== 'string')
|
|
230
|
-
return setTimeout(handler, ...args);
|
|
231
|
-
return setTimeout(func(handler), ...args);
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
export function sandboxedSetInterval(func) {
|
|
235
|
-
return function sandboxSetInterval(handler, ...args) {
|
|
236
|
-
if (typeof handler !== 'string')
|
|
237
|
-
return setInterval(handler, ...args);
|
|
238
|
-
return setInterval(func(handler), ...args);
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
74
|
export function assignCheck(obj, context, op = 'assign') {
|
|
242
75
|
if (obj.context === undefined) {
|
|
243
76
|
throw new ReferenceError(`Cannot ${op} value to undefined.`);
|
|
@@ -251,26 +84,43 @@ export function assignCheck(obj, context, op = 'assign') {
|
|
|
251
84
|
if (obj.isGlobal) {
|
|
252
85
|
throw new SandboxError(`Cannot ${op} property '${obj.prop}' of a global object`);
|
|
253
86
|
}
|
|
87
|
+
if (obj.context === null) {
|
|
88
|
+
throw new TypeError('Cannot set properties of null');
|
|
89
|
+
}
|
|
254
90
|
if (typeof obj.context[obj.prop] === 'function' && !obj.context.hasOwnProperty(obj.prop)) {
|
|
255
91
|
throw new SandboxError(`Override prototype property '${obj.prop}' not allowed`);
|
|
256
92
|
}
|
|
257
|
-
if (op ===
|
|
93
|
+
if (op === 'delete') {
|
|
258
94
|
if (obj.context.hasOwnProperty(obj.prop)) {
|
|
259
|
-
context.changeSubscriptions
|
|
260
|
-
|
|
95
|
+
context.changeSubscriptions
|
|
96
|
+
.get(obj.context)
|
|
97
|
+
?.forEach((cb) => cb({ type: 'delete', prop: obj.prop }));
|
|
98
|
+
context.changeSubscriptionsGlobal
|
|
99
|
+
.get(obj.context)
|
|
100
|
+
?.forEach((cb) => cb({ type: 'delete', prop: obj.prop }));
|
|
261
101
|
}
|
|
262
102
|
}
|
|
263
103
|
else if (obj.context.hasOwnProperty(obj.prop)) {
|
|
264
|
-
context.setSubscriptions
|
|
265
|
-
|
|
104
|
+
context.setSubscriptions
|
|
105
|
+
.get(obj.context)
|
|
106
|
+
?.get(obj.prop)
|
|
107
|
+
?.forEach((cb) => cb({
|
|
108
|
+
type: 'replace',
|
|
266
109
|
}));
|
|
267
|
-
context.setSubscriptionsGlobal
|
|
268
|
-
|
|
110
|
+
context.setSubscriptionsGlobal
|
|
111
|
+
.get(obj.context)
|
|
112
|
+
?.get(obj.prop)
|
|
113
|
+
?.forEach((cb) => cb({
|
|
114
|
+
type: 'replace',
|
|
269
115
|
}));
|
|
270
116
|
}
|
|
271
117
|
else {
|
|
272
|
-
context.changeSubscriptions
|
|
273
|
-
|
|
118
|
+
context.changeSubscriptions
|
|
119
|
+
.get(obj.context)
|
|
120
|
+
?.forEach((cb) => cb({ type: 'create', prop: obj.prop }));
|
|
121
|
+
context.changeSubscriptionsGlobal
|
|
122
|
+
.get(obj.context)
|
|
123
|
+
?.forEach((cb) => cb({ type: 'create', prop: obj.prop }));
|
|
274
124
|
}
|
|
275
125
|
}
|
|
276
126
|
const arrayChange = new Set([
|
|
@@ -281,7 +131,7 @@ const arrayChange = new Set([
|
|
|
281
131
|
[].splice,
|
|
282
132
|
[].reverse,
|
|
283
133
|
[].sort,
|
|
284
|
-
[].copyWithin
|
|
134
|
+
[].copyWithin,
|
|
285
135
|
]);
|
|
286
136
|
export class KeyVal {
|
|
287
137
|
constructor(key, val) {
|
|
@@ -316,12 +166,14 @@ addOps(1 /* LispType.Prop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
316
166
|
}
|
|
317
167
|
const type = typeof a;
|
|
318
168
|
if (type === 'undefined' && obj === undefined) {
|
|
319
|
-
|
|
169
|
+
const prop = scope.get(b);
|
|
320
170
|
if (prop.context === context.ctx.sandboxGlobal) {
|
|
321
171
|
if (context.ctx.options.audit) {
|
|
322
|
-
context.ctx.auditReport
|
|
172
|
+
context.ctx.auditReport?.globalsAccess.add(b);
|
|
323
173
|
}
|
|
324
|
-
const rep = context.ctx.globalsWhitelist.has(context.ctx.sandboxGlobal[b])
|
|
174
|
+
const rep = context.ctx.globalsWhitelist.has(context.ctx.sandboxGlobal[b])
|
|
175
|
+
? context.evals.get(context.ctx.sandboxGlobal[b])
|
|
176
|
+
: undefined;
|
|
325
177
|
if (rep) {
|
|
326
178
|
done(undefined, rep);
|
|
327
179
|
return;
|
|
@@ -353,39 +205,38 @@ addOps(1 /* LispType.Prop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
353
205
|
return;
|
|
354
206
|
}
|
|
355
207
|
const isFunction = type === 'function';
|
|
356
|
-
|
|
208
|
+
const prototypeAccess = isFunction || !(a.hasOwnProperty(b) || typeof b === 'number');
|
|
357
209
|
if (context.ctx.options.audit && prototypeAccess) {
|
|
358
210
|
if (typeof b === 'string') {
|
|
359
211
|
let prot = Object.getPrototypeOf(a);
|
|
360
212
|
do {
|
|
361
213
|
if (prot.hasOwnProperty(b)) {
|
|
362
|
-
if (
|
|
214
|
+
if (context.ctx.auditReport &&
|
|
215
|
+
!context.ctx.auditReport.prototypeAccess[prot.constructor.name]) {
|
|
363
216
|
context.ctx.auditReport.prototypeAccess[prot.constructor.name] = new Set();
|
|
364
217
|
}
|
|
365
|
-
context.ctx.auditReport
|
|
218
|
+
context.ctx.auditReport?.prototypeAccess[prot.constructor.name].add(b);
|
|
366
219
|
}
|
|
367
|
-
} while (prot = Object.getPrototypeOf(prot));
|
|
220
|
+
} while ((prot = Object.getPrototypeOf(prot)));
|
|
368
221
|
}
|
|
369
222
|
}
|
|
370
223
|
if (prototypeAccess) {
|
|
371
224
|
if (isFunction) {
|
|
372
|
-
if (!['name', 'length', 'constructor'].includes(b) && a.hasOwnProperty(b)) {
|
|
225
|
+
if (!['name', 'length', 'constructor'].includes(b) && (a.hasOwnProperty(b) || b === '__proto__')) {
|
|
373
226
|
const whitelist = context.ctx.prototypeWhitelist.get(a.prototype);
|
|
374
227
|
const replace = context.ctx.options.prototypeReplacements.get(a);
|
|
375
228
|
if (replace) {
|
|
376
229
|
done(undefined, new Prop(replace(a, true), b));
|
|
377
230
|
return;
|
|
378
231
|
}
|
|
379
|
-
if (whitelist && (!whitelist.size || whitelist.has(b))) {
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
232
|
+
if (!(whitelist && (!whitelist.size || whitelist.has(b)))) {
|
|
382
233
|
throw new SandboxError(`Static method or property access not permitted: ${a.name}.${b}`);
|
|
383
234
|
}
|
|
384
235
|
}
|
|
385
236
|
}
|
|
386
237
|
else if (b !== 'constructor') {
|
|
387
238
|
let prot = a;
|
|
388
|
-
while (prot = Object.getPrototypeOf(prot)) {
|
|
239
|
+
while ((prot = Object.getPrototypeOf(prot))) {
|
|
389
240
|
if (prot.hasOwnProperty(b)) {
|
|
390
241
|
const whitelist = context.ctx.prototypeWhitelist.get(prot);
|
|
391
242
|
const replace = context.ctx.options.prototypeReplacements.get(prot.constuctor);
|
|
@@ -399,7 +250,6 @@ addOps(1 /* LispType.Prop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
399
250
|
throw new SandboxError(`Method or property access not permitted: ${prot.constructor.name}.${b}`);
|
|
400
251
|
}
|
|
401
252
|
}
|
|
402
|
-
;
|
|
403
253
|
}
|
|
404
254
|
}
|
|
405
255
|
if (context.evals.has(a[b])) {
|
|
@@ -410,23 +260,28 @@ addOps(1 /* LispType.Prop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
410
260
|
done(undefined, context.ctx.globalScope.get('this'));
|
|
411
261
|
return;
|
|
412
262
|
}
|
|
413
|
-
|
|
263
|
+
const g = obj.isGlobal ||
|
|
264
|
+
(isFunction && !sandboxedFunctions.has(a)) ||
|
|
265
|
+
context.ctx.globalsWhitelist.has(a);
|
|
414
266
|
done(undefined, new Prop(a, b, false, g));
|
|
415
267
|
});
|
|
416
|
-
addOps(5 /* LispType.Call */, (exec, done, ticks, a, b, obj, context
|
|
268
|
+
addOps(5 /* LispType.Call */, (exec, done, ticks, a, b, obj, context) => {
|
|
417
269
|
if (context.ctx.options.forbidFunctionCalls)
|
|
418
|
-
throw new SandboxError(
|
|
270
|
+
throw new SandboxError('Function invocations are not allowed');
|
|
419
271
|
if (typeof a !== 'function') {
|
|
420
272
|
throw new TypeError(`${typeof obj.prop === 'symbol' ? 'Symbol' : obj.prop} is not a function`);
|
|
421
273
|
}
|
|
422
|
-
const vals = b
|
|
274
|
+
const vals = b
|
|
275
|
+
.map((item) => {
|
|
423
276
|
if (item instanceof SpreadArray) {
|
|
424
277
|
return [...item.item];
|
|
425
278
|
}
|
|
426
279
|
else {
|
|
427
280
|
return [item];
|
|
428
281
|
}
|
|
429
|
-
})
|
|
282
|
+
})
|
|
283
|
+
.flat()
|
|
284
|
+
.map((item) => valueOrProp(item, context));
|
|
430
285
|
if (typeof obj === 'function') {
|
|
431
286
|
done(undefined, obj(...vals));
|
|
432
287
|
return;
|
|
@@ -437,66 +292,71 @@ addOps(5 /* LispType.Call */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
437
292
|
if (!x || !(typeof x === 'object') || cache.has(x))
|
|
438
293
|
return;
|
|
439
294
|
cache.add(x);
|
|
440
|
-
for (
|
|
295
|
+
for (const y of Object.keys(x)) {
|
|
441
296
|
context.getSubscriptions.forEach((cb) => cb(x, y));
|
|
442
297
|
recurse(x[y]);
|
|
443
298
|
}
|
|
444
299
|
};
|
|
445
300
|
recurse(vals[0]);
|
|
446
301
|
}
|
|
447
|
-
if (obj.context instanceof Array &&
|
|
302
|
+
if (obj.context instanceof Array &&
|
|
303
|
+
arrayChange.has(obj.context[obj.prop]) &&
|
|
304
|
+
(context.changeSubscriptions.get(obj.context) ||
|
|
305
|
+
context.changeSubscriptionsGlobal.get(obj.context))) {
|
|
448
306
|
let change;
|
|
449
307
|
let changed = false;
|
|
450
|
-
if (obj.prop ===
|
|
308
|
+
if (obj.prop === 'push') {
|
|
451
309
|
change = {
|
|
452
|
-
type:
|
|
453
|
-
added: vals
|
|
310
|
+
type: 'push',
|
|
311
|
+
added: vals,
|
|
454
312
|
};
|
|
455
313
|
changed = !!vals.length;
|
|
456
314
|
}
|
|
457
|
-
else if (obj.prop ===
|
|
315
|
+
else if (obj.prop === 'pop') {
|
|
458
316
|
change = {
|
|
459
|
-
type:
|
|
460
|
-
removed: obj.context.slice(-1)
|
|
317
|
+
type: 'pop',
|
|
318
|
+
removed: obj.context.slice(-1),
|
|
461
319
|
};
|
|
462
320
|
changed = !!change.removed.length;
|
|
463
321
|
}
|
|
464
|
-
else if (obj.prop ===
|
|
322
|
+
else if (obj.prop === 'shift') {
|
|
465
323
|
change = {
|
|
466
|
-
type:
|
|
467
|
-
removed: obj.context.slice(0, 1)
|
|
324
|
+
type: 'shift',
|
|
325
|
+
removed: obj.context.slice(0, 1),
|
|
468
326
|
};
|
|
469
327
|
changed = !!change.removed.length;
|
|
470
328
|
}
|
|
471
|
-
else if (obj.prop ===
|
|
329
|
+
else if (obj.prop === 'unshift') {
|
|
472
330
|
change = {
|
|
473
|
-
type:
|
|
474
|
-
added: vals
|
|
331
|
+
type: 'unshift',
|
|
332
|
+
added: vals,
|
|
475
333
|
};
|
|
476
334
|
changed = !!vals.length;
|
|
477
335
|
}
|
|
478
|
-
else if (obj.prop ===
|
|
336
|
+
else if (obj.prop === 'splice') {
|
|
479
337
|
change = {
|
|
480
|
-
type:
|
|
338
|
+
type: 'splice',
|
|
481
339
|
startIndex: vals[0],
|
|
482
340
|
deleteCount: vals[1] === undefined ? obj.context.length : vals[1],
|
|
483
341
|
added: vals.slice(2),
|
|
484
|
-
removed: obj.context.slice(vals[0], vals[1] === undefined ? undefined : vals[0] + vals[1])
|
|
342
|
+
removed: obj.context.slice(vals[0], vals[1] === undefined ? undefined : vals[0] + vals[1]),
|
|
485
343
|
};
|
|
486
344
|
changed = !!change.added.length || !!change.removed.length;
|
|
487
345
|
}
|
|
488
|
-
else if (obj.prop ===
|
|
346
|
+
else if (obj.prop === 'reverse' || obj.prop === 'sort') {
|
|
489
347
|
change = { type: obj.prop };
|
|
490
348
|
changed = !!obj.context.length;
|
|
491
349
|
}
|
|
492
|
-
else if (obj.prop ===
|
|
493
|
-
|
|
350
|
+
else if (obj.prop === 'copyWithin') {
|
|
351
|
+
const len = vals[2] === undefined
|
|
352
|
+
? obj.context.length - vals[1]
|
|
353
|
+
: Math.min(obj.context.length, vals[2] - vals[1]);
|
|
494
354
|
change = {
|
|
495
|
-
type:
|
|
355
|
+
type: 'copyWithin',
|
|
496
356
|
startIndex: vals[0],
|
|
497
357
|
endIndex: vals[0] + len,
|
|
498
358
|
added: obj.context.slice(vals[1], vals[1] + len),
|
|
499
|
-
removed: obj.context.slice(vals[0], vals[0] + len)
|
|
359
|
+
removed: obj.context.slice(vals[0], vals[0] + len),
|
|
500
360
|
};
|
|
501
361
|
changed = !!change.added.length || !!change.removed.length;
|
|
502
362
|
}
|
|
@@ -508,9 +368,9 @@ addOps(5 /* LispType.Call */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
508
368
|
obj.get(context);
|
|
509
369
|
done(undefined, obj.context[obj.prop](...vals));
|
|
510
370
|
});
|
|
511
|
-
addOps(22 /* LispType.CreateObject */, (exec, done, ticks, a, b
|
|
371
|
+
addOps(22 /* LispType.CreateObject */, (exec, done, ticks, a, b) => {
|
|
512
372
|
let res = {};
|
|
513
|
-
for (
|
|
373
|
+
for (const item of b) {
|
|
514
374
|
if (item.key instanceof SpreadObject) {
|
|
515
375
|
res = { ...res, ...item.key.item };
|
|
516
376
|
}
|
|
@@ -521,26 +381,35 @@ addOps(22 /* LispType.CreateObject */, (exec, done, ticks, a, b, obj, context, s
|
|
|
521
381
|
done(undefined, res);
|
|
522
382
|
});
|
|
523
383
|
addOps(6 /* LispType.KeyVal */, (exec, done, ticks, a, b) => done(undefined, new KeyVal(a, b)));
|
|
524
|
-
addOps(12 /* LispType.CreateArray */, (exec, done, ticks, a, b, obj, context
|
|
525
|
-
const items = b
|
|
384
|
+
addOps(12 /* LispType.CreateArray */, (exec, done, ticks, a, b, obj, context) => {
|
|
385
|
+
const items = b
|
|
386
|
+
.map((item) => {
|
|
526
387
|
if (item instanceof SpreadArray) {
|
|
527
388
|
return [...item.item];
|
|
528
389
|
}
|
|
529
390
|
else {
|
|
530
391
|
return [item];
|
|
531
392
|
}
|
|
532
|
-
})
|
|
393
|
+
})
|
|
394
|
+
.flat()
|
|
395
|
+
.map((item) => valueOrProp(item, context));
|
|
533
396
|
done(undefined, items);
|
|
534
397
|
});
|
|
535
398
|
addOps(23 /* LispType.Group */, (exec, done, ticks, a, b) => done(undefined, b));
|
|
536
399
|
addOps(35 /* LispType.GlobalSymbol */, (exec, done, ticks, a, b) => {
|
|
537
400
|
switch (b) {
|
|
538
|
-
case 'true':
|
|
539
|
-
|
|
540
|
-
case '
|
|
541
|
-
|
|
542
|
-
case '
|
|
543
|
-
|
|
401
|
+
case 'true':
|
|
402
|
+
return done(undefined, true);
|
|
403
|
+
case 'false':
|
|
404
|
+
return done(undefined, false);
|
|
405
|
+
case 'null':
|
|
406
|
+
return done(undefined, null);
|
|
407
|
+
case 'undefined':
|
|
408
|
+
return done(undefined, undefined);
|
|
409
|
+
case 'NaN':
|
|
410
|
+
return done(undefined, NaN);
|
|
411
|
+
case 'Infinity':
|
|
412
|
+
return done(undefined, Infinity);
|
|
544
413
|
}
|
|
545
414
|
done(new Error('Unknown symbol: ' + b));
|
|
546
415
|
});
|
|
@@ -550,19 +419,19 @@ addOps(2 /* LispType.StringIndex */, (exec, done, ticks, a, b, obj, context) =>
|
|
|
550
419
|
addOps(85 /* LispType.RegexIndex */, (exec, done, ticks, a, b, obj, context) => {
|
|
551
420
|
const reg = context.constants.regexes[parseInt(b)];
|
|
552
421
|
if (!context.ctx.globalsWhitelist.has(RegExp)) {
|
|
553
|
-
throw new SandboxError(
|
|
422
|
+
throw new SandboxError('Regex not permitted');
|
|
554
423
|
}
|
|
555
424
|
else {
|
|
556
425
|
done(undefined, new RegExp(reg.regex, reg.flags));
|
|
557
426
|
}
|
|
558
427
|
});
|
|
559
428
|
addOps(84 /* LispType.LiteralIndex */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
560
|
-
|
|
429
|
+
const item = context.constants.literals[parseInt(b)];
|
|
561
430
|
const [, name, js] = item;
|
|
562
|
-
|
|
431
|
+
const found = [];
|
|
563
432
|
let f;
|
|
564
|
-
|
|
565
|
-
while (f = literalRegex.exec(name)) {
|
|
433
|
+
const resnums = [];
|
|
434
|
+
while ((f = literalRegex.exec(name))) {
|
|
566
435
|
if (!f[2]) {
|
|
567
436
|
found.push(js[parseInt(f[3], 10)]);
|
|
568
437
|
resnums.push(f[3]);
|
|
@@ -574,22 +443,22 @@ addOps(84 /* LispType.LiteralIndex */, (exec, done, ticks, a, b, obj, context, s
|
|
|
574
443
|
done(err);
|
|
575
444
|
return;
|
|
576
445
|
}
|
|
577
|
-
for (
|
|
446
|
+
for (const i of Object.keys(processed)) {
|
|
578
447
|
const num = resnums[i];
|
|
579
448
|
reses[num] = processed[i];
|
|
580
449
|
}
|
|
581
450
|
done(undefined, name.replace(/(\\\\)*(\\)?\${(\d+)}/g, (match, $$, $, num) => {
|
|
582
451
|
if ($)
|
|
583
452
|
return match;
|
|
584
|
-
|
|
453
|
+
const res = reses[num];
|
|
585
454
|
return ($$ ? $$ : '') + `${valueOrProp(res, context)}`;
|
|
586
455
|
}));
|
|
587
456
|
});
|
|
588
457
|
});
|
|
589
|
-
addOps(18 /* LispType.SpreadArray */, (exec, done, ticks, a, b
|
|
458
|
+
addOps(18 /* LispType.SpreadArray */, (exec, done, ticks, a, b) => {
|
|
590
459
|
done(undefined, new SpreadArray(b));
|
|
591
460
|
});
|
|
592
|
-
addOps(17 /* LispType.SpreadObject */, (exec, done, ticks, a, b
|
|
461
|
+
addOps(17 /* LispType.SpreadObject */, (exec, done, ticks, a, b) => {
|
|
593
462
|
done(undefined, new SpreadObject(b));
|
|
594
463
|
});
|
|
595
464
|
addOps(24 /* LispType.Not */, (exec, done, ticks, a, b) => done(undefined, !b));
|
|
@@ -612,55 +481,55 @@ addOps(28 /* LispType.DecrementAfter */, (exec, done, ticks, a, b, obj, context)
|
|
|
612
481
|
});
|
|
613
482
|
addOps(9 /* LispType.Assign */, (exec, done, ticks, a, b, obj, context) => {
|
|
614
483
|
assignCheck(obj, context);
|
|
615
|
-
done(undefined, obj.context[obj.prop] = b);
|
|
484
|
+
done(undefined, (obj.context[obj.prop] = b));
|
|
616
485
|
});
|
|
617
486
|
addOps(66 /* LispType.AddEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
618
487
|
assignCheck(obj, context);
|
|
619
|
-
done(undefined, obj.context[obj.prop] += b);
|
|
488
|
+
done(undefined, (obj.context[obj.prop] += b));
|
|
620
489
|
});
|
|
621
490
|
addOps(65 /* LispType.SubractEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
622
491
|
assignCheck(obj, context);
|
|
623
|
-
done(undefined, obj.context[obj.prop] -= b);
|
|
492
|
+
done(undefined, (obj.context[obj.prop] -= b));
|
|
624
493
|
});
|
|
625
494
|
addOps(67 /* LispType.DivideEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
626
495
|
assignCheck(obj, context);
|
|
627
|
-
done(undefined, obj.context[obj.prop] /= b);
|
|
496
|
+
done(undefined, (obj.context[obj.prop] /= b));
|
|
628
497
|
});
|
|
629
498
|
addOps(69 /* LispType.MultiplyEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
630
499
|
assignCheck(obj, context);
|
|
631
|
-
done(undefined, obj.context[obj.prop] *= b);
|
|
500
|
+
done(undefined, (obj.context[obj.prop] *= b));
|
|
632
501
|
});
|
|
633
502
|
addOps(68 /* LispType.PowerEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
634
503
|
assignCheck(obj, context);
|
|
635
|
-
done(undefined, obj.context[obj.prop] **= b);
|
|
504
|
+
done(undefined, (obj.context[obj.prop] **= b));
|
|
636
505
|
});
|
|
637
506
|
addOps(70 /* LispType.ModulusEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
638
507
|
assignCheck(obj, context);
|
|
639
|
-
done(undefined, obj.context[obj.prop] %= b);
|
|
508
|
+
done(undefined, (obj.context[obj.prop] %= b));
|
|
640
509
|
});
|
|
641
510
|
addOps(71 /* LispType.BitNegateEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
642
511
|
assignCheck(obj, context);
|
|
643
|
-
done(undefined, obj.context[obj.prop] ^= b);
|
|
512
|
+
done(undefined, (obj.context[obj.prop] ^= b));
|
|
644
513
|
});
|
|
645
514
|
addOps(72 /* LispType.BitAndEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
646
515
|
assignCheck(obj, context);
|
|
647
|
-
done(undefined, obj.context[obj.prop] &= b);
|
|
516
|
+
done(undefined, (obj.context[obj.prop] &= b));
|
|
648
517
|
});
|
|
649
518
|
addOps(73 /* LispType.BitOrEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
650
519
|
assignCheck(obj, context);
|
|
651
|
-
done(undefined, obj.context[obj.prop] |= b);
|
|
520
|
+
done(undefined, (obj.context[obj.prop] |= b));
|
|
652
521
|
});
|
|
653
522
|
addOps(76 /* LispType.ShiftLeftEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
654
523
|
assignCheck(obj, context);
|
|
655
|
-
done(undefined, obj.context[obj.prop] <<= b);
|
|
524
|
+
done(undefined, (obj.context[obj.prop] <<= b));
|
|
656
525
|
});
|
|
657
526
|
addOps(75 /* LispType.ShiftRightEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
658
527
|
assignCheck(obj, context);
|
|
659
|
-
done(undefined, obj.context[obj.prop] >>= b);
|
|
528
|
+
done(undefined, (obj.context[obj.prop] >>= b));
|
|
660
529
|
});
|
|
661
530
|
addOps(74 /* LispType.UnsignedShiftRightEquals */, (exec, done, ticks, a, b, obj, context) => {
|
|
662
531
|
assignCheck(obj, context);
|
|
663
|
-
done(undefined, obj.context[obj.prop] >>= b);
|
|
532
|
+
done(undefined, (obj.context[obj.prop] >>= b));
|
|
664
533
|
});
|
|
665
534
|
addOps(57 /* LispType.LargerThan */, (exec, done, ticks, a, b) => done(undefined, a > b));
|
|
666
535
|
addOps(56 /* LispType.SmallerThan */, (exec, done, ticks, a, b) => done(undefined, a < b));
|
|
@@ -702,22 +571,27 @@ addOps(61 /* LispType.Delete */, (exec, done, ticks, a, b, obj, context, scope,
|
|
|
702
571
|
done(undefined, false);
|
|
703
572
|
return;
|
|
704
573
|
}
|
|
705
|
-
done(undefined, delete bobj.context[bobj.prop]);
|
|
574
|
+
done(undefined, delete bobj.context?.[bobj.prop]);
|
|
706
575
|
});
|
|
707
|
-
addOps(8 /* LispType.Return */, (exec, done, ticks, a, b
|
|
708
|
-
addOps(34 /* LispType.Var */, (exec, done, ticks, a, b, obj, context, scope
|
|
709
|
-
done(undefined, scope.declare(a, VarType.var
|
|
576
|
+
addOps(8 /* LispType.Return */, (exec, done, ticks, a, b) => done(undefined, b));
|
|
577
|
+
addOps(34 /* LispType.Var */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
578
|
+
done(undefined, scope.declare(a, "var" /* VarType.var */, b));
|
|
710
579
|
});
|
|
711
580
|
addOps(3 /* LispType.Let */, (exec, done, ticks, a, b, obj, context, scope, bobj) => {
|
|
712
|
-
done(undefined, scope.declare(a, VarType.let
|
|
581
|
+
done(undefined, scope.declare(a, "let" /* VarType.let */, b, bobj && bobj.isGlobal));
|
|
713
582
|
});
|
|
714
|
-
addOps(4 /* LispType.Const */, (exec, done, ticks, a, b, obj, context, scope
|
|
715
|
-
done(undefined, scope.declare(a, VarType.const
|
|
583
|
+
addOps(4 /* LispType.Const */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
584
|
+
done(undefined, scope.declare(a, "const" /* VarType.const */, b));
|
|
716
585
|
});
|
|
717
586
|
addOps(11 /* LispType.ArrowFunction */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
718
587
|
a = [...a];
|
|
719
|
-
if (typeof obj[2] ===
|
|
720
|
-
|
|
588
|
+
if (typeof obj[2] === 'string' || obj[2] instanceof CodeString) {
|
|
589
|
+
if (context.allowJit && context.evalContext) {
|
|
590
|
+
obj[2] = b = context.evalContext.lispifyFunction(new CodeString(obj[2]), context.constants);
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
throw new SandboxError('Unevaluated code detected, JIT not allowed');
|
|
594
|
+
}
|
|
721
595
|
}
|
|
722
596
|
if (a.shift()) {
|
|
723
597
|
done(undefined, createFunctionAsync(a, b, ticks, context, scope));
|
|
@@ -727,11 +601,16 @@ addOps(11 /* LispType.ArrowFunction */, (exec, done, ticks, a, b, obj, context,
|
|
|
727
601
|
}
|
|
728
602
|
});
|
|
729
603
|
addOps(37 /* LispType.Function */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
730
|
-
if (typeof obj[2] ===
|
|
731
|
-
|
|
604
|
+
if (typeof obj[2] === 'string' || obj[2] instanceof CodeString) {
|
|
605
|
+
if (context.allowJit && context.evalContext) {
|
|
606
|
+
obj[2] = b = context.evalContext.lispifyFunction(new CodeString(obj[2]), context.constants);
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
throw new SandboxError('Unevaluated code detected, JIT not allowed');
|
|
610
|
+
}
|
|
732
611
|
}
|
|
733
|
-
|
|
734
|
-
|
|
612
|
+
const isAsync = a.shift();
|
|
613
|
+
const name = a.shift();
|
|
735
614
|
let func;
|
|
736
615
|
if (isAsync === 88 /* LispType.True */) {
|
|
737
616
|
func = createFunctionAsync(a, b, ticks, context, scope, name);
|
|
@@ -740,16 +619,21 @@ addOps(37 /* LispType.Function */, (exec, done, ticks, a, b, obj, context, scope
|
|
|
740
619
|
func = createFunction(a, b, ticks, context, scope, name);
|
|
741
620
|
}
|
|
742
621
|
if (name) {
|
|
743
|
-
scope.declare(name, VarType.var
|
|
622
|
+
scope.declare(name, "var" /* VarType.var */, func);
|
|
744
623
|
}
|
|
745
624
|
done(undefined, func);
|
|
746
625
|
});
|
|
747
626
|
addOps(10 /* LispType.InlineFunction */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
748
|
-
if (typeof obj[2] ===
|
|
749
|
-
|
|
627
|
+
if (typeof obj[2] === 'string' || obj[2] instanceof CodeString) {
|
|
628
|
+
if (context.allowJit && context.evalContext) {
|
|
629
|
+
obj[2] = b = context.evalContext.lispifyFunction(new CodeString(obj[2]), context.constants);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
throw new SandboxError('Unevaluated code detected, JIT not allowed');
|
|
633
|
+
}
|
|
750
634
|
}
|
|
751
|
-
|
|
752
|
-
|
|
635
|
+
const isAsync = a.shift();
|
|
636
|
+
const name = a.shift();
|
|
753
637
|
if (name) {
|
|
754
638
|
scope = new Scope(scope, {});
|
|
755
639
|
}
|
|
@@ -761,7 +645,7 @@ addOps(10 /* LispType.InlineFunction */, (exec, done, ticks, a, b, obj, context,
|
|
|
761
645
|
func = createFunction(a, b, ticks, context, scope, name);
|
|
762
646
|
}
|
|
763
647
|
if (name) {
|
|
764
|
-
scope.declare(name, VarType.let
|
|
648
|
+
scope.declare(name, "let" /* VarType.let */, func);
|
|
765
649
|
}
|
|
766
650
|
done(undefined, func);
|
|
767
651
|
});
|
|
@@ -769,23 +653,30 @@ addOps(38 /* LispType.Loop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
769
653
|
const [checkFirst, startInternal, getIterator, startStep, step, condition, beforeStep] = a;
|
|
770
654
|
let loop = true;
|
|
771
655
|
const loopScope = new Scope(scope, {});
|
|
772
|
-
|
|
773
|
-
|
|
656
|
+
const internalVars = {
|
|
657
|
+
$$obj: undefined,
|
|
774
658
|
};
|
|
775
659
|
const interalScope = new Scope(loopScope, internalVars);
|
|
776
660
|
if (exec === execAsync) {
|
|
777
661
|
(async () => {
|
|
778
662
|
let ad;
|
|
779
663
|
ad = asyncDone((d) => exec(ticks, startStep, loopScope, context, d));
|
|
780
|
-
internalVars['$$obj'] =
|
|
664
|
+
internalVars['$$obj'] =
|
|
665
|
+
(ad = asyncDone((d) => exec(ticks, getIterator, loopScope, context, d))).isInstant === true
|
|
666
|
+
? ad.instant
|
|
667
|
+
: (await ad.p).result;
|
|
781
668
|
ad = asyncDone((d) => exec(ticks, startInternal, interalScope, context, d));
|
|
782
669
|
if (checkFirst)
|
|
783
|
-
loop =
|
|
670
|
+
loop =
|
|
671
|
+
(ad = asyncDone((d) => exec(ticks, condition, interalScope, context, d))).isInstant ===
|
|
672
|
+
true
|
|
673
|
+
? ad.instant
|
|
674
|
+
: (await ad.p).result;
|
|
784
675
|
while (loop) {
|
|
785
|
-
|
|
676
|
+
const innerLoopVars = {};
|
|
786
677
|
ad = asyncDone((d) => exec(ticks, beforeStep, new Scope(interalScope, innerLoopVars), context, d));
|
|
787
678
|
ad.isInstant === true ? ad.instant : (await ad.p).result;
|
|
788
|
-
|
|
679
|
+
const res = await executeTreeAsync(ticks, context, b, [new Scope(loopScope, innerLoopVars)], 'loop');
|
|
789
680
|
if (res instanceof ExecReturn && res.returned) {
|
|
790
681
|
done(undefined, res);
|
|
791
682
|
return;
|
|
@@ -794,7 +685,11 @@ addOps(38 /* LispType.Loop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
794
685
|
break;
|
|
795
686
|
}
|
|
796
687
|
ad = asyncDone((d) => exec(ticks, step, interalScope, context, d));
|
|
797
|
-
loop =
|
|
688
|
+
loop =
|
|
689
|
+
(ad = asyncDone((d) => exec(ticks, condition, interalScope, context, d))).isInstant ===
|
|
690
|
+
true
|
|
691
|
+
? ad.instant
|
|
692
|
+
: (await ad.p).result;
|
|
798
693
|
}
|
|
799
694
|
done();
|
|
800
695
|
})().catch(done);
|
|
@@ -804,11 +699,11 @@ addOps(38 /* LispType.Loop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
804
699
|
internalVars['$$obj'] = syncDone((d) => exec(ticks, getIterator, loopScope, context, d)).result;
|
|
805
700
|
syncDone((d) => exec(ticks, startInternal, interalScope, context, d));
|
|
806
701
|
if (checkFirst)
|
|
807
|
-
loop =
|
|
702
|
+
loop = syncDone((d) => exec(ticks, condition, interalScope, context, d)).result;
|
|
808
703
|
while (loop) {
|
|
809
|
-
|
|
704
|
+
const innerLoopVars = {};
|
|
810
705
|
syncDone((d) => exec(ticks, beforeStep, new Scope(interalScope, innerLoopVars), context, d));
|
|
811
|
-
|
|
706
|
+
const res = executeTree(ticks, context, b, [new Scope(loopScope, innerLoopVars)], 'loop');
|
|
812
707
|
if (res instanceof ExecReturn && res.returned) {
|
|
813
708
|
done(undefined, res);
|
|
814
709
|
return;
|
|
@@ -817,18 +712,18 @@ addOps(38 /* LispType.Loop */, (exec, done, ticks, a, b, obj, context, scope) =>
|
|
|
817
712
|
break;
|
|
818
713
|
}
|
|
819
714
|
syncDone((d) => exec(ticks, step, interalScope, context, d));
|
|
820
|
-
loop =
|
|
715
|
+
loop = syncDone((d) => exec(ticks, condition, interalScope, context, d)).result;
|
|
821
716
|
}
|
|
822
717
|
done();
|
|
823
718
|
}
|
|
824
719
|
});
|
|
825
720
|
addOps(86 /* LispType.LoopAction */, (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
|
|
826
|
-
if ((inLoopOrSwitch ===
|
|
827
|
-
throw new SandboxError(
|
|
721
|
+
if ((inLoopOrSwitch === 'switch' && a === 'continue') || !inLoopOrSwitch) {
|
|
722
|
+
throw new SandboxError('Illegal ' + a + ' statement');
|
|
828
723
|
}
|
|
829
|
-
done(undefined, new ExecReturn(context.ctx.auditReport, undefined, false, a ===
|
|
724
|
+
done(undefined, new ExecReturn(context.ctx.auditReport, undefined, false, a === 'break', a === 'continue'));
|
|
830
725
|
});
|
|
831
|
-
addOps(13 /* LispType.If */, (exec, done, ticks, a, b, obj, context, scope
|
|
726
|
+
addOps(13 /* LispType.If */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
832
727
|
exec(ticks, valueOrProp(a, context) ? b.t : b.f, scope, context, done);
|
|
833
728
|
});
|
|
834
729
|
addOps(15 /* LispType.InlineIf */, (exec, done, ticks, a, b, obj, context, scope) => {
|
|
@@ -846,18 +741,23 @@ addOps(40 /* LispType.Switch */, (exec, done, ticks, a, b, obj, context, scope)
|
|
|
846
741
|
if (exec === execSync) {
|
|
847
742
|
let res;
|
|
848
743
|
let isTrue = false;
|
|
849
|
-
for (
|
|
850
|
-
if (isTrue ||
|
|
744
|
+
for (const caseItem of b) {
|
|
745
|
+
if (isTrue ||
|
|
746
|
+
(isTrue =
|
|
747
|
+
!caseItem[1] ||
|
|
748
|
+
toTest ===
|
|
749
|
+
valueOrProp(syncDone((d) => exec(ticks, caseItem[1], scope, context, d)).result, context))) {
|
|
851
750
|
if (!caseItem[2])
|
|
852
751
|
continue;
|
|
853
|
-
res = executeTree(ticks, context, caseItem[2], [scope],
|
|
752
|
+
res = executeTree(ticks, context, caseItem[2], [scope], 'switch');
|
|
854
753
|
if (res.breakLoop)
|
|
855
754
|
break;
|
|
856
755
|
if (res.returned) {
|
|
857
756
|
done(undefined, res);
|
|
858
757
|
return;
|
|
859
758
|
}
|
|
860
|
-
if (!caseItem[1]) {
|
|
759
|
+
if (!caseItem[1]) {
|
|
760
|
+
// default case
|
|
861
761
|
break;
|
|
862
762
|
}
|
|
863
763
|
}
|
|
@@ -868,19 +768,27 @@ addOps(40 /* LispType.Switch */, (exec, done, ticks, a, b, obj, context, scope)
|
|
|
868
768
|
(async () => {
|
|
869
769
|
let res;
|
|
870
770
|
let isTrue = false;
|
|
871
|
-
for (
|
|
771
|
+
for (const caseItem of b) {
|
|
872
772
|
let ad;
|
|
873
|
-
if (isTrue ||
|
|
773
|
+
if (isTrue ||
|
|
774
|
+
(isTrue =
|
|
775
|
+
!caseItem[1] ||
|
|
776
|
+
toTest ===
|
|
777
|
+
valueOrProp((ad = asyncDone((d) => exec(ticks, caseItem[1], scope, context, d))).isInstant ===
|
|
778
|
+
true
|
|
779
|
+
? ad.instant
|
|
780
|
+
: (await ad.p).result, context))) {
|
|
874
781
|
if (!caseItem[2])
|
|
875
782
|
continue;
|
|
876
|
-
res = await executeTreeAsync(ticks, context, caseItem[2], [scope],
|
|
783
|
+
res = await executeTreeAsync(ticks, context, caseItem[2], [scope], 'switch');
|
|
877
784
|
if (res.breakLoop)
|
|
878
785
|
break;
|
|
879
786
|
if (res.returned) {
|
|
880
787
|
done(undefined, res);
|
|
881
788
|
return;
|
|
882
789
|
}
|
|
883
|
-
if (!caseItem[1]) {
|
|
790
|
+
if (!caseItem[1]) {
|
|
791
|
+
// default case
|
|
884
792
|
break;
|
|
885
793
|
}
|
|
886
794
|
}
|
|
@@ -897,7 +805,7 @@ addOps(39 /* LispType.Try */, (exec, done, ticks, a, b, obj, context, scope, bob
|
|
|
897
805
|
if (e)
|
|
898
806
|
done(e);
|
|
899
807
|
else if (err) {
|
|
900
|
-
|
|
808
|
+
const sc = {};
|
|
901
809
|
if (exception)
|
|
902
810
|
sc[exception] = err;
|
|
903
811
|
executeTreeWithDone(exec, done, ticks, context, catchBody, [new Scope(scope)], inLoopOrSwitch);
|
|
@@ -908,16 +816,20 @@ addOps(39 /* LispType.Try */, (exec, done, ticks, a, b, obj, context, scope, bob
|
|
|
908
816
|
}, ticks, context, finallyBody, [new Scope(scope, {})]);
|
|
909
817
|
}, ticks, context, a, [new Scope(scope)], inLoopOrSwitch);
|
|
910
818
|
});
|
|
911
|
-
addOps(87 /* LispType.Void */, (exec, done
|
|
819
|
+
addOps(87 /* LispType.Void */, (exec, done) => {
|
|
820
|
+
done();
|
|
821
|
+
});
|
|
912
822
|
addOps(45 /* LispType.New */, (exec, done, ticks, a, b, obj, context) => {
|
|
913
823
|
if (!context.ctx.globalsWhitelist.has(a) && !sandboxedFunctions.has(a)) {
|
|
914
824
|
throw new SandboxError(`Object construction not allowed: ${a.constructor.name}`);
|
|
915
825
|
}
|
|
916
826
|
done(undefined, new a(...b));
|
|
917
827
|
});
|
|
918
|
-
addOps(46 /* LispType.Throw */, (exec, done, ticks, a, b) => {
|
|
828
|
+
addOps(46 /* LispType.Throw */, (exec, done, ticks, a, b) => {
|
|
829
|
+
done(b);
|
|
830
|
+
});
|
|
919
831
|
addOps(43 /* LispType.Expression */, (exec, done, ticks, a) => done(undefined, a.pop()));
|
|
920
|
-
addOps(0 /* LispType.None */, (exec, done
|
|
832
|
+
addOps(0 /* LispType.None */, (exec, done) => done());
|
|
921
833
|
function valueOrProp(a, context) {
|
|
922
834
|
if (a instanceof Prop)
|
|
923
835
|
return a.get(context);
|
|
@@ -934,7 +846,7 @@ export function execMany(ticks, exec, tree, done, scope, context, inLoopOrSwitch
|
|
|
934
846
|
}
|
|
935
847
|
}
|
|
936
848
|
function _execManySync(ticks, tree, done, scope, context, inLoopOrSwitch) {
|
|
937
|
-
|
|
849
|
+
const ret = [];
|
|
938
850
|
for (let i = 0; i < tree.length; i++) {
|
|
939
851
|
let res;
|
|
940
852
|
try {
|
|
@@ -957,12 +869,16 @@ function _execManySync(ticks, tree, done, scope, context, inLoopOrSwitch) {
|
|
|
957
869
|
done(undefined, ret);
|
|
958
870
|
}
|
|
959
871
|
async function _execManyAsync(ticks, tree, done, scope, context, inLoopOrSwitch) {
|
|
960
|
-
|
|
872
|
+
const ret = [];
|
|
961
873
|
for (let i = 0; i < tree.length; i++) {
|
|
962
874
|
let res;
|
|
963
875
|
try {
|
|
964
876
|
let ad;
|
|
965
|
-
res =
|
|
877
|
+
res =
|
|
878
|
+
(ad = asyncDone((d) => execAsync(ticks, tree[i], scope, context, d, inLoopOrSwitch)))
|
|
879
|
+
.isInstant === true
|
|
880
|
+
? ad.instant
|
|
881
|
+
: (await ad.p).result;
|
|
966
882
|
}
|
|
967
883
|
catch (e) {
|
|
968
884
|
done(e);
|
|
@@ -992,13 +908,12 @@ export function asyncDone(callback) {
|
|
|
992
908
|
instant = result;
|
|
993
909
|
resolve({ result });
|
|
994
910
|
}
|
|
995
|
-
;
|
|
996
911
|
});
|
|
997
912
|
});
|
|
998
913
|
return {
|
|
999
914
|
isInstant,
|
|
1000
915
|
instant,
|
|
1001
|
-
p
|
|
916
|
+
p,
|
|
1002
917
|
};
|
|
1003
918
|
}
|
|
1004
919
|
export function syncDone(callback) {
|
|
@@ -1020,14 +935,16 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
|
|
|
1020
935
|
resolve();
|
|
1021
936
|
};
|
|
1022
937
|
});
|
|
1023
|
-
if (_execNoneRecurse(ticks, tree, scope, context, done, true, inLoopOrSwitch)) {
|
|
1024
|
-
}
|
|
1025
|
-
else if (isLisp(tree)) {
|
|
938
|
+
if (!_execNoneRecurse(ticks, tree, scope, context, done, true, inLoopOrSwitch) && isLisp(tree)) {
|
|
1026
939
|
let op = tree[0];
|
|
1027
940
|
let obj;
|
|
1028
941
|
try {
|
|
1029
942
|
let ad;
|
|
1030
|
-
obj =
|
|
943
|
+
obj =
|
|
944
|
+
(ad = asyncDone((d) => execAsync(ticks, tree[1], scope, context, d, inLoopOrSwitch)))
|
|
945
|
+
.isInstant === true
|
|
946
|
+
? ad.instant
|
|
947
|
+
: (await ad.p).result;
|
|
1031
948
|
}
|
|
1032
949
|
catch (e) {
|
|
1033
950
|
done(e);
|
|
@@ -1060,7 +977,11 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
|
|
|
1060
977
|
let bobj;
|
|
1061
978
|
try {
|
|
1062
979
|
let ad;
|
|
1063
|
-
bobj =
|
|
980
|
+
bobj =
|
|
981
|
+
(ad = asyncDone((d) => execAsync(ticks, tree[2], scope, context, d, inLoopOrSwitch)))
|
|
982
|
+
.isInstant === true
|
|
983
|
+
? ad.instant
|
|
984
|
+
: (await ad.p).result;
|
|
1064
985
|
}
|
|
1065
986
|
catch (e) {
|
|
1066
987
|
done(e);
|
|
@@ -1079,7 +1000,7 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
|
|
|
1079
1000
|
}
|
|
1080
1001
|
if (ops.has(op)) {
|
|
1081
1002
|
try {
|
|
1082
|
-
ops.get(op)(execAsync, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch);
|
|
1003
|
+
ops.get(op)?.(execAsync, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch);
|
|
1083
1004
|
}
|
|
1084
1005
|
catch (err) {
|
|
1085
1006
|
done(err);
|
|
@@ -1092,9 +1013,7 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
|
|
|
1092
1013
|
await p;
|
|
1093
1014
|
}
|
|
1094
1015
|
export function execSync(ticks, tree, scope, context, done, inLoopOrSwitch) {
|
|
1095
|
-
if (_execNoneRecurse(ticks, tree, scope, context, done, false, inLoopOrSwitch)) {
|
|
1096
|
-
}
|
|
1097
|
-
else if (isLisp(tree)) {
|
|
1016
|
+
if (!_execNoneRecurse(ticks, tree, scope, context, done, false, inLoopOrSwitch) && isLisp(tree)) {
|
|
1098
1017
|
let op = tree[0];
|
|
1099
1018
|
let obj;
|
|
1100
1019
|
try {
|
|
@@ -1149,7 +1068,7 @@ export function execSync(ticks, tree, scope, context, done, inLoopOrSwitch) {
|
|
|
1149
1068
|
}
|
|
1150
1069
|
if (ops.has(op)) {
|
|
1151
1070
|
try {
|
|
1152
|
-
ops.get(op)(execSync, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch);
|
|
1071
|
+
ops.get(op)?.(execSync, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch);
|
|
1153
1072
|
}
|
|
1154
1073
|
catch (err) {
|
|
1155
1074
|
done(err);
|
|
@@ -1169,20 +1088,20 @@ const unexecTypes = new Set([
|
|
|
1169
1088
|
40 /* LispType.Switch */,
|
|
1170
1089
|
14 /* LispType.IfCase */,
|
|
1171
1090
|
16 /* LispType.InlineIfCase */,
|
|
1172
|
-
60 /* LispType.Typeof
|
|
1091
|
+
60 /* LispType.Typeof */,
|
|
1173
1092
|
]);
|
|
1093
|
+
export const currentTicks = { current: { ticks: BigInt(0) } };
|
|
1174
1094
|
function _execNoneRecurse(ticks, tree, scope, context, done, isAsync, inLoopOrSwitch) {
|
|
1175
1095
|
const exec = isAsync ? execAsync : execSync;
|
|
1176
|
-
if (context.ctx.options.executionQuota <= ticks.ticks) {
|
|
1177
|
-
if (typeof context.ctx.options.onExecutionQuotaReached === 'function' &&
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
return;
|
|
1096
|
+
if (context.ctx.options.executionQuota && context.ctx.options.executionQuota <= ticks.ticks) {
|
|
1097
|
+
if (!(typeof context.ctx.options.onExecutionQuotaReached === 'function' &&
|
|
1098
|
+
context.ctx.options.onExecutionQuotaReached(ticks, scope, context, tree))) {
|
|
1099
|
+
done(new SandboxError('Execution quota exceeded'));
|
|
1100
|
+
return true;
|
|
1182
1101
|
}
|
|
1183
1102
|
}
|
|
1184
1103
|
ticks.ticks++;
|
|
1185
|
-
currentTicks = ticks;
|
|
1104
|
+
currentTicks.current = ticks;
|
|
1186
1105
|
if (tree instanceof Prop) {
|
|
1187
1106
|
try {
|
|
1188
1107
|
done(undefined, tree.get(context));
|
|
@@ -1231,7 +1150,7 @@ function _execNoneRecurse(ticks, tree, scope, context, done, isAsync, inLoopOrSw
|
|
|
1231
1150
|
}
|
|
1232
1151
|
else if (unexecTypes.has(tree[0])) {
|
|
1233
1152
|
try {
|
|
1234
|
-
ops.get(tree[0])(exec, done, ticks, tree[1], tree[2], tree, context, scope, undefined, inLoopOrSwitch);
|
|
1153
|
+
ops.get(tree[0])?.(exec, done, ticks, tree[1], tree[2], tree, context, scope, undefined, inLoopOrSwitch);
|
|
1235
1154
|
}
|
|
1236
1155
|
catch (err) {
|
|
1237
1156
|
done(err);
|
|
@@ -1247,7 +1166,9 @@ export function executeTree(ticks, context, executionTree, scopes = [], inLoopOr
|
|
|
1247
1166
|
}
|
|
1248
1167
|
export async function executeTreeAsync(ticks, context, executionTree, scopes = [], inLoopOrSwitch) {
|
|
1249
1168
|
let ad;
|
|
1250
|
-
return (ad = asyncDone((done) => executeTreeWithDone(execAsync, done, ticks, context, executionTree, scopes, inLoopOrSwitch))).isInstant === true
|
|
1169
|
+
return (ad = asyncDone((done) => executeTreeWithDone(execAsync, done, ticks, context, executionTree, scopes, inLoopOrSwitch))).isInstant === true
|
|
1170
|
+
? ad.instant
|
|
1171
|
+
: (await ad.p).result;
|
|
1251
1172
|
}
|
|
1252
1173
|
function executeTreeWithDone(exec, done, ticks, context, executionTree, scopes = [], inLoopOrSwitch) {
|
|
1253
1174
|
if (!executionTree) {
|
|
@@ -1259,8 +1180,8 @@ function executeTreeWithDone(exec, done, ticks, context, executionTree, scopes =
|
|
|
1259
1180
|
}
|
|
1260
1181
|
let scope = context.ctx.globalScope;
|
|
1261
1182
|
let s;
|
|
1262
|
-
while (s = scopes.shift()) {
|
|
1263
|
-
if (typeof s !==
|
|
1183
|
+
while ((s = scopes.shift())) {
|
|
1184
|
+
if (typeof s !== 'object')
|
|
1264
1185
|
continue;
|
|
1265
1186
|
if (s instanceof Scope) {
|
|
1266
1187
|
scope = s;
|