@nyariv/sandboxjs 0.8.22 → 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.
Files changed (50) hide show
  1. package/.eslintignore +6 -0
  2. package/.eslintrc.js +22 -0
  3. package/.prettierrc +4 -0
  4. package/.vscode/settings.json +4 -0
  5. package/build/Sandbox.d.ts +11 -78
  6. package/build/Sandbox.js +21 -216
  7. package/build/SandboxExec.d.ts +25 -0
  8. package/build/SandboxExec.js +169 -0
  9. package/build/eval.d.ts +18 -0
  10. package/build/eval.js +43 -0
  11. package/build/executor.d.ts +56 -95
  12. package/build/executor.js +739 -815
  13. package/build/parser.d.ts +112 -74
  14. package/build/parser.js +504 -542
  15. package/build/unraw.js +13 -16
  16. package/build/utils.d.ts +242 -0
  17. package/build/utils.js +276 -0
  18. package/dist/Sandbox.d.ts +11 -78
  19. package/dist/Sandbox.js +106 -1
  20. package/dist/Sandbox.js.map +1 -1
  21. package/dist/Sandbox.min.js +1 -1
  22. package/dist/Sandbox.min.js.map +1 -1
  23. package/dist/SandboxExec.d.ts +25 -0
  24. package/dist/SandboxExec.js +173 -0
  25. package/dist/SandboxExec.js.map +1 -0
  26. package/dist/SandboxExec.min.js +2 -0
  27. package/dist/SandboxExec.min.js.map +1 -0
  28. package/dist/eval.d.ts +18 -0
  29. package/dist/executor.d.ts +56 -95
  30. package/dist/executor.js +1270 -0
  31. package/dist/executor.js.map +1 -0
  32. package/dist/node/Sandbox.d.ts +11 -78
  33. package/dist/node/Sandbox.js +37 -3091
  34. package/dist/node/SandboxExec.d.ts +25 -0
  35. package/dist/node/SandboxExec.js +176 -0
  36. package/dist/node/eval.d.ts +18 -0
  37. package/dist/node/executor.d.ts +56 -95
  38. package/dist/node/executor.js +1289 -0
  39. package/dist/node/parser.d.ts +112 -74
  40. package/dist/node/parser.js +1528 -0
  41. package/dist/node/utils.d.ts +242 -0
  42. package/dist/node/utils.js +290 -0
  43. package/dist/parser.d.ts +112 -74
  44. package/dist/parser.js +1514 -0
  45. package/dist/parser.js.map +1 -0
  46. package/dist/utils.d.ts +242 -0
  47. package/dist/utils.js +279 -0
  48. package/dist/utils.js.map +1 -0
  49. package/package.json +22 -14
  50. package/.github/workflows/npm-publish.yml +0 -34
package/.eslintignore ADDED
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ dist
3
+ build
4
+ test
5
+ .*
6
+ *.json
package/.eslintrc.js ADDED
@@ -0,0 +1,22 @@
1
+ module.exports = {
2
+ env: {
3
+ browser: true,
4
+ es2021: true,
5
+ },
6
+ extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
7
+ overrides: [],
8
+ parser: '@typescript-eslint/parser',
9
+ parserOptions: {
10
+ ecmaVersion: 'latest',
11
+ sourceType: 'module',
12
+ },
13
+ plugins: ['@typescript-eslint'],
14
+ rules: {
15
+ 'no-prototype-builtins': 0,
16
+ '@typescript-eslint/no-explicit-any': 0,
17
+ '@typescript-eslint/ban-types': 0,
18
+ '@typescript-eslint/no-non-null-assertion': 0,
19
+ 'no-cond-assign': 0,
20
+ 'no-fallthrough': 0,
21
+ },
22
+ };
package/.prettierrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "printWidth": 100,
3
+ "singleQuote": true
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
3
+ "editor.formatOnSave": true
4
+ }
@@ -1,90 +1,23 @@
1
- import { IGlobals, replacementCallback, IAuditReport, Change, ExecReturn, executeTree, executeTreeAsync, ops, assignCheck, execMany, execAsync, execSync, asyncDone, Scope, IScope, FunctionScope, LocalScope, syncDone } from "./executor.js";
2
- import { IExecutionTree, expectTypes, setLispType, LispItem, LispArray, IConstants } from "./parser.js";
3
- export { expectTypes, setLispType, ops as executionOps, assignCheck, execMany, execAsync, execSync, asyncDone, syncDone, executeTree, executeTreeAsync, FunctionScope, LocalScope, };
4
- export interface IOptions {
5
- audit?: boolean;
6
- forbidFunctionCalls?: boolean;
7
- forbidFunctionCreation?: boolean;
8
- prototypeReplacements?: Map<new () => any, replacementCallback>;
9
- prototypeWhitelist?: Map<any, Set<string>>;
10
- globals: IGlobals;
11
- executionQuota?: bigint;
12
- onExecutionQuotaReached?: (ticks: Ticks, scope: Scope, context: IExecutionTree, tree: LispItem) => boolean | void;
13
- }
14
- export interface IContext {
15
- sandbox: Sandbox;
16
- globalScope: Scope;
17
- sandboxGlobal: SandboxGlobal;
18
- globalsWhitelist?: Set<any>;
19
- prototypeWhitelist?: Map<any, Set<string>>;
20
- options: IOptions;
21
- auditReport?: IAuditReport;
22
- }
23
- export interface Ticks {
24
- ticks: bigint;
25
- }
26
- export interface IExecContext extends IExecutionTree {
27
- ctx: IContext;
28
- getSubscriptions: Set<(obj: object, name: string) => void>;
29
- setSubscriptions: WeakMap<object, Map<string, Set<(modification: Change) => void>>>;
30
- changeSubscriptions: WeakMap<object, Set<(modification: Change) => void>>;
31
- setSubscriptionsGlobal: WeakMap<object, Map<string, Set<(modification: Change) => void>>>;
32
- changeSubscriptionsGlobal: WeakMap<object, Set<(modification: Change) => void>>;
33
- registerSandboxFunction: (fn: (...args: any[]) => any) => void;
34
- evals: Map<any, any>;
35
- }
36
- export declare class SandboxGlobal {
37
- constructor(globals: IGlobals);
38
- }
39
- export declare class ExecContext implements IExecContext {
40
- ctx: IContext;
41
- constants: IConstants;
42
- tree: LispArray;
43
- getSubscriptions: Set<(obj: object, name: string) => void>;
44
- setSubscriptions: WeakMap<object, Map<string, Set<(modification: Change) => void>>>;
45
- changeSubscriptions: WeakMap<object, Set<(modification: Change) => void>>;
46
- setSubscriptionsGlobal: WeakMap<object, Map<string, Set<(modification: Change) => void>>>;
47
- changeSubscriptionsGlobal: WeakMap<object, Set<(modification: Change) => void>>;
48
- evals: Map<any, any>;
49
- registerSandboxFunction: (fn: (...args: any[]) => any) => void;
50
- constructor(ctx: IContext, constants: IConstants, tree: LispArray, getSubscriptions: Set<(obj: object, name: string) => void>, setSubscriptions: WeakMap<object, Map<string, Set<(modification: Change) => void>>>, changeSubscriptions: WeakMap<object, Set<(modification: Change) => void>>, setSubscriptionsGlobal: WeakMap<object, Map<string, Set<(modification: Change) => void>>>, changeSubscriptionsGlobal: WeakMap<object, Set<(modification: Change) => void>>, evals: Map<any, any>, registerSandboxFunction: (fn: (...args: any[]) => any) => void);
51
- }
52
- export default class Sandbox {
53
- context: IContext;
54
- setSubscriptions: WeakMap<object, Map<string, Set<(modification: Change) => void>>>;
55
- changeSubscriptions: WeakMap<object, Set<(modification: Change) => void>>;
56
- sandboxFunctions: WeakMap<(...args: any[]) => any, IExecContext>;
57
- constructor(options?: IOptions);
58
- static get SAFE_GLOBALS(): IGlobals;
59
- static get SAFE_PROTOTYPES(): Map<any, Set<string>>;
60
- subscribeGet(callback: (obj: object, name: string) => void, context: IExecContext): {
61
- unsubscribe: () => void;
62
- };
63
- subscribeSet(obj: object, name: string, callback: (modification: Change) => void, context: Sandbox | IExecContext): {
64
- unsubscribe: () => void;
65
- };
66
- subscribeSetGlobal(obj: object, name: string, callback: (modification: Change) => void): {
67
- unsubscribe: () => void;
68
- };
69
- static audit<T>(code: string, scopes?: (IScope)[]): ExecReturn<T>;
70
- static parse(code: string): IExecutionTree;
71
- createContext(context: IContext, executionTree: IExecutionTree): any;
72
- getContext(fn: (...args: any[]) => any): IExecContext;
73
- executeTree<T>(context: IExecContext, scopes?: (IScope)[]): ExecReturn<T>;
74
- executeTreeAsync<T>(context: IExecContext, scopes?: (IScope)[]): Promise<ExecReturn<T>>;
75
- compile<T>(code: string, optimize?: boolean): (...scopes: (IScope)[]) => {
1
+ import { IExecContext, IOptionParams, IScope } from './utils.js';
2
+ import { ExecReturn } from './executor.js';
3
+ import SandboxExec from './SandboxExec.js';
4
+ export default class Sandbox extends SandboxExec {
5
+ constructor(options?: IOptionParams);
6
+ static audit<T>(code: string, scopes?: IScope[]): ExecReturn<T>;
7
+ static parse(code: string): import("./parser.js").IExecutionTree;
8
+ compile<T>(code: string, optimize?: boolean): (...scopes: IScope[]) => {
76
9
  context: IExecContext;
77
10
  run: () => T;
78
11
  };
79
- compileAsync<T>(code: string, optimize?: boolean): (...scopes: (IScope)[]) => {
12
+ compileAsync<T>(code: string, optimize?: boolean): (...scopes: IScope[]) => {
80
13
  context: IExecContext;
81
14
  run: () => Promise<T>;
82
15
  };
83
- compileExpression<T>(code: string, optimize?: boolean): (...scopes: (IScope)[]) => {
16
+ compileExpression<T>(code: string, optimize?: boolean): (...scopes: IScope[]) => {
84
17
  context: IExecContext;
85
18
  run: () => T;
86
19
  };
87
- compileExpressionAsync<T>(code: string, optimize?: boolean): (...scopes: (IScope)[]) => {
20
+ compileExpressionAsync<T>(code: string, optimize?: boolean): (...scopes: IScope[]) => {
88
21
  context: IExecContext;
89
22
  run: () => Promise<T>;
90
23
  };
package/build/Sandbox.js CHANGED
@@ -1,246 +1,48 @@
1
- import { sandboxFunction, sandboxedEval, sandboxedSetTimeout, sandboxedSetInterval, executeTree, executeTreeAsync, ops, assignCheck, execMany, execAsync, execSync, asyncDone, Scope, FunctionScope, LocalScope, syncDone } from "./executor.js";
2
- import { parse, expectTypes, setLispType } from "./parser.js";
3
- export { expectTypes, setLispType, ops as executionOps, assignCheck, execMany, execAsync, execSync, asyncDone, syncDone, executeTree, executeTreeAsync, FunctionScope, LocalScope, };
4
- export class SandboxGlobal {
5
- constructor(globals) {
6
- if (globals === globalThis)
7
- return globalThis;
8
- for (let i in globals) {
9
- this[i] = globals[i];
10
- }
11
- }
12
- }
13
- export class ExecContext {
14
- constructor(ctx, constants, tree, getSubscriptions, setSubscriptions, changeSubscriptions, setSubscriptionsGlobal, changeSubscriptionsGlobal, evals, registerSandboxFunction) {
15
- this.ctx = ctx;
16
- this.constants = constants;
17
- this.tree = tree;
18
- this.getSubscriptions = getSubscriptions;
19
- this.setSubscriptions = setSubscriptions;
20
- this.changeSubscriptions = changeSubscriptions;
21
- this.setSubscriptionsGlobal = setSubscriptionsGlobal;
22
- this.changeSubscriptionsGlobal = changeSubscriptionsGlobal;
23
- this.evals = evals;
24
- this.registerSandboxFunction = registerSandboxFunction;
25
- }
26
- }
27
- function subscribeSet(obj, name, callback, context) {
28
- const names = context.setSubscriptions.get(obj) || new Map();
29
- context.setSubscriptions.set(obj, names);
30
- const callbacks = names.get(name) || new Set();
31
- names.set(name, callbacks);
32
- callbacks.add(callback);
33
- let changeCbs;
34
- if (obj && obj[name] && typeof obj[name] === "object") {
35
- changeCbs = context.changeSubscriptions.get(obj[name]) || new Set();
36
- changeCbs.add(callback);
37
- context.changeSubscriptions.set(obj[name], changeCbs);
38
- }
39
- return {
40
- unsubscribe: () => {
41
- callbacks.delete(callback);
42
- changeCbs === null || changeCbs === void 0 ? void 0 : changeCbs.delete(callback);
43
- }
44
- };
45
- }
46
- export default class Sandbox {
1
+ import { createExecContext } from './utils.js';
2
+ import { createEvalContext } from './eval.js';
3
+ import parse from './parser.js';
4
+ import SandboxExec from './SandboxExec.js';
5
+ export default class Sandbox extends SandboxExec {
47
6
  constructor(options) {
48
- this.setSubscriptions = new WeakMap();
49
- this.changeSubscriptions = new WeakMap();
50
- this.sandboxFunctions = new WeakMap();
51
- options = Object.assign({
52
- audit: false,
53
- forbidFunctionCalls: false,
54
- forbidFunctionCreation: false,
55
- globals: Sandbox.SAFE_GLOBALS,
56
- prototypeWhitelist: Sandbox.SAFE_PROTOTYPES,
57
- prototypeReplacements: new Map(),
58
- }, options || {});
59
- const sandboxGlobal = new SandboxGlobal(options.globals);
60
- this.context = {
61
- sandbox: this,
62
- globalsWhitelist: new Set(Object.values(options.globals)),
63
- prototypeWhitelist: new Map([...options.prototypeWhitelist].map((a) => [a[0].prototype, a[1]])),
64
- options,
65
- globalScope: new Scope(null, options.globals, sandboxGlobal),
66
- sandboxGlobal
67
- };
68
- this.context.prototypeWhitelist.set(Object.getPrototypeOf([][Symbol.iterator]()), new Set());
69
- }
70
- static get SAFE_GLOBALS() {
71
- return {
72
- Function,
73
- console: {
74
- debug: console.debug,
75
- error: console.error,
76
- info: console.info,
77
- log: console.log,
78
- table: console.table,
79
- warn: console.warn
80
- },
81
- isFinite,
82
- isNaN,
83
- parseFloat,
84
- parseInt,
85
- decodeURI,
86
- decodeURIComponent,
87
- encodeURI,
88
- encodeURIComponent,
89
- escape,
90
- unescape,
91
- Boolean,
92
- Number,
93
- BigInt,
94
- String,
95
- Object,
96
- Array,
97
- Symbol,
98
- Error,
99
- EvalError,
100
- RangeError,
101
- ReferenceError,
102
- SyntaxError,
103
- TypeError,
104
- URIError,
105
- Int8Array,
106
- Uint8Array,
107
- Uint8ClampedArray,
108
- Int16Array,
109
- Uint16Array,
110
- Int32Array,
111
- Uint32Array,
112
- Float32Array,
113
- Float64Array,
114
- Map,
115
- Set,
116
- WeakMap,
117
- WeakSet,
118
- Promise,
119
- Intl,
120
- JSON,
121
- Math,
122
- Date,
123
- RegExp
124
- };
125
- }
126
- static get SAFE_PROTOTYPES() {
127
- let protos = [
128
- SandboxGlobal,
129
- Function,
130
- Boolean,
131
- Number,
132
- BigInt,
133
- String,
134
- Date,
135
- Error,
136
- Array,
137
- Int8Array,
138
- Uint8Array,
139
- Uint8ClampedArray,
140
- Int16Array,
141
- Uint16Array,
142
- Int32Array,
143
- Uint32Array,
144
- Float32Array,
145
- Float64Array,
146
- Map,
147
- Set,
148
- WeakMap,
149
- WeakSet,
150
- Promise,
151
- Symbol,
152
- Date,
153
- RegExp
154
- ];
155
- let map = new Map();
156
- protos.forEach((proto) => {
157
- map.set(proto, new Set());
158
- });
159
- map.set(Object, new Set([
160
- 'entries',
161
- 'fromEntries',
162
- 'getOwnPropertyNames',
163
- 'is',
164
- 'keys',
165
- 'hasOwnProperty',
166
- 'isPrototypeOf',
167
- 'propertyIsEnumerable',
168
- 'toLocaleString',
169
- 'toString',
170
- 'valueOf',
171
- 'values'
172
- ]));
173
- return map;
174
- }
175
- subscribeGet(callback, context) {
176
- context.getSubscriptions.add(callback);
177
- return { unsubscribe: () => context.getSubscriptions.delete(callback) };
178
- }
179
- subscribeSet(obj, name, callback, context) {
180
- return subscribeSet(obj, name, callback, context);
181
- }
182
- subscribeSetGlobal(obj, name, callback) {
183
- return subscribeSet(obj, name, callback, this);
7
+ super(options, createEvalContext());
184
8
  }
185
9
  static audit(code, scopes = []) {
186
10
  const globals = {};
187
- for (let i of Object.getOwnPropertyNames(globalThis)) {
11
+ for (const i of Object.getOwnPropertyNames(globalThis)) {
188
12
  globals[i] = globalThis[i];
189
13
  }
190
- const sandbox = new Sandbox({
14
+ const sandbox = new SandboxExec({
191
15
  globals,
192
16
  audit: true,
193
17
  });
194
- return sandbox.executeTree(sandbox.createContext(sandbox.context, parse(code)), scopes);
18
+ return sandbox.executeTree(createExecContext(sandbox, parse(code, true), createEvalContext()), scopes);
195
19
  }
196
20
  static parse(code) {
197
21
  return parse(code);
198
22
  }
199
- createContext(context, executionTree) {
200
- const evals = new Map();
201
- const execContext = new ExecContext(context, executionTree.constants, executionTree.tree, new Set(), new WeakMap(), new WeakMap(), this.setSubscriptions, this.changeSubscriptions, evals, (fn) => this.sandboxFunctions.set(fn, execContext));
202
- const func = sandboxFunction(execContext);
203
- evals.set(Function, func);
204
- evals.set(eval, sandboxedEval(func));
205
- evals.set(setTimeout, sandboxedSetTimeout(func));
206
- evals.set(setInterval, sandboxedSetInterval(func));
207
- return execContext;
208
- }
209
- getContext(fn) {
210
- return this.sandboxFunctions.get(fn);
211
- }
212
- executeTree(context, scopes = []) {
213
- return executeTree({
214
- ticks: BigInt(0),
215
- }, context, context.tree, scopes);
216
- }
217
- executeTreeAsync(context, scopes = []) {
218
- return executeTreeAsync({
219
- ticks: BigInt(0),
220
- }, context, context.tree, scopes);
221
- }
222
23
  compile(code, optimize = false) {
223
24
  const parsed = parse(code, optimize);
224
25
  const exec = (...scopes) => {
225
- const context = this.createContext(this.context, parsed);
26
+ const context = createExecContext(this, parsed, this.evalContext);
226
27
  return { context, run: () => this.executeTree(context, [...scopes]).result };
227
28
  };
228
29
  return exec;
229
30
  }
230
- ;
231
31
  compileAsync(code, optimize = false) {
232
32
  const parsed = parse(code, optimize);
233
33
  const exec = (...scopes) => {
234
- const context = this.createContext(this.context, parsed);
235
- return { context, run: () => this.executeTreeAsync(context, [...scopes]).then((ret) => ret.result) };
34
+ const context = createExecContext(this, parsed, this.evalContext);
35
+ return {
36
+ context,
37
+ run: () => this.executeTreeAsync(context, [...scopes]).then((ret) => ret.result),
38
+ };
236
39
  };
237
40
  return exec;
238
41
  }
239
- ;
240
42
  compileExpression(code, optimize = false) {
241
43
  const parsed = parse(code, optimize, true);
242
44
  const exec = (...scopes) => {
243
- const context = this.createContext(this.context, parsed);
45
+ const context = createExecContext(this, parsed, this.evalContext);
244
46
  return { context, run: () => this.executeTree(context, [...scopes]).result };
245
47
  };
246
48
  return exec;
@@ -248,8 +50,11 @@ export default class Sandbox {
248
50
  compileExpressionAsync(code, optimize = false) {
249
51
  const parsed = parse(code, optimize, true);
250
52
  const exec = (...scopes) => {
251
- const context = this.createContext(this.context, parsed);
252
- return { context, run: () => this.executeTreeAsync(context, [...scopes]).then((ret) => ret.result) };
53
+ const context = createExecContext(this, parsed, this.evalContext);
54
+ return {
55
+ context,
56
+ run: () => this.executeTreeAsync(context, [...scopes]).then((ret) => ret.result),
57
+ };
253
58
  };
254
59
  return exec;
255
60
  }
@@ -0,0 +1,25 @@
1
+ import { IEvalContext } from './eval.js';
2
+ import { Change, ExecReturn } from './executor.js';
3
+ import { IContext, IExecContext, IGlobals, IOptionParams, IScope, SubscriptionSubject } from './utils.js';
4
+ export default class SandboxExec {
5
+ evalContext?: IEvalContext | undefined;
6
+ context: IContext;
7
+ setSubscriptions: WeakMap<SubscriptionSubject, Map<string, Set<(modification: Change) => void>>>;
8
+ changeSubscriptions: WeakMap<SubscriptionSubject, Set<(modification: Change) => void>>;
9
+ sandboxFunctions: WeakMap<(...args: any[]) => any, IExecContext>;
10
+ constructor(options?: IOptionParams, evalContext?: IEvalContext | undefined);
11
+ static get SAFE_GLOBALS(): IGlobals;
12
+ static get SAFE_PROTOTYPES(): Map<any, Set<string>>;
13
+ subscribeGet(callback: (obj: SubscriptionSubject, name: string) => void, context: IExecContext): {
14
+ unsubscribe: () => void;
15
+ };
16
+ subscribeSet(obj: object, name: string, callback: (modification: Change) => void, context: SandboxExec | IExecContext): {
17
+ unsubscribe: () => void;
18
+ };
19
+ subscribeSetGlobal(obj: SubscriptionSubject, name: string, callback: (modification: Change) => void): {
20
+ unsubscribe: () => void;
21
+ };
22
+ getContext(fn: (...args: any[]) => any): IExecContext | undefined;
23
+ executeTree<T>(context: IExecContext, scopes?: IScope[]): ExecReturn<T>;
24
+ executeTreeAsync<T>(context: IExecContext, scopes?: IScope[]): Promise<ExecReturn<T>>;
25
+ }
@@ -0,0 +1,169 @@
1
+ import { executeTree, executeTreeAsync } from './executor.js';
2
+ import { createContext, SandboxGlobal, } from './utils.js';
3
+ function subscribeSet(obj, name, callback, context) {
4
+ if (!(obj instanceof Object))
5
+ throw new Error('Invalid subscription object, got ' + (typeof obj === 'object' ? 'null' : typeof obj));
6
+ const names = context.setSubscriptions.get(obj) || new Map();
7
+ context.setSubscriptions.set(obj, names);
8
+ const callbacks = names.get(name) || new Set();
9
+ names.set(name, callbacks);
10
+ callbacks.add(callback);
11
+ let changeCbs;
12
+ const val = obj[name];
13
+ if (val instanceof Object) {
14
+ changeCbs = context.changeSubscriptions.get(val) || new Set();
15
+ changeCbs.add(callback);
16
+ context.changeSubscriptions.set(val, changeCbs);
17
+ }
18
+ return {
19
+ unsubscribe: () => {
20
+ callbacks.delete(callback);
21
+ changeCbs?.delete(callback);
22
+ },
23
+ };
24
+ }
25
+ export default class SandboxExec {
26
+ constructor(options, evalContext) {
27
+ this.evalContext = evalContext;
28
+ this.setSubscriptions = new WeakMap();
29
+ this.changeSubscriptions = new WeakMap();
30
+ this.sandboxFunctions = new WeakMap();
31
+ const opt = Object.assign({
32
+ audit: false,
33
+ forbidFunctionCalls: false,
34
+ forbidFunctionCreation: false,
35
+ globals: SandboxExec.SAFE_GLOBALS,
36
+ prototypeWhitelist: SandboxExec.SAFE_PROTOTYPES,
37
+ prototypeReplacements: new Map(),
38
+ }, options || {});
39
+ this.context = createContext(this, opt);
40
+ }
41
+ static get SAFE_GLOBALS() {
42
+ return {
43
+ Function,
44
+ console: {
45
+ debug: console.debug,
46
+ error: console.error,
47
+ info: console.info,
48
+ log: console.log,
49
+ table: console.table,
50
+ warn: console.warn,
51
+ },
52
+ isFinite,
53
+ isNaN,
54
+ parseFloat,
55
+ parseInt,
56
+ decodeURI,
57
+ decodeURIComponent,
58
+ encodeURI,
59
+ encodeURIComponent,
60
+ escape,
61
+ unescape,
62
+ Boolean,
63
+ Number,
64
+ BigInt,
65
+ String,
66
+ Object,
67
+ Array,
68
+ Symbol,
69
+ Error,
70
+ EvalError,
71
+ RangeError,
72
+ ReferenceError,
73
+ SyntaxError,
74
+ TypeError,
75
+ URIError,
76
+ Int8Array,
77
+ Uint8Array,
78
+ Uint8ClampedArray,
79
+ Int16Array,
80
+ Uint16Array,
81
+ Int32Array,
82
+ Uint32Array,
83
+ Float32Array,
84
+ Float64Array,
85
+ Map,
86
+ Set,
87
+ WeakMap,
88
+ WeakSet,
89
+ Promise,
90
+ Intl,
91
+ JSON,
92
+ Math,
93
+ Date,
94
+ RegExp,
95
+ };
96
+ }
97
+ static get SAFE_PROTOTYPES() {
98
+ const protos = [
99
+ SandboxGlobal,
100
+ Function,
101
+ Boolean,
102
+ Number,
103
+ BigInt,
104
+ String,
105
+ Date,
106
+ Error,
107
+ Array,
108
+ Int8Array,
109
+ Uint8Array,
110
+ Uint8ClampedArray,
111
+ Int16Array,
112
+ Uint16Array,
113
+ Int32Array,
114
+ Uint32Array,
115
+ Float32Array,
116
+ Float64Array,
117
+ Map,
118
+ Set,
119
+ WeakMap,
120
+ WeakSet,
121
+ Promise,
122
+ Symbol,
123
+ Date,
124
+ RegExp,
125
+ ];
126
+ const map = new Map();
127
+ protos.forEach((proto) => {
128
+ map.set(proto, new Set());
129
+ });
130
+ map.set(Object, new Set([
131
+ 'entries',
132
+ 'fromEntries',
133
+ 'getOwnPropertyNames',
134
+ 'is',
135
+ 'keys',
136
+ 'hasOwnProperty',
137
+ 'isPrototypeOf',
138
+ 'propertyIsEnumerable',
139
+ 'toLocaleString',
140
+ 'toString',
141
+ 'valueOf',
142
+ 'values',
143
+ ]));
144
+ return map;
145
+ }
146
+ subscribeGet(callback, context) {
147
+ context.getSubscriptions.add(callback);
148
+ return { unsubscribe: () => context.getSubscriptions.delete(callback) };
149
+ }
150
+ subscribeSet(obj, name, callback, context) {
151
+ return subscribeSet(obj, name, callback, context);
152
+ }
153
+ subscribeSetGlobal(obj, name, callback) {
154
+ return subscribeSet(obj, name, callback, this);
155
+ }
156
+ getContext(fn) {
157
+ return this.sandboxFunctions.get(fn);
158
+ }
159
+ executeTree(context, scopes = []) {
160
+ return executeTree({
161
+ ticks: BigInt(0),
162
+ }, context, context.tree, scopes);
163
+ }
164
+ executeTreeAsync(context, scopes = []) {
165
+ return executeTreeAsync({
166
+ ticks: BigInt(0),
167
+ }, context, context.tree, scopes);
168
+ }
169
+ }
@@ -0,0 +1,18 @@
1
+ import { lispifyFunction } from './parser.js';
2
+ import { IExecContext, Ticks } from './utils.js';
3
+ export interface IEvalContext {
4
+ sandboxFunction: typeof sandboxFunction;
5
+ sandboxedEval: typeof sandboxedEval;
6
+ sandboxedSetTimeout: typeof sandboxedSetTimeout;
7
+ sandboxedSetInterval: typeof sandboxedSetInterval;
8
+ lispifyFunction: typeof lispifyFunction;
9
+ }
10
+ export type SandboxFunction = (code: string, ...args: string[]) => () => unknown;
11
+ export type SandboxEval = (code: string) => unknown;
12
+ export type SandboxSetTimeout = (handler: TimerHandler, timeout?: number, ...args: unknown[]) => any;
13
+ export type SandboxSetInterval = (handler: TimerHandler, timeout?: number, ...args: unknown[]) => any;
14
+ export declare function createEvalContext(): IEvalContext;
15
+ export declare function sandboxFunction(context: IExecContext, ticks?: Ticks): SandboxFunction;
16
+ export declare function sandboxedEval(func: SandboxFunction): SandboxEval;
17
+ export declare function sandboxedSetTimeout(func: SandboxFunction): SandboxSetTimeout;
18
+ export declare function sandboxedSetInterval(func: SandboxFunction): SandboxSetInterval;
package/build/eval.js ADDED
@@ -0,0 +1,43 @@
1
+ import { createFunction, currentTicks } from './executor.js';
2
+ import parse, { lispifyFunction } from './parser.js';
3
+ export function createEvalContext() {
4
+ return {
5
+ sandboxFunction,
6
+ sandboxedEval,
7
+ sandboxedSetTimeout,
8
+ sandboxedSetInterval,
9
+ lispifyFunction,
10
+ };
11
+ }
12
+ export function sandboxFunction(context, ticks) {
13
+ return SandboxFunction;
14
+ function SandboxFunction(...params) {
15
+ const code = params.pop() || '';
16
+ const parsed = parse(code);
17
+ return createFunction(params, parsed.tree, ticks || currentTicks.current, {
18
+ ...context,
19
+ constants: parsed.constants,
20
+ tree: parsed.tree,
21
+ }, undefined, 'anonymous');
22
+ }
23
+ }
24
+ export function sandboxedEval(func) {
25
+ return sandboxEval;
26
+ function sandboxEval(code) {
27
+ return func(code)();
28
+ }
29
+ }
30
+ export function sandboxedSetTimeout(func) {
31
+ return function sandboxSetTimeout(handler, ...args) {
32
+ if (typeof handler !== 'string')
33
+ return setTimeout(handler, ...args);
34
+ return setTimeout(func(handler), ...args);
35
+ };
36
+ }
37
+ export function sandboxedSetInterval(func) {
38
+ return function sandboxSetInterval(handler, ...args) {
39
+ if (typeof handler !== 'string')
40
+ return setInterval(handler, ...args);
41
+ return setInterval(func(handler), ...args);
42
+ };
43
+ }