@casual-simulation/js-interpreter 3.5.0-alpha.15494496163 → 3.10.2
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/README.md +212 -2
- package/package.json +44 -45
package/README.md
CHANGED
|
@@ -1,3 +1,213 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @casual-simulation/js-interpreter
|
|
2
2
|
|
|
3
|
-
A sandboxed JavaScript interpreter
|
|
3
|
+
A sandboxed JavaScript interpreter built on top of [engine262](https://github.com/engine262/engine262), providing a secure execution environment for running untrusted JavaScript code with full ES6+ support, debugging capabilities, and controlled object marshalling between sandboxed and host environments.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides a complete JavaScript execution environment with isolation from the host environment, making it ideal for running user-provided code safely. It features step-by-step debugging, breakpoint support, and sophisticated object proxying to bridge sandboxed and host contexts.
|
|
8
|
+
|
|
9
|
+
## Main Exports
|
|
10
|
+
|
|
11
|
+
### `Interpreter`
|
|
12
|
+
|
|
13
|
+
A comprehensive JavaScript interpreter class that wraps engine262 capabilities with additional sandboxing, debugging, and object marshalling features.
|
|
14
|
+
|
|
15
|
+
**Features:**
|
|
16
|
+
|
|
17
|
+
- **Full ES6+ Support**: Complete ECMAScript specification compliance via engine262
|
|
18
|
+
- **Module System**: Create and execute ES6 modules with import/export support
|
|
19
|
+
- **Debugging**: Step-through execution with breakpoint support
|
|
20
|
+
- **Object Marshalling**: Bidirectional object proxying between sandboxed and host environments
|
|
21
|
+
- **Generator-based Execution**: Pausable/resumable execution for async operations
|
|
22
|
+
- **Symbol Mapping**: Automatic mapping of well-known symbols between contexts
|
|
23
|
+
- **Job Queue Management**: Full async operation support
|
|
24
|
+
|
|
25
|
+
**Key Methods:**
|
|
26
|
+
|
|
27
|
+
- `createAndLinkModule(code, moduleId)` - Create ES6 modules from code strings
|
|
28
|
+
- `createFunction(name, code, ...params)` - Create callable functions in the sandbox
|
|
29
|
+
- `callFunction(func, ...args)` - Execute sandboxed functions with host arguments
|
|
30
|
+
- `runJobQueue()` - Process async operations (promises, timers, etc.)
|
|
31
|
+
- `copyToValue(value)` - Convert host values to sandboxed values
|
|
32
|
+
- `copyFromValue(value)` - Convert sandboxed values to host values
|
|
33
|
+
- `proxyObject(obj)` - Create bidirectional object proxies
|
|
34
|
+
|
|
35
|
+
**Properties:**
|
|
36
|
+
|
|
37
|
+
- `agent` - The engine262 Agent managing execution
|
|
38
|
+
- `realm` - The isolated execution realm
|
|
39
|
+
- `debugging` - Enable/disable step-by-step execution
|
|
40
|
+
- `breakpoints` - Configured breakpoints for debugging
|
|
41
|
+
|
|
42
|
+
**Usage:**
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { Interpreter, unwind } from '@casual-simulation/js-interpreter';
|
|
46
|
+
|
|
47
|
+
// Create interpreter instance
|
|
48
|
+
const interpreter = new Interpreter();
|
|
49
|
+
|
|
50
|
+
// Create a function in the sandbox
|
|
51
|
+
const func = interpreter.createFunction('add', 'return a + b;', 'a', 'b');
|
|
52
|
+
|
|
53
|
+
// Call the function
|
|
54
|
+
const result = unwind(interpreter.callFunction(func, 5, 3));
|
|
55
|
+
console.log(result); // 8
|
|
56
|
+
|
|
57
|
+
// Create and execute a module
|
|
58
|
+
const module = interpreter.createAndLinkModule(
|
|
59
|
+
`
|
|
60
|
+
export function multiply(x, y) {
|
|
61
|
+
return x * y;
|
|
62
|
+
}
|
|
63
|
+
`,
|
|
64
|
+
'mathModule'
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Enable debugging
|
|
68
|
+
interpreter.debugging = true;
|
|
69
|
+
|
|
70
|
+
// Set breakpoints
|
|
71
|
+
const breakpoint = {
|
|
72
|
+
func,
|
|
73
|
+
lineNumber: 1,
|
|
74
|
+
columnNumber: 0,
|
|
75
|
+
states: ['before', 'after'],
|
|
76
|
+
disabled: false,
|
|
77
|
+
};
|
|
78
|
+
interpreter.breakpoints.push(breakpoint);
|
|
79
|
+
|
|
80
|
+
// Step through execution
|
|
81
|
+
const generator = interpreter.callFunction(func, 10, 20);
|
|
82
|
+
for (const step of generator) {
|
|
83
|
+
console.log('Breakpoint hit:', step);
|
|
84
|
+
// Continue execution by calling generator.next()
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `InterpreterUtils`
|
|
89
|
+
|
|
90
|
+
Utility functions for working with the interpreter, particularly for managing object marshalling and generator unwinding.
|
|
91
|
+
|
|
92
|
+
**Key Functions:**
|
|
93
|
+
|
|
94
|
+
#### `unwind<T>(generator): T`
|
|
95
|
+
|
|
96
|
+
Unwraps a generator by running it to completion and returning the final value. Essential for synchronous execution of interpreter operations.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const result = unwind(interpreter.callFunction(func, arg1, arg2));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### `unwindAndCapture<T, TReturn>(generator): { result: TReturn; states: T[] }`
|
|
103
|
+
|
|
104
|
+
Unwraps a generator while capturing all yielded intermediate states, useful for debugging.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const { result, states } = unwindAndCapture(generator);
|
|
108
|
+
console.log('Execution steps:', states);
|
|
109
|
+
console.log('Final result:', result);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### `isGenerator(value): boolean`
|
|
113
|
+
|
|
114
|
+
Type guard to check if a value is a generator object.
|
|
115
|
+
|
|
116
|
+
#### `isConstructor(func): boolean`
|
|
117
|
+
|
|
118
|
+
Determines if a function can be called as a constructor.
|
|
119
|
+
|
|
120
|
+
#### Object Marking Functions
|
|
121
|
+
|
|
122
|
+
- `markWithInterpretedObject(value, obj)` - Mark host objects with their sandboxed equivalents
|
|
123
|
+
- `markWithRegularObject(value, obj)` - Mark sandboxed objects with their host equivalents
|
|
124
|
+
- `markAsProxyObject(value)` - Mark objects as proxy objects
|
|
125
|
+
- `markAsUncopiableObject(value)` - Prevent automatic copying of objects
|
|
126
|
+
|
|
127
|
+
#### Symbol Constants
|
|
128
|
+
|
|
129
|
+
- `INTERPRETER_OBJECT` - Symbol for storing sandboxed object references
|
|
130
|
+
- `REGULAR_OBJECT` - Symbol for storing host object references
|
|
131
|
+
- `IS_PROXY_OBJECT` - Symbol for marking proxy objects
|
|
132
|
+
- `UNCOPIABLE` - Symbol for marking non-copyable objects
|
|
133
|
+
|
|
134
|
+
## Object Marshalling
|
|
135
|
+
|
|
136
|
+
The interpreter provides sophisticated marshalling between sandboxed and host environments:
|
|
137
|
+
|
|
138
|
+
### Copy vs. Proxy
|
|
139
|
+
|
|
140
|
+
**Copying** (via `copyToValue`/`copyFromValue`):
|
|
141
|
+
|
|
142
|
+
- Primitives: strings, numbers, booleans, null, undefined
|
|
143
|
+
- Simple objects and arrays (deep copy)
|
|
144
|
+
- Functions become wrapped functions
|
|
145
|
+
|
|
146
|
+
**Proxying** (via `proxyObject`):
|
|
147
|
+
|
|
148
|
+
- Complex objects that need live synchronization
|
|
149
|
+
- Objects marked with special symbols
|
|
150
|
+
- Error objects (to preserve stack traces)
|
|
151
|
+
|
|
152
|
+
### Bidirectional Communication
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// Host object available in sandbox
|
|
156
|
+
const hostObj = { value: 42 };
|
|
157
|
+
interpreter.proxyObject(hostObj);
|
|
158
|
+
|
|
159
|
+
// Changes in sandbox reflect in host
|
|
160
|
+
// Changes in host reflect in sandbox
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Debugging Features
|
|
164
|
+
|
|
165
|
+
### Breakpoints
|
|
166
|
+
|
|
167
|
+
Set breakpoints at specific locations with state control:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const breakpoint = {
|
|
171
|
+
func: constructedFunction,
|
|
172
|
+
lineNumber: 5,
|
|
173
|
+
columnNumber: 0,
|
|
174
|
+
states: ['before', 'after'], // Break before and/or after execution
|
|
175
|
+
disabled: false,
|
|
176
|
+
};
|
|
177
|
+
interpreter.breakpoints.push(breakpoint);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Execution States
|
|
181
|
+
|
|
182
|
+
When a breakpoint is hit, you receive:
|
|
183
|
+
|
|
184
|
+
- `state`: 'before' or 'after' the statement
|
|
185
|
+
- `breakpoint`: The breakpoint that was hit
|
|
186
|
+
- `node`: The AST node being executed
|
|
187
|
+
- `stack`: Current execution context stack
|
|
188
|
+
- `result`: (for 'after' state) The result of execution
|
|
189
|
+
|
|
190
|
+
## Use Cases
|
|
191
|
+
|
|
192
|
+
- **Code Sandboxing**: Run untrusted user code safely
|
|
193
|
+
- **Educational Tools**: Step-through execution for learning
|
|
194
|
+
- **Plugin Systems**: Execute plugins in isolated environments
|
|
195
|
+
- **Testing**: Controlled execution environments for tests
|
|
196
|
+
- **Scripting Engines**: Embeddable scripting for applications
|
|
197
|
+
|
|
198
|
+
## Dependencies
|
|
199
|
+
|
|
200
|
+
- **@casual-simulation/engine262**: ECMAScript specification implementation
|
|
201
|
+
- **@casual-simulation/error-stack-parser**: Stack trace parsing for better error reporting
|
|
202
|
+
- **@types/estree**: TypeScript types for ESTree AST nodes
|
|
203
|
+
- **stackframe**: Stack frame manipulation utilities
|
|
204
|
+
|
|
205
|
+
## Installation
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npm install @casual-simulation/js-interpreter
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Credits
|
|
212
|
+
|
|
213
|
+
Originally inspired by [NeilFraser/JS-Interpreter](https://github.com/NeilFraser/JS-Interpreter), rebuilt on engine262 for full ES6+ specification compliance.
|
package/package.json
CHANGED
|
@@ -1,46 +1,45 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
2
|
+
"name": "@casual-simulation/js-interpreter",
|
|
3
|
+
"version": "3.10.2",
|
|
4
|
+
"description": "A JavaScript interpreter",
|
|
5
|
+
"keywords": [],
|
|
6
|
+
"author": "Casual Simulation, Inc.",
|
|
7
|
+
"homepage": "https://github.com/casual-simulation/casualos",
|
|
8
|
+
"license": "AGPL-3.0-only",
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"types": "index.d.ts",
|
|
11
|
+
"module": "index",
|
|
12
|
+
"directories": {
|
|
13
|
+
"lib": "."
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"/README.md",
|
|
17
|
+
"/LICENSE.txt",
|
|
18
|
+
"**/*.js",
|
|
19
|
+
"**/*.js.map",
|
|
20
|
+
"**/*.d.ts"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/casual-simulation/casualos.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/casual-simulation/casualos/issues"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@casual-simulation/engine262": "0.0.1-4de2170374e22761996e46eb1362f4496ee57f8f",
|
|
34
|
+
"@casual-simulation/error-stack-parser": "^2.0.7",
|
|
35
|
+
"@types/estree": "1.0.0",
|
|
36
|
+
"stackframe": "^1.2.0"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"watch": "tsc --watch",
|
|
40
|
+
"watch:player": "npm run watch",
|
|
41
|
+
"build": "echo \"Nothing to do.\"",
|
|
42
|
+
"test": "jest",
|
|
43
|
+
"test:watch": "jest --watchAll"
|
|
44
|
+
}
|
|
45
|
+
}
|