@dronedeploy/rocos-js-sdk 3.0.11 → 3.0.12
Sign up to get free protection for your applications and to get access to all the features.
- package/cjs/api/StreamRegister.d.ts +3 -3
- package/cjs/api/StreamRegister.js +6 -6
- package/cjs/api/streams/telemetry/TelemetryStreamAbstract.js +8 -7
- package/cjs/helpers/kscript/Context.d.ts +14 -8
- package/cjs/helpers/kscript/Context.js +59 -22
- package/cjs/helpers/kscript/kscript.js +1 -1
- package/cjs/helpers/kscript/nodes/Identifier.js +1 -1
- package/cjs/helpers/kscript/nodes/Node.d.ts +0 -1
- package/cjs/helpers/kscript/nodes/Node.js +0 -1
- package/cjs/helpers/kscript/nodes/Program.js +8 -5
- package/cjs/helpers/kscript/nodes/VariableDeclaration.d.ts +8 -0
- package/cjs/helpers/kscript/nodes/VariableDeclaration.js +43 -0
- package/cjs/helpers/kscript/nodes/expressions/ArrowFunctionExpression.js +11 -4
- package/cjs/helpers/kscript/nodes/expressions/AssignmentExpression.d.ts +8 -0
- package/cjs/helpers/kscript/nodes/expressions/AssignmentExpression.js +33 -0
- package/cjs/helpers/kscript/nodes/expressions/BinaryExpression.d.ts +2 -0
- package/cjs/helpers/kscript/nodes/expressions/BinaryExpression.js +16 -0
- package/cjs/helpers/kscript/nodes/expressions/NewExpression.d.ts +9 -0
- package/cjs/helpers/kscript/nodes/expressions/NewExpression.js +44 -0
- package/cjs/helpers/kscript/nodes/expressions/index.d.ts +2 -1
- package/cjs/helpers/kscript/nodes/expressions/index.js +5 -3
- package/cjs/helpers/kscript/nodes/nodeTypes.d.ts +9 -1
- package/cjs/helpers/kscript/nodes/nodeTypes.js +9 -1
- package/cjs/helpers/kscript/nodes/statements/BlockStatement.d.ts +8 -0
- package/cjs/helpers/kscript/nodes/statements/BlockStatement.js +29 -0
- package/cjs/helpers/kscript/nodes/statements/ReturnStatement.d.ts +12 -0
- package/cjs/helpers/kscript/nodes/statements/ReturnStatement.js +33 -0
- package/cjs/helpers/kscript/nodes/statements/SwitchStatement.d.ts +9 -0
- package/cjs/helpers/kscript/nodes/statements/SwitchStatement.js +52 -0
- package/cjs/helpers/kscript/nodes/statements/index.d.ts +4 -0
- package/cjs/helpers/kscript/nodes/statements/index.js +14 -0
- package/cjs/services/BaseStreamService.js +1 -1
- package/cjs/services/WebRTCSignallingService.js +1 -2
- package/esm/api/StreamRegister.d.ts +3 -3
- package/esm/api/StreamRegister.js +6 -6
- package/esm/api/streams/telemetry/TelemetryStreamAbstract.js +8 -7
- package/esm/helpers/kscript/Context.d.ts +14 -8
- package/esm/helpers/kscript/Context.js +59 -22
- package/esm/helpers/kscript/kscript.js +1 -1
- package/esm/helpers/kscript/nodes/Identifier.js +1 -1
- package/esm/helpers/kscript/nodes/Node.d.ts +0 -1
- package/esm/helpers/kscript/nodes/Node.js +0 -1
- package/esm/helpers/kscript/nodes/Program.js +8 -5
- package/esm/helpers/kscript/nodes/VariableDeclaration.d.ts +8 -0
- package/esm/helpers/kscript/nodes/VariableDeclaration.js +37 -0
- package/esm/helpers/kscript/nodes/expressions/ArrowFunctionExpression.js +11 -4
- package/esm/helpers/kscript/nodes/expressions/AssignmentExpression.d.ts +8 -0
- package/esm/helpers/kscript/nodes/expressions/AssignmentExpression.js +27 -0
- package/esm/helpers/kscript/nodes/expressions/BinaryExpression.d.ts +2 -0
- package/esm/helpers/kscript/nodes/expressions/BinaryExpression.js +16 -0
- package/esm/helpers/kscript/nodes/expressions/NewExpression.d.ts +9 -0
- package/esm/helpers/kscript/nodes/expressions/NewExpression.js +38 -0
- package/esm/helpers/kscript/nodes/expressions/index.d.ts +2 -1
- package/esm/helpers/kscript/nodes/expressions/index.js +2 -1
- package/esm/helpers/kscript/nodes/nodeTypes.d.ts +9 -1
- package/esm/helpers/kscript/nodes/nodeTypes.js +9 -1
- package/esm/helpers/kscript/nodes/statements/BlockStatement.d.ts +8 -0
- package/esm/helpers/kscript/nodes/statements/BlockStatement.js +23 -0
- package/esm/helpers/kscript/nodes/statements/ReturnStatement.d.ts +12 -0
- package/esm/helpers/kscript/nodes/statements/ReturnStatement.js +25 -0
- package/esm/helpers/kscript/nodes/statements/SwitchStatement.d.ts +9 -0
- package/esm/helpers/kscript/nodes/statements/SwitchStatement.js +46 -0
- package/esm/helpers/kscript/nodes/statements/index.d.ts +4 -0
- package/esm/helpers/kscript/nodes/statements/index.js +4 -0
- package/esm/services/BaseStreamService.js +1 -1
- package/esm/services/WebRTCSignallingService.js +1 -2
- package/package.json +1 -1
- /package/cjs/helpers/kscript/nodes/{expressions → statements}/ExpressionStatement.d.ts +0 -0
- /package/cjs/helpers/kscript/nodes/{expressions → statements}/ExpressionStatement.js +0 -0
- /package/esm/helpers/kscript/nodes/{expressions → statements}/ExpressionStatement.d.ts +0 -0
- /package/esm/helpers/kscript/nodes/{expressions → statements}/ExpressionStatement.js +0 -0
@@ -6,8 +6,8 @@ export declare class StreamRegister {
|
|
6
6
|
private constructor();
|
7
7
|
static getInstance(): StreamRegister;
|
8
8
|
static getIdentifier($identifier: string, scope?: string): string;
|
9
|
-
addStream(stream: IBaseStream):
|
9
|
+
addStream(stream: IBaseStream): void;
|
10
10
|
getStream(identifier: string): IBaseStream | undefined;
|
11
|
-
removeStream(stream: IBaseStream):
|
12
|
-
removeAllStreams():
|
11
|
+
removeStream(stream: IBaseStream): void;
|
12
|
+
removeAllStreams(): boolean;
|
13
13
|
}
|
@@ -17,10 +17,10 @@ class StreamRegister {
|
|
17
17
|
static getIdentifier($identifier, scope) {
|
18
18
|
return `${$identifier}-${scope ?? ''}`;
|
19
19
|
}
|
20
|
-
|
20
|
+
addStream(stream) {
|
21
21
|
try {
|
22
22
|
if (this.teleStreams.has(stream.identifier)) {
|
23
|
-
|
23
|
+
this.removeStream(stream);
|
24
24
|
}
|
25
25
|
this.teleStreams.set(stream.identifier, stream);
|
26
26
|
}
|
@@ -37,9 +37,9 @@ class StreamRegister {
|
|
37
37
|
getStream(identifier) {
|
38
38
|
return this.teleStreams.get(identifier);
|
39
39
|
}
|
40
|
-
|
40
|
+
removeStream(stream) {
|
41
41
|
try {
|
42
|
-
|
42
|
+
stream.stopStream();
|
43
43
|
this.teleStreams.delete(stream.identifier);
|
44
44
|
}
|
45
45
|
catch (e) {
|
@@ -52,10 +52,10 @@ class StreamRegister {
|
|
52
52
|
}
|
53
53
|
}
|
54
54
|
}
|
55
|
-
|
55
|
+
removeAllStreams() {
|
56
56
|
try {
|
57
57
|
for (const [, stream] of this.teleStreams.entries()) {
|
58
|
-
|
58
|
+
this.removeStream(stream);
|
59
59
|
}
|
60
60
|
}
|
61
61
|
catch (e) {
|
@@ -103,6 +103,14 @@ class TelemetryStreamAbstract {
|
|
103
103
|
const before = this.getSubscriptions();
|
104
104
|
this.subscriptions.delete(params.uniqueId);
|
105
105
|
const after = this.getSubscriptions();
|
106
|
+
// Do this before we send the telemetry request so that new subscriptions don't get this stream from the register while it is closing
|
107
|
+
if (!this.subscriptions.size) {
|
108
|
+
this.logger.info('No subscriptions remaining closing stream', params.uniqueId);
|
109
|
+
this.stopStream();
|
110
|
+
// self remove when no subscriptions are left
|
111
|
+
StreamRegister_1.StreamRegister.getInstance().removeStream(this);
|
112
|
+
this.logger.info('Stream closed');
|
113
|
+
}
|
106
114
|
// assign the current values from state after change
|
107
115
|
this.callsignsLookup = new models_1.CallsignsLookup(Object.keys(after));
|
108
116
|
this.sources = (0, arrayUnique_1.arrayUnique)(Object.values(after).reduce((a, v) => a.concat(v), []));
|
@@ -116,13 +124,6 @@ class TelemetryStreamAbstract {
|
|
116
124
|
this.logger.error(`Failed to unsubscribe: ${err}`);
|
117
125
|
}
|
118
126
|
}
|
119
|
-
if (!this.subscriptions.size) {
|
120
|
-
this.logger.info('No subscriptions remaining closing stream', params.uniqueId);
|
121
|
-
this.stopStream();
|
122
|
-
// self remove when no subscriptions a re left
|
123
|
-
void StreamRegister_1.StreamRegister.getInstance().removeStream(this);
|
124
|
-
this.logger.info('Stream closed');
|
125
|
-
}
|
126
127
|
}
|
127
128
|
sendAcknowledgment(uid, status, noRetry) {
|
128
129
|
return this.sendAcknowledgmentInternal(uid, status, noRetry);
|
@@ -7,19 +7,20 @@ import type { NodeType } from './nodes';
|
|
7
7
|
* If the set is null, all properties are allowed.
|
8
8
|
*/
|
9
9
|
export type PrototypeWhitelist = Map<unknown, Set<string> | null>;
|
10
|
-
export type Scope =
|
10
|
+
export type Scope = Record<string, unknown> | Map<string, unknown>;
|
11
11
|
export interface ContextOptions {
|
12
12
|
nodeBlacklist?: Set<NodeType>;
|
13
13
|
prototypeWhitelist?: PrototypeWhitelist;
|
14
14
|
functionCallsAllowed?: boolean;
|
15
15
|
}
|
16
16
|
export default class Context {
|
17
|
-
readonly
|
18
|
-
readonly
|
19
|
-
private readonly
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
private readonly parent;
|
18
|
+
private readonly scope;
|
19
|
+
private readonly config;
|
20
|
+
static create(scope?: Scope, options?: ContextOptions): Context;
|
21
|
+
private static buildMap;
|
22
|
+
private constructor();
|
23
|
+
newChild(scope?: Scope): Context;
|
23
24
|
/** Returns true if the property is allowed to be accessed on the prototype.
|
24
25
|
*
|
25
26
|
* - If the prototype is not in the whitelist, the property is allowed only if it is an own property.
|
@@ -30,5 +31,10 @@ export default class Context {
|
|
30
31
|
* @param ownProperty Whether the property is owned by the object it is being accessed on.
|
31
32
|
*/
|
32
33
|
isPrototypeAllowed(prototype: unknown, property: string, ownProperty: boolean): boolean;
|
33
|
-
|
34
|
+
isNodeAllowed(nodeType: AnyNode['type']): boolean;
|
35
|
+
get isFunctionCallAllowed(): boolean;
|
36
|
+
private getDescriptor;
|
37
|
+
get(key: string): unknown;
|
38
|
+
set(key: string, value: unknown): void;
|
39
|
+
declare(key: string, value: unknown, constant: boolean): void;
|
34
40
|
}
|
@@ -1,28 +1,29 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
class Context {
|
4
|
-
|
4
|
+
static create(scope, options) {
|
5
|
+
return new Context(null, {
|
6
|
+
functionCallsAllowed: true,
|
7
|
+
nodeBlacklist: new Set(),
|
8
|
+
prototypeWhitelist: new Map(),
|
9
|
+
...(options ?? {}),
|
10
|
+
}, scope);
|
11
|
+
}
|
12
|
+
static buildMap(obj) {
|
13
|
+
const entries = obj instanceof Map ? Array.from(obj.entries()) : Object.entries(obj);
|
14
|
+
return new Map(entries.map(([key, value]) => [key, { value, constant: false }]));
|
15
|
+
}
|
16
|
+
constructor(parent, config, scope) {
|
17
|
+
this.parent = parent;
|
5
18
|
this.scope = scope ? Context.buildMap(scope) : new Map();
|
6
|
-
this.
|
7
|
-
nodeBlacklist:
|
8
|
-
prototypeWhitelist:
|
9
|
-
functionCallsAllowed:
|
19
|
+
this.config = {
|
20
|
+
nodeBlacklist: config.nodeBlacklist ?? new Set(),
|
21
|
+
prototypeWhitelist: config.prototypeWhitelist ?? new Map(),
|
22
|
+
functionCallsAllowed: config.functionCallsAllowed ?? true,
|
10
23
|
};
|
11
|
-
this.isFunctionCallAllowed = this.options.functionCallsAllowed;
|
12
|
-
}
|
13
|
-
isNodeAllowed(nodeType) {
|
14
|
-
return !this.options.nodeBlacklist.has(nodeType);
|
15
24
|
}
|
16
|
-
|
17
|
-
|
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);
|
25
|
+
newChild(scope) {
|
26
|
+
return new Context(this, this.config, scope);
|
26
27
|
}
|
27
28
|
/** Returns true if the property is allowed to be accessed on the prototype.
|
28
29
|
*
|
@@ -34,7 +35,7 @@ class Context {
|
|
34
35
|
* @param ownProperty Whether the property is owned by the object it is being accessed on.
|
35
36
|
*/
|
36
37
|
isPrototypeAllowed(prototype, property, ownProperty) {
|
37
|
-
const whitelist = this.
|
38
|
+
const whitelist = this.config.prototypeWhitelist.get(prototype);
|
38
39
|
// If the object owns the property, and it's not in the whitelist, it's allowed.
|
39
40
|
// This prevents direct calls to non-whitelisted properties on allowed prototypes
|
40
41
|
// e.g. Object.prototype.hasOwnProperty.call(obj, 'toString')
|
@@ -45,8 +46,44 @@ class Context {
|
|
45
46
|
return true;
|
46
47
|
return whitelist.has(property);
|
47
48
|
}
|
48
|
-
|
49
|
-
return
|
49
|
+
isNodeAllowed(nodeType) {
|
50
|
+
return !this.config.nodeBlacklist.has(nodeType);
|
51
|
+
}
|
52
|
+
get isFunctionCallAllowed() {
|
53
|
+
return this.config.functionCallsAllowed;
|
54
|
+
}
|
55
|
+
getDescriptor(key, searchParents = true) {
|
56
|
+
if (this.scope.has(key)) {
|
57
|
+
return this.scope.get(key);
|
58
|
+
}
|
59
|
+
if (searchParents && this.parent) {
|
60
|
+
return this.parent.getDescriptor(key);
|
61
|
+
}
|
62
|
+
return undefined;
|
63
|
+
}
|
64
|
+
get(key) {
|
65
|
+
const descriptor = this.getDescriptor(key);
|
66
|
+
if (descriptor) {
|
67
|
+
return descriptor.value;
|
68
|
+
}
|
69
|
+
return undefined;
|
70
|
+
}
|
71
|
+
set(key, value) {
|
72
|
+
const descriptor = this.getDescriptor(key);
|
73
|
+
if (!descriptor) {
|
74
|
+
throw new Error(`no variable with name ${key}`);
|
75
|
+
}
|
76
|
+
if (descriptor.constant) {
|
77
|
+
throw new Error(`cannot reassign to constant variable ${key}`);
|
78
|
+
}
|
79
|
+
descriptor.value = value;
|
80
|
+
}
|
81
|
+
declare(key, value, constant) {
|
82
|
+
const descriptor = this.getDescriptor(key, false);
|
83
|
+
if (descriptor) {
|
84
|
+
throw new Error(`variable ${key} already declared`);
|
85
|
+
}
|
86
|
+
this.scope.set(key, { value, constant });
|
50
87
|
}
|
51
88
|
}
|
52
89
|
exports.default = Context;
|
@@ -24,7 +24,7 @@ const parse = (code) => {
|
|
24
24
|
};
|
25
25
|
const compile = (code, scope, options) => {
|
26
26
|
const program = parse(code);
|
27
|
-
const context =
|
27
|
+
const context = Context_1.default.create(scope ?? exports.SAFE_GLOBALS, {
|
28
28
|
prototypeWhitelist: exports.SAFE_PROTOTYPES,
|
29
29
|
...options,
|
30
30
|
});
|
@@ -3,7 +3,6 @@ import type Context from '../Context';
|
|
3
3
|
export default abstract class Node<T extends AnyNode = AnyNode> {
|
4
4
|
protected context: Context;
|
5
5
|
protected node: T;
|
6
|
-
protected scope: Context['scope'];
|
7
6
|
protected constructor(node: AnyNode, context: Context, expectedType: T['type'] | T['type'][]);
|
8
7
|
/** Runs the node. */
|
9
8
|
abstract run(): unknown;
|
@@ -14,17 +14,20 @@ class ProgramNode extends Node_1.default {
|
|
14
14
|
super(node, scope, 'Program');
|
15
15
|
}
|
16
16
|
validate(validateChildren = false) {
|
17
|
-
if (this.node.body.length !== 1) {
|
18
|
-
throw new Error('Only a single statement is supported in the sandbox');
|
19
|
-
}
|
20
17
|
if (!validateChildren) {
|
21
18
|
return;
|
22
19
|
}
|
23
|
-
(
|
20
|
+
for (const child of this.node.body) {
|
21
|
+
(0, utils_1.construct)(child, this.context).validate(true);
|
22
|
+
}
|
24
23
|
}
|
25
24
|
run() {
|
26
25
|
this.validate();
|
27
|
-
|
26
|
+
let result;
|
27
|
+
for (const child of this.node.body) {
|
28
|
+
result = (0, utils_1.construct)(child, this.context).run();
|
29
|
+
}
|
30
|
+
return result;
|
28
31
|
}
|
29
32
|
}
|
30
33
|
exports.default = ProgramNode;
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { AnyNode, VariableDeclaration } from 'acorn';
|
2
|
+
import Context from '../Context';
|
3
|
+
import Node from './Node';
|
4
|
+
export default class VariableDeclarationNode extends Node<VariableDeclaration> {
|
5
|
+
constructor(node: AnyNode, context: Context);
|
6
|
+
validate(validateChildren?: boolean): void;
|
7
|
+
run(): void;
|
8
|
+
}
|
@@ -0,0 +1,43 @@
|
|
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 VariableDeclarationNode extends Node_1.default {
|
9
|
+
constructor(node, context) {
|
10
|
+
super(node, context, 'VariableDeclaration');
|
11
|
+
}
|
12
|
+
validate(validateChildren = false) {
|
13
|
+
if (this.node.kind === 'var') {
|
14
|
+
throw new Error('var is not supported. use let or const instead');
|
15
|
+
}
|
16
|
+
for (const declaration of this.node.declarations) {
|
17
|
+
if (declaration.id.type !== 'Identifier') {
|
18
|
+
throw new Error('variable name must be an identifier');
|
19
|
+
}
|
20
|
+
}
|
21
|
+
if (!validateChildren) {
|
22
|
+
return;
|
23
|
+
}
|
24
|
+
for (const declaration of this.node.declarations) {
|
25
|
+
(0, utils_1.construct)(declaration.id, this.context).validate(true);
|
26
|
+
if (declaration.init) {
|
27
|
+
(0, utils_1.construct)(declaration.init, this.context).validate(true);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
run() {
|
32
|
+
this.validate();
|
33
|
+
for (const declaration of this.node.declarations) {
|
34
|
+
const id = declaration.id.name;
|
35
|
+
let init;
|
36
|
+
if (declaration.init) {
|
37
|
+
init = (0, utils_1.construct)(declaration.init, this.context).run();
|
38
|
+
}
|
39
|
+
this.context.declare(id, init, this.node.kind === 'const');
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
exports.default = VariableDeclarationNode;
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const Node_1 = __importDefault(require("../Node"));
|
7
|
+
const ReturnStatement_1 = require("../statements/ReturnStatement");
|
7
8
|
const utils_1 = require("../../utils");
|
8
9
|
/** Represents an arrow function expression.
|
9
10
|
*
|
@@ -22,8 +23,6 @@ class ArrowFunctionExpressionNode extends Node_1.default {
|
|
22
23
|
validate(validateChildren = false) {
|
23
24
|
if (!this.context.isFunctionCallAllowed)
|
24
25
|
throw new Error('functions are not allowed');
|
25
|
-
if (!this.node.expression)
|
26
|
-
throw new Error('functions must be an expression');
|
27
26
|
if (this.node.async)
|
28
27
|
throw new Error('async functions are not supported');
|
29
28
|
if (!validateChildren) {
|
@@ -39,8 +38,16 @@ class ArrowFunctionExpressionNode extends Node_1.default {
|
|
39
38
|
const index = this.params.indexOf(param);
|
40
39
|
scope.set(param.name, args?.[index]);
|
41
40
|
}
|
42
|
-
const newContext = this.context.
|
43
|
-
|
41
|
+
const newContext = this.context.newChild(scope);
|
42
|
+
try {
|
43
|
+
return (0, utils_1.construct)(this.node.body, newContext).run();
|
44
|
+
}
|
45
|
+
catch (e) {
|
46
|
+
if (e instanceof ReturnStatement_1.ReturnStatementError) {
|
47
|
+
return e.value;
|
48
|
+
}
|
49
|
+
throw e;
|
50
|
+
}
|
44
51
|
};
|
45
52
|
}
|
46
53
|
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { AnyNode, AssignmentExpression } from 'acorn';
|
2
|
+
import Context from '../../Context';
|
3
|
+
import Node from '../Node';
|
4
|
+
export default class AssignmentExpressionNode extends Node<AssignmentExpression> {
|
5
|
+
constructor(node: AnyNode, context: Context);
|
6
|
+
validate(validateChildren?: boolean): void;
|
7
|
+
run(): unknown;
|
8
|
+
}
|
@@ -0,0 +1,33 @@
|
|
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 AssignmentExpressionNode extends Node_1.default {
|
9
|
+
constructor(node, context) {
|
10
|
+
super(node, context, 'AssignmentExpression');
|
11
|
+
}
|
12
|
+
validate(validateChildren = false) {
|
13
|
+
if (this.node.operator !== '=') {
|
14
|
+
throw new Error('Only = operator is supported');
|
15
|
+
}
|
16
|
+
if (this.node.left.type !== 'Identifier') {
|
17
|
+
throw new Error('Left side of assignment must be an identifier');
|
18
|
+
}
|
19
|
+
if (!validateChildren) {
|
20
|
+
return;
|
21
|
+
}
|
22
|
+
(0, utils_1.construct)(this.node.left, this.context).validate(true);
|
23
|
+
(0, utils_1.construct)(this.node.right, this.context).validate(true);
|
24
|
+
}
|
25
|
+
run() {
|
26
|
+
this.validate();
|
27
|
+
const identifier = this.node.left.name;
|
28
|
+
const right = (0, utils_1.construct)(this.node.right, this.context).run();
|
29
|
+
this.context.set(identifier, right);
|
30
|
+
return right;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
exports.default = AssignmentExpressionNode;
|
@@ -9,12 +9,14 @@ export default class BinaryExpressionNode extends Node<BinaryExpression> {
|
|
9
9
|
private static readonly EQUALITY_OPERATORS;
|
10
10
|
private static readonly COMPARISON_OPERATORS;
|
11
11
|
private static readonly ARITHMETIC_OPERATORS;
|
12
|
+
private static readonly BITWISE_OPERATORS;
|
12
13
|
private static readonly IN_OPERATOR;
|
13
14
|
private static readonly SUPPORTED_OPERATORS;
|
14
15
|
constructor(node: AnyNode, context: Context);
|
15
16
|
validate(validateChildren?: boolean): void;
|
16
17
|
run(): unknown;
|
17
18
|
private operate;
|
19
|
+
private bitwise;
|
18
20
|
private arithmetic;
|
19
21
|
private comparison;
|
20
22
|
private equality;
|
@@ -38,11 +38,25 @@ class BinaryExpressionNode extends Node_1.default {
|
|
38
38
|
if (BinaryExpressionNode.ARITHMETIC_OPERATORS.has(this.node.operator)) {
|
39
39
|
return this.arithmetic(this.node.operator, left, right);
|
40
40
|
}
|
41
|
+
if (BinaryExpressionNode.BITWISE_OPERATORS.has(this.node.operator)) {
|
42
|
+
return this.bitwise(this.node.operator, left, right);
|
43
|
+
}
|
41
44
|
if (this.node.operator === BinaryExpressionNode.IN_OPERATOR) {
|
42
45
|
return this.checkIn(left, right);
|
43
46
|
}
|
44
47
|
throw new Error(`Unsupported operator: ${this.node.operator}`);
|
45
48
|
}
|
49
|
+
bitwise(operator, left, right) {
|
50
|
+
if (typeof left !== 'number' || typeof right !== 'number') {
|
51
|
+
throw new Error('Bitwise operators are only supported for numbers');
|
52
|
+
}
|
53
|
+
switch (operator) {
|
54
|
+
case '<<':
|
55
|
+
return left << right;
|
56
|
+
case '>>':
|
57
|
+
return left >> right;
|
58
|
+
}
|
59
|
+
}
|
46
60
|
arithmetic(operator, left, right) {
|
47
61
|
if (operator === '+' && (typeof left === 'string' || typeof right === 'string')) {
|
48
62
|
return `${left}${right}`;
|
@@ -111,11 +125,13 @@ BinaryExpressionNode.ARITHMETIC_OPERATORS = new Set([
|
|
111
125
|
'%',
|
112
126
|
'**',
|
113
127
|
]);
|
128
|
+
BinaryExpressionNode.BITWISE_OPERATORS = new Set(['<<', '>>']);
|
114
129
|
BinaryExpressionNode.IN_OPERATOR = 'in';
|
115
130
|
BinaryExpressionNode.SUPPORTED_OPERATORS = new Set([
|
116
131
|
...BinaryExpressionNode.EQUALITY_OPERATORS,
|
117
132
|
...BinaryExpressionNode.COMPARISON_OPERATORS,
|
118
133
|
...BinaryExpressionNode.ARITHMETIC_OPERATORS,
|
134
|
+
...BinaryExpressionNode.BITWISE_OPERATORS,
|
119
135
|
BinaryExpressionNode.IN_OPERATOR,
|
120
136
|
]);
|
121
137
|
exports.default = BinaryExpressionNode;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { AnyNode, NewExpression } from 'acorn';
|
2
|
+
import Context from '../../Context';
|
3
|
+
import Node from '../Node';
|
4
|
+
export default class NewExpressionNode extends Node<NewExpression> {
|
5
|
+
constructor(node: AnyNode, context: Context);
|
6
|
+
validate(validateChildren?: boolean): void;
|
7
|
+
run(): unknown;
|
8
|
+
private spreadArgs;
|
9
|
+
}
|
@@ -0,0 +1,44 @@
|
|
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 NewExpressionNode extends Node_1.default {
|
9
|
+
constructor(node, context) {
|
10
|
+
super(node, context, 'NewExpression');
|
11
|
+
}
|
12
|
+
validate(validateChildren = false) {
|
13
|
+
if (!this.context.isFunctionCallAllowed)
|
14
|
+
throw new Error('Constructors are not allowed');
|
15
|
+
if (!validateChildren) {
|
16
|
+
return;
|
17
|
+
}
|
18
|
+
(0, utils_1.construct)(this.node.callee, this.context).validate(true);
|
19
|
+
for (const arg of this.node.arguments) {
|
20
|
+
(0, utils_1.construct)(arg, this.context).validate(true);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
run() {
|
24
|
+
this.validate();
|
25
|
+
const callee = (0, utils_1.construct)(this.node.callee, this.context).run();
|
26
|
+
if (typeof callee !== 'function') {
|
27
|
+
throw new Error('callee is not a function');
|
28
|
+
}
|
29
|
+
const args = this.spreadArgs(this.node.arguments);
|
30
|
+
return new (Function.prototype.bind.apply(callee, [null, ...args]))();
|
31
|
+
}
|
32
|
+
spreadArgs(args) {
|
33
|
+
return args.reduce((acc, arg) => {
|
34
|
+
if (arg.type === 'SpreadElement') {
|
35
|
+
acc.push(...(0, utils_1.construct)(arg.argument, this.context).run());
|
36
|
+
}
|
37
|
+
else {
|
38
|
+
acc.push((0, utils_1.construct)(arg, this.context).run());
|
39
|
+
}
|
40
|
+
return acc;
|
41
|
+
}, []);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
exports.default = NewExpressionNode;
|
@@ -1,4 +1,3 @@
|
|
1
|
-
export { default as ExpressionStatement } from './ExpressionStatement';
|
2
1
|
export { default as ArrayExpression } from './ArrayExpression';
|
3
2
|
export { default as ObjectExpression } from './ObjectExpression';
|
4
3
|
export { default as BinaryExpression } from './BinaryExpression';
|
@@ -9,3 +8,5 @@ export { default as CallExpression } from './CallExpression';
|
|
9
8
|
export { default as ArrowFunctionExpression } from './ArrowFunctionExpression';
|
10
9
|
export { default as MemberExpression } from './MemberExpression';
|
11
10
|
export { default as ChainExpression } from './ChainExpression';
|
11
|
+
export { default as NewExpression } from './NewExpression';
|
12
|
+
export { default as AssignmentExpression } from './AssignmentExpression';
|
@@ -3,9 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.ChainExpression = exports.MemberExpression = exports.ArrowFunctionExpression = exports.CallExpression = exports.ConditionalExpression = exports.LogicalExpression = exports.UnaryExpression = exports.BinaryExpression = exports.ObjectExpression = exports.ArrayExpression =
|
7
|
-
var ExpressionStatement_1 = require("./ExpressionStatement");
|
8
|
-
Object.defineProperty(exports, "ExpressionStatement", { enumerable: true, get: function () { return __importDefault(ExpressionStatement_1).default; } });
|
6
|
+
exports.AssignmentExpression = exports.NewExpression = exports.ChainExpression = exports.MemberExpression = exports.ArrowFunctionExpression = exports.CallExpression = exports.ConditionalExpression = exports.LogicalExpression = exports.UnaryExpression = exports.BinaryExpression = exports.ObjectExpression = exports.ArrayExpression = void 0;
|
9
7
|
var ArrayExpression_1 = require("./ArrayExpression");
|
10
8
|
Object.defineProperty(exports, "ArrayExpression", { enumerable: true, get: function () { return __importDefault(ArrayExpression_1).default; } });
|
11
9
|
var ObjectExpression_1 = require("./ObjectExpression");
|
@@ -26,3 +24,7 @@ var MemberExpression_1 = require("./MemberExpression");
|
|
26
24
|
Object.defineProperty(exports, "MemberExpression", { enumerable: true, get: function () { return __importDefault(MemberExpression_1).default; } });
|
27
25
|
var ChainExpression_1 = require("./ChainExpression");
|
28
26
|
Object.defineProperty(exports, "ChainExpression", { enumerable: true, get: function () { return __importDefault(ChainExpression_1).default; } });
|
27
|
+
var NewExpression_1 = require("./NewExpression");
|
28
|
+
Object.defineProperty(exports, "NewExpression", { enumerable: true, get: function () { return __importDefault(NewExpression_1).default; } });
|
29
|
+
var AssignmentExpression_1 = require("./AssignmentExpression");
|
30
|
+
Object.defineProperty(exports, "AssignmentExpression", { enumerable: true, get: function () { return __importDefault(AssignmentExpression_1).default; } });
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import { ArrayExpression, ArrowFunctionExpression, BinaryExpression, CallExpression, ChainExpression, ConditionalExpression,
|
1
|
+
import { ArrayExpression, ArrowFunctionExpression, AssignmentExpression, BinaryExpression, CallExpression, ChainExpression, ConditionalExpression, LogicalExpression, MemberExpression, NewExpression, ObjectExpression, UnaryExpression } from './expressions';
|
2
|
+
import { BlockStatement, ExpressionStatement, ReturnStatement, SwitchStatement } from './statements';
|
2
3
|
import { AnyNode } from 'acorn';
|
3
4
|
import type Context from '../Context';
|
4
5
|
import Identifier from './Identifier';
|
@@ -6,6 +7,7 @@ import Literal from './Literal';
|
|
6
7
|
import Node from './Node';
|
7
8
|
import Program from './Program';
|
8
9
|
import TemplateLiteral from './TemplateLiteral';
|
10
|
+
import VariableDeclaration from './VariableDeclaration';
|
9
11
|
type NodeConstructor = {
|
10
12
|
new (node: AnyNode, scope: Context): Node<AnyNode>;
|
11
13
|
};
|
@@ -27,6 +29,12 @@ declare const nodes: {
|
|
27
29
|
readonly CallExpression: typeof CallExpression;
|
28
30
|
readonly MemberExpression: typeof MemberExpression;
|
29
31
|
readonly ChainExpression: typeof ChainExpression;
|
32
|
+
readonly NewExpression: typeof NewExpression;
|
33
|
+
readonly BlockStatement: typeof BlockStatement;
|
34
|
+
readonly ReturnStatement: typeof ReturnStatement;
|
35
|
+
readonly VariableDeclaration: typeof VariableDeclaration;
|
36
|
+
readonly AssignmentExpression: typeof AssignmentExpression;
|
37
|
+
readonly SwitchStatement: typeof SwitchStatement;
|
30
38
|
};
|
31
39
|
export type NodeType = keyof typeof nodes;
|
32
40
|
declare const _default: NodeMap;
|
@@ -4,14 +4,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const expressions_1 = require("./expressions");
|
7
|
+
const statements_1 = require("./statements");
|
7
8
|
const Identifier_1 = __importDefault(require("./Identifier"));
|
8
9
|
const Literal_1 = __importDefault(require("./Literal"));
|
9
10
|
const Program_1 = __importDefault(require("./Program"));
|
10
11
|
const TemplateLiteral_1 = __importDefault(require("./TemplateLiteral"));
|
12
|
+
const VariableDeclaration_1 = __importDefault(require("./VariableDeclaration"));
|
11
13
|
const nodes = {
|
12
14
|
Program: Program_1.default,
|
13
15
|
Literal: Literal_1.default,
|
14
|
-
ExpressionStatement:
|
16
|
+
ExpressionStatement: statements_1.ExpressionStatement,
|
15
17
|
ArrayExpression: expressions_1.ArrayExpression,
|
16
18
|
ObjectExpression: expressions_1.ObjectExpression,
|
17
19
|
Identifier: Identifier_1.default,
|
@@ -25,5 +27,11 @@ const nodes = {
|
|
25
27
|
CallExpression: expressions_1.CallExpression,
|
26
28
|
MemberExpression: expressions_1.MemberExpression,
|
27
29
|
ChainExpression: expressions_1.ChainExpression,
|
30
|
+
NewExpression: expressions_1.NewExpression,
|
31
|
+
BlockStatement: statements_1.BlockStatement,
|
32
|
+
ReturnStatement: statements_1.ReturnStatement,
|
33
|
+
VariableDeclaration: VariableDeclaration_1.default,
|
34
|
+
AssignmentExpression: expressions_1.AssignmentExpression,
|
35
|
+
SwitchStatement: statements_1.SwitchStatement,
|
28
36
|
};
|
29
37
|
exports.default = new Map(Object.entries(nodes));
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { AnyNode, BlockStatement } from 'acorn';
|
2
|
+
import Context from '../../Context';
|
3
|
+
import Node from '../Node';
|
4
|
+
export default class BlockStatementNode extends Node<BlockStatement> {
|
5
|
+
constructor(node: AnyNode, context: Context);
|
6
|
+
validate(validateChildren?: boolean): void;
|
7
|
+
run(): unknown;
|
8
|
+
}
|