@dronedeploy/rocos-js-sdk 3.0.1-alpha.20 → 3.0.1-alpha.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. package/cjs/helpers/index.d.ts +1 -0
  2. package/cjs/helpers/index.js +1 -0
  3. package/cjs/helpers/kscript/Context.d.ts +34 -0
  4. package/cjs/helpers/kscript/Context.js +52 -0
  5. package/cjs/helpers/kscript/index.d.ts +1 -0
  6. package/cjs/helpers/kscript/index.js +27 -0
  7. package/cjs/helpers/kscript/kscript.d.ts +6 -0
  8. package/cjs/helpers/kscript/kscript.js +115 -0
  9. package/cjs/helpers/kscript/nodes/Identifier.d.ts +12 -0
  10. package/cjs/helpers/kscript/nodes/Identifier.js +20 -0
  11. package/cjs/helpers/kscript/nodes/Literal.d.ts +11 -0
  12. package/cjs/helpers/kscript/nodes/Literal.js +22 -0
  13. package/cjs/helpers/kscript/nodes/Node.d.ts +9 -0
  14. package/cjs/helpers/kscript/nodes/Node.js +15 -0
  15. package/cjs/helpers/kscript/nodes/Program.d.ts +11 -0
  16. package/cjs/helpers/kscript/nodes/Program.js +24 -0
  17. package/cjs/helpers/kscript/nodes/TemplateLiteral.d.ts +23 -0
  18. package/cjs/helpers/kscript/nodes/TemplateLiteral.js +35 -0
  19. package/cjs/helpers/kscript/nodes/expressions/ArrayExpression.d.ts +7 -0
  20. package/cjs/helpers/kscript/nodes/expressions/ArrayExpression.js +31 -0
  21. package/cjs/helpers/kscript/nodes/expressions/ArrowFunctionExpression.d.ts +14 -0
  22. package/cjs/helpers/kscript/nodes/expressions/ArrowFunctionExpression.js +40 -0
  23. package/cjs/helpers/kscript/nodes/expressions/BinaryExpression.d.ts +16 -0
  24. package/cjs/helpers/kscript/nodes/expressions/BinaryExpression.js +104 -0
  25. package/cjs/helpers/kscript/nodes/expressions/CallExpression.d.ts +8 -0
  26. package/cjs/helpers/kscript/nodes/expressions/CallExpression.js +38 -0
  27. package/cjs/helpers/kscript/nodes/expressions/ChainExpression.d.ts +16 -0
  28. package/cjs/helpers/kscript/nodes/expressions/ChainExpression.js +25 -0
  29. package/cjs/helpers/kscript/nodes/expressions/ConditionalExpression.d.ts +14 -0
  30. package/cjs/helpers/kscript/nodes/expressions/ConditionalExpression.js +30 -0
  31. package/cjs/helpers/kscript/nodes/expressions/ExpressionStatement.d.ts +7 -0
  32. package/cjs/helpers/kscript/nodes/expressions/ExpressionStatement.js +18 -0
  33. package/cjs/helpers/kscript/nodes/expressions/LogicalExpression.d.ts +10 -0
  34. package/cjs/helpers/kscript/nodes/expressions/LogicalExpression.js +47 -0
  35. package/cjs/helpers/kscript/nodes/expressions/MemberExpression.d.ts +44 -0
  36. package/cjs/helpers/kscript/nodes/expressions/MemberExpression.js +98 -0
  37. package/cjs/helpers/kscript/nodes/expressions/ObjectExpression.d.ts +11 -0
  38. package/cjs/helpers/kscript/nodes/expressions/ObjectExpression.js +59 -0
  39. package/cjs/helpers/kscript/nodes/expressions/UnaryExpression.d.ts +12 -0
  40. package/cjs/helpers/kscript/nodes/expressions/UnaryExpression.js +44 -0
  41. package/cjs/helpers/kscript/nodes/expressions/index.d.ts +11 -0
  42. package/cjs/helpers/kscript/nodes/expressions/index.js +28 -0
  43. package/cjs/helpers/kscript/nodes/index.d.ts +4 -0
  44. package/cjs/helpers/kscript/nodes/index.js +10 -0
  45. package/cjs/helpers/kscript/nodes/nodeTypes.d.ts +33 -0
  46. package/cjs/helpers/kscript/nodes/nodeTypes.js +29 -0
  47. package/cjs/helpers/kscript/utils.d.ts +4 -0
  48. package/cjs/helpers/kscript/utils.js +15 -0
  49. package/cjs/services/AuthService.d.ts +3 -3
  50. package/cjs/services/AuthService.js +7 -6
  51. package/esm/helpers/index.d.ts +1 -0
  52. package/esm/helpers/index.js +1 -0
  53. package/esm/helpers/kscript/Context.d.ts +34 -0
  54. package/esm/helpers/kscript/Context.js +49 -0
  55. package/esm/helpers/kscript/index.d.ts +1 -0
  56. package/esm/helpers/kscript/index.js +1 -0
  57. package/esm/helpers/kscript/kscript.d.ts +6 -0
  58. package/esm/helpers/kscript/kscript.js +107 -0
  59. package/esm/helpers/kscript/nodes/Identifier.d.ts +12 -0
  60. package/esm/helpers/kscript/nodes/Identifier.js +14 -0
  61. package/esm/helpers/kscript/nodes/Literal.d.ts +11 -0
  62. package/esm/helpers/kscript/nodes/Literal.js +16 -0
  63. package/esm/helpers/kscript/nodes/Node.d.ts +9 -0
  64. package/esm/helpers/kscript/nodes/Node.js +12 -0
  65. package/esm/helpers/kscript/nodes/Program.d.ts +11 -0
  66. package/esm/helpers/kscript/nodes/Program.js +18 -0
  67. package/esm/helpers/kscript/nodes/TemplateLiteral.d.ts +23 -0
  68. package/esm/helpers/kscript/nodes/TemplateLiteral.js +29 -0
  69. package/esm/helpers/kscript/nodes/expressions/ArrayExpression.d.ts +7 -0
  70. package/esm/helpers/kscript/nodes/expressions/ArrayExpression.js +25 -0
  71. package/esm/helpers/kscript/nodes/expressions/ArrowFunctionExpression.d.ts +14 -0
  72. package/esm/helpers/kscript/nodes/expressions/ArrowFunctionExpression.js +34 -0
  73. package/esm/helpers/kscript/nodes/expressions/BinaryExpression.d.ts +16 -0
  74. package/esm/helpers/kscript/nodes/expressions/BinaryExpression.js +98 -0
  75. package/esm/helpers/kscript/nodes/expressions/CallExpression.d.ts +8 -0
  76. package/esm/helpers/kscript/nodes/expressions/CallExpression.js +32 -0
  77. package/esm/helpers/kscript/nodes/expressions/ChainExpression.d.ts +16 -0
  78. package/esm/helpers/kscript/nodes/expressions/ChainExpression.js +19 -0
  79. package/esm/helpers/kscript/nodes/expressions/ConditionalExpression.d.ts +14 -0
  80. package/esm/helpers/kscript/nodes/expressions/ConditionalExpression.js +24 -0
  81. package/esm/helpers/kscript/nodes/expressions/ExpressionStatement.d.ts +7 -0
  82. package/esm/helpers/kscript/nodes/expressions/ExpressionStatement.js +12 -0
  83. package/esm/helpers/kscript/nodes/expressions/LogicalExpression.d.ts +10 -0
  84. package/esm/helpers/kscript/nodes/expressions/LogicalExpression.js +41 -0
  85. package/esm/helpers/kscript/nodes/expressions/MemberExpression.d.ts +44 -0
  86. package/esm/helpers/kscript/nodes/expressions/MemberExpression.js +92 -0
  87. package/esm/helpers/kscript/nodes/expressions/ObjectExpression.d.ts +11 -0
  88. package/esm/helpers/kscript/nodes/expressions/ObjectExpression.js +53 -0
  89. package/esm/helpers/kscript/nodes/expressions/UnaryExpression.d.ts +12 -0
  90. package/esm/helpers/kscript/nodes/expressions/UnaryExpression.js +38 -0
  91. package/esm/helpers/kscript/nodes/expressions/index.d.ts +11 -0
  92. package/esm/helpers/kscript/nodes/expressions/index.js +11 -0
  93. package/esm/helpers/kscript/nodes/index.d.ts +4 -0
  94. package/esm/helpers/kscript/nodes/index.js +3 -0
  95. package/esm/helpers/kscript/nodes/nodeTypes.d.ts +33 -0
  96. package/esm/helpers/kscript/nodes/nodeTypes.js +24 -0
  97. package/esm/helpers/kscript/utils.d.ts +4 -0
  98. package/esm/helpers/kscript/utils.js +11 -0
  99. package/esm/services/AuthService.d.ts +3 -3
  100. package/esm/services/AuthService.js +7 -6
  101. package/package.json +2 -1
@@ -3,3 +3,4 @@ export * from './standardDeviation';
3
3
  export * from './generateUUID';
4
4
  export * from './getURLSearchParams';
5
5
  export * from './websandbox';
6
+ export * from './kscript';
@@ -19,3 +19,4 @@ __exportStar(require("./standardDeviation"), exports);
19
19
  __exportStar(require("./generateUUID"), exports);
20
20
  __exportStar(require("./getURLSearchParams"), exports);
21
21
  __exportStar(require("./websandbox"), exports);
22
+ __exportStar(require("./kscript"), exports);
@@ -0,0 +1,34 @@
1
+ import { AnyNode } from 'acorn';
2
+ import type { NodeType } from './nodes';
3
+ /**
4
+ * A map of node types to a set of property names that are allowed to be accessed
5
+ * on the prototype of the object.
6
+ *
7
+ * If the set is null, all properties are allowed.
8
+ */
9
+ export type PrototypeWhitelist = Map<unknown, Set<string> | null>;
10
+ export type Scope = Map<string, unknown> | Record<string, unknown>;
11
+ export interface ContextOptions {
12
+ nodeBlacklist?: Set<NodeType>;
13
+ prototypeWhitelist?: PrototypeWhitelist;
14
+ functionCallsAllowed?: boolean;
15
+ }
16
+ export default class Context {
17
+ readonly scope: Map<string, unknown>;
18
+ readonly isFunctionCallAllowed: boolean;
19
+ private readonly options;
20
+ constructor(scope?: Scope, options?: ContextOptions);
21
+ isNodeAllowed(nodeType: AnyNode['type']): boolean;
22
+ newChildContext(scope: Scope): Context;
23
+ /** Returns true if the property is allowed to be accessed on the prototype.
24
+ *
25
+ * - If the prototype is not in the whitelist, the property is allowed only if it is an own property.
26
+ * - If the prototype is in the whitelist, the property is allowed if it is in the set or the set is null.
27
+ *
28
+ * @param prototype The prototype which contains the property being accessed.
29
+ * @param property The name of the property being accessed.
30
+ * @param ownProperty Whether the property is owned by the object it is being accessed on.
31
+ */
32
+ isPrototypeAllowed(prototype: unknown, property: string, ownProperty: boolean): boolean;
33
+ private static buildMap;
34
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Context {
4
+ constructor(scope, options) {
5
+ this.scope = scope ? Context.buildMap(scope) : new Map();
6
+ this.options = {
7
+ nodeBlacklist: options?.nodeBlacklist ?? new Set(),
8
+ prototypeWhitelist: options?.prototypeWhitelist ?? new Map(),
9
+ functionCallsAllowed: options?.functionCallsAllowed ?? true,
10
+ };
11
+ this.isFunctionCallAllowed = this.options.functionCallsAllowed;
12
+ }
13
+ isNodeAllowed(nodeType) {
14
+ return !this.options.nodeBlacklist.has(nodeType);
15
+ }
16
+ newChildContext(scope) {
17
+ let newEntries;
18
+ if (scope instanceof Map) {
19
+ newEntries = [...scope.entries()];
20
+ }
21
+ else {
22
+ newEntries = Object.entries(scope);
23
+ }
24
+ const newScope = new Map([...this.scope.entries(), ...newEntries]);
25
+ return new Context(newScope, this.options);
26
+ }
27
+ /** Returns true if the property is allowed to be accessed on the prototype.
28
+ *
29
+ * - If the prototype is not in the whitelist, the property is allowed only if it is an own property.
30
+ * - If the prototype is in the whitelist, the property is allowed if it is in the set or the set is null.
31
+ *
32
+ * @param prototype The prototype which contains the property being accessed.
33
+ * @param property The name of the property being accessed.
34
+ * @param ownProperty Whether the property is owned by the object it is being accessed on.
35
+ */
36
+ isPrototypeAllowed(prototype, property, ownProperty) {
37
+ const whitelist = this.options.prototypeWhitelist.get(prototype);
38
+ // If the object owns the property, and it's not in the whitelist, it's allowed.
39
+ // This prevents direct calls to non-whitelisted properties on allowed prototypes
40
+ // e.g. Object.prototype.hasOwnProperty.call(obj, 'toString')
41
+ if (whitelist === undefined)
42
+ return ownProperty;
43
+ // all properties allowed if no set is provided
44
+ if (whitelist === null)
45
+ return true;
46
+ return whitelist.has(property);
47
+ }
48
+ static buildMap(obj) {
49
+ return obj instanceof Map ? obj : new Map(Object.entries(obj));
50
+ }
51
+ }
52
+ exports.default = Context;
@@ -0,0 +1 @@
1
+ export * as kscript from './kscript';
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.kscript = void 0;
27
+ exports.kscript = __importStar(require("./kscript"));
@@ -0,0 +1,6 @@
1
+ import { ContextOptions, PrototypeWhitelist, Scope } from './Context';
2
+ import { Node } from './nodes';
3
+ export declare function execute(code: string, scope?: Scope, options?: ContextOptions): unknown;
4
+ export declare function compile(code: string, scope?: Scope, options?: ContextOptions): Node;
5
+ export declare const SAFE_GLOBALS: Map<string, unknown>;
6
+ export declare const SAFE_PROTOTYPES: PrototypeWhitelist;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SAFE_PROTOTYPES = exports.SAFE_GLOBALS = exports.compile = exports.execute = void 0;
7
+ const Context_1 = __importDefault(require("./Context"));
8
+ const acorn_1 = require("acorn");
9
+ const utils_1 = require("./utils");
10
+ function execute(code, scope, options) {
11
+ return compile(code, scope, options).run();
12
+ }
13
+ exports.execute = execute;
14
+ function compile(code, scope, options) {
15
+ let program;
16
+ try {
17
+ // we add the brackets to ensure that object literals are parsed correctly
18
+ program = (0, acorn_1.parse)(`(${code})`, { ecmaVersion: 2020, sourceType: 'script' });
19
+ }
20
+ catch (error) {
21
+ if (error instanceof SyntaxError) {
22
+ // fallback to non-wrapped code for edge cases where the brackets cause issues
23
+ program = (0, acorn_1.parse)(`${code}`, { ecmaVersion: 2020, sourceType: 'script' });
24
+ }
25
+ else {
26
+ throw error;
27
+ }
28
+ }
29
+ const context = new Context_1.default(scope ?? exports.SAFE_GLOBALS, {
30
+ prototypeWhitelist: exports.SAFE_PROTOTYPES,
31
+ ...options,
32
+ });
33
+ return (0, utils_1.construct)(program, context);
34
+ }
35
+ exports.compile = compile;
36
+ exports.SAFE_GLOBALS = new Map(Object.entries({
37
+ console: {
38
+ debug: console.debug,
39
+ error: console.error,
40
+ info: console.info,
41
+ log: console.log,
42
+ warn: console.warn,
43
+ },
44
+ isFinite,
45
+ isNaN,
46
+ Number,
47
+ Object,
48
+ Array,
49
+ Symbol,
50
+ Error,
51
+ JSON,
52
+ Math,
53
+ Date,
54
+ RegExp,
55
+ }));
56
+ exports.SAFE_PROTOTYPES = new Map([
57
+ [Number.prototype, new Set(['toString', 'toFixed', 'toExponential', 'toPrecision'])],
58
+ [
59
+ String.prototype,
60
+ new Set([
61
+ 'toString',
62
+ 'charAt',
63
+ 'charCodeAt',
64
+ 'concat',
65
+ 'indexOf',
66
+ 'lastIndexOf',
67
+ 'localeCompare',
68
+ 'match',
69
+ 'replace',
70
+ 'search',
71
+ 'slice',
72
+ 'split',
73
+ 'substring',
74
+ 'toLowerCase',
75
+ 'toUpperCase',
76
+ 'trim',
77
+ 'valueOf',
78
+ ]),
79
+ ],
80
+ [
81
+ Array.prototype,
82
+ new Set([
83
+ 'filter',
84
+ 'map',
85
+ 'find',
86
+ 'findIndex',
87
+ 'forEach',
88
+ 'every',
89
+ 'some',
90
+ 'reduce',
91
+ 'reduceRight',
92
+ 'sort',
93
+ 'slice',
94
+ 'splice',
95
+ 'concat',
96
+ 'indexOf',
97
+ 'lastIndexOf',
98
+ 'includes',
99
+ 'join',
100
+ 'reverse',
101
+ 'shift',
102
+ 'unshift',
103
+ 'pop',
104
+ 'push',
105
+ 'copyWithin',
106
+ 'fill',
107
+ 'entries',
108
+ 'keys',
109
+ 'values',
110
+ 'flat',
111
+ 'flatMap',
112
+ ]),
113
+ ],
114
+ [Object.prototype, new Set(['toString'])],
115
+ ]);
@@ -0,0 +1,12 @@
1
+ import { AnyNode, Identifier } from 'acorn';
2
+ import type Context from '../Context';
3
+ import Node from './Node';
4
+ /** An Identifier is a reference to a variable.
5
+ *
6
+ * Variables must be declared in the current scope.
7
+ * If the variable is not found, undefined is returned.
8
+ */
9
+ export default class IdentifierNode extends Node<Identifier> {
10
+ constructor(node: AnyNode, context: Context);
11
+ run(): unknown;
12
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("./Node"));
7
+ /** An Identifier is a reference to a variable.
8
+ *
9
+ * Variables must be declared in the current scope.
10
+ * If the variable is not found, undefined is returned.
11
+ */
12
+ class IdentifierNode extends Node_1.default {
13
+ constructor(node, context) {
14
+ super(node, context, 'Identifier');
15
+ }
16
+ run() {
17
+ return this.scope.get(this.node.name);
18
+ }
19
+ }
20
+ exports.default = IdentifierNode;
@@ -0,0 +1,11 @@
1
+ import { AnyNode, Literal } from 'acorn';
2
+ import Context from '../Context';
3
+ import Node from './Node';
4
+ /** Represents a literal value
5
+ *
6
+ * e.g. `1`, `'hello'`, `true`
7
+ */
8
+ export default class LiteralNode extends Node<Literal> {
9
+ constructor(node: AnyNode, context: Context);
10
+ run(): unknown;
11
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("./Node"));
7
+ /** Represents a literal value
8
+ *
9
+ * e.g. `1`, `'hello'`, `true`
10
+ */
11
+ class LiteralNode extends Node_1.default {
12
+ constructor(node, context) {
13
+ super(node, context, 'Literal');
14
+ }
15
+ run() {
16
+ if (this.node.bigint) {
17
+ throw new Error('BigInts are not supported');
18
+ }
19
+ return this.node.value;
20
+ }
21
+ }
22
+ exports.default = LiteralNode;
@@ -0,0 +1,9 @@
1
+ import { AnyNode } from 'acorn';
2
+ import type Context from '../Context';
3
+ export default abstract class Node<T extends AnyNode = AnyNode> {
4
+ protected context: Context;
5
+ protected node: T;
6
+ protected scope: Context['scope'];
7
+ protected constructor(node: AnyNode, context: Context, expectedType: T['type'] | T['type'][]);
8
+ abstract run(): unknown;
9
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Node {
4
+ constructor(node, context, expectedType) {
5
+ this.context = context;
6
+ const expectedTypes = Array.isArray(expectedType) ? expectedType : [expectedType];
7
+ if (!expectedTypes.includes(node.type)) {
8
+ console.error(node);
9
+ throw new Error(`Expected node type to be ${expectedTypes.join(' or ')}, but got ${node.type}`);
10
+ }
11
+ this.node = node;
12
+ this.scope = context.scope;
13
+ }
14
+ }
15
+ exports.default = Node;
@@ -0,0 +1,11 @@
1
+ import { AnyNode, Program } from 'acorn';
2
+ import Context from '../Context';
3
+ import Node from './Node';
4
+ /** Represents the root node of the program
5
+ *
6
+ * Since the sandbox only supports a single statement, this node will only ever run the first child.
7
+ */
8
+ export default class ProgramNode extends Node<Program> {
9
+ constructor(node: AnyNode, scope: Context);
10
+ run(): unknown;
11
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("./Node"));
7
+ const utils_1 = require("../utils");
8
+ /** Represents the root node of the program
9
+ *
10
+ * Since the sandbox only supports a single statement, this node will only ever run the first child.
11
+ */
12
+ class ProgramNode extends Node_1.default {
13
+ constructor(node, scope) {
14
+ super(node, scope, 'Program');
15
+ }
16
+ run() {
17
+ const children = this.node.body;
18
+ if (children.length !== 1) {
19
+ throw new Error('Only a single statement is supported in the sandbox');
20
+ }
21
+ return (0, utils_1.construct)(children[0], this.context).run();
22
+ }
23
+ }
24
+ exports.default = ProgramNode;
@@ -0,0 +1,23 @@
1
+ import { AnyNode, TemplateLiteral } from 'acorn';
2
+ import Context from '../Context';
3
+ import Node from './Node';
4
+ /**
5
+ * A template literal is a string literal that allows embedded expressions.
6
+ *
7
+ * e.g. `Hello ${name}`
8
+ *
9
+ * The `quasis` property is an array of strings that are the static parts of the template literal.
10
+ * The `expressions` property is an array of expressions that are the dynamic parts of the template literal.
11
+ *
12
+ * The template literal is constructed by merging the static parts with the results of evaluating the dynamic parts.
13
+ *
14
+ * i.e. `Hello ${name}. My name is ${name}.`
15
+ * Would result in three quasi values: `Hello `, `. My name is ` and `.`
16
+ * And two expressions: `Identifier<name>` and `Identifier<name>`
17
+ *
18
+ * There is *always* one more quasi value than there are expressions, even if the last quasi is an empty string.
19
+ */
20
+ export default class TemplateLiteralNode extends Node<TemplateLiteral> {
21
+ constructor(node: AnyNode, scope: Context);
22
+ run(): unknown;
23
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("./Node"));
7
+ const utils_1 = require("../utils");
8
+ /**
9
+ * A template literal is a string literal that allows embedded expressions.
10
+ *
11
+ * e.g. `Hello ${name}`
12
+ *
13
+ * The `quasis` property is an array of strings that are the static parts of the template literal.
14
+ * The `expressions` property is an array of expressions that are the dynamic parts of the template literal.
15
+ *
16
+ * The template literal is constructed by merging the static parts with the results of evaluating the dynamic parts.
17
+ *
18
+ * i.e. `Hello ${name}. My name is ${name}.`
19
+ * Would result in three quasi values: `Hello `, `. My name is ` and `.`
20
+ * And two expressions: `Identifier<name>` and `Identifier<name>`
21
+ *
22
+ * There is *always* one more quasi value than there are expressions, even if the last quasi is an empty string.
23
+ */
24
+ class TemplateLiteralNode extends Node_1.default {
25
+ constructor(node, scope) {
26
+ super(node, scope, 'TemplateLiteral');
27
+ }
28
+ run() {
29
+ return this.node.quasis.reduce((acc, quasi, i) => {
30
+ const expression = this.node.expressions[i] ? (0, utils_1.construct)(this.node.expressions[i], this.context).run() : '';
31
+ return acc + quasi.value.raw + expression;
32
+ }, '');
33
+ }
34
+ }
35
+ exports.default = TemplateLiteralNode;
@@ -0,0 +1,7 @@
1
+ import { AnyNode, ArrayExpression } from 'acorn';
2
+ import type Context from '../../Context';
3
+ import Node from '../Node';
4
+ export default class ArrayExpressionNode extends Node<ArrayExpression> {
5
+ constructor(node: AnyNode, context: Context);
6
+ run(): unknown;
7
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("../Node"));
7
+ const utils_1 = require("../../utils");
8
+ class ArrayExpressionNode extends Node_1.default {
9
+ constructor(node, context) {
10
+ super(node, context, 'ArrayExpression');
11
+ }
12
+ run() {
13
+ const array = [];
14
+ for (const element of this.node.elements) {
15
+ if (element === null) {
16
+ // null implies an empty slot in the array (e.g. [1, , 3])
17
+ // an actual null value would be a literal node.
18
+ array.push(null);
19
+ delete array[array.length - 1];
20
+ }
21
+ else if (element.type === 'SpreadElement') {
22
+ array.push(...(0, utils_1.construct)(element.argument, this.context).run());
23
+ }
24
+ else {
25
+ array.push((0, utils_1.construct)(element, this.context).run());
26
+ }
27
+ }
28
+ return array;
29
+ }
30
+ }
31
+ exports.default = ArrayExpressionNode;
@@ -0,0 +1,14 @@
1
+ import { AnyNode, ArrowFunctionExpression } from 'acorn';
2
+ import type Context from '../../Context';
3
+ import Node from '../Node';
4
+ /** Represents an arrow function expression.
5
+ *
6
+ * e.g. `(a, b) => a + b`
7
+ *
8
+ * In the sandbox this is the only way to define a function.
9
+ */
10
+ export default class ArrowFunctionExpressionNode extends Node<ArrowFunctionExpression> {
11
+ private readonly params;
12
+ constructor(node: AnyNode, context: Context);
13
+ run(): unknown;
14
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("../Node"));
7
+ const utils_1 = require("../../utils");
8
+ /** Represents an arrow function expression.
9
+ *
10
+ * e.g. `(a, b) => a + b`
11
+ *
12
+ * In the sandbox this is the only way to define a function.
13
+ */
14
+ class ArrowFunctionExpressionNode extends Node_1.default {
15
+ constructor(node, context) {
16
+ super(node, context, 'ArrowFunctionExpression');
17
+ if (this.node.params.some((param) => param.type !== 'Identifier')) {
18
+ throw new Error('only identifiers are supported as parameters');
19
+ }
20
+ this.params = this.node.params;
21
+ }
22
+ run() {
23
+ if (!this.context.isFunctionCallAllowed)
24
+ throw new Error('functions are not allowed');
25
+ if (!this.node.expression)
26
+ throw new Error('functions must be an expression');
27
+ if (this.node.async)
28
+ throw new Error('async functions are not supported');
29
+ return (...args) => {
30
+ const scope = new Map();
31
+ for (const param of this.params) {
32
+ const index = this.params.indexOf(param);
33
+ scope.set(param.name, args?.[index]);
34
+ }
35
+ const newContext = this.context.newChildContext(scope);
36
+ return (0, utils_1.construct)(this.node.body, newContext).run();
37
+ };
38
+ }
39
+ }
40
+ exports.default = ArrowFunctionExpressionNode;
@@ -0,0 +1,16 @@
1
+ import { AnyNode, BinaryExpression } from 'acorn';
2
+ import Context from '../../Context';
3
+ import Node from '../Node';
4
+ /** A binary expression is an expression that consists of two operands and an operator
5
+ *
6
+ * e.g. `1 + 2`, `a === b`, `c < d`
7
+ */
8
+ export default class BinaryExpressionNode extends Node<BinaryExpression> {
9
+ constructor(node: AnyNode, context: Context);
10
+ run(): unknown;
11
+ private operate;
12
+ private arithmetic;
13
+ private comparison;
14
+ private equality;
15
+ private checkIn;
16
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Node_1 = __importDefault(require("../Node"));
7
+ const utils_1 = require("../../utils");
8
+ /** A binary expression is an expression that consists of two operands and an operator
9
+ *
10
+ * e.g. `1 + 2`, `a === b`, `c < d`
11
+ */
12
+ class BinaryExpressionNode extends Node_1.default {
13
+ constructor(node, context) {
14
+ super(node, context, 'BinaryExpression');
15
+ }
16
+ run() {
17
+ const left = (0, utils_1.construct)(this.node.left, this.context).run();
18
+ const right = (0, utils_1.construct)(this.node.right, this.context).run();
19
+ return this.operate(left, right);
20
+ }
21
+ operate(left, right) {
22
+ switch (this.node.operator) {
23
+ case '==':
24
+ case '!=':
25
+ case '===':
26
+ case '!==':
27
+ return this.equality(this.node.operator, left, right);
28
+ case '<':
29
+ case '<=':
30
+ case '>':
31
+ case '>=':
32
+ return this.comparison(this.node.operator, left, right);
33
+ case 'in':
34
+ return this.checkIn(left, right);
35
+ case '**':
36
+ case '+':
37
+ case '-':
38
+ case '*':
39
+ case '/':
40
+ case '%':
41
+ return this.arithmetic(this.node.operator, left, right);
42
+ default:
43
+ throw new Error(`Unsupported operator: ${this.node.operator}`);
44
+ }
45
+ }
46
+ arithmetic(operator, left, right) {
47
+ if (operator === '+' && (typeof left === 'string' || typeof right === 'string')) {
48
+ return `${left}${right}`;
49
+ }
50
+ if (typeof left !== 'number' || typeof right !== 'number') {
51
+ throw new Error('Arithmetic operators are only supported for numbers');
52
+ }
53
+ switch (operator) {
54
+ case '+':
55
+ return left + right;
56
+ case '-':
57
+ return left - right;
58
+ case '*':
59
+ return left * right;
60
+ case '/':
61
+ return left / right;
62
+ case '%':
63
+ return left % right;
64
+ case '**':
65
+ return left ** right;
66
+ }
67
+ }
68
+ comparison(operator, left, right) {
69
+ if (typeof left !== 'number' || typeof right !== 'number') {
70
+ throw new Error('Comparison operators are only supported for numbers');
71
+ }
72
+ switch (operator) {
73
+ case '<':
74
+ return left < right;
75
+ case '<=':
76
+ return left <= right;
77
+ case '>':
78
+ return left > right;
79
+ case '>=':
80
+ return left >= right;
81
+ }
82
+ }
83
+ equality(operator, left, right) {
84
+ switch (operator) {
85
+ case '==':
86
+ // eslint-disable-next-line eqeqeq
87
+ return left == right;
88
+ case '!=':
89
+ // eslint-disable-next-line eqeqeq
90
+ return left != right;
91
+ case '===':
92
+ return left === right;
93
+ case '!==':
94
+ return left !== right;
95
+ }
96
+ }
97
+ checkIn(left, right) {
98
+ if (!Array.isArray(right)) {
99
+ throw new Error('The "in" operator is only supported for arrays');
100
+ }
101
+ return right.includes(left);
102
+ }
103
+ }
104
+ exports.default = BinaryExpressionNode;