quickjs-emscripten-sync 1.2.0 → 1.5.0
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/LICENSE +2 -2
- package/README.md +71 -44
- package/dist/index.d.ts +116 -23
- package/dist/quickjs-emscripten-sync.mjs +842 -0
- package/dist/quickjs-emscripten-sync.umd.js +64 -2
- package/package.json +22 -53
- package/src/default.ts +2 -2
- package/src/index.test.ts +223 -59
- package/src/index.ts +72 -66
- package/src/marshal/custom.test.ts +50 -0
- package/src/marshal/custom.ts +36 -0
- package/src/marshal/function.test.ts +64 -75
- package/src/marshal/function.ts +15 -18
- package/src/marshal/index.test.ts +122 -77
- package/src/marshal/index.ts +19 -15
- package/src/marshal/json.test.ts +37 -41
- package/src/marshal/json.ts +5 -7
- package/src/marshal/object.test.ts +59 -84
- package/src/marshal/object.ts +8 -15
- package/src/marshal/primitive.test.ts +18 -21
- package/src/marshal/primitive.ts +11 -10
- package/src/marshal/promise.test.ts +85 -0
- package/src/marshal/promise.ts +19 -0
- package/src/marshal/properties.test.ts +24 -27
- package/src/marshal/properties.ts +15 -17
- package/src/unmarshal/custom.test.ts +50 -0
- package/src/unmarshal/custom.ts +31 -0
- package/src/unmarshal/function.test.ts +63 -86
- package/src/unmarshal/function.ts +13 -22
- package/src/unmarshal/index.test.ts +114 -109
- package/src/unmarshal/index.ts +15 -14
- package/src/unmarshal/object.test.ts +42 -46
- package/src/unmarshal/object.ts +16 -20
- package/src/unmarshal/primitive.test.ts +17 -15
- package/src/unmarshal/primitive.ts +11 -18
- package/src/unmarshal/promise.test.ts +44 -0
- package/src/unmarshal/promise.ts +31 -0
- package/src/unmarshal/properties.test.ts +11 -9
- package/src/unmarshal/properties.ts +44 -45
- package/src/util.test.ts +14 -2
- package/src/util.ts +18 -8
- package/src/vmmap.test.ts +88 -82
- package/src/vmmap.ts +30 -44
- package/src/vmutil.test.ts +100 -75
- package/src/vmutil.ts +51 -34
- package/src/wrapper.test.ts +129 -167
- package/src/wrapper.ts +59 -62
- package/dist/default.d.ts +0 -4
- package/dist/marshal/function.d.ts +0 -2
- package/dist/marshal/index.d.ts +0 -11
- package/dist/marshal/json.d.ts +0 -2
- package/dist/marshal/object.d.ts +0 -2
- package/dist/marshal/primitive.d.ts +0 -2
- package/dist/marshal/properties.d.ts +0 -2
- package/dist/marshal/symbol.d.ts +0 -2
- package/dist/quickjs-emscripten-sync.cjs +0 -2
- package/dist/quickjs-emscripten-sync.cjs.map +0 -1
- package/dist/quickjs-emscripten-sync.modern.js +0 -2
- package/dist/quickjs-emscripten-sync.modern.js.map +0 -1
- package/dist/quickjs-emscripten-sync.module.js +0 -2
- package/dist/quickjs-emscripten-sync.module.js.map +0 -1
- package/dist/quickjs-emscripten-sync.umd.js.map +0 -1
- package/dist/unmarshal/function.d.ts +0 -2
- package/dist/unmarshal/index.d.ts +0 -9
- package/dist/unmarshal/object.d.ts +0 -2
- package/dist/unmarshal/primitive.d.ts +0 -2
- package/dist/unmarshal/properties.d.ts +0 -2
- package/dist/unmarshal/symbol.d.ts +0 -2
- package/dist/util.d.ts +0 -7
- package/dist/vmmap.d.ts +0 -35
- package/dist/vmutil.d.ts +0 -11
- package/dist/wrapper.d.ts +0 -11
- package/src/marshal/symbol.test.ts +0 -22
- package/src/marshal/symbol.ts +0 -20
- package/src/unmarshal/symbol.test.ts +0 -23
- package/src/unmarshal/symbol.ts +0 -12
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2022 rot1024
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# quickjs-emscripten-sync
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/reearth/quickjs-emscripten-sync/actions/workflows/main.yml) [](https://codecov.io/gh/reearth/quickjs-emscripten-sync)
|
|
4
|
+
|
|
5
|
+
Build a secure plugin system in web browsers
|
|
4
6
|
|
|
5
7
|
This library wraps [quickjs-emscripten](https://github.com/justjake/quickjs-emscripten) and provides a way to sync object state between the browser and sandboxed QuickJS.
|
|
6
8
|
|
|
@@ -10,6 +12,7 @@ This library wraps [quickjs-emscripten](https://github.com/justjake/quickjs-emsc
|
|
|
10
12
|
- Functions
|
|
11
13
|
- Classes and instances
|
|
12
14
|
- Objects with prototypes and any property descriptors
|
|
15
|
+
- Promises
|
|
13
16
|
- Expose objects as a global object in QuickJS
|
|
14
17
|
- Marshaling limitation for specific objects
|
|
15
18
|
- Register a pair of objects that will be considered the same between the browser and QuickJS
|
|
@@ -30,10 +33,10 @@ class Cls {
|
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
const
|
|
34
|
-
const arena = new Arena(
|
|
36
|
+
const ctx = (await getQuickJS()).newContext();
|
|
37
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
35
38
|
|
|
36
|
-
// We can pass objects to the
|
|
39
|
+
// We can pass objects to the context and run code safely
|
|
37
40
|
const exposed = {
|
|
38
41
|
Cls,
|
|
39
42
|
cls: new Cls(),
|
|
@@ -41,17 +44,17 @@ const exposed = {
|
|
|
41
44
|
};
|
|
42
45
|
arena.expose(exposed);
|
|
43
46
|
|
|
44
|
-
arena.evalCode(`cls instanceof Cls`)
|
|
45
|
-
arena.evalCode(`cls.field`)
|
|
46
|
-
arena.evalCode(`cls.method()`)
|
|
47
|
-
arena.evalCode(`cls.field`)
|
|
47
|
+
arena.evalCode(`cls instanceof Cls`); // returns true
|
|
48
|
+
arena.evalCode(`cls.field`); // returns 0
|
|
49
|
+
arena.evalCode(`cls.method()`); // returns 1
|
|
50
|
+
arena.evalCode(`cls.field`); // returns 1
|
|
48
51
|
|
|
49
|
-
arena.evalCode(`syncedCls.field`);
|
|
50
|
-
exposed.syncedCls.method();
|
|
51
|
-
arena.evalCode(`syncedCls.field`);
|
|
52
|
+
arena.evalCode(`syncedCls.field`); // returns 0
|
|
53
|
+
exposed.syncedCls.method(); // returns 1
|
|
54
|
+
arena.evalCode(`syncedCls.field`); // returns 1
|
|
52
55
|
|
|
53
56
|
arena.dispose();
|
|
54
|
-
|
|
57
|
+
ctx.dispose();
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
[Example code](src/index.test.ts) is available as the unit test code.
|
|
@@ -70,13 +73,14 @@ import { getQuickJS } from "quickjs-emscripten";
|
|
|
70
73
|
import { Arena } from "quickjs-emscripten-sync";
|
|
71
74
|
|
|
72
75
|
(async function() {
|
|
73
|
-
const
|
|
74
|
-
const vm = quickjs.createVm();
|
|
76
|
+
const ctx = (await getQuickJS()).newContext();
|
|
75
77
|
|
|
76
78
|
// init Arena
|
|
77
|
-
|
|
79
|
+
// ⚠️ Marshaling is opt-in for security reasons.
|
|
80
|
+
// ⚠️ Be careful when activating marshalling.
|
|
81
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
78
82
|
|
|
79
|
-
// expose objects as global objects in QuickJS
|
|
83
|
+
// expose objects as global objects in QuickJS context
|
|
80
84
|
arena.expose({
|
|
81
85
|
console: {
|
|
82
86
|
log: console.log
|
|
@@ -87,23 +91,23 @@ import { Arena } from "quickjs-emscripten-sync";
|
|
|
87
91
|
|
|
88
92
|
// expose objects but also enable sync
|
|
89
93
|
const data = arena.sync({ hoge: "foo" });
|
|
90
|
-
|
|
94
|
+
arena.expose({ data });
|
|
91
95
|
|
|
92
96
|
arena.evalCode(`data.hoge = "bar"`);
|
|
93
97
|
// eval code and operations to exposed objects are automatically synced
|
|
94
98
|
console.log(data.hoge); // "bar"
|
|
95
|
-
|
|
99
|
+
data.hoge = "changed!";
|
|
96
100
|
console.log(arena.evalCode(`data.hoge`)); // "changed!"
|
|
97
101
|
|
|
98
|
-
// Don't forget calling arena.dispose() before disposing QuickJS
|
|
102
|
+
// Don't forget calling arena.dispose() before disposing QuickJS context!
|
|
99
103
|
arena.dispose();
|
|
100
|
-
|
|
104
|
+
ctx.dispose();
|
|
101
105
|
})();
|
|
102
106
|
```
|
|
103
107
|
|
|
104
108
|
## Marshaling Limitations
|
|
105
109
|
|
|
106
|
-
Objects are automatically converted when they cross between the host and the QuickJS
|
|
110
|
+
Objects are automatically converted when they cross between the host and the QuickJS context. The conversion of a host's object to a handle is called marshaling, and the conversion of a handle to a host's object is called unmarshaling.
|
|
107
111
|
|
|
108
112
|
And for marshalling, it is possible to control whether the conversion is performed or not.
|
|
109
113
|
|
|
@@ -112,7 +116,7 @@ For example, exposing the host's global object to QuickJS is very heavy and dang
|
|
|
112
116
|
```js
|
|
113
117
|
import { Arena, complexity } from "quickjs-emscripten-sync";
|
|
114
118
|
|
|
115
|
-
const arena = new Arena(
|
|
119
|
+
const arena = new Arena(ctx, {
|
|
116
120
|
isMarshalable: (target: any) => {
|
|
117
121
|
// prevent passing globalThis to QuickJS
|
|
118
122
|
if (target === window) return false;
|
|
@@ -179,32 +183,55 @@ By default, quickjs-emscripten-sync doesn't prevent any marshaling, even in such
|
|
|
179
183
|
|
|
180
184
|
### `Arena`
|
|
181
185
|
|
|
182
|
-
The Arena class manages all generated handles at once by quickjs-emscripten and automatically converts objects between the host and the QuickJS
|
|
186
|
+
The Arena class manages all generated handles at once by quickjs-emscripten and automatically converts objects between the host and the QuickJS context.
|
|
183
187
|
|
|
184
|
-
#### `new Arena(
|
|
188
|
+
#### `new Arena(ctx: QuickJSContext, options?: Options)`
|
|
185
189
|
|
|
186
|
-
Constructs a new Arena instance. It requires a quickjs-emscripten
|
|
190
|
+
Constructs a new Arena instance. It requires a quickjs-emscripten context initialized with `quickjs.newContext()`.
|
|
187
191
|
|
|
188
192
|
Options accepted:
|
|
189
193
|
|
|
190
194
|
```ts
|
|
191
195
|
type Options = {
|
|
196
|
+
/** A callback that returns a boolean value that determines whether an object is marshalled or not. If false, no marshaling will be done and undefined will be passed to the QuickJS VM, otherwise marshaling will be done. By default, all objects will be marshalled. */
|
|
192
197
|
isMarshalable?: boolean | "json" | ((target: any) => boolean | "json");
|
|
198
|
+
/** Pre-registered pairs of objects that will be considered the same between the host and the QuickJS VM. This will be used automatically during the conversion. By default, it will be registered automatically with `defaultRegisteredObjects`.
|
|
199
|
+
*
|
|
200
|
+
* Instead of a string, you can also pass a QuickJSHandle directly. In that case, however, you have to dispose of them manually when destroying the VM.
|
|
201
|
+
*/
|
|
193
202
|
registeredObjects?: Iterable<[any, QuickJSHandle | string]>;
|
|
203
|
+
/** Register functions to convert an object to a QuickJS handle. */
|
|
204
|
+
customMarshaller?: Iterable<
|
|
205
|
+
(target: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined
|
|
206
|
+
>;
|
|
207
|
+
/** Register functions to convert a QuickJS handle to an object. */
|
|
208
|
+
customUnmarshaller?: Iterable<
|
|
209
|
+
(target: QuickJSHandle, ctx: QuickJSContext) => any
|
|
210
|
+
>;
|
|
211
|
+
/** A callback that returns a boolean value that determines whether an object is wrappable by proxies. If returns false, note that the object cannot be synchronized between the host and the QuickJS even if arena.sync is used. */
|
|
212
|
+
isWrappable?: (target: any) => boolean;
|
|
213
|
+
/** A callback that returns a boolean value that determines whether an QuickJS handle is wrappable by proxies. If returns false, note that the handle cannot be synchronized between the host and the QuickJS even if arena.sync is used. */
|
|
214
|
+
isHandleWrappable?: (handle: QuickJSHandle, ctx: QuickJSContext) => boolean;
|
|
215
|
+
/** Compatibility with quickjs-emscripten prior to v0.15. Inject code for compatibility into context at Arena class initialization time. */
|
|
216
|
+
compat?: boolean;
|
|
194
217
|
}
|
|
195
218
|
```
|
|
196
219
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
220
|
+
Notes:
|
|
221
|
+
|
|
222
|
+
**`isMarshalable`**: Determines how marshalling will be done when sending objects from the host to the context. **Make sure to set the marshalling to be the minimum necessary as it may reduce the security of your application.** [Please read the section on security above.](#security-warning)
|
|
223
|
+
|
|
224
|
+
- `"json"` (**default**, safety): Target object will be serialized as JSON in host and then parsed in context. Functions and classes will be lost in the process.
|
|
225
|
+
- `false` (safety): Target object will not be always marshalled as `undefined`.
|
|
226
|
+
- `(target: any) => boolean | "json"` (recoomended): You can control marshalling mode for each objects. If you want to do marshalling, usually use this method. Allow partial marshalling by returning `true` only for some objects.
|
|
227
|
+
- `true` (**risky and not recommended**): Target object will be always marshaled. This setting may reduce security.
|
|
228
|
+
|
|
229
|
+
**`registeredObjects`**: You can pre-register a pair of objects that will be considered the same between the host and the QuickJS context. This will be used automatically during the conversion. By default, it will be registered automatically with [`defaultRegisteredObjects`](src/default.ts). If you want to add a new pair to this, please do the following:
|
|
203
230
|
|
|
204
231
|
```js
|
|
205
232
|
import { defaultRegisteredObjects } from "quickjs-emscripten-sync";
|
|
206
233
|
|
|
207
|
-
const arena = new Arena(
|
|
234
|
+
const arena = new Arena(ctx, {
|
|
208
235
|
registeredObjects: [
|
|
209
236
|
...defaultRegisteredObjects,
|
|
210
237
|
[Math, "Math"]
|
|
@@ -212,36 +239,36 @@ const arena = new Arena(vm, {
|
|
|
212
239
|
});
|
|
213
240
|
```
|
|
214
241
|
|
|
215
|
-
Instead of a string, you can also pass a QuickJSHandle directly. In that case, however, you have to dispose of them manually when destroying the
|
|
242
|
+
Instead of a string, you can also pass a QuickJSHandle directly. In that case, however, you have to dispose of them manually when destroying the context.
|
|
216
243
|
|
|
217
244
|
#### `dispose()`
|
|
218
245
|
|
|
219
|
-
Dispose of the arena and managed handles. This method won't dispose the
|
|
246
|
+
Dispose of the arena and managed handles. This method won't dispose the context itself, so the context has to be disposed of manually.
|
|
220
247
|
|
|
221
248
|
#### `evalCode<T = any>(code: string): T | undefined`
|
|
222
249
|
|
|
223
|
-
Evaluate JS code in the
|
|
250
|
+
Evaluate JS code in the context and get the result as an object on the host side. It also converts and re-throws error objects when an error is thrown during evaluation.
|
|
224
251
|
|
|
225
252
|
#### `executePendingJobs(): number`
|
|
226
253
|
|
|
227
|
-
Almost same as `
|
|
254
|
+
Almost same as `ctx.runtime.executePendingJobs()`, but it converts and re-throws error objects when an error is thrown during evaluation.
|
|
228
255
|
|
|
229
256
|
#### `expose(obj: { [k: string]: any })`
|
|
230
257
|
|
|
231
|
-
Expose objects as global objects in the
|
|
258
|
+
Expose objects as global objects in the context.
|
|
232
259
|
|
|
233
|
-
By default, exposed objects are not synchronized between the host and the
|
|
260
|
+
By default, exposed objects are not synchronized between the host and the context.
|
|
234
261
|
If you want to sync an objects, first wrap the object with `sync` method, and then expose the wrapped object.
|
|
235
262
|
|
|
236
263
|
#### `sync<T>(target: T): T`
|
|
237
264
|
|
|
238
|
-
Enables sync for the object between the host and the
|
|
265
|
+
Enables sync for the object between the host and the context and returns objects wrapped with proxies.
|
|
239
266
|
|
|
240
|
-
The return value is necessary in order to reflect changes to the object from the host to the
|
|
267
|
+
The return value is necessary in order to reflect changes to the object from the host to the context. Please note that setting a value in the field or deleting a field in the original object will not synchronize it.
|
|
241
268
|
|
|
242
269
|
#### `register(target: any, code: string | QuickJSHandle)`
|
|
243
270
|
|
|
244
|
-
Register a pair of objects that will be considered the same between the host and the QuickJS
|
|
271
|
+
Register a pair of objects that will be considered the same between the host and the QuickJS context.
|
|
245
272
|
|
|
246
273
|
#### `unregisterAll(targets: Iterable<[any, string | QuickJSHandle]>)`
|
|
247
274
|
|
|
@@ -267,9 +294,9 @@ Measure the complexity of an object as you traverse the field and prototype chai
|
|
|
267
294
|
|
|
268
295
|
### How to work
|
|
269
296
|
|
|
270
|
-
quickjs-emscripten can execute JS code safely, but it requires to deal with a lot of handles and lifetimes. Also, when destroying the
|
|
297
|
+
quickjs-emscripten can execute JS code safely, but it requires to deal with a lot of handles and lifetimes. Also, when destroying the context, any un-destroyed handle will result in an error.
|
|
271
298
|
|
|
272
|
-
quickjs-emscripten-sync will automatically manage all handles once generated by QuickJS
|
|
299
|
+
quickjs-emscripten-sync will automatically manage all handles once generated by QuickJS context in an Arena class.
|
|
273
300
|
And it will automatically "marshal" objects as handles and "unmarshal" handles as objects to enable seamless data exchange between the browser and QuickJS. It recursively traverses the object properties and prototype chain to transform objects. A function is called after its arguments and this arg are automatically converted for the environment in which the function is defined. The return value will be automatically converted to match the environment of the caller.
|
|
274
301
|
Most objects are wrapped by proxies during conversion, allowing "set" and "delete" operations on objects to be synchronized between the browser and QuickJS.
|
|
275
302
|
|
|
@@ -277,7 +304,7 @@ Most objects are wrapped by proxies during conversion, allowing "set" and "delet
|
|
|
277
304
|
|
|
278
305
|
#### Class constructor
|
|
279
306
|
|
|
280
|
-
When initializing a new instance, it is not possible to fully proxy this arg (a.k.a. `new.target`) inside the class constructor. Therefore, after the constructor call, the fields set for this are re-set to this on the
|
|
307
|
+
When initializing a new instance, it is not possible to fully proxy this arg (a.k.a. `new.target`) inside the class constructor. Therefore, after the constructor call, the fields set for this are re-set to this on the context side. Therefore, there may be some edge cases where the constructor may not work properly.
|
|
281
308
|
|
|
282
309
|
```js
|
|
283
310
|
class Cls {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import { complexity, isES2015Class, isObject, walkObject } from "./util";
|
|
8
|
-
import { call, eq, isHandleObject, json, consumeAll } from "./vmutil";
|
|
9
|
-
import { defaultRegisteredObjects } from "./default";
|
|
10
|
-
export { VMMap, defaultRegisteredObjects, marshal, unmarshal, complexity, isES2015Class, isObject, walkObject, call, eq, isHandleObject, json, consumeAll, };
|
|
11
|
-
export declare type Options = {
|
|
12
|
-
/** A callback that returns a boolean value that determines whether an object is marshalled or not. If false, no marshaling will be done and undefined will be passed to the QuickJS VM, otherwise marshaling will be done. By default, all objects will be marshalled. */
|
|
13
|
-
isMarshalable?: boolean | "json" | ((target: any) => boolean | "json");
|
|
14
|
-
/** You can pre-register a pair of objects that will be considered the same between the host and the QuickJS VM. This will be used automatically during the conversion. By default, it will be registered automatically with `defaultRegisteredObjects`.
|
|
15
|
-
*
|
|
16
|
-
* Instead of a string, you can also pass a QuickJSHandle directly. In that case, however, you have to dispose of them manually when destroying the VM.
|
|
17
|
-
*/
|
|
18
|
-
registeredObjects?: Iterable<[any, QuickJSHandle | string]>;
|
|
19
|
-
};
|
|
1
|
+
import type { QuickJSContext } from 'quickjs-emscripten';
|
|
2
|
+
import type { QuickJSDeferredPromise } from 'quickjs-emscripten';
|
|
3
|
+
import type { QuickJSHandle } from 'quickjs-emscripten';
|
|
4
|
+
import type { SuccessOrFail } from 'quickjs-emscripten';
|
|
5
|
+
import type { VmCallResult } from 'quickjs-emscripten';
|
|
6
|
+
|
|
20
7
|
/**
|
|
21
8
|
* The Arena class manages all generated handles at once by quickjs-emscripten and automatically converts objects between the host and the QuickJS VM.
|
|
22
9
|
*/
|
|
23
10
|
export declare class Arena {
|
|
24
|
-
|
|
11
|
+
context: QuickJSContext;
|
|
25
12
|
_map: VMMap;
|
|
26
13
|
_registeredMap: VMMap;
|
|
27
14
|
_registeredMapDispose: Set<any>;
|
|
@@ -30,8 +17,8 @@ export declare class Arena {
|
|
|
30
17
|
_symbol: symbol;
|
|
31
18
|
_symbolHandle: QuickJSHandle;
|
|
32
19
|
_options?: Options;
|
|
33
|
-
/** Constructs a new Arena instance. It requires a quickjs-emscripten
|
|
34
|
-
constructor(
|
|
20
|
+
/** Constructs a new Arena instance. It requires a quickjs-emscripten context initialized with `quickjs.newContext()`. */
|
|
21
|
+
constructor(ctx: QuickJSContext, options?: Options);
|
|
35
22
|
/**
|
|
36
23
|
* Dispose of the arena and managed handles. This method won't dispose the VM itself, so the VM has to be disposed of manually.
|
|
37
24
|
*/
|
|
@@ -83,7 +70,7 @@ export declare class Arena {
|
|
|
83
70
|
_unwrapResultAndUnmarshal(result: VmCallResult<QuickJSHandle> | undefined): any;
|
|
84
71
|
_isMarshalable: (t: unknown) => boolean | "json";
|
|
85
72
|
_marshalFind: (t: unknown) => QuickJSHandle | undefined;
|
|
86
|
-
_marshalPre: (t: unknown, h: QuickJSHandle, mode: true | "json" | undefined) => Wrapped<QuickJSHandle> | undefined;
|
|
73
|
+
_marshalPre: (t: unknown, h: QuickJSHandle | QuickJSDeferredPromise, mode: true | "json" | undefined) => Wrapped<QuickJSHandle> | undefined;
|
|
87
74
|
_marshalPreApply: (target: Function, that: unknown, args: unknown[]) => void;
|
|
88
75
|
_marshal: (target: any) => [QuickJSHandle, boolean];
|
|
89
76
|
_preUnmarshal: (t: any, h: QuickJSHandle) => Wrapped<any>;
|
|
@@ -97,3 +84,109 @@ export declare class Arena {
|
|
|
97
84
|
_wrapHandle(handle: QuickJSHandle): [Wrapped<QuickJSHandle> | undefined, boolean];
|
|
98
85
|
_unwrapHandle(target: QuickJSHandle): [QuickJSHandle, boolean];
|
|
99
86
|
}
|
|
87
|
+
|
|
88
|
+
export declare function call(ctx: QuickJSContext, code: string, thisArg?: QuickJSHandle, ...args: QuickJSHandle[]): QuickJSHandle;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Measure the complexity of an object as you traverse the field and prototype chain. If max is specified, when the complexity reaches max, the traversal is terminated and it returns the max. In this function, one object and function are counted as a complexity of 1, and primitives are not counted as a complexity.
|
|
92
|
+
*/
|
|
93
|
+
export declare function complexity(value: any, max?: number): number;
|
|
94
|
+
|
|
95
|
+
export declare function consumeAll<T extends QuickJSHandle[], K>(handles: T, cb: (handles: T) => K): K;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Default value of registeredObjects option of the Arena class constructor.
|
|
99
|
+
*/
|
|
100
|
+
export declare const defaultRegisteredObjects: [any, string][];
|
|
101
|
+
|
|
102
|
+
export declare function eq(ctx: QuickJSContext, a: QuickJSHandle, b: QuickJSHandle): boolean;
|
|
103
|
+
|
|
104
|
+
export declare function isES2015Class(cls: any): cls is new (...args: any[]) => any;
|
|
105
|
+
|
|
106
|
+
export declare function isHandleObject(ctx: QuickJSContext, h: QuickJSHandle): boolean;
|
|
107
|
+
|
|
108
|
+
export declare function isObject(value: any): value is object | Function;
|
|
109
|
+
|
|
110
|
+
export declare function json(ctx: QuickJSContext, target: any): QuickJSHandle;
|
|
111
|
+
|
|
112
|
+
export declare function marshal(target: unknown, options: Options_2): QuickJSHandle;
|
|
113
|
+
|
|
114
|
+
export declare type Options = {
|
|
115
|
+
/** A callback that returns a boolean value that determines whether an object is marshalled or not. If false, no marshaling will be done and undefined will be passed to the QuickJS VM, otherwise marshaling will be done. By default, all objects will be marshalled. */
|
|
116
|
+
isMarshalable?: boolean | "json" | ((target: any) => boolean | "json");
|
|
117
|
+
/** Pre-registered pairs of objects that will be considered the same between the host and the QuickJS VM. This will be used automatically during the conversion. By default, it will be registered automatically with `defaultRegisteredObjects`.
|
|
118
|
+
*
|
|
119
|
+
* Instead of a string, you can also pass a QuickJSHandle directly. In that case, however, you have to dispose of them manually when destroying the VM.
|
|
120
|
+
*/
|
|
121
|
+
registeredObjects?: Iterable<[any, QuickJSHandle | string]>;
|
|
122
|
+
/** Register functions to convert an object to a QuickJS handle. */
|
|
123
|
+
customMarshaller?: Iterable<(target: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined>;
|
|
124
|
+
/** Register functions to convert a QuickJS handle to an object. */
|
|
125
|
+
customUnmarshaller?: Iterable<(target: QuickJSHandle, ctx: QuickJSContext) => any>;
|
|
126
|
+
/** A callback that returns a boolean value that determines whether an object is wrappable by proxies. If returns false, note that the object cannot be synchronized between the host and the QuickJS even if arena.sync is used. */
|
|
127
|
+
isWrappable?: (target: any) => boolean;
|
|
128
|
+
/** A callback that returns a boolean value that determines whether an QuickJS handle is wrappable by proxies. If returns false, note that the handle cannot be synchronized between the host and the QuickJS even if arena.sync is used. */
|
|
129
|
+
isHandleWrappable?: (handle: QuickJSHandle, ctx: QuickJSContext) => boolean;
|
|
130
|
+
/** Compatibility with quickjs-emscripten prior to v0.15. Inject code for compatibility into context at Arena class initialization time. */
|
|
131
|
+
compat?: boolean;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
declare type Options_2 = {
|
|
135
|
+
ctx: QuickJSContext;
|
|
136
|
+
unmarshal: (handle: QuickJSHandle) => unknown;
|
|
137
|
+
isMarshalable?: (target: unknown) => boolean | "json";
|
|
138
|
+
find: (target: unknown) => QuickJSHandle | undefined;
|
|
139
|
+
pre: (target: unknown, handle: QuickJSHandle | QuickJSDeferredPromise, mode: true | "json" | undefined) => QuickJSHandle | undefined;
|
|
140
|
+
preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any;
|
|
141
|
+
custom?: Iterable<(obj: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined>;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
declare type Options_3 = {
|
|
145
|
+
ctx: QuickJSContext;
|
|
146
|
+
/** marshal returns handle and boolean indicates that the handle should be disposed after use */
|
|
147
|
+
marshal: (target: unknown) => [QuickJSHandle, boolean];
|
|
148
|
+
find: (handle: QuickJSHandle) => unknown | undefined;
|
|
149
|
+
pre: <T = unknown>(target: T, handle: QuickJSHandle) => T | undefined;
|
|
150
|
+
custom?: Iterable<(obj: QuickJSHandle, ctx: QuickJSContext) => any>;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export declare function unmarshal(handle: QuickJSHandle, options: Options_3): any;
|
|
154
|
+
|
|
155
|
+
export declare class VMMap {
|
|
156
|
+
ctx: QuickJSContext;
|
|
157
|
+
_map1: Map<any, number>;
|
|
158
|
+
_map2: Map<any, number>;
|
|
159
|
+
_map3: Map<number, QuickJSHandle>;
|
|
160
|
+
_map4: Map<number, QuickJSHandle>;
|
|
161
|
+
_counterMap: Map<number, any>;
|
|
162
|
+
_disposables: Set<QuickJSHandle>;
|
|
163
|
+
_mapGet: QuickJSHandle;
|
|
164
|
+
_mapSet: QuickJSHandle;
|
|
165
|
+
_mapDelete: QuickJSHandle;
|
|
166
|
+
_mapClear: QuickJSHandle;
|
|
167
|
+
_counter: number;
|
|
168
|
+
constructor(ctx: QuickJSContext);
|
|
169
|
+
set(key: any, handle: QuickJSHandle, key2?: any, handle2?: QuickJSHandle): boolean;
|
|
170
|
+
merge(iteratable: Iterable<[any, QuickJSHandle | undefined] | [any, QuickJSHandle | undefined, any, QuickJSHandle | undefined]> | undefined): void;
|
|
171
|
+
get(key: any): QuickJSHandle | undefined;
|
|
172
|
+
getByHandle(handle: QuickJSHandle): any;
|
|
173
|
+
has(key: any): boolean;
|
|
174
|
+
hasHandle(handle: QuickJSHandle): boolean;
|
|
175
|
+
keys(): IterableIterator<any>;
|
|
176
|
+
delete(key: any, dispose?: boolean): void;
|
|
177
|
+
deleteByHandle(handle: QuickJSHandle, dispose?: boolean): void;
|
|
178
|
+
clear(): void;
|
|
179
|
+
dispose(): void;
|
|
180
|
+
get size(): number;
|
|
181
|
+
[Symbol.iterator](): Iterator<[any, QuickJSHandle, any, QuickJSHandle | undefined]>;
|
|
182
|
+
_get2(num: number): any;
|
|
183
|
+
_call(fn: QuickJSHandle, thisArg: QuickJSHandle | undefined, ...args: QuickJSHandle[]): QuickJSHandle;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export declare function walkObject(value: any, callback?: (target: any, set: Set<any>) => boolean | void): Set<any>;
|
|
187
|
+
|
|
188
|
+
declare type Wrapped<T> = T & {
|
|
189
|
+
__qes_wrapped: never;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export { }
|