quickjs-emscripten-sync 1.2.0 → 1.3.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 +13 -9
- package/dist/index.d.ts +106 -20
- package/dist/quickjs-emscripten-sync.es.js +951 -0
- package/dist/quickjs-emscripten-sync.umd.js +64 -2
- package/package.json +24 -46
- package/src/index.test.ts +70 -0
- package/src/index.ts +9 -4
- package/src/marshal/function.test.ts +8 -7
- package/src/marshal/index.test.ts +46 -5
- package/src/marshal/index.ts +9 -3
- package/src/marshal/json.test.ts +5 -3
- package/src/marshal/object.test.ts +9 -7
- package/src/marshal/primitive.test.ts +2 -0
- package/src/marshal/promise.test.ts +86 -0
- package/src/marshal/promise.ts +26 -0
- package/src/marshal/properties.test.ts +4 -2
- package/src/marshal/symbol.test.ts +3 -1
- package/src/unmarshal/function.test.ts +15 -16
- package/src/unmarshal/index.test.ts +81 -84
- package/src/unmarshal/index.ts +4 -2
- package/src/unmarshal/object.test.ts +11 -9
- package/src/unmarshal/primitive.test.ts +2 -0
- package/src/unmarshal/promise.test.ts +44 -0
- package/src/unmarshal/promise.ts +40 -0
- package/src/unmarshal/properties.test.ts +3 -1
- package/src/unmarshal/symbol.test.ts +3 -1
- package/src/util.test.ts +19 -2
- package/src/util.ts +15 -0
- package/src/vmmap.test.ts +22 -0
- package/src/vmmap.ts +4 -0
- package/src/vmutil.test.ts +44 -3
- package/src/vmutil.ts +47 -7
- package/src/wrapper.test.ts +24 -22
- 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/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
|
|
|
@@ -31,7 +33,7 @@ class Cls {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
const vm = (await getQuickJS()).createVm();
|
|
34
|
-
const arena = new Arena(vm);
|
|
36
|
+
const arena = new Arena(vm, { isMarshalable: true });
|
|
35
37
|
|
|
36
38
|
// We can pass objects to the VM and run code safely
|
|
37
39
|
const exposed = {
|
|
@@ -41,10 +43,10 @@ const exposed = {
|
|
|
41
43
|
};
|
|
42
44
|
arena.expose(exposed);
|
|
43
45
|
|
|
44
|
-
arena.evalCode(`cls instanceof Cls`)
|
|
45
|
-
arena.evalCode(`cls.field`)
|
|
46
|
-
arena.evalCode(`cls.method()`)
|
|
47
|
-
arena.evalCode(`cls.field`)
|
|
46
|
+
arena.evalCode(`cls instanceof Cls`); // returns true
|
|
47
|
+
arena.evalCode(`cls.field`); // returns 0
|
|
48
|
+
arena.evalCode(`cls.method()`); // returns 1
|
|
49
|
+
arena.evalCode(`cls.field`); // returns 1
|
|
48
50
|
|
|
49
51
|
arena.evalCode(`syncedCls.field`); // returns 0
|
|
50
52
|
exposed.syncedCls.method(); // returns 1
|
|
@@ -74,7 +76,9 @@ import { Arena } from "quickjs-emscripten-sync";
|
|
|
74
76
|
const vm = quickjs.createVm();
|
|
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(vm, { isMarshalable: true });
|
|
78
82
|
|
|
79
83
|
// expose objects as global objects in QuickJS VM
|
|
80
84
|
arena.expose({
|
|
@@ -87,12 +91,12 @@ 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
102
|
// Don't forget calling arena.dispose() before disposing QuickJS VM!
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
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 { QuickJSDeferredPromise } from 'quickjs-emscripten';
|
|
2
|
+
import { QuickJSHandle } from 'quickjs-emscripten';
|
|
3
|
+
import { QuickJSVm } from 'quickjs-emscripten';
|
|
4
|
+
import type { SuccessOrFail } from 'quickjs-emscripten/dist/vm-interface';
|
|
5
|
+
import type { VmCallResult } from 'quickjs-emscripten/dist/vm-interface';
|
|
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
|
*/
|
|
@@ -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,102 @@ 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(vm: QuickJSVm, 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(vm: QuickJSVm, 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(vm: QuickJSVm, a: QuickJSHandle): boolean;
|
|
107
|
+
|
|
108
|
+
export declare function isObject(value: any): value is object | Function;
|
|
109
|
+
|
|
110
|
+
export declare function json(vm: QuickJSVm, 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
|
+
/** 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`.
|
|
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
|
+
};
|
|
123
|
+
|
|
124
|
+
declare type Options_2 = {
|
|
125
|
+
vm: QuickJSVm;
|
|
126
|
+
unmarshal: (handle: QuickJSHandle) => unknown;
|
|
127
|
+
isMarshalable?: (target: unknown) => boolean | "json";
|
|
128
|
+
find: (target: unknown) => QuickJSHandle | undefined;
|
|
129
|
+
pre: (target: unknown, handle: QuickJSHandle | QuickJSDeferredPromise, mode: true | "json" | undefined) => QuickJSHandle | undefined;
|
|
130
|
+
preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
declare type Options_3 = {
|
|
134
|
+
vm: QuickJSVm;
|
|
135
|
+
/** marshal returns handle and boolean indicates that the handle should be disposed after use */
|
|
136
|
+
marshal: (target: unknown) => [QuickJSHandle, boolean];
|
|
137
|
+
find: (handle: QuickJSHandle) => unknown | undefined;
|
|
138
|
+
pre: <T = unknown>(target: T, handle: QuickJSHandle) => T | undefined;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export declare function unmarshal(handle: QuickJSHandle, options: Options_3): any;
|
|
142
|
+
|
|
143
|
+
export declare class VMMap {
|
|
144
|
+
vm: QuickJSVm;
|
|
145
|
+
_map1: Map<any, number>;
|
|
146
|
+
_map2: Map<any, number>;
|
|
147
|
+
_map3: Map<number, QuickJSHandle>;
|
|
148
|
+
_map4: Map<number, QuickJSHandle>;
|
|
149
|
+
_counterMap: Map<number, any>;
|
|
150
|
+
_disposables: Set<QuickJSHandle>;
|
|
151
|
+
_mapGet: QuickJSHandle;
|
|
152
|
+
_mapSet: QuickJSHandle;
|
|
153
|
+
_mapDelete: QuickJSHandle;
|
|
154
|
+
_mapClear: QuickJSHandle;
|
|
155
|
+
_counter: number;
|
|
156
|
+
constructor(vm: QuickJSVm);
|
|
157
|
+
set(key: any, handle: QuickJSHandle, key2?: any, handle2?: QuickJSHandle): boolean;
|
|
158
|
+
merge(iteratable: Iterable<[any, QuickJSHandle | undefined] | [any, QuickJSHandle | undefined, any, QuickJSHandle | undefined]> | undefined): void;
|
|
159
|
+
get(key: any): QuickJSHandle | undefined;
|
|
160
|
+
getByHandle(handle: QuickJSHandle): any;
|
|
161
|
+
has(key: any): boolean;
|
|
162
|
+
hasHandle(handle: QuickJSHandle): boolean;
|
|
163
|
+
keys(): IterableIterator<any>;
|
|
164
|
+
delete(key: any, dispose?: boolean): void;
|
|
165
|
+
deleteByHandle(handle: QuickJSHandle, dispose?: boolean): void;
|
|
166
|
+
clear(): void;
|
|
167
|
+
dispose(): void;
|
|
168
|
+
get size(): number;
|
|
169
|
+
[Symbol.iterator](): Iterator<[
|
|
170
|
+
any,
|
|
171
|
+
QuickJSHandle,
|
|
172
|
+
any,
|
|
173
|
+
QuickJSHandle | undefined
|
|
174
|
+
]>;
|
|
175
|
+
_get2(num: number): any;
|
|
176
|
+
_call(fn: QuickJSHandle, thisArg: QuickJSHandle | undefined, ...args: QuickJSHandle[]): QuickJSHandle;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export declare function walkObject(value: any, callback?: (target: any, set: Set<any>) => boolean | void): Set<any>;
|
|
180
|
+
|
|
181
|
+
declare type Wrapped<T> = T & {
|
|
182
|
+
__qes_wrapped: never;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export { }
|