@nyariv/sandboxjs 0.8.22 → 0.8.23

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/build/executor.js CHANGED
@@ -1,4 +1,4 @@
1
- import { SpreadArray, KeyVal, SpreadObject, If, Lisp, toLispArray, parse, lispifyFunction, CodeString, lispArrayKey } from "./parser.js";
1
+ import { parse, lispifyFunction, CodeString, isLisp } from "./parser.js";
2
2
  export class ExecReturn {
3
3
  constructor(auditReport, result, returned, breakLoop = false, continueLoop = false) {
4
4
  this.auditReport = auditReport;
@@ -193,11 +193,10 @@ export function createFunction(argNames, parsed, ticks, context, scope, name) {
193
193
  return func;
194
194
  }
195
195
  export function createFunctionAsync(argNames, parsed, ticks, context, scope, name) {
196
- var _a;
197
196
  if (context.ctx.options.forbidFunctionCreation) {
198
197
  throw new SandboxError("Function creation is forbidden");
199
198
  }
200
- if (!((_a = context.ctx.prototypeWhitelist) === null || _a === void 0 ? void 0 : _a.has(Promise.prototype))) {
199
+ if (!context.ctx.prototypeWhitelist?.has(Promise.prototype)) {
201
200
  throw new SandboxError("Async/await not permitted");
202
201
  }
203
202
  let func;
@@ -240,7 +239,6 @@ export function sandboxedSetInterval(func) {
240
239
  };
241
240
  }
242
241
  export function assignCheck(obj, context, op = 'assign') {
243
- var _a, _b, _c, _d, _e, _f, _g, _h;
244
242
  if (obj.context === undefined) {
245
243
  throw new ReferenceError(`Cannot ${op} value to undefined.`);
246
244
  }
@@ -258,21 +256,21 @@ export function assignCheck(obj, context, op = 'assign') {
258
256
  }
259
257
  if (op === "delete") {
260
258
  if (obj.context.hasOwnProperty(obj.prop)) {
261
- (_a = context.changeSubscriptions.get(obj.context)) === null || _a === void 0 ? void 0 : _a.forEach((cb) => cb({ type: "delete", prop: obj.prop }));
262
- (_b = context.changeSubscriptionsGlobal.get(obj.context)) === null || _b === void 0 ? void 0 : _b.forEach((cb) => cb({ type: "delete", prop: obj.prop }));
259
+ context.changeSubscriptions.get(obj.context)?.forEach((cb) => cb({ type: "delete", prop: obj.prop }));
260
+ context.changeSubscriptionsGlobal.get(obj.context)?.forEach((cb) => cb({ type: "delete", prop: obj.prop }));
263
261
  }
264
262
  }
265
263
  else if (obj.context.hasOwnProperty(obj.prop)) {
266
- (_d = (_c = context.setSubscriptions.get(obj.context)) === null || _c === void 0 ? void 0 : _c.get(obj.prop)) === null || _d === void 0 ? void 0 : _d.forEach((cb) => cb({
264
+ context.setSubscriptions.get(obj.context)?.get(obj.prop)?.forEach((cb) => cb({
267
265
  type: "replace"
268
266
  }));
269
- (_f = (_e = context.setSubscriptionsGlobal.get(obj.context)) === null || _e === void 0 ? void 0 : _e.get(obj.prop)) === null || _f === void 0 ? void 0 : _f.forEach((cb) => cb({
267
+ context.setSubscriptionsGlobal.get(obj.context)?.get(obj.prop)?.forEach((cb) => cb({
270
268
  type: "replace"
271
269
  }));
272
270
  }
273
271
  else {
274
- (_g = context.changeSubscriptions.get(obj.context)) === null || _g === void 0 ? void 0 : _g.forEach((cb) => cb({ type: "create", prop: obj.prop }));
275
- (_h = context.changeSubscriptionsGlobal.get(obj.context)) === null || _h === void 0 ? void 0 : _h.forEach((cb) => cb({ type: "create", prop: obj.prop }));
272
+ context.changeSubscriptions.get(obj.context)?.forEach((cb) => cb({ type: "create", prop: obj.prop }));
273
+ context.changeSubscriptionsGlobal.get(obj.context)?.forEach((cb) => cb({ type: "create", prop: obj.prop }));
276
274
  }
277
275
  }
278
276
  const arrayChange = new Set([
@@ -285,544 +283,509 @@ const arrayChange = new Set([
285
283
  [].sort,
286
284
  [].copyWithin
287
285
  ]);
286
+ export class KeyVal {
287
+ constructor(key, val) {
288
+ this.key = key;
289
+ this.val = val;
290
+ }
291
+ }
292
+ export class SpreadObject {
293
+ constructor(item) {
294
+ this.item = item;
295
+ }
296
+ }
297
+ export class SpreadArray {
298
+ constructor(item) {
299
+ this.item = item;
300
+ }
301
+ }
302
+ export class If {
303
+ constructor(t, f) {
304
+ this.t = t;
305
+ this.f = f;
306
+ }
307
+ }
288
308
  const literalRegex = /(\$\$)*(\$)?\${(\d+)}/g;
289
- let ops2 = {
290
- 'prop': (exec, done, ticks, a, b, obj, context, scope) => {
291
- if (a === null) {
292
- throw new TypeError(`Cannot get property ${b} of null`);
293
- }
294
- const type = typeof a;
295
- if (type === 'undefined' && obj === undefined) {
296
- let prop = scope.get(b);
297
- if (prop.context === context.ctx.sandboxGlobal) {
298
- if (context.ctx.options.audit) {
299
- context.ctx.auditReport.globalsAccess.add(b);
300
- }
301
- const rep = context.ctx.globalsWhitelist.has(context.ctx.sandboxGlobal[b]) ? context.evals.get(context.ctx.sandboxGlobal[b]) : undefined;
302
- if (rep) {
303
- done(undefined, rep);
304
- return;
305
- }
309
+ export const ops = new Map();
310
+ export function addOps(type, cb) {
311
+ ops.set(type, cb);
312
+ }
313
+ addOps(1 /* LispType.Prop */, (exec, done, ticks, a, b, obj, context, scope) => {
314
+ if (a === null) {
315
+ throw new TypeError(`Cannot get property ${b} of null`);
316
+ }
317
+ const type = typeof a;
318
+ if (type === 'undefined' && obj === undefined) {
319
+ let prop = scope.get(b);
320
+ if (prop.context === context.ctx.sandboxGlobal) {
321
+ if (context.ctx.options.audit) {
322
+ context.ctx.auditReport.globalsAccess.add(b);
306
323
  }
307
- if (prop.context && prop.context[b] === globalThis) {
308
- done(undefined, context.ctx.globalScope.get('this'));
324
+ const rep = context.ctx.globalsWhitelist.has(context.ctx.sandboxGlobal[b]) ? context.evals.get(context.ctx.sandboxGlobal[b]) : undefined;
325
+ if (rep) {
326
+ done(undefined, rep);
309
327
  return;
310
328
  }
311
- done(undefined, prop);
329
+ }
330
+ if (prop.context && prop.context[b] === globalThis) {
331
+ done(undefined, context.ctx.globalScope.get('this'));
312
332
  return;
313
333
  }
314
- else if (a === undefined) {
315
- throw new SandboxError("Cannot get property '" + b + "' of undefined");
334
+ done(undefined, prop);
335
+ return;
336
+ }
337
+ else if (a === undefined) {
338
+ throw new SandboxError("Cannot get property '" + b + "' of undefined");
339
+ }
340
+ if (type !== 'object') {
341
+ if (type === 'number') {
342
+ a = new Number(a);
316
343
  }
317
- if (type !== 'object') {
318
- if (type === 'number') {
319
- a = new Number(a);
320
- }
321
- else if (type === 'string') {
322
- a = new String(a);
323
- }
324
- else if (type === 'boolean') {
325
- a = new Boolean(a);
326
- }
344
+ else if (type === 'string') {
345
+ a = new String(a);
327
346
  }
328
- else if (typeof a.hasOwnProperty === 'undefined') {
329
- done(undefined, new Prop(undefined, b));
330
- return;
347
+ else if (type === 'boolean') {
348
+ a = new Boolean(a);
331
349
  }
332
- const isFunction = type === 'function';
333
- let prototypeAccess = isFunction || !(a.hasOwnProperty(b) || typeof b === 'number');
334
- if (context.ctx.options.audit && prototypeAccess) {
335
- if (typeof b === 'string') {
336
- let prot = Object.getPrototypeOf(a);
337
- do {
338
- if (prot.hasOwnProperty(b)) {
339
- if (!context.ctx.auditReport.prototypeAccess[prot.constructor.name]) {
340
- context.ctx.auditReport.prototypeAccess[prot.constructor.name] = new Set();
341
- }
342
- context.ctx.auditReport.prototypeAccess[prot.constructor.name].add(b);
350
+ }
351
+ else if (typeof a.hasOwnProperty === 'undefined') {
352
+ done(undefined, new Prop(undefined, b));
353
+ return;
354
+ }
355
+ const isFunction = type === 'function';
356
+ let prototypeAccess = isFunction || !(a.hasOwnProperty(b) || typeof b === 'number');
357
+ if (context.ctx.options.audit && prototypeAccess) {
358
+ if (typeof b === 'string') {
359
+ let prot = Object.getPrototypeOf(a);
360
+ do {
361
+ if (prot.hasOwnProperty(b)) {
362
+ if (!context.ctx.auditReport.prototypeAccess[prot.constructor.name]) {
363
+ context.ctx.auditReport.prototypeAccess[prot.constructor.name] = new Set();
343
364
  }
344
- } while (prot = Object.getPrototypeOf(prot));
345
- }
365
+ context.ctx.auditReport.prototypeAccess[prot.constructor.name].add(b);
366
+ }
367
+ } while (prot = Object.getPrototypeOf(prot));
346
368
  }
347
- if (prototypeAccess) {
348
- if (isFunction) {
349
- if (!['name', 'length', 'constructor'].includes(b) && a.hasOwnProperty(b)) {
350
- const whitelist = context.ctx.prototypeWhitelist.get(a.prototype);
351
- const replace = context.ctx.options.prototypeReplacements.get(a);
352
- if (replace) {
353
- done(undefined, new Prop(replace(a, true), b));
354
- return;
355
- }
356
- if (whitelist && (!whitelist.size || whitelist.has(b))) {
357
- }
358
- else {
359
- throw new SandboxError(`Static method or property access not permitted: ${a.name}.${b}`);
360
- }
369
+ }
370
+ if (prototypeAccess) {
371
+ if (isFunction) {
372
+ if (!['name', 'length', 'constructor'].includes(b) && a.hasOwnProperty(b)) {
373
+ const whitelist = context.ctx.prototypeWhitelist.get(a.prototype);
374
+ const replace = context.ctx.options.prototypeReplacements.get(a);
375
+ if (replace) {
376
+ done(undefined, new Prop(replace(a, true), b));
377
+ return;
361
378
  }
362
- }
363
- else if (b !== 'constructor') {
364
- let prot = a;
365
- while (prot = Object.getPrototypeOf(prot)) {
366
- if (prot.hasOwnProperty(b)) {
367
- const whitelist = context.ctx.prototypeWhitelist.get(prot);
368
- const replace = context.ctx.options.prototypeReplacements.get(prot.constuctor);
369
- if (replace) {
370
- done(undefined, new Prop(replace(a, false), b));
371
- return;
372
- }
373
- if (whitelist && (!whitelist.size || whitelist.has(b))) {
374
- break;
375
- }
376
- throw new SandboxError(`Method or property access not permitted: ${prot.constructor.name}.${b}`);
377
- }
379
+ if (whitelist && (!whitelist.size || whitelist.has(b))) {
380
+ }
381
+ else {
382
+ throw new SandboxError(`Static method or property access not permitted: ${a.name}.${b}`);
378
383
  }
379
- ;
380
384
  }
381
385
  }
382
- if (context.evals.has(a[b])) {
383
- done(undefined, context.evals.get(a[b]));
384
- return;
385
- }
386
- if (a[b] === globalThis) {
387
- done(undefined, context.ctx.globalScope.get('this'));
388
- return;
389
- }
390
- let g = obj.isGlobal || (isFunction && !sandboxedFunctions.has(a)) || context.ctx.globalsWhitelist.has(a);
391
- done(undefined, new Prop(a, b, false, g));
392
- },
393
- 'call': (exec, done, ticks, a, b, obj, context, scope) => {
394
- if (context.ctx.options.forbidFunctionCalls)
395
- throw new SandboxError("Function invocations are not allowed");
396
- if (typeof a !== 'function') {
397
- throw new TypeError(`${obj.prop} is not a function`);
398
- }
399
- const args = b.map((item) => {
400
- if (item instanceof SpreadArray) {
401
- return [...item.item];
402
- }
403
- else {
404
- return [item];
405
- }
406
- }).flat();
407
- execMany(ticks, exec, toLispArray(args), (err, vals) => {
408
- var _a, _b;
409
- if (err) {
410
- done(err);
411
- return;
412
- }
413
- if (typeof obj === 'function') {
414
- done(undefined, obj(...vals));
415
- return;
416
- }
417
- if (obj.context[obj.prop] === JSON.stringify && context.getSubscriptions.size) {
418
- const cache = new Set();
419
- const recurse = (x) => {
420
- if (!x || !(typeof x === 'object') || cache.has(x))
386
+ else if (b !== 'constructor') {
387
+ let prot = a;
388
+ while (prot = Object.getPrototypeOf(prot)) {
389
+ if (prot.hasOwnProperty(b)) {
390
+ const whitelist = context.ctx.prototypeWhitelist.get(prot);
391
+ const replace = context.ctx.options.prototypeReplacements.get(prot.constuctor);
392
+ if (replace) {
393
+ done(undefined, new Prop(replace(a, false), b));
421
394
  return;
422
- cache.add(x);
423
- for (let y in x) {
424
- context.getSubscriptions.forEach((cb) => cb(x, y));
425
- recurse(x[y]);
426
395
  }
427
- };
428
- recurse(vals[0]);
429
- }
430
- if (obj.context instanceof Array && arrayChange.has(obj.context[obj.prop]) && (context.changeSubscriptions.get(obj.context) || context.changeSubscriptionsGlobal.get(obj.context))) {
431
- let change;
432
- let changed = false;
433
- if (obj.prop === "push") {
434
- change = {
435
- type: "push",
436
- added: vals
437
- };
438
- changed = !!vals.length;
439
- }
440
- else if (obj.prop === "pop") {
441
- change = {
442
- type: "pop",
443
- removed: obj.context.slice(-1)
444
- };
445
- changed = !!change.removed.length;
446
- }
447
- else if (obj.prop === "shift") {
448
- change = {
449
- type: "shift",
450
- removed: obj.context.slice(0, 1)
451
- };
452
- changed = !!change.removed.length;
453
- }
454
- else if (obj.prop === "unshift") {
455
- change = {
456
- type: "unshift",
457
- added: vals
458
- };
459
- changed = !!vals.length;
460
- }
461
- else if (obj.prop === "splice") {
462
- change = {
463
- type: "splice",
464
- startIndex: vals[0],
465
- deleteCount: vals[1] === undefined ? obj.context.length : vals[1],
466
- added: vals.slice(2),
467
- removed: obj.context.slice(vals[0], vals[1] === undefined ? undefined : vals[0] + vals[1])
468
- };
469
- changed = !!change.added.length || !!change.removed.length;
470
- }
471
- else if (obj.prop === "reverse" || obj.prop === "sort") {
472
- change = { type: obj.prop };
473
- changed = !!obj.context.length;
474
- }
475
- else if (obj.prop === "copyWithin") {
476
- let len = vals[2] === undefined ? obj.context.length - vals[1] : Math.min(obj.context.length, vals[2] - vals[1]);
477
- change = {
478
- type: "copyWithin",
479
- startIndex: vals[0],
480
- endIndex: vals[0] + len,
481
- added: obj.context.slice(vals[1], vals[1] + len),
482
- removed: obj.context.slice(vals[0], vals[0] + len)
483
- };
484
- changed = !!change.added.length || !!change.removed.length;
485
- }
486
- if (changed) {
487
- (_a = context.changeSubscriptions.get(obj.context)) === null || _a === void 0 ? void 0 : _a.forEach((cb) => cb(change));
488
- (_b = context.changeSubscriptionsGlobal.get(obj.context)) === null || _b === void 0 ? void 0 : _b.forEach((cb) => cb(change));
396
+ if (whitelist && (!whitelist.size || whitelist.has(b))) {
397
+ break;
398
+ }
399
+ throw new SandboxError(`Method or property access not permitted: ${prot.constructor.name}.${b}`);
489
400
  }
490
401
  }
491
- obj.get(context);
492
- done(undefined, obj.context[obj.prop](...vals));
493
- }, scope, context);
494
- },
495
- 'createObject': (exec, done, ticks, a, b, obj, context, scope) => {
496
- let res = {};
497
- for (let item of b) {
498
- if (item instanceof SpreadObject) {
499
- res = { ...res, ...item.item };
500
- }
501
- else {
502
- res[item.key] = item.val;
503
- }
402
+ ;
504
403
  }
505
- done(undefined, res);
506
- },
507
- 'keyVal': (exec, done, ticks, a, b) => done(undefined, new KeyVal(a, b)),
508
- 'createArray': (exec, done, ticks, a, b, obj, context, scope) => {
509
- const items = b.map((item) => {
510
- if (item instanceof SpreadArray) {
511
- return [...item.item];
512
- }
513
- else {
514
- return [item];
515
- }
516
- }).flat();
517
- execMany(ticks, exec, toLispArray(items), done, scope, context);
518
- },
519
- 'group': (exec, done, ticks, a, b) => done(undefined, b),
520
- 'string': (exec, done, ticks, a, b, obj, context) => done(undefined, context.constants.strings[b]),
521
- 'regex': (exec, done, ticks, a, b, obj, context) => {
522
- const reg = context.constants.regexes[b];
523
- if (!context.ctx.globalsWhitelist.has(RegExp)) {
524
- throw new SandboxError("Regex not permitted");
404
+ }
405
+ if (context.evals.has(a[b])) {
406
+ done(undefined, context.evals.get(a[b]));
407
+ return;
408
+ }
409
+ if (a[b] === globalThis) {
410
+ done(undefined, context.ctx.globalScope.get('this'));
411
+ return;
412
+ }
413
+ let g = obj.isGlobal || (isFunction && !sandboxedFunctions.has(a)) || context.ctx.globalsWhitelist.has(a);
414
+ done(undefined, new Prop(a, b, false, g));
415
+ });
416
+ addOps(5 /* LispType.Call */, (exec, done, ticks, a, b, obj, context, scope) => {
417
+ if (context.ctx.options.forbidFunctionCalls)
418
+ throw new SandboxError("Function invocations are not allowed");
419
+ if (typeof a !== 'function') {
420
+ throw new TypeError(`${typeof obj.prop === 'symbol' ? 'Symbol' : obj.prop} is not a function`);
421
+ }
422
+ const vals = b.map((item) => {
423
+ if (item instanceof SpreadArray) {
424
+ return [...item.item];
525
425
  }
526
426
  else {
527
- done(undefined, new RegExp(reg.regex, reg.flags));
528
- }
529
- },
530
- 'literal': (exec, done, ticks, a, b, obj, context, scope) => {
531
- let name = context.constants.literals[b].a;
532
- let found = toLispArray([]);
533
- let f;
534
- let resnums = [];
535
- while (f = literalRegex.exec(name)) {
536
- if (!f[2]) {
537
- found.push(context.constants.literals[b].b[parseInt(f[3], 10)]);
538
- resnums.push(f[3]);
539
- }
540
- }
541
- execMany(ticks, exec, found, (err, processed) => {
542
- const reses = {};
543
- if (err) {
544
- done(err);
545
- return;
546
- }
547
- for (let i in resnums) {
548
- const num = resnums[i];
549
- reses[num] = processed[i];
550
- }
551
- done(undefined, name.replace(/(\\\\)*(\\)?\${(\d+)}/g, (match, $$, $, num) => {
552
- if ($)
553
- return match;
554
- let res = reses[num];
555
- return ($$ ? $$ : '') + `${valueOrProp(res, context)}`;
556
- }));
557
- }, scope, context);
558
- },
559
- 'spreadArray': (exec, done, ticks, a, b, obj, context, scope) => {
560
- exec(ticks, b, scope, context, (err, res) => {
561
- if (err) {
562
- done(err);
563
- return;
564
- }
565
- done(undefined, new SpreadArray(res));
566
- });
567
- },
568
- 'spreadObject': (exec, done, ticks, a, b, obj, context, scope) => {
569
- exec(ticks, b, scope, context, (err, res) => {
570
- if (err) {
571
- done(err);
572
- return;
573
- }
574
- done(undefined, new SpreadObject(res));
575
- });
576
- },
577
- '!': (exec, done, ticks, a, b) => done(undefined, !b),
578
- '~': (exec, done, ticks, a, b) => done(undefined, ~b),
579
- '++$': (exec, done, ticks, a, b, obj, context) => {
580
- assignCheck(obj, context);
581
- done(undefined, ++obj.context[obj.prop]);
582
- },
583
- '$++': (exec, done, ticks, a, b, obj, context) => {
584
- assignCheck(obj, context);
585
- done(undefined, obj.context[obj.prop]++);
586
- },
587
- '--$': (exec, done, ticks, a, b, obj, context) => {
588
- assignCheck(obj, context);
589
- done(undefined, --obj.context[obj.prop]);
590
- },
591
- '$--': (exec, done, ticks, a, b, obj, context) => {
592
- assignCheck(obj, context);
593
- done(undefined, obj.context[obj.prop]--);
594
- },
595
- '=': (exec, done, ticks, a, b, obj, context) => {
596
- assignCheck(obj, context);
597
- done(undefined, obj.context[obj.prop] = b);
598
- },
599
- '+=': (exec, done, ticks, a, b, obj, context) => {
600
- assignCheck(obj, context);
601
- done(undefined, obj.context[obj.prop] += b);
602
- },
603
- '-=': (exec, done, ticks, a, b, obj, context) => {
604
- assignCheck(obj, context);
605
- done(undefined, obj.context[obj.prop] -= b);
606
- },
607
- '/=': (exec, done, ticks, a, b, obj, context) => {
608
- assignCheck(obj, context);
609
- done(undefined, obj.context[obj.prop] /= b);
610
- },
611
- '*=': (exec, done, ticks, a, b, obj, context) => {
612
- assignCheck(obj, context);
613
- done(undefined, obj.context[obj.prop] *= b);
614
- },
615
- '**=': (exec, done, ticks, a, b, obj, context) => {
616
- assignCheck(obj, context);
617
- done(undefined, obj.context[obj.prop] **= b);
618
- },
619
- '%=': (exec, done, ticks, a, b, obj, context) => {
620
- assignCheck(obj, context);
621
- done(undefined, obj.context[obj.prop] %= b);
622
- },
623
- '^=': (exec, done, ticks, a, b, obj, context) => {
624
- assignCheck(obj, context);
625
- done(undefined, obj.context[obj.prop] ^= b);
626
- },
627
- '&=': (exec, done, ticks, a, b, obj, context) => {
628
- assignCheck(obj, context);
629
- done(undefined, obj.context[obj.prop] &= b);
630
- },
631
- '|=': (exec, done, ticks, a, b, obj, context) => {
632
- assignCheck(obj, context);
633
- done(undefined, obj.context[obj.prop] |= b);
634
- },
635
- '<<=': (exec, done, ticks, a, b, obj, context) => {
636
- assignCheck(obj, context);
637
- done(undefined, obj.context[obj.prop] <<= b);
638
- },
639
- '>>=': (exec, done, ticks, a, b, obj, context) => {
640
- assignCheck(obj, context);
641
- done(undefined, obj.context[obj.prop] >>= b);
642
- },
643
- '>>>=': (exec, done, ticks, a, b, obj, context) => {
644
- assignCheck(obj, context);
645
- done(undefined, obj.context[obj.prop] >>= b);
646
- },
647
- '?': (exec, done, ticks, a, b, obj, context, scope) => {
648
- if (!(b instanceof If)) {
649
- throw new SyntaxError('Invalid inline if');
650
- }
651
- exec(ticks, a, scope, context, (err, res) => {
652
- if (err) {
653
- done(err);
654
- }
655
- else {
656
- exec(ticks, valueOrProp(res, context) ? b.t : b.f, scope, context, done);
657
- }
658
- });
659
- },
660
- '>': (exec, done, ticks, a, b) => done(undefined, a > b),
661
- '<': (exec, done, ticks, a, b) => done(undefined, a < b),
662
- '>=': (exec, done, ticks, a, b) => done(undefined, a >= b),
663
- '<=': (exec, done, ticks, a, b) => done(undefined, a <= b),
664
- '==': (exec, done, ticks, a, b) => done(undefined, a == b),
665
- '===': (exec, done, ticks, a, b) => done(undefined, a === b),
666
- '!=': (exec, done, ticks, a, b) => done(undefined, a != b),
667
- '!==': (exec, done, ticks, a, b) => done(undefined, a !== b),
668
- '&&': (exec, done, ticks, a, b) => done(undefined, a && b),
669
- '||': (exec, done, ticks, a, b) => done(undefined, a || b),
670
- '&': (exec, done, ticks, a, b) => done(undefined, a & b),
671
- '|': (exec, done, ticks, a, b) => done(undefined, a | b),
672
- ':': (exec, done, ticks, a, b) => done(undefined, new If(a, b)),
673
- '+': (exec, done, ticks, a, b) => done(undefined, a + b),
674
- '-': (exec, done, ticks, a, b) => done(undefined, a - b),
675
- '$+': (exec, done, ticks, a, b) => done(undefined, +b),
676
- '$-': (exec, done, ticks, a, b) => done(undefined, -b),
677
- '/': (exec, done, ticks, a, b) => done(undefined, a / b),
678
- '^': (exec, done, ticks, a, b) => done(undefined, a ^ b),
679
- '*': (exec, done, ticks, a, b) => done(undefined, a * b),
680
- '%': (exec, done, ticks, a, b) => done(undefined, a % b),
681
- '<<': (exec, done, ticks, a, b) => done(undefined, a << b),
682
- '>>': (exec, done, ticks, a, b) => done(undefined, a >> b),
683
- '>>>': (exec, done, ticks, a, b) => done(undefined, a >>> b),
684
- 'typeof': (exec, done, ticks, a, b, obj, context, scope) => {
685
- exec(ticks, b, scope, context, (e, prop) => {
686
- done(undefined, typeof valueOrProp(prop, context));
687
- });
688
- },
689
- 'instanceof': (exec, done, ticks, a, b) => done(undefined, a instanceof b),
690
- 'in': (exec, done, ticks, a, b) => done(undefined, a in b),
691
- 'delete': (exec, done, ticks, a, b, obj, context, scope, bobj) => {
692
- if (bobj.context === undefined) {
693
- done(undefined, true);
694
- return;
427
+ return [item];
695
428
  }
696
- assignCheck(bobj, context, 'delete');
697
- if (bobj.isVariable) {
698
- done(undefined, false);
699
- return;
700
- }
701
- done(undefined, delete bobj.context[bobj.prop]);
702
- },
703
- 'return': (exec, done, ticks, a, b, obj, context) => done(undefined, b),
704
- 'var': (exec, done, ticks, a, b, obj, context, scope, bobj) => {
705
- exec(ticks, b, scope, context, (err, res) => {
706
- if (err) {
707
- done(err);
708
- return;
709
- }
710
- done(undefined, scope.declare(a, VarType.var, res));
711
- });
712
- },
713
- 'let': (exec, done, ticks, a, b, obj, context, scope, bobj) => {
714
- exec(ticks, b, scope, context, (err, res) => {
715
- if (err) {
716
- done(err);
717
- return;
718
- }
719
- done(undefined, scope.declare(a, VarType.let, res, bobj && bobj.isGlobal));
720
- });
721
- },
722
- 'const': (exec, done, ticks, a, b, obj, context, scope, bobj) => {
723
- exec(ticks, b, scope, context, (err, res) => {
724
- if (err) {
725
- done(err);
429
+ }).flat().map((item) => valueOrProp(item, context));
430
+ if (typeof obj === 'function') {
431
+ done(undefined, obj(...vals));
432
+ return;
433
+ }
434
+ if (obj.context[obj.prop] === JSON.stringify && context.getSubscriptions.size) {
435
+ const cache = new Set();
436
+ const recurse = (x) => {
437
+ if (!x || !(typeof x === 'object') || cache.has(x))
726
438
  return;
439
+ cache.add(x);
440
+ for (let y in x) {
441
+ context.getSubscriptions.forEach((cb) => cb(x, y));
442
+ recurse(x[y]);
727
443
  }
728
- done(undefined, scope.declare(a, VarType.const, res));
729
- });
730
- },
731
- 'arrowFunc': (exec, done, ticks, a, b, obj, context, scope) => {
732
- a = [...a];
733
- if (typeof obj.b === "string" || obj.b instanceof CodeString) {
734
- obj.b = b = lispifyFunction(new CodeString(obj.b), context.constants);
444
+ };
445
+ recurse(vals[0]);
446
+ }
447
+ if (obj.context instanceof Array && arrayChange.has(obj.context[obj.prop]) && (context.changeSubscriptions.get(obj.context) || context.changeSubscriptionsGlobal.get(obj.context))) {
448
+ let change;
449
+ let changed = false;
450
+ if (obj.prop === "push") {
451
+ change = {
452
+ type: "push",
453
+ added: vals
454
+ };
455
+ changed = !!vals.length;
456
+ }
457
+ else if (obj.prop === "pop") {
458
+ change = {
459
+ type: "pop",
460
+ removed: obj.context.slice(-1)
461
+ };
462
+ changed = !!change.removed.length;
463
+ }
464
+ else if (obj.prop === "shift") {
465
+ change = {
466
+ type: "shift",
467
+ removed: obj.context.slice(0, 1)
468
+ };
469
+ changed = !!change.removed.length;
470
+ }
471
+ else if (obj.prop === "unshift") {
472
+ change = {
473
+ type: "unshift",
474
+ added: vals
475
+ };
476
+ changed = !!vals.length;
477
+ }
478
+ else if (obj.prop === "splice") {
479
+ change = {
480
+ type: "splice",
481
+ startIndex: vals[0],
482
+ deleteCount: vals[1] === undefined ? obj.context.length : vals[1],
483
+ added: vals.slice(2),
484
+ removed: obj.context.slice(vals[0], vals[1] === undefined ? undefined : vals[0] + vals[1])
485
+ };
486
+ changed = !!change.added.length || !!change.removed.length;
487
+ }
488
+ else if (obj.prop === "reverse" || obj.prop === "sort") {
489
+ change = { type: obj.prop };
490
+ changed = !!obj.context.length;
491
+ }
492
+ else if (obj.prop === "copyWithin") {
493
+ let len = vals[2] === undefined ? obj.context.length - vals[1] : Math.min(obj.context.length, vals[2] - vals[1]);
494
+ change = {
495
+ type: "copyWithin",
496
+ startIndex: vals[0],
497
+ endIndex: vals[0] + len,
498
+ added: obj.context.slice(vals[1], vals[1] + len),
499
+ removed: obj.context.slice(vals[0], vals[0] + len)
500
+ };
501
+ changed = !!change.added.length || !!change.removed.length;
502
+ }
503
+ if (changed) {
504
+ context.changeSubscriptions.get(obj.context)?.forEach((cb) => cb(change));
505
+ context.changeSubscriptionsGlobal.get(obj.context)?.forEach((cb) => cb(change));
735
506
  }
736
- if (a.shift()) {
737
- done(undefined, createFunctionAsync(a, b, ticks, context, scope));
507
+ }
508
+ obj.get(context);
509
+ done(undefined, obj.context[obj.prop](...vals));
510
+ });
511
+ addOps(22 /* LispType.CreateObject */, (exec, done, ticks, a, b, obj, context, scope) => {
512
+ let res = {};
513
+ for (let item of b) {
514
+ if (item.key instanceof SpreadObject) {
515
+ res = { ...res, ...item.key.item };
738
516
  }
739
517
  else {
740
- done(undefined, createFunction(a, b, ticks, context, scope));
741
- }
742
- },
743
- 'function': (exec, done, ticks, a, b, obj, context, scope) => {
744
- if (typeof obj.b === "string" || obj.b instanceof CodeString) {
745
- obj.b = b = lispifyFunction(new CodeString(obj.b), context.constants);
518
+ res[item.key] = item.val;
746
519
  }
747
- let isAsync = a.shift();
748
- let name = a.shift();
749
- let func;
750
- if (isAsync) {
751
- func = createFunctionAsync(a, b, ticks, context, scope, name);
520
+ }
521
+ done(undefined, res);
522
+ });
523
+ 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, scope) => {
525
+ const items = b.map((item) => {
526
+ if (item instanceof SpreadArray) {
527
+ return [...item.item];
752
528
  }
753
529
  else {
754
- func = createFunction(a, b, ticks, context, scope, name);
755
- }
756
- if (name) {
757
- scope.declare(name, VarType.var, func);
758
- }
759
- done(undefined, func);
760
- },
761
- 'inlineFunction': (exec, done, ticks, a, b, obj, context, scope) => {
762
- if (typeof obj.b === "string" || obj.b instanceof CodeString) {
763
- obj.b = b = lispifyFunction(new CodeString(obj.b), context.constants);
530
+ return [item];
531
+ }
532
+ }).flat().map((item) => valueOrProp(item, context));
533
+ done(undefined, items);
534
+ });
535
+ addOps(23 /* LispType.Group */, (exec, done, ticks, a, b) => done(undefined, b));
536
+ addOps(35 /* LispType.GlobalSymbol */, (exec, done, ticks, a, b) => {
537
+ switch (b) {
538
+ case 'true': return done(undefined, true);
539
+ case 'false': return done(undefined, false);
540
+ case 'null': return done(undefined, null);
541
+ case 'undefined': return done(undefined, undefined);
542
+ case 'NaN': return done(undefined, NaN);
543
+ case 'Infinity': return done(undefined, Infinity);
544
+ }
545
+ done(new Error('Unknown symbol: ' + b));
546
+ });
547
+ addOps(7 /* LispType.Number */, (exec, done, ticks, a, b) => done(undefined, Number(b)));
548
+ addOps(83 /* LispType.BigInt */, (exec, done, ticks, a, b) => done(undefined, BigInt(b)));
549
+ addOps(2 /* LispType.StringIndex */, (exec, done, ticks, a, b, obj, context) => done(undefined, context.constants.strings[parseInt(b)]));
550
+ addOps(85 /* LispType.RegexIndex */, (exec, done, ticks, a, b, obj, context) => {
551
+ const reg = context.constants.regexes[parseInt(b)];
552
+ if (!context.ctx.globalsWhitelist.has(RegExp)) {
553
+ throw new SandboxError("Regex not permitted");
554
+ }
555
+ else {
556
+ done(undefined, new RegExp(reg.regex, reg.flags));
557
+ }
558
+ });
559
+ addOps(84 /* LispType.LiteralIndex */, (exec, done, ticks, a, b, obj, context, scope) => {
560
+ let item = context.constants.literals[parseInt(b)];
561
+ const [, name, js] = item;
562
+ let found = [];
563
+ let f;
564
+ let resnums = [];
565
+ while (f = literalRegex.exec(name)) {
566
+ if (!f[2]) {
567
+ found.push(js[parseInt(f[3], 10)]);
568
+ resnums.push(f[3]);
764
569
  }
765
- let isAsync = a.shift();
766
- let name = a.shift();
767
- if (name) {
768
- scope = new Scope(scope, {});
570
+ }
571
+ exec(ticks, found, scope, context, (err, processed) => {
572
+ const reses = {};
573
+ if (err) {
574
+ done(err);
575
+ return;
769
576
  }
770
- let func;
771
- if (isAsync) {
772
- func = createFunctionAsync(a, b, ticks, context, scope, name);
577
+ for (let i in resnums) {
578
+ const num = resnums[i];
579
+ reses[num] = processed[i];
773
580
  }
774
- else {
775
- func = createFunction(a, b, ticks, context, scope, name);
776
- }
777
- if (name) {
778
- scope.declare(name, VarType.let, func);
779
- }
780
- done(undefined, func);
781
- },
782
- 'loop': (exec, done, ticks, a, b, obj, context, scope) => {
783
- const [checkFirst, startInternal, getIterator, startStep, step, condition, beforeStep] = a;
784
- let loop = true;
785
- const loopScope = new Scope(scope, {});
786
- let internalVars = {
787
- '$$obj': undefined
788
- };
789
- const interalScope = new Scope(loopScope, internalVars);
790
- if (exec === execAsync) {
791
- (async () => {
792
- let ad;
793
- ad = asyncDone((d) => exec(ticks, startStep, loopScope, context, d));
794
- internalVars['$$obj'] = (ad = asyncDone((d) => exec(ticks, getIterator, loopScope, context, d))).isInstant === true ? ad.instant : (await ad.p).result;
795
- ad = asyncDone((d) => exec(ticks, startInternal, interalScope, context, d));
796
- if (checkFirst)
797
- loop = (ad = asyncDone((d) => exec(ticks, condition, interalScope, context, d))).isInstant === true ? ad.instant : (await ad.p).result;
798
- while (loop) {
799
- let innerLoopVars = {};
800
- ad = asyncDone((d) => exec(ticks, beforeStep, new Scope(interalScope, innerLoopVars), context, d));
801
- ad.isInstant === true ? ad.instant : (await ad.p).result;
802
- let res = await executeTreeAsync(ticks, context, b, [new Scope(loopScope, innerLoopVars)], "loop");
803
- if (res instanceof ExecReturn && res.returned) {
804
- done(undefined, res);
805
- return;
806
- }
807
- if (res instanceof ExecReturn && res.breakLoop) {
808
- break;
809
- }
810
- ad = asyncDone((d) => exec(ticks, step, interalScope, context, d));
811
- loop = (ad = asyncDone((d) => exec(ticks, condition, interalScope, context, d))).isInstant === true ? ad.instant : (await ad.p).result;
812
- }
813
- done();
814
- })().catch(done);
815
- }
816
- else {
817
- syncDone((d) => exec(ticks, startStep, loopScope, context, d));
818
- internalVars['$$obj'] = syncDone((d) => exec(ticks, getIterator, loopScope, context, d)).result;
819
- syncDone((d) => exec(ticks, startInternal, interalScope, context, d));
581
+ done(undefined, name.replace(/(\\\\)*(\\)?\${(\d+)}/g, (match, $$, $, num) => {
582
+ if ($)
583
+ return match;
584
+ let res = reses[num];
585
+ return ($$ ? $$ : '') + `${valueOrProp(res, context)}`;
586
+ }));
587
+ });
588
+ });
589
+ addOps(18 /* LispType.SpreadArray */, (exec, done, ticks, a, b, obj, context, scope) => {
590
+ done(undefined, new SpreadArray(b));
591
+ });
592
+ addOps(17 /* LispType.SpreadObject */, (exec, done, ticks, a, b, obj, context, scope) => {
593
+ done(undefined, new SpreadObject(b));
594
+ });
595
+ addOps(24 /* LispType.Not */, (exec, done, ticks, a, b) => done(undefined, !b));
596
+ addOps(64 /* LispType.Inverse */, (exec, done, ticks, a, b) => done(undefined, ~b));
597
+ addOps(25 /* LispType.IncrementBefore */, (exec, done, ticks, a, b, obj, context) => {
598
+ assignCheck(obj, context);
599
+ done(undefined, ++obj.context[obj.prop]);
600
+ });
601
+ addOps(26 /* LispType.IncrementAfter */, (exec, done, ticks, a, b, obj, context) => {
602
+ assignCheck(obj, context);
603
+ done(undefined, obj.context[obj.prop]++);
604
+ });
605
+ addOps(27 /* LispType.DecrementBefore */, (exec, done, ticks, a, b, obj, context) => {
606
+ assignCheck(obj, context);
607
+ done(undefined, --obj.context[obj.prop]);
608
+ });
609
+ addOps(28 /* LispType.DecrementAfter */, (exec, done, ticks, a, b, obj, context) => {
610
+ assignCheck(obj, context);
611
+ done(undefined, obj.context[obj.prop]--);
612
+ });
613
+ addOps(9 /* LispType.Assign */, (exec, done, ticks, a, b, obj, context) => {
614
+ assignCheck(obj, context);
615
+ done(undefined, obj.context[obj.prop] = b);
616
+ });
617
+ addOps(66 /* LispType.AddEquals */, (exec, done, ticks, a, b, obj, context) => {
618
+ assignCheck(obj, context);
619
+ done(undefined, obj.context[obj.prop] += b);
620
+ });
621
+ addOps(65 /* LispType.SubractEquals */, (exec, done, ticks, a, b, obj, context) => {
622
+ assignCheck(obj, context);
623
+ done(undefined, obj.context[obj.prop] -= b);
624
+ });
625
+ addOps(67 /* LispType.DivideEquals */, (exec, done, ticks, a, b, obj, context) => {
626
+ assignCheck(obj, context);
627
+ done(undefined, obj.context[obj.prop] /= b);
628
+ });
629
+ addOps(69 /* LispType.MultiplyEquals */, (exec, done, ticks, a, b, obj, context) => {
630
+ assignCheck(obj, context);
631
+ done(undefined, obj.context[obj.prop] *= b);
632
+ });
633
+ addOps(68 /* LispType.PowerEquals */, (exec, done, ticks, a, b, obj, context) => {
634
+ assignCheck(obj, context);
635
+ done(undefined, obj.context[obj.prop] **= b);
636
+ });
637
+ addOps(70 /* LispType.ModulusEquals */, (exec, done, ticks, a, b, obj, context) => {
638
+ assignCheck(obj, context);
639
+ done(undefined, obj.context[obj.prop] %= b);
640
+ });
641
+ addOps(71 /* LispType.BitNegateEquals */, (exec, done, ticks, a, b, obj, context) => {
642
+ assignCheck(obj, context);
643
+ done(undefined, obj.context[obj.prop] ^= b);
644
+ });
645
+ addOps(72 /* LispType.BitAndEquals */, (exec, done, ticks, a, b, obj, context) => {
646
+ assignCheck(obj, context);
647
+ done(undefined, obj.context[obj.prop] &= b);
648
+ });
649
+ addOps(73 /* LispType.BitOrEquals */, (exec, done, ticks, a, b, obj, context) => {
650
+ assignCheck(obj, context);
651
+ done(undefined, obj.context[obj.prop] |= b);
652
+ });
653
+ addOps(76 /* LispType.ShiftLeftEquals */, (exec, done, ticks, a, b, obj, context) => {
654
+ assignCheck(obj, context);
655
+ done(undefined, obj.context[obj.prop] <<= b);
656
+ });
657
+ addOps(75 /* LispType.ShiftRightEquals */, (exec, done, ticks, a, b, obj, context) => {
658
+ assignCheck(obj, context);
659
+ done(undefined, obj.context[obj.prop] >>= b);
660
+ });
661
+ addOps(74 /* LispType.UnsignedShiftRightEquals */, (exec, done, ticks, a, b, obj, context) => {
662
+ assignCheck(obj, context);
663
+ done(undefined, obj.context[obj.prop] >>= b);
664
+ });
665
+ addOps(57 /* LispType.LargerThan */, (exec, done, ticks, a, b) => done(undefined, a > b));
666
+ addOps(56 /* LispType.SmallerThan */, (exec, done, ticks, a, b) => done(undefined, a < b));
667
+ addOps(55 /* LispType.LargerEqualThan */, (exec, done, ticks, a, b) => done(undefined, a >= b));
668
+ addOps(54 /* LispType.SmallerEqualThan */, (exec, done, ticks, a, b) => done(undefined, a <= b));
669
+ addOps(52 /* LispType.Equal */, (exec, done, ticks, a, b) => done(undefined, a == b));
670
+ addOps(32 /* LispType.StrictEqual */, (exec, done, ticks, a, b) => done(undefined, a === b));
671
+ addOps(53 /* LispType.NotEqual */, (exec, done, ticks, a, b) => done(undefined, a != b));
672
+ addOps(31 /* LispType.StrictNotEqual */, (exec, done, ticks, a, b) => done(undefined, a !== b));
673
+ addOps(29 /* LispType.And */, (exec, done, ticks, a, b) => done(undefined, a && b));
674
+ addOps(30 /* LispType.Or */, (exec, done, ticks, a, b) => done(undefined, a || b));
675
+ addOps(77 /* LispType.BitAnd */, (exec, done, ticks, a, b) => done(undefined, a & b));
676
+ addOps(78 /* LispType.BitOr */, (exec, done, ticks, a, b) => done(undefined, a | b));
677
+ addOps(33 /* LispType.Plus */, (exec, done, ticks, a, b) => done(undefined, a + b));
678
+ addOps(47 /* LispType.Minus */, (exec, done, ticks, a, b) => done(undefined, a - b));
679
+ addOps(59 /* LispType.Positive */, (exec, done, ticks, a, b) => done(undefined, +b));
680
+ addOps(58 /* LispType.Negative */, (exec, done, ticks, a, b) => done(undefined, -b));
681
+ addOps(48 /* LispType.Divide */, (exec, done, ticks, a, b) => done(undefined, a / b));
682
+ addOps(79 /* LispType.BitNegate */, (exec, done, ticks, a, b) => done(undefined, a ^ b));
683
+ addOps(50 /* LispType.Multiply */, (exec, done, ticks, a, b) => done(undefined, a * b));
684
+ addOps(51 /* LispType.Modulus */, (exec, done, ticks, a, b) => done(undefined, a % b));
685
+ addOps(80 /* LispType.BitShiftLeft */, (exec, done, ticks, a, b) => done(undefined, a << b));
686
+ addOps(81 /* LispType.BitShiftRight */, (exec, done, ticks, a, b) => done(undefined, a >> b));
687
+ addOps(82 /* LispType.BitUnsignedShiftRight */, (exec, done, ticks, a, b) => done(undefined, a >>> b));
688
+ addOps(60 /* LispType.Typeof */, (exec, done, ticks, a, b, obj, context, scope) => {
689
+ exec(ticks, b, scope, context, (e, prop) => {
690
+ done(undefined, typeof valueOrProp(prop, context));
691
+ });
692
+ });
693
+ addOps(62 /* LispType.Instanceof */, (exec, done, ticks, a, b) => done(undefined, a instanceof b));
694
+ addOps(63 /* LispType.In */, (exec, done, ticks, a, b) => done(undefined, a in b));
695
+ addOps(61 /* LispType.Delete */, (exec, done, ticks, a, b, obj, context, scope, bobj) => {
696
+ if (bobj.context === undefined) {
697
+ done(undefined, true);
698
+ return;
699
+ }
700
+ assignCheck(bobj, context, 'delete');
701
+ if (bobj.isVariable) {
702
+ done(undefined, false);
703
+ return;
704
+ }
705
+ done(undefined, delete bobj.context[bobj.prop]);
706
+ });
707
+ addOps(8 /* LispType.Return */, (exec, done, ticks, a, b, obj, context) => done(undefined, b));
708
+ addOps(34 /* LispType.Var */, (exec, done, ticks, a, b, obj, context, scope, bobj) => {
709
+ done(undefined, scope.declare(a, VarType.var, b));
710
+ });
711
+ addOps(3 /* LispType.Let */, (exec, done, ticks, a, b, obj, context, scope, bobj) => {
712
+ done(undefined, scope.declare(a, VarType.let, b, bobj && bobj.isGlobal));
713
+ });
714
+ addOps(4 /* LispType.Const */, (exec, done, ticks, a, b, obj, context, scope, bobj) => {
715
+ done(undefined, scope.declare(a, VarType.const, b));
716
+ });
717
+ addOps(11 /* LispType.ArrowFunction */, (exec, done, ticks, a, b, obj, context, scope) => {
718
+ a = [...a];
719
+ if (typeof obj[2] === "string" || obj[2] instanceof CodeString) {
720
+ obj[2] = b = lispifyFunction(new CodeString(obj[2]), context.constants);
721
+ }
722
+ if (a.shift()) {
723
+ done(undefined, createFunctionAsync(a, b, ticks, context, scope));
724
+ }
725
+ else {
726
+ done(undefined, createFunction(a, b, ticks, context, scope));
727
+ }
728
+ });
729
+ addOps(37 /* LispType.Function */, (exec, done, ticks, a, b, obj, context, scope) => {
730
+ if (typeof obj[2] === "string" || obj[2] instanceof CodeString) {
731
+ obj[2] = b = lispifyFunction(new CodeString(obj[2]), context.constants);
732
+ }
733
+ let isAsync = a.shift();
734
+ let name = a.shift();
735
+ let func;
736
+ if (isAsync === 88 /* LispType.True */) {
737
+ func = createFunctionAsync(a, b, ticks, context, scope, name);
738
+ }
739
+ else {
740
+ func = createFunction(a, b, ticks, context, scope, name);
741
+ }
742
+ if (name) {
743
+ scope.declare(name, VarType.var, func);
744
+ }
745
+ done(undefined, func);
746
+ });
747
+ addOps(10 /* LispType.InlineFunction */, (exec, done, ticks, a, b, obj, context, scope) => {
748
+ if (typeof obj[2] === "string" || obj[2] instanceof CodeString) {
749
+ obj[2] = b = lispifyFunction(new CodeString(obj[2]), context.constants);
750
+ }
751
+ let isAsync = a.shift();
752
+ let name = a.shift();
753
+ if (name) {
754
+ scope = new Scope(scope, {});
755
+ }
756
+ let func;
757
+ if (isAsync === 88 /* LispType.True */) {
758
+ func = createFunctionAsync(a, b, ticks, context, scope, name);
759
+ }
760
+ else {
761
+ func = createFunction(a, b, ticks, context, scope, name);
762
+ }
763
+ if (name) {
764
+ scope.declare(name, VarType.let, func);
765
+ }
766
+ done(undefined, func);
767
+ });
768
+ addOps(38 /* LispType.Loop */, (exec, done, ticks, a, b, obj, context, scope) => {
769
+ const [checkFirst, startInternal, getIterator, startStep, step, condition, beforeStep] = a;
770
+ let loop = true;
771
+ const loopScope = new Scope(scope, {});
772
+ let internalVars = {
773
+ '$$obj': undefined
774
+ };
775
+ const interalScope = new Scope(loopScope, internalVars);
776
+ if (exec === execAsync) {
777
+ (async () => {
778
+ let ad;
779
+ ad = asyncDone((d) => exec(ticks, startStep, loopScope, context, d));
780
+ internalVars['$$obj'] = (ad = asyncDone((d) => exec(ticks, getIterator, loopScope, context, d))).isInstant === true ? ad.instant : (await ad.p).result;
781
+ ad = asyncDone((d) => exec(ticks, startInternal, interalScope, context, d));
820
782
  if (checkFirst)
821
- loop = (syncDone((d) => exec(ticks, condition, interalScope, context, d))).result;
783
+ loop = (ad = asyncDone((d) => exec(ticks, condition, interalScope, context, d))).isInstant === true ? ad.instant : (await ad.p).result;
822
784
  while (loop) {
823
785
  let innerLoopVars = {};
824
- syncDone((d) => exec(ticks, beforeStep, new Scope(interalScope, innerLoopVars), context, d));
825
- let res = executeTree(ticks, context, b, [new Scope(loopScope, innerLoopVars)], "loop");
786
+ ad = asyncDone((d) => exec(ticks, beforeStep, new Scope(interalScope, innerLoopVars), context, d));
787
+ ad.isInstant === true ? ad.instant : (await ad.p).result;
788
+ let res = await executeTreeAsync(ticks, context, b, [new Scope(loopScope, innerLoopVars)], "loop");
826
789
  if (res instanceof ExecReturn && res.returned) {
827
790
  done(undefined, res);
828
791
  return;
@@ -830,116 +793,131 @@ let ops2 = {
830
793
  if (res instanceof ExecReturn && res.breakLoop) {
831
794
  break;
832
795
  }
833
- syncDone((d) => exec(ticks, step, interalScope, context, d));
834
- loop = (syncDone((d) => exec(ticks, condition, interalScope, context, d))).result;
796
+ ad = asyncDone((d) => exec(ticks, step, interalScope, context, d));
797
+ loop = (ad = asyncDone((d) => exec(ticks, condition, interalScope, context, d))).isInstant === true ? ad.instant : (await ad.p).result;
835
798
  }
836
799
  done();
837
- }
838
- },
839
- 'loopAction': (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
840
- if ((inLoopOrSwitch === "switch" && a === "continue") || !inLoopOrSwitch) {
841
- throw new SandboxError("Illegal " + a + " statement");
842
- }
843
- done(undefined, new ExecReturn(context.ctx.auditReport, undefined, false, a === "break", a === "continue"));
844
- },
845
- 'if': (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
846
- if (!(b instanceof If)) {
847
- throw new SyntaxError('Invalid if');
848
- }
849
- exec(ticks, a, scope, context, (err, res) => {
850
- if (err) {
851
- done(err);
800
+ })().catch(done);
801
+ }
802
+ else {
803
+ syncDone((d) => exec(ticks, startStep, loopScope, context, d));
804
+ internalVars['$$obj'] = syncDone((d) => exec(ticks, getIterator, loopScope, context, d)).result;
805
+ syncDone((d) => exec(ticks, startInternal, interalScope, context, d));
806
+ if (checkFirst)
807
+ loop = (syncDone((d) => exec(ticks, condition, interalScope, context, d))).result;
808
+ while (loop) {
809
+ let innerLoopVars = {};
810
+ syncDone((d) => exec(ticks, beforeStep, new Scope(interalScope, innerLoopVars), context, d));
811
+ let res = executeTree(ticks, context, b, [new Scope(loopScope, innerLoopVars)], "loop");
812
+ if (res instanceof ExecReturn && res.returned) {
813
+ done(undefined, res);
852
814
  return;
853
815
  }
854
- executeTreeWithDone(exec, done, ticks, context, valueOrProp(res, context) ? b.t : b.f, [new Scope(scope)], inLoopOrSwitch);
855
- });
856
- },
857
- 'switch': (exec, done, ticks, a, b, obj, context, scope) => {
858
- exec(ticks, a, scope, context, (err, toTest) => {
859
- if (err) {
860
- done(err);
861
- return;
816
+ if (res instanceof ExecReturn && res.breakLoop) {
817
+ break;
818
+ }
819
+ syncDone((d) => exec(ticks, step, interalScope, context, d));
820
+ loop = (syncDone((d) => exec(ticks, condition, interalScope, context, d))).result;
821
+ }
822
+ done();
823
+ }
824
+ });
825
+ addOps(86 /* LispType.LoopAction */, (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
826
+ if ((inLoopOrSwitch === "switch" && a === "continue") || !inLoopOrSwitch) {
827
+ throw new SandboxError("Illegal " + a + " statement");
828
+ }
829
+ done(undefined, new ExecReturn(context.ctx.auditReport, undefined, false, a === "break", a === "continue"));
830
+ });
831
+ addOps(13 /* LispType.If */, (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
832
+ exec(ticks, valueOrProp(a, context) ? b.t : b.f, scope, context, done);
833
+ });
834
+ addOps(15 /* LispType.InlineIf */, (exec, done, ticks, a, b, obj, context, scope) => {
835
+ exec(ticks, valueOrProp(a, context) ? b.t : b.f, scope, context, done);
836
+ });
837
+ addOps(16 /* LispType.InlineIfCase */, (exec, done, ticks, a, b) => done(undefined, new If(a, b)));
838
+ addOps(14 /* LispType.IfCase */, (exec, done, ticks, a, b) => done(undefined, new If(a, b)));
839
+ addOps(40 /* LispType.Switch */, (exec, done, ticks, a, b, obj, context, scope) => {
840
+ exec(ticks, a, scope, context, (err, toTest) => {
841
+ if (err) {
842
+ done(err);
843
+ return;
844
+ }
845
+ toTest = valueOrProp(toTest, context);
846
+ if (exec === execSync) {
847
+ let res;
848
+ let isTrue = false;
849
+ for (let caseItem of b) {
850
+ if (isTrue || (isTrue = !caseItem[1] || toTest === valueOrProp((syncDone((d) => exec(ticks, caseItem[1], scope, context, d))).result, context))) {
851
+ if (!caseItem[2])
852
+ continue;
853
+ res = executeTree(ticks, context, caseItem[2], [scope], "switch");
854
+ if (res.breakLoop)
855
+ break;
856
+ if (res.returned) {
857
+ done(undefined, res);
858
+ return;
859
+ }
860
+ if (!caseItem[1]) { // default case
861
+ break;
862
+ }
863
+ }
862
864
  }
863
- toTest = valueOrProp(toTest, context);
864
- if (exec === execSync) {
865
+ done();
866
+ }
867
+ else {
868
+ (async () => {
865
869
  let res;
866
870
  let isTrue = false;
867
871
  for (let caseItem of b) {
868
- if (isTrue || (isTrue = !caseItem.a || toTest === valueOrProp((syncDone((d) => exec(ticks, caseItem.a, scope, context, d))).result, context))) {
869
- if (!caseItem.b)
872
+ let ad;
873
+ if (isTrue || (isTrue = !caseItem[1] || toTest === valueOrProp((ad = asyncDone((d) => exec(ticks, caseItem[1], scope, context, d))).isInstant === true ? ad.instant : (await ad.p).result, context))) {
874
+ if (!caseItem[2])
870
875
  continue;
871
- res = executeTree(ticks, context, caseItem.b, [scope], "switch");
876
+ res = await executeTreeAsync(ticks, context, caseItem[2], [scope], "switch");
872
877
  if (res.breakLoop)
873
878
  break;
874
879
  if (res.returned) {
875
880
  done(undefined, res);
876
881
  return;
877
882
  }
878
- if (!caseItem.a) { // default case
883
+ if (!caseItem[1]) { // default case
879
884
  break;
880
885
  }
881
886
  }
882
887
  }
883
888
  done();
889
+ })().catch(done);
890
+ }
891
+ });
892
+ });
893
+ addOps(39 /* LispType.Try */, (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
894
+ const [exception, catchBody, finallyBody] = b;
895
+ executeTreeWithDone(exec, (err, res) => {
896
+ executeTreeWithDone(exec, (e) => {
897
+ if (e)
898
+ done(e);
899
+ else if (err) {
900
+ let sc = {};
901
+ if (exception)
902
+ sc[exception] = err;
903
+ executeTreeWithDone(exec, done, ticks, context, catchBody, [new Scope(scope)], inLoopOrSwitch);
884
904
  }
885
905
  else {
886
- (async () => {
887
- let res;
888
- let isTrue = false;
889
- for (let caseItem of b) {
890
- let ad;
891
- if (isTrue || (isTrue = !caseItem.a || toTest === valueOrProp((ad = asyncDone((d) => exec(ticks, caseItem.a, scope, context, d))).isInstant === true ? ad.instant : (await ad.p).result, context))) {
892
- if (!caseItem.b)
893
- continue;
894
- res = await executeTreeAsync(ticks, context, caseItem.b, [scope], "switch");
895
- if (res.breakLoop)
896
- break;
897
- if (res.returned) {
898
- done(undefined, res);
899
- return;
900
- }
901
- if (!caseItem.a) { // default case
902
- break;
903
- }
904
- }
905
- }
906
- done();
907
- })().catch(done);
906
+ done(undefined, res);
908
907
  }
909
- });
910
- },
911
- 'try': (exec, done, ticks, a, b, obj, context, scope, bobj, inLoopOrSwitch) => {
912
- const [exception, catchBody, finallyBody] = b;
913
- executeTreeWithDone(exec, (err, res) => {
914
- executeTreeWithDone(exec, (e) => {
915
- if (e)
916
- done(e);
917
- else if (err) {
918
- let sc = {};
919
- if (exception)
920
- sc[exception] = err;
921
- executeTreeWithDone(exec, done, ticks, context, catchBody, [new Scope(scope)], inLoopOrSwitch);
922
- }
923
- else {
924
- done(undefined, res);
925
- }
926
- }, ticks, context, finallyBody, [new Scope(scope, {})]);
927
- }, ticks, context, a, [new Scope(scope)], inLoopOrSwitch);
928
- },
929
- 'void': (exec, done, ticks, a) => { done(); },
930
- 'new': (exec, done, ticks, a, b, obj, context) => {
931
- if (!context.ctx.globalsWhitelist.has(a) && !sandboxedFunctions.has(a)) {
932
- throw new SandboxError(`Object construction not allowed: ${a.constructor.name}`);
933
- }
934
- done(undefined, new a(...b));
935
- },
936
- 'throw': (exec, done, ticks, a, b) => { done(b); },
937
- 'multi': (exec, done, ticks, a) => done(undefined, a.pop())
938
- };
939
- export let ops = new Map();
940
- for (let op in ops2) {
941
- ops.set(op, ops2[op]);
942
- }
908
+ }, ticks, context, finallyBody, [new Scope(scope, {})]);
909
+ }, ticks, context, a, [new Scope(scope)], inLoopOrSwitch);
910
+ });
911
+ addOps(87 /* LispType.Void */, (exec, done, ticks, a) => { done(); });
912
+ addOps(45 /* LispType.New */, (exec, done, ticks, a, b, obj, context) => {
913
+ if (!context.ctx.globalsWhitelist.has(a) && !sandboxedFunctions.has(a)) {
914
+ throw new SandboxError(`Object construction not allowed: ${a.constructor.name}`);
915
+ }
916
+ done(undefined, new a(...b));
917
+ });
918
+ addOps(46 /* LispType.Throw */, (exec, done, ticks, a, b) => { done(b); });
919
+ addOps(43 /* LispType.Expression */, (exec, done, ticks, a) => done(undefined, a.pop()));
920
+ addOps(0 /* LispType.None */, (exec, done, ticks, a) => done());
943
921
  function valueOrProp(a, context) {
944
922
  if (a instanceof Prop)
945
923
  return a.get(context);
@@ -970,6 +948,10 @@ function _execManySync(ticks, tree, done, scope, context, inLoopOrSwitch) {
970
948
  done(undefined, res);
971
949
  return;
972
950
  }
951
+ if (isLisp(tree[i]) && tree[i][0] === 8 /* LispType.Return */) {
952
+ done(undefined, new ExecReturn(context.ctx.auditReport, res, true));
953
+ return;
954
+ }
973
955
  ret.push(res);
974
956
  }
975
957
  done(undefined, ret);
@@ -990,6 +972,10 @@ async function _execManyAsync(ticks, tree, done, scope, context, inLoopOrSwitch)
990
972
  done(undefined, res);
991
973
  return;
992
974
  }
975
+ if (isLisp(tree[i]) && tree[i][0] === 8 /* LispType.Return */) {
976
+ done(undefined, new ExecReturn(context.ctx.auditReport, res, true));
977
+ return;
978
+ }
993
979
  ret.push(res);
994
980
  }
995
981
  done(undefined, ret);
@@ -1036,11 +1022,12 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
1036
1022
  });
1037
1023
  if (_execNoneRecurse(ticks, tree, scope, context, done, true, inLoopOrSwitch)) {
1038
1024
  }
1039
- else if (tree instanceof Lisp) {
1025
+ else if (isLisp(tree)) {
1026
+ let op = tree[0];
1040
1027
  let obj;
1041
1028
  try {
1042
1029
  let ad;
1043
- obj = (ad = asyncDone((d) => execAsync(ticks, tree.a, scope, context, d, inLoopOrSwitch))).isInstant === true ? ad.instant : (await ad.p).result;
1030
+ obj = (ad = asyncDone((d) => execAsync(ticks, tree[1], scope, context, d, inLoopOrSwitch))).isInstant === true ? ad.instant : (await ad.p).result;
1044
1031
  }
1045
1032
  catch (e) {
1046
1033
  done(e);
@@ -1054,16 +1041,15 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
1054
1041
  done(e);
1055
1042
  return;
1056
1043
  }
1057
- let op = tree.op;
1058
- if (op === '?prop' || op === '?call') {
1044
+ if (op === 20 /* LispType.PropOptional */ || op === 21 /* LispType.CallOptional */) {
1059
1045
  if (a === undefined || a === null) {
1060
1046
  done(undefined, optional);
1061
1047
  return;
1062
1048
  }
1063
- op = op.slice(1);
1049
+ op = op === 20 /* LispType.PropOptional */ ? 1 /* LispType.Prop */ : 5 /* LispType.Call */;
1064
1050
  }
1065
1051
  if (a === optional) {
1066
- if (op === 'prop' || op === 'call') {
1052
+ if (op === 1 /* LispType.Prop */ || op === 5 /* LispType.Call */) {
1067
1053
  done(undefined, a);
1068
1054
  return;
1069
1055
  }
@@ -1074,7 +1060,7 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
1074
1060
  let bobj;
1075
1061
  try {
1076
1062
  let ad;
1077
- bobj = (ad = asyncDone((d) => execAsync(ticks, tree.b, scope, context, d, inLoopOrSwitch))).isInstant === true ? ad.instant : (await ad.p).result;
1063
+ bobj = (ad = asyncDone((d) => execAsync(ticks, tree[2], scope, context, d, inLoopOrSwitch))).isInstant === true ? ad.instant : (await ad.p).result;
1078
1064
  }
1079
1065
  catch (e) {
1080
1066
  done(e);
@@ -1108,10 +1094,11 @@ export async function execAsync(ticks, tree, scope, context, doneOriginal, inLoo
1108
1094
  export function execSync(ticks, tree, scope, context, done, inLoopOrSwitch) {
1109
1095
  if (_execNoneRecurse(ticks, tree, scope, context, done, false, inLoopOrSwitch)) {
1110
1096
  }
1111
- else if (tree instanceof Lisp) {
1097
+ else if (isLisp(tree)) {
1098
+ let op = tree[0];
1112
1099
  let obj;
1113
1100
  try {
1114
- obj = syncDone((d) => execSync(ticks, tree.a, scope, context, d, inLoopOrSwitch)).result;
1101
+ obj = syncDone((d) => execSync(ticks, tree[1], scope, context, d, inLoopOrSwitch)).result;
1115
1102
  }
1116
1103
  catch (e) {
1117
1104
  done(e);
@@ -1125,16 +1112,15 @@ export function execSync(ticks, tree, scope, context, done, inLoopOrSwitch) {
1125
1112
  done(e);
1126
1113
  return;
1127
1114
  }
1128
- let op = tree.op;
1129
- if (op === '?prop' || op === '?call') {
1115
+ if (op === 20 /* LispType.PropOptional */ || op === 21 /* LispType.CallOptional */) {
1130
1116
  if (a === undefined || a === null) {
1131
1117
  done(undefined, optional);
1132
1118
  return;
1133
1119
  }
1134
- op = op.slice(1);
1120
+ op = op === 20 /* LispType.PropOptional */ ? 1 /* LispType.Prop */ : 5 /* LispType.Call */;
1135
1121
  }
1136
1122
  if (a === optional) {
1137
- if (op === 'prop' || op === 'call') {
1123
+ if (op === 1 /* LispType.Prop */ || op === 5 /* LispType.Call */) {
1138
1124
  done(undefined, a);
1139
1125
  return;
1140
1126
  }
@@ -1144,7 +1130,7 @@ export function execSync(ticks, tree, scope, context, done, inLoopOrSwitch) {
1144
1130
  }
1145
1131
  let bobj;
1146
1132
  try {
1147
- bobj = syncDone((d) => execSync(ticks, tree.b, scope, context, d, inLoopOrSwitch)).result;
1133
+ bobj = syncDone((d) => execSync(ticks, tree[2], scope, context, d, inLoopOrSwitch)).result;
1148
1134
  }
1149
1135
  catch (e) {
1150
1136
  done(e);
@@ -1174,9 +1160,18 @@ export function execSync(ticks, tree, scope, context, done, inLoopOrSwitch) {
1174
1160
  }
1175
1161
  }
1176
1162
  }
1177
- const unexecTypes = new Set(['arrowFunc', 'function', 'inlineFunction', 'loop', 'try', 'switch', 'if', '?', 'typeof']);
1163
+ const unexecTypes = new Set([
1164
+ 11 /* LispType.ArrowFunction */,
1165
+ 37 /* LispType.Function */,
1166
+ 10 /* LispType.InlineFunction */,
1167
+ 38 /* LispType.Loop */,
1168
+ 39 /* LispType.Try */,
1169
+ 40 /* LispType.Switch */,
1170
+ 14 /* LispType.IfCase */,
1171
+ 16 /* LispType.InlineIfCase */,
1172
+ 60 /* LispType.Typeof */
1173
+ ]);
1178
1174
  function _execNoneRecurse(ticks, tree, scope, context, done, isAsync, inLoopOrSwitch) {
1179
- var _a;
1180
1175
  const exec = isAsync ? execAsync : execSync;
1181
1176
  if (context.ctx.options.executionQuota <= ticks.ticks) {
1182
1177
  if (typeof context.ctx.options.onExecutionQuotaReached === 'function' && context.ctx.options.onExecutionQuotaReached(ticks, scope, context, tree)) {
@@ -1199,18 +1194,26 @@ function _execNoneRecurse(ticks, tree, scope, context, done, isAsync, inLoopOrSw
1199
1194
  else if (tree === optional) {
1200
1195
  done();
1201
1196
  }
1202
- else if (Array.isArray(tree) && tree.lisp === lispArrayKey) {
1203
- execMany(ticks, exec, tree, done, scope, context, inLoopOrSwitch);
1197
+ else if (Array.isArray(tree) && !isLisp(tree)) {
1198
+ if (tree[0] === 0 /* LispType.None */) {
1199
+ done();
1200
+ }
1201
+ else {
1202
+ execMany(ticks, exec, tree, done, scope, context, inLoopOrSwitch);
1203
+ }
1204
1204
  }
1205
- else if (!(tree instanceof Lisp)) {
1205
+ else if (!isLisp(tree)) {
1206
1206
  done(undefined, tree);
1207
1207
  }
1208
- else if (tree.op === 'await') {
1208
+ else if (tree[0] === 42 /* LispType.Block */) {
1209
+ execMany(ticks, exec, tree[1], done, scope, context, inLoopOrSwitch);
1210
+ }
1211
+ else if (tree[0] === 44 /* LispType.Await */) {
1209
1212
  if (!isAsync) {
1210
1213
  done(new SandboxError("Illegal use of 'await', must be inside async function"));
1211
1214
  }
1212
- else if ((_a = context.ctx.prototypeWhitelist) === null || _a === void 0 ? void 0 : _a.has(Promise.prototype)) {
1213
- execAsync(ticks, tree.a, scope, context, async (e, r) => {
1215
+ else if (context.ctx.prototypeWhitelist?.has(Promise.prototype)) {
1216
+ execAsync(ticks, tree[1], scope, context, async (e, r) => {
1214
1217
  if (e)
1215
1218
  done(e);
1216
1219
  else
@@ -1226,9 +1229,9 @@ function _execNoneRecurse(ticks, tree, scope, context, done, isAsync, inLoopOrSw
1226
1229
  done(new SandboxError('Async/await is not permitted'));
1227
1230
  }
1228
1231
  }
1229
- else if (unexecTypes.has(tree.op)) {
1232
+ else if (unexecTypes.has(tree[0])) {
1230
1233
  try {
1231
- ops.get(tree.op)(exec, done, ticks, tree.a, tree.b, tree, context, scope, undefined, inLoopOrSwitch);
1234
+ ops.get(tree[0])(exec, done, ticks, tree[1], tree[2], tree, context, scope, undefined, inLoopOrSwitch);
1232
1235
  }
1233
1236
  catch (err) {
1234
1237
  done(err);
@@ -1304,7 +1307,7 @@ function _executeWithDoneSync(done, ticks, context, executionTree, scope, inLoop
1304
1307
  done(undefined, res);
1305
1308
  return;
1306
1309
  }
1307
- if (current instanceof Lisp && current.op === 'return') {
1310
+ if (isLisp(current) && current[0] === 8 /* LispType.Return */) {
1308
1311
  done(undefined, new ExecReturn(context.ctx.auditReport, res, true));
1309
1312
  return;
1310
1313
  }
@@ -1336,7 +1339,7 @@ async function _executeWithDoneAsync(done, ticks, context, executionTree, scope,
1336
1339
  done(undefined, res);
1337
1340
  return;
1338
1341
  }
1339
- if (current instanceof Lisp && current.op === 'return') {
1342
+ if (isLisp(current) && current[0] === 8 /* LispType.Return */) {
1340
1343
  done(undefined, new ExecReturn(context.ctx.auditReport, res, true));
1341
1344
  return;
1342
1345
  }