quickjs-emscripten-sync 1.0.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 +303 -0
- package/dist/index.d.ts +129 -29
- package/dist/quickjs-emscripten-sync.es.js +951 -0
- package/dist/quickjs-emscripten-sync.umd.js +64 -0
- package/package.json +28 -40
- package/src/default.ts +6 -2
- package/src/index.test.ts +266 -51
- package/src/index.ts +123 -66
- package/src/marshal/function.test.ts +11 -10
- package/src/marshal/function.ts +3 -3
- package/src/marshal/index.test.ts +75 -10
- package/src/marshal/index.ts +28 -14
- package/src/marshal/json.test.ts +94 -0
- package/src/marshal/json.ts +15 -0
- package/src/marshal/object.test.ts +49 -6
- package/src/marshal/object.ts +2 -2
- package/src/marshal/primitive.test.ts +2 -0
- package/src/marshal/primitive.ts +8 -2
- package/src/marshal/promise.test.ts +86 -0
- package/src/marshal/promise.ts +26 -0
- package/src/marshal/properties.test.ts +7 -5
- package/src/marshal/properties.ts +2 -2
- package/src/marshal/symbol.test.ts +3 -1
- package/src/unmarshal/function.test.ts +28 -21
- package/src/unmarshal/function.ts +31 -23
- package/src/unmarshal/index.test.ts +86 -86
- package/src/unmarshal/index.ts +5 -4
- package/src/unmarshal/object.test.ts +36 -8
- package/src/unmarshal/object.ts +8 -4
- package/src/unmarshal/primitive.test.ts +2 -0
- package/src/unmarshal/primitive.ts +1 -2
- package/src/unmarshal/promise.test.ts +44 -0
- package/src/unmarshal/promise.ts +40 -0
- package/src/unmarshal/properties.test.ts +4 -2
- package/src/unmarshal/properties.ts +11 -9
- package/src/unmarshal/symbol.test.ts +3 -1
- package/src/util.test.ts +22 -5
- package/src/util.ts +15 -0
- package/src/vmmap.test.ts +22 -0
- package/src/vmmap.ts +6 -2
- package/src/vmutil.test.ts +116 -8
- package/src/vmutil.ts +76 -8
- package/src/wrapper.test.ts +44 -31
- package/src/wrapper.ts +47 -30
- package/dist/default.d.ts +0 -4
- package/dist/index.js +0 -8
- package/dist/marshal/array.d.ts +0 -2
- package/dist/marshal/function.d.ts +0 -2
- package/dist/marshal/index.d.ts +0 -11
- 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.development.js +0 -1302
- package/dist/quickjs-emscripten-sync.cjs.development.js.map +0 -1
- package/dist/quickjs-emscripten-sync.cjs.production.min.js +0 -2
- package/dist/quickjs-emscripten-sync.cjs.production.min.js.map +0 -1
- package/dist/quickjs-emscripten-sync.esm.js +0 -1285
- package/dist/quickjs-emscripten-sync.esm.js.map +0 -1
- package/dist/unmarshal/array.d.ts +0 -2
- 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 -7
- package/dist/wrapper.d.ts +0 -11
- package/src/marshal/array.test.ts +0 -40
- package/src/marshal/array.ts +0 -24
- package/src/unmarshal/array.test.ts +0 -45
- package/src/unmarshal/array.ts +0 -32
package/src/vmmap.test.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getQuickJS } from "quickjs-emscripten";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
|
|
2
4
|
import VMMap from "./vmmap";
|
|
3
5
|
import { call } from "./vmutil";
|
|
4
6
|
|
|
@@ -55,6 +57,26 @@ test("getByHandle", async () => {
|
|
|
55
57
|
vm.dispose();
|
|
56
58
|
});
|
|
57
59
|
|
|
60
|
+
test("keys", async () => {
|
|
61
|
+
const quickjs = await getQuickJS();
|
|
62
|
+
const vm = quickjs.createVm();
|
|
63
|
+
|
|
64
|
+
const target = {};
|
|
65
|
+
const handle = vm.newObject();
|
|
66
|
+
const handle2 = vm.newObject();
|
|
67
|
+
|
|
68
|
+
const map = new VMMap(vm);
|
|
69
|
+
expect(Array.from(map.keys())).toEqual([]);
|
|
70
|
+
map.set(target, handle);
|
|
71
|
+
expect(Array.from(map.keys())).toEqual([target]);
|
|
72
|
+
handle.dispose();
|
|
73
|
+
expect(Array.from(map.keys())).toEqual([target]);
|
|
74
|
+
|
|
75
|
+
handle2.dispose();
|
|
76
|
+
map.dispose();
|
|
77
|
+
vm.dispose();
|
|
78
|
+
});
|
|
79
|
+
|
|
58
80
|
test("delete", async () => {
|
|
59
81
|
const quickjs = await getQuickJS();
|
|
60
82
|
const vm = quickjs.createVm();
|
package/src/vmmap.ts
CHANGED
|
@@ -44,7 +44,7 @@ export default class VMMap {
|
|
|
44
44
|
};
|
|
45
45
|
}`)
|
|
46
46
|
)
|
|
47
|
-
.consume(fn => this._call(fn, undefined));
|
|
47
|
+
.consume((fn) => this._call(fn, undefined));
|
|
48
48
|
|
|
49
49
|
this._mapGet = vm.getProp(result, "get");
|
|
50
50
|
this._mapSet = vm.getProp(result, "set");
|
|
@@ -84,7 +84,7 @@ export default class VMMap {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
this.vm.newNumber(counter).consume(c => {
|
|
87
|
+
this.vm.newNumber(counter).consume((c) => {
|
|
88
88
|
this._call(
|
|
89
89
|
this._mapSet,
|
|
90
90
|
undefined,
|
|
@@ -144,6 +144,10 @@ export default class VMMap {
|
|
|
144
144
|
return typeof this.getByHandle(handle) !== "undefined";
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
keys() {
|
|
148
|
+
return this._map1.keys();
|
|
149
|
+
}
|
|
150
|
+
|
|
147
151
|
delete(key: any, dispose?: boolean) {
|
|
148
152
|
const num = this._map1.get(key) ?? this._map2.get(key);
|
|
149
153
|
if (typeof num === "undefined") return;
|
package/src/vmutil.test.ts
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
|
-
import { getQuickJS } from "quickjs-emscripten";
|
|
1
|
+
import { getQuickJS, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
import { expect, test, vi } from "vitest";
|
|
3
|
+
|
|
2
4
|
import {
|
|
5
|
+
fn,
|
|
3
6
|
call,
|
|
4
7
|
consumeAll,
|
|
5
8
|
eq,
|
|
6
9
|
instanceOf,
|
|
7
10
|
isHandleObject,
|
|
8
|
-
|
|
11
|
+
json,
|
|
12
|
+
mayConsume,
|
|
13
|
+
mayConsumeAll,
|
|
14
|
+
handleFrom,
|
|
9
15
|
} from "./vmutil";
|
|
10
16
|
|
|
17
|
+
test("fn", async () => {
|
|
18
|
+
const quickjs = await getQuickJS();
|
|
19
|
+
const vm = quickjs.createVm();
|
|
20
|
+
|
|
21
|
+
const f = fn(vm, "(a, b) => a + b");
|
|
22
|
+
expect(vm.getNumber(f(undefined, vm.newNumber(1), vm.newNumber(2)))).toBe(3);
|
|
23
|
+
|
|
24
|
+
const obj = vm.newObject();
|
|
25
|
+
vm.setProp(obj, "a", vm.newNumber(2));
|
|
26
|
+
const f2 = fn(vm, "(function() { return this.a + 1; })");
|
|
27
|
+
expect(vm.getNumber(f2(obj))).toBe(3);
|
|
28
|
+
|
|
29
|
+
obj.dispose();
|
|
30
|
+
expect(f.alive).toBe(true);
|
|
31
|
+
expect(f2.alive).toBe(true);
|
|
32
|
+
f2.dispose();
|
|
33
|
+
f.dispose();
|
|
34
|
+
expect(f.alive).toBe(false);
|
|
35
|
+
expect(f2.alive).toBe(false);
|
|
36
|
+
vm.dispose();
|
|
37
|
+
});
|
|
38
|
+
|
|
11
39
|
test("call", async () => {
|
|
12
40
|
const quickjs = await getQuickJS();
|
|
13
41
|
const vm = quickjs.createVm();
|
|
@@ -80,17 +108,17 @@ test("isHandleObject", async () => {
|
|
|
80
108
|
vm.dispose();
|
|
81
109
|
});
|
|
82
110
|
|
|
83
|
-
test("
|
|
111
|
+
test("json", async () => {
|
|
84
112
|
const quickjs = await getQuickJS();
|
|
85
113
|
const vm = quickjs.createVm();
|
|
86
114
|
|
|
87
|
-
const handle =
|
|
115
|
+
const handle = json(vm, {
|
|
88
116
|
hoge: { foo: ["bar"] },
|
|
89
117
|
});
|
|
90
118
|
expect(
|
|
91
119
|
vm.dump(call(vm, `a => a.hoge.foo[0] === "bar"`, undefined, handle))
|
|
92
120
|
).toBe(true);
|
|
93
|
-
expect(vm.typeof(
|
|
121
|
+
expect(vm.typeof(json(vm, undefined))).toBe("undefined");
|
|
94
122
|
|
|
95
123
|
handle.dispose();
|
|
96
124
|
vm.dispose();
|
|
@@ -106,10 +134,10 @@ test("consumeAll", async () => {
|
|
|
106
134
|
expect(
|
|
107
135
|
consumeAll(
|
|
108
136
|
handles,
|
|
109
|
-
|
|
137
|
+
vi.fn(() => o)
|
|
110
138
|
)
|
|
111
139
|
).toBe(o);
|
|
112
|
-
expect(handles.every(h => !h.alive)).toBe(true);
|
|
140
|
+
expect(handles.every((h) => !h.alive)).toBe(true);
|
|
113
141
|
|
|
114
142
|
const handles2 = [vm.newObject(), vm.newObject()];
|
|
115
143
|
expect(() =>
|
|
@@ -117,7 +145,87 @@ test("consumeAll", async () => {
|
|
|
117
145
|
throw new Error("qes error");
|
|
118
146
|
})
|
|
119
147
|
).toThrow("qes error");
|
|
120
|
-
expect(handles2.every(h => !h.alive)).toBe(true);
|
|
148
|
+
expect(handles2.every((h) => !h.alive)).toBe(true);
|
|
149
|
+
|
|
150
|
+
vm.dispose();
|
|
151
|
+
});
|
|
121
152
|
|
|
153
|
+
test("mayConsume", async () => {
|
|
154
|
+
const quickjs = await getQuickJS();
|
|
155
|
+
const vm = quickjs.createVm();
|
|
156
|
+
|
|
157
|
+
const o = {};
|
|
158
|
+
|
|
159
|
+
const handle = vm.newArray();
|
|
160
|
+
expect(
|
|
161
|
+
mayConsume(
|
|
162
|
+
[handle, false],
|
|
163
|
+
vi.fn(() => o)
|
|
164
|
+
)
|
|
165
|
+
).toBe(o);
|
|
166
|
+
expect(handle.alive).toBe(true);
|
|
167
|
+
|
|
168
|
+
mayConsume([handle, true], () => {});
|
|
169
|
+
expect(handle.alive).toBe(false);
|
|
170
|
+
|
|
171
|
+
const handle2 = vm.newArray();
|
|
172
|
+
expect(() =>
|
|
173
|
+
mayConsume([handle2, true], () => {
|
|
174
|
+
throw new Error("qes error");
|
|
175
|
+
})
|
|
176
|
+
).toThrow("qes error");
|
|
177
|
+
expect(handle.alive).toBe(false);
|
|
178
|
+
|
|
179
|
+
vm.dispose();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("mayConsumeAll", async () => {
|
|
183
|
+
const quickjs = await getQuickJS();
|
|
184
|
+
const vm = quickjs.createVm();
|
|
185
|
+
|
|
186
|
+
const o = {};
|
|
187
|
+
|
|
188
|
+
const handles: [QuickJSHandle, boolean][] = [
|
|
189
|
+
[vm.newObject(), false],
|
|
190
|
+
[vm.newObject(), true],
|
|
191
|
+
];
|
|
192
|
+
expect(
|
|
193
|
+
mayConsumeAll(
|
|
194
|
+
handles,
|
|
195
|
+
vi.fn((..._: any[]) => o)
|
|
196
|
+
)
|
|
197
|
+
).toBe(o);
|
|
198
|
+
expect(handles[0][0].alive).toBe(true);
|
|
199
|
+
expect(handles[1][0].alive).toBe(false);
|
|
200
|
+
|
|
201
|
+
const handles2: [QuickJSHandle, boolean][] = [
|
|
202
|
+
[vm.newObject(), false],
|
|
203
|
+
[vm.newObject(), true],
|
|
204
|
+
];
|
|
205
|
+
expect(() =>
|
|
206
|
+
mayConsumeAll(handles2, (..._args) => {
|
|
207
|
+
throw new Error("qes error");
|
|
208
|
+
})
|
|
209
|
+
).toThrow("qes error");
|
|
210
|
+
expect(handles2[0][0].alive).toBe(true);
|
|
211
|
+
expect(handles2[1][0].alive).toBe(false);
|
|
212
|
+
|
|
213
|
+
handles[0][0].dispose();
|
|
214
|
+
handles2[0][0].dispose();
|
|
215
|
+
vm.dispose();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test("handleFrom", async () => {
|
|
219
|
+
const quickjs = await getQuickJS();
|
|
220
|
+
const vm = quickjs.createVm();
|
|
221
|
+
|
|
222
|
+
const handle = vm.newObject();
|
|
223
|
+
const promise = vm.newPromise();
|
|
224
|
+
|
|
225
|
+
expect(handleFrom(handle) === handle).toBe(true);
|
|
226
|
+
expect(handleFrom(promise) === promise.handle).toBe(true);
|
|
227
|
+
|
|
228
|
+
handle.dispose();
|
|
229
|
+
promise.dispose();
|
|
122
230
|
vm.dispose();
|
|
123
231
|
});
|
package/src/vmutil.ts
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
|
+
Disposable,
|
|
3
|
+
QuickJSVm,
|
|
4
|
+
QuickJSHandle,
|
|
5
|
+
QuickJSDeferredPromise,
|
|
6
|
+
} from "quickjs-emscripten";
|
|
7
|
+
|
|
8
|
+
export function fn(
|
|
9
|
+
vm: QuickJSVm,
|
|
10
|
+
code: string
|
|
11
|
+
): ((
|
|
12
|
+
thisArg: QuickJSHandle | undefined,
|
|
13
|
+
...args: QuickJSHandle[]
|
|
14
|
+
) => QuickJSHandle) &
|
|
15
|
+
Disposable {
|
|
16
|
+
const handle = vm.unwrapResult(vm.evalCode(code));
|
|
17
|
+
const f = (
|
|
18
|
+
thisArg: QuickJSHandle | undefined,
|
|
19
|
+
...args: QuickJSHandle[]
|
|
20
|
+
): any => {
|
|
21
|
+
return vm.unwrapResult(
|
|
22
|
+
vm.callFunction(handle, thisArg ?? vm.undefined, ...args)
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
f.dispose = () => handle.dispose();
|
|
26
|
+
f.alive = true;
|
|
27
|
+
Object.defineProperty(f, "alive", {
|
|
28
|
+
get: () => handle.alive,
|
|
29
|
+
});
|
|
30
|
+
return f;
|
|
31
|
+
}
|
|
2
32
|
|
|
3
33
|
export function call(
|
|
4
34
|
vm: QuickJSVm,
|
|
@@ -6,12 +36,12 @@ export function call(
|
|
|
6
36
|
thisArg?: QuickJSHandle,
|
|
7
37
|
...args: QuickJSHandle[]
|
|
8
38
|
): QuickJSHandle {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
);
|
|
14
|
-
}
|
|
39
|
+
const f = fn(vm, code);
|
|
40
|
+
try {
|
|
41
|
+
return f(thisArg, ...args);
|
|
42
|
+
} finally {
|
|
43
|
+
f.dispose();
|
|
44
|
+
}
|
|
15
45
|
}
|
|
16
46
|
|
|
17
47
|
export function eq(vm: QuickJSVm, a: QuickJSHandle, b: QuickJSHandle): boolean {
|
|
@@ -37,7 +67,7 @@ export function isHandleObject(vm: QuickJSVm, a: QuickJSHandle): boolean {
|
|
|
37
67
|
);
|
|
38
68
|
}
|
|
39
69
|
|
|
40
|
-
export function
|
|
70
|
+
export function json(vm: QuickJSVm, target: any): QuickJSHandle {
|
|
41
71
|
const json = JSON.stringify(target);
|
|
42
72
|
if (!json) return vm.undefined;
|
|
43
73
|
return call(vm, `JSON.parse`, undefined, vm.newString(json));
|
|
@@ -55,3 +85,41 @@ export function consumeAll<T extends QuickJSHandle[], K>(
|
|
|
55
85
|
}
|
|
56
86
|
}
|
|
57
87
|
}
|
|
88
|
+
|
|
89
|
+
export function mayConsume<T>(
|
|
90
|
+
[handle, shouldBeDisposed]: [QuickJSHandle, boolean],
|
|
91
|
+
fn: (h: QuickJSHandle) => T
|
|
92
|
+
) {
|
|
93
|
+
try {
|
|
94
|
+
return fn(handle);
|
|
95
|
+
} finally {
|
|
96
|
+
if (shouldBeDisposed) {
|
|
97
|
+
handle.dispose();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function mayConsumeAll<T, H extends QuickJSHandle[]>(
|
|
103
|
+
handles: { [P in keyof H]: [QuickJSHandle, boolean] },
|
|
104
|
+
fn: (...args: H) => T
|
|
105
|
+
) {
|
|
106
|
+
try {
|
|
107
|
+
return fn(...(handles.map((h) => h[0]) as H));
|
|
108
|
+
} finally {
|
|
109
|
+
for (const [handle, shouldBeDisposed] of handles) {
|
|
110
|
+
if (shouldBeDisposed) {
|
|
111
|
+
handle.dispose();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function isQuickJSDeferredPromise(d: Disposable): d is QuickJSDeferredPromise {
|
|
118
|
+
return "handle" in d;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function handleFrom(
|
|
122
|
+
d: QuickJSDeferredPromise | QuickJSHandle
|
|
123
|
+
): QuickJSHandle {
|
|
124
|
+
return isQuickJSDeferredPromise(d) ? d.handle : d;
|
|
125
|
+
}
|
package/src/wrapper.test.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { QuickJSHandle, getQuickJS } from "quickjs-emscripten";
|
|
2
|
+
import { expect, test, vi } from "vitest";
|
|
3
|
+
|
|
2
4
|
import {
|
|
3
5
|
wrap,
|
|
4
6
|
unwrap,
|
|
@@ -8,7 +10,7 @@ import {
|
|
|
8
10
|
isHandleWrapped,
|
|
9
11
|
SyncMode,
|
|
10
12
|
} from "./wrapper";
|
|
11
|
-
import { call, eq,
|
|
13
|
+
import { call, eq, json } from "./vmutil";
|
|
12
14
|
|
|
13
15
|
test("wrap, unwrap, isWrapped", async () => {
|
|
14
16
|
const vm = (await getQuickJS()).createVm();
|
|
@@ -16,8 +18,8 @@ test("wrap, unwrap, isWrapped", async () => {
|
|
|
16
18
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
17
19
|
const proxyKeySymbol = Symbol();
|
|
18
20
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
19
|
-
const marshal =
|
|
20
|
-
const syncMode =
|
|
21
|
+
const marshal = vi.fn();
|
|
22
|
+
const syncMode = vi.fn();
|
|
21
23
|
|
|
22
24
|
expect(isWrapped(target, proxyKeySymbol)).toBe(false);
|
|
23
25
|
expect(unwrap(target, proxyKeySymbol)).toBe(target);
|
|
@@ -51,8 +53,8 @@ test("wrap without sync", async () => {
|
|
|
51
53
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
52
54
|
const proxyKeySymbol = Symbol();
|
|
53
55
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
54
|
-
const marshal =
|
|
55
|
-
const syncMode =
|
|
56
|
+
const marshal = vi.fn();
|
|
57
|
+
const syncMode = vi.fn();
|
|
56
58
|
|
|
57
59
|
const wrapped = wrap(
|
|
58
60
|
vm,
|
|
@@ -78,6 +80,9 @@ test("wrap without sync", async () => {
|
|
|
78
80
|
proxyKeySymbolHandle.dispose();
|
|
79
81
|
handle.dispose();
|
|
80
82
|
vm.dispose();
|
|
83
|
+
|
|
84
|
+
wrapped.a = 3; // no error even if vm is disposed
|
|
85
|
+
expect(wrapped.a).toBe(3);
|
|
81
86
|
});
|
|
82
87
|
|
|
83
88
|
test("wrap with both sync", async () => {
|
|
@@ -86,10 +91,11 @@ test("wrap with both sync", async () => {
|
|
|
86
91
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
87
92
|
const proxyKeySymbol = Symbol();
|
|
88
93
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
89
|
-
const marshal =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
const marshal = vi.fn((t: any): [QuickJSHandle, boolean] => [
|
|
95
|
+
t === wrapped ? handle : json(vm, t),
|
|
96
|
+
false,
|
|
97
|
+
]);
|
|
98
|
+
const syncMode = vi.fn((): SyncMode => "both");
|
|
93
99
|
|
|
94
100
|
const wrapped = wrap(
|
|
95
101
|
vm,
|
|
@@ -121,6 +127,9 @@ test("wrap with both sync", async () => {
|
|
|
121
127
|
proxyKeySymbolHandle.dispose();
|
|
122
128
|
handle.dispose();
|
|
123
129
|
vm.dispose();
|
|
130
|
+
|
|
131
|
+
wrapped.a = 3; // no error even if vm is disposed
|
|
132
|
+
expect(wrapped.a).toBe(3);
|
|
124
133
|
});
|
|
125
134
|
|
|
126
135
|
test("wrap with vm sync", async () => {
|
|
@@ -129,10 +138,11 @@ test("wrap with vm sync", async () => {
|
|
|
129
138
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
130
139
|
const proxyKeySymbol = Symbol();
|
|
131
140
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
132
|
-
const marshal =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
141
|
+
const marshal = vi.fn((t: any): [QuickJSHandle, boolean] => [
|
|
142
|
+
t === wrapped ? handle : json(vm, t),
|
|
143
|
+
false,
|
|
144
|
+
]);
|
|
145
|
+
const syncMode = vi.fn((): SyncMode => "vm");
|
|
136
146
|
|
|
137
147
|
const wrapped = wrap(
|
|
138
148
|
vm,
|
|
@@ -164,6 +174,9 @@ test("wrap with vm sync", async () => {
|
|
|
164
174
|
proxyKeySymbolHandle.dispose();
|
|
165
175
|
handle.dispose();
|
|
166
176
|
vm.dispose();
|
|
177
|
+
|
|
178
|
+
wrapped.a = 3; // no error even after vm is disposed
|
|
179
|
+
expect(wrapped.a).toBe(1); // vm mode cannot modify obj in host
|
|
167
180
|
});
|
|
168
181
|
|
|
169
182
|
test("wrapHandle, unwrapHandle, isHandleWrapped", async () => {
|
|
@@ -172,8 +185,8 @@ test("wrapHandle, unwrapHandle, isHandleWrapped", async () => {
|
|
|
172
185
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
173
186
|
const proxyKeySymbol = Symbol();
|
|
174
187
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
175
|
-
const unmarshal =
|
|
176
|
-
const syncMode =
|
|
188
|
+
const unmarshal = vi.fn();
|
|
189
|
+
const syncMode = vi.fn();
|
|
177
190
|
|
|
178
191
|
expect(isHandleWrapped(vm, handle, proxyKeySymbolHandle)).toBe(false);
|
|
179
192
|
expect(unwrapHandle(vm, handle, proxyKeySymbolHandle)).toEqual([
|
|
@@ -197,7 +210,7 @@ test("wrapHandle, unwrapHandle, isHandleWrapped", async () => {
|
|
|
197
210
|
|
|
198
211
|
const [handle2, unwrapped2] = unwrapHandle(vm, wrapped, proxyKeySymbolHandle);
|
|
199
212
|
expect(unwrapped2).toBe(true);
|
|
200
|
-
handle2.consume(h => {
|
|
213
|
+
handle2.consume((h) => {
|
|
201
214
|
expect(eq(vm, handle, h)).toBe(true);
|
|
202
215
|
});
|
|
203
216
|
|
|
@@ -223,10 +236,10 @@ test("wrapHandle without sync", async () => {
|
|
|
223
236
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
224
237
|
const proxyKeySymbol = Symbol();
|
|
225
238
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
226
|
-
const unmarshal =
|
|
239
|
+
const unmarshal = vi.fn((h: QuickJSHandle) =>
|
|
227
240
|
wrapped && eq(vm, h, wrapped) ? target : vm.dump(h)
|
|
228
241
|
);
|
|
229
|
-
const syncMode =
|
|
242
|
+
const syncMode = vi.fn();
|
|
230
243
|
|
|
231
244
|
const [wrapped, w] = wrapHandle(
|
|
232
245
|
vm,
|
|
@@ -262,10 +275,10 @@ test("wrapHandle with both sync", async () => {
|
|
|
262
275
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
263
276
|
const proxyKeySymbol = Symbol();
|
|
264
277
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
265
|
-
const unmarshal =
|
|
278
|
+
const unmarshal = vi.fn((h: QuickJSHandle) => {
|
|
266
279
|
return wrapped && eq(vm, h, wrapped) ? target : vm.dump(h);
|
|
267
280
|
});
|
|
268
|
-
const syncMode =
|
|
281
|
+
const syncMode = vi.fn((): SyncMode => "both");
|
|
269
282
|
|
|
270
283
|
const [wrapped, w] = wrapHandle(
|
|
271
284
|
vm,
|
|
@@ -314,10 +327,10 @@ test("wrapHandle with host sync", async () => {
|
|
|
314
327
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
315
328
|
const proxyKeySymbol = Symbol();
|
|
316
329
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
317
|
-
const unmarshal =
|
|
330
|
+
const unmarshal = vi.fn((handle: QuickJSHandle) =>
|
|
318
331
|
wrapped && eq(vm, handle, wrapped) ? target : vm.dump(handle)
|
|
319
332
|
);
|
|
320
|
-
const syncMode =
|
|
333
|
+
const syncMode = vi.fn((): SyncMode => "host");
|
|
321
334
|
|
|
322
335
|
const [wrapped, w] = wrapHandle(
|
|
323
336
|
vm,
|
|
@@ -359,14 +372,14 @@ test("wrap and wrapHandle", async () => {
|
|
|
359
372
|
const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
|
|
360
373
|
const proxyKeySymbol = Symbol();
|
|
361
374
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
362
|
-
const marshal =
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
);
|
|
366
|
-
const unmarshal =
|
|
375
|
+
const marshal = vi.fn((t: any): [QuickJSHandle, boolean] => [
|
|
376
|
+
wrappedHandle && t === wrapped ? wrappedHandle : json(vm, t),
|
|
377
|
+
false,
|
|
378
|
+
]);
|
|
379
|
+
const unmarshal = vi.fn((handle: QuickJSHandle) =>
|
|
367
380
|
wrappedHandle && eq(vm, handle, wrappedHandle) ? wrapped : vm.dump(handle)
|
|
368
381
|
);
|
|
369
|
-
const syncMode =
|
|
382
|
+
const syncMode = vi.fn((): SyncMode => "both");
|
|
370
383
|
|
|
371
384
|
const wrapped = wrap(
|
|
372
385
|
vm,
|
|
@@ -424,7 +437,7 @@ test("non object", async () => {
|
|
|
424
437
|
const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
|
|
425
438
|
|
|
426
439
|
expect(
|
|
427
|
-
wrap(vm, target, proxyKeySymbol, proxyKeySymbolHandle,
|
|
440
|
+
wrap(vm, target, proxyKeySymbol, proxyKeySymbolHandle, vi.fn(), vi.fn())
|
|
428
441
|
).toBe(undefined);
|
|
429
442
|
|
|
430
443
|
expect(
|
|
@@ -433,8 +446,8 @@ test("non object", async () => {
|
|
|
433
446
|
handle,
|
|
434
447
|
proxyKeySymbol,
|
|
435
448
|
proxyKeySymbolHandle,
|
|
436
|
-
|
|
437
|
-
|
|
449
|
+
vi.fn(),
|
|
450
|
+
vi.fn()
|
|
438
451
|
)
|
|
439
452
|
).toEqual([undefined, false]);
|
|
440
453
|
|
package/src/wrapper.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
|
|
2
2
|
import { isObject } from "./util";
|
|
3
|
-
import { call, isHandleObject, consumeAll } from "./vmutil";
|
|
3
|
+
import { call, isHandleObject, consumeAll, mayConsumeAll } from "./vmutil";
|
|
4
4
|
|
|
5
5
|
export type SyncMode = "both" | "vm" | "host";
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ export function wrap<T = any>(
|
|
|
11
11
|
target: T,
|
|
12
12
|
proxyKeySymbol: symbol,
|
|
13
13
|
proxyKeySymbolHandle: QuickJSHandle,
|
|
14
|
-
marshal: (target: any) => QuickJSHandle,
|
|
14
|
+
marshal: (target: any) => [QuickJSHandle, boolean],
|
|
15
15
|
syncMode?: (target: T) => SyncMode | undefined
|
|
16
16
|
): Wrapped<T> | undefined {
|
|
17
17
|
if (!isObject(target)) return undefined;
|
|
@@ -24,39 +24,56 @@ export function wrap<T = any>(
|
|
|
24
24
|
set(obj, key, value, receiver) {
|
|
25
25
|
const v = unwrap(value, proxyKeySymbol);
|
|
26
26
|
const sync = syncMode?.(receiver) ?? "host";
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
if (
|
|
28
|
+
(sync !== "vm" && !Reflect.set(obj, key, v, receiver)) ||
|
|
29
|
+
sync === "host" ||
|
|
30
|
+
!vm.alive
|
|
31
|
+
)
|
|
32
|
+
return true;
|
|
33
|
+
|
|
34
|
+
mayConsumeAll(
|
|
35
|
+
[marshal(receiver), marshal(key), marshal(v)],
|
|
36
|
+
(receiverHandle, keyHandle, valueHandle) => {
|
|
37
|
+
const [handle2, unwrapped] = unwrapHandle(
|
|
38
|
+
vm,
|
|
39
|
+
receiverHandle,
|
|
40
|
+
proxyKeySymbolHandle
|
|
41
|
+
);
|
|
42
|
+
if (unwrapped) {
|
|
43
|
+
handle2.consume((h) => vm.setProp(h, keyHandle, valueHandle));
|
|
44
|
+
} else {
|
|
45
|
+
vm.setProp(handle2, keyHandle, valueHandle);
|
|
46
|
+
}
|
|
38
47
|
}
|
|
39
|
-
|
|
48
|
+
);
|
|
49
|
+
|
|
40
50
|
return true;
|
|
41
51
|
},
|
|
42
52
|
deleteProperty(obj, key) {
|
|
43
53
|
const sync = syncMode?.(rec) ?? "host";
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (unwrapped) {
|
|
52
|
-
handle2.consume(h =>
|
|
53
|
-
call(vm, `(a, b) => delete a[b]`, undefined, h, marshal(key))
|
|
54
|
+
return mayConsumeAll(
|
|
55
|
+
[marshal(rec), marshal(key)],
|
|
56
|
+
(recHandle, keyHandle) => {
|
|
57
|
+
const [handle2, unwrapped] = unwrapHandle(
|
|
58
|
+
vm,
|
|
59
|
+
recHandle,
|
|
60
|
+
proxyKeySymbolHandle
|
|
54
61
|
);
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
|
|
63
|
+
if (sync === "vm" || Reflect.deleteProperty(obj, key)) {
|
|
64
|
+
if (sync === "host" || !vm.alive) return true;
|
|
65
|
+
|
|
66
|
+
if (unwrapped) {
|
|
67
|
+
handle2.consume((h) =>
|
|
68
|
+
call(vm, `(a, b) => delete a[b]`, undefined, h, keyHandle)
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
call(vm, `(a, b) => delete a[b]`, undefined, handle2, keyHandle);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
57
75
|
}
|
|
58
|
-
|
|
59
|
-
return true;
|
|
76
|
+
);
|
|
60
77
|
},
|
|
61
78
|
}) as Wrapped<T>;
|
|
62
79
|
return rec;
|
|
@@ -75,7 +92,7 @@ export function wrapHandle(
|
|
|
75
92
|
|
|
76
93
|
return consumeAll(
|
|
77
94
|
[
|
|
78
|
-
vm.newFunction("getSyncMode", h => {
|
|
95
|
+
vm.newFunction("getSyncMode", (h) => {
|
|
79
96
|
const res = syncMode?.(unmarshal(h));
|
|
80
97
|
if (typeof res === "string") return vm.newString(res);
|
|
81
98
|
return vm.undefined;
|
|
@@ -95,7 +112,7 @@ export function wrapHandle(
|
|
|
95
112
|
delete unwrap(target, proxyKeySymbol)[key];
|
|
96
113
|
}),
|
|
97
114
|
],
|
|
98
|
-
args => [
|
|
115
|
+
(args) => [
|
|
99
116
|
call(
|
|
100
117
|
vm,
|
|
101
118
|
`(target, sym, getSyncMode, setter, deleter) => {
|
package/dist/default.d.ts
DELETED
package/dist/index.js
DELETED
package/dist/marshal/array.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
-
export default function marshalArray(vm: QuickJSVm, target: unknown, marshal: (target: any) => QuickJSHandle, preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined): QuickJSHandle | undefined;
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
-
export default function marshalFunction(vm: QuickJSVm, target: unknown, marshal: (target: unknown) => QuickJSHandle, unmarshal: (handle: QuickJSHandle) => unknown, preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined, preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any): QuickJSHandle | undefined;
|
package/dist/marshal/index.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { QuickJSHandle, QuickJSVm } from "quickjs-emscripten";
|
|
2
|
-
export declare type Options = {
|
|
3
|
-
vm: QuickJSVm;
|
|
4
|
-
unmarshal: (handle: QuickJSHandle) => unknown;
|
|
5
|
-
isMarshalable?: (target: unknown) => boolean;
|
|
6
|
-
find: (target: unknown) => QuickJSHandle | undefined;
|
|
7
|
-
pre: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined;
|
|
8
|
-
preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any;
|
|
9
|
-
};
|
|
10
|
-
export declare function marshal(target: unknown, options: Options): QuickJSHandle;
|
|
11
|
-
export default marshal;
|
package/dist/marshal/object.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
-
export default function marshalObject(vm: QuickJSVm, target: unknown, marshal: (target: unknown) => QuickJSHandle, preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined): QuickJSHandle | undefined;
|