quickjs-emscripten-sync 1.3.0 → 1.4.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/README.md +36 -34
- package/dist/index.d.ts +17 -15
- package/dist/quickjs-emscripten-sync.es.js +146 -135
- package/dist/quickjs-emscripten-sync.umd.js +6 -6
- package/package.json +3 -3
- package/src/index.test.ts +146 -60
- package/src/index.ts +40 -26
- package/src/marshal/function.test.ts +61 -53
- package/src/marshal/function.ts +7 -6
- package/src/marshal/index.test.ts +73 -65
- package/src/marshal/index.ts +12 -11
- package/src/marshal/json.test.ts +30 -30
- package/src/marshal/json.ts +4 -3
- package/src/marshal/object.test.ts +55 -50
- package/src/marshal/object.ts +6 -5
- package/src/marshal/primitive.test.ts +21 -17
- package/src/marshal/primitive.ts +10 -9
- package/src/marshal/promise.test.ts +14 -14
- package/src/marshal/promise.ts +3 -3
- package/src/marshal/properties.test.ts +17 -15
- package/src/marshal/properties.ts +10 -9
- package/src/marshal/symbol.test.ts +6 -6
- package/src/marshal/symbol.ts +5 -4
- package/src/unmarshal/function.test.ts +45 -43
- package/src/unmarshal/function.ts +9 -8
- package/src/unmarshal/index.test.ts +41 -40
- package/src/unmarshal/index.ts +9 -8
- package/src/unmarshal/object.test.ts +33 -31
- package/src/unmarshal/object.ts +12 -11
- package/src/unmarshal/primitive.test.ts +18 -15
- package/src/unmarshal/primitive.ts +9 -9
- package/src/unmarshal/promise.test.ts +11 -11
- package/src/unmarshal/promise.ts +9 -11
- package/src/unmarshal/properties.test.ts +6 -6
- package/src/unmarshal/properties.ts +47 -44
- package/src/unmarshal/symbol.test.ts +6 -6
- package/src/unmarshal/symbol.ts +4 -4
- package/src/util.test.ts +1 -0
- package/src/vmmap.test.ts +72 -88
- package/src/vmmap.ts +16 -16
- package/src/vmutil.test.ts +71 -73
- package/src/vmutil.ts +22 -18
- package/src/wrapper.test.ts +111 -88
- package/src/wrapper.ts +31 -27
|
@@ -5,68 +5,68 @@ import { call } from "../vmutil";
|
|
|
5
5
|
import marshalObject from "./object";
|
|
6
6
|
|
|
7
7
|
test("empty object", async () => {
|
|
8
|
-
const
|
|
9
|
-
const prototypeCheck =
|
|
10
|
-
|
|
8
|
+
const ctx = (await getQuickJS()).newContext();
|
|
9
|
+
const prototypeCheck = ctx.unwrapResult(
|
|
10
|
+
ctx.evalCode(`o => Object.getPrototypeOf(o) === Object.prototype`)
|
|
11
11
|
);
|
|
12
12
|
|
|
13
13
|
const obj = {};
|
|
14
14
|
const marshal = vi.fn();
|
|
15
15
|
const preMarshal = vi.fn((_, a) => a);
|
|
16
16
|
|
|
17
|
-
const handle = marshalObject(
|
|
17
|
+
const handle = marshalObject(ctx, obj, marshal, preMarshal);
|
|
18
18
|
if (!handle) throw new Error("handle is undefined");
|
|
19
19
|
|
|
20
|
-
expect(
|
|
20
|
+
expect(ctx.typeof(handle)).toBe("object");
|
|
21
21
|
expect(marshal).toBeCalledTimes(0);
|
|
22
22
|
expect(preMarshal).toBeCalledTimes(1);
|
|
23
23
|
expect(preMarshal.mock.calls[0][0]).toBe(obj);
|
|
24
24
|
expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
|
|
25
25
|
expect(
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
ctx.dump(
|
|
27
|
+
ctx.unwrapResult(ctx.callFunction(prototypeCheck, ctx.undefined, handle))
|
|
28
28
|
)
|
|
29
29
|
).toBe(true);
|
|
30
30
|
|
|
31
31
|
handle.dispose();
|
|
32
32
|
prototypeCheck.dispose();
|
|
33
|
-
|
|
33
|
+
ctx.dispose();
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
test("normal object", async () => {
|
|
37
|
-
const
|
|
38
|
-
const prototypeCheck =
|
|
39
|
-
|
|
37
|
+
const ctx = (await getQuickJS()).newContext();
|
|
38
|
+
const prototypeCheck = ctx.unwrapResult(
|
|
39
|
+
ctx.evalCode(`o => Object.getPrototypeOf(o) === Object.prototype`)
|
|
40
40
|
);
|
|
41
|
-
const entries =
|
|
41
|
+
const entries = ctx.unwrapResult(ctx.evalCode(`Object.entries`));
|
|
42
42
|
|
|
43
43
|
const obj = { a: 100, b: "hoge" };
|
|
44
44
|
const marshal = vi.fn((v) =>
|
|
45
45
|
typeof v === "number"
|
|
46
|
-
?
|
|
46
|
+
? ctx.newNumber(v)
|
|
47
47
|
: typeof v === "string"
|
|
48
|
-
?
|
|
49
|
-
:
|
|
48
|
+
? ctx.newString(v)
|
|
49
|
+
: ctx.null
|
|
50
50
|
);
|
|
51
51
|
const preMarshal = vi.fn((_, a) => a);
|
|
52
52
|
|
|
53
|
-
const handle = marshalObject(
|
|
53
|
+
const handle = marshalObject(ctx, obj, marshal, preMarshal);
|
|
54
54
|
if (!handle) throw new Error("handle is undefined");
|
|
55
55
|
|
|
56
|
-
expect(
|
|
57
|
-
expect(
|
|
58
|
-
expect(
|
|
56
|
+
expect(ctx.typeof(handle)).toBe("object");
|
|
57
|
+
expect(ctx.getNumber(ctx.getProp(handle, "a"))).toBe(100);
|
|
58
|
+
expect(ctx.getString(ctx.getProp(handle, "b"))).toBe("hoge");
|
|
59
59
|
expect(marshal.mock.calls).toEqual([["a"], [100], ["b"], ["hoge"]]);
|
|
60
60
|
expect(preMarshal).toBeCalledTimes(1);
|
|
61
61
|
expect(preMarshal.mock.calls[0][0]).toBe(obj);
|
|
62
62
|
expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
|
|
63
63
|
expect(
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
ctx.dump(
|
|
65
|
+
ctx.unwrapResult(ctx.callFunction(prototypeCheck, ctx.undefined, handle))
|
|
66
66
|
)
|
|
67
67
|
).toBe(true);
|
|
68
|
-
const e =
|
|
69
|
-
expect(
|
|
68
|
+
const e = ctx.unwrapResult(ctx.callFunction(entries, ctx.undefined, handle));
|
|
69
|
+
expect(ctx.dump(e)).toEqual([
|
|
70
70
|
["a", 100],
|
|
71
71
|
["b", "hoge"],
|
|
72
72
|
]);
|
|
@@ -75,30 +75,30 @@ test("normal object", async () => {
|
|
|
75
75
|
handle.dispose();
|
|
76
76
|
prototypeCheck.dispose();
|
|
77
77
|
entries.dispose();
|
|
78
|
-
|
|
78
|
+
ctx.dispose();
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
test("array", async () => {
|
|
82
|
-
const
|
|
83
|
-
const isArray =
|
|
82
|
+
const ctx = (await getQuickJS()).newContext();
|
|
83
|
+
const isArray = ctx.unwrapResult(ctx.evalCode(`Array.isArray`));
|
|
84
84
|
|
|
85
85
|
const array = [1, "aa"];
|
|
86
86
|
const marshal = vi.fn((v) =>
|
|
87
87
|
typeof v === "number"
|
|
88
|
-
?
|
|
88
|
+
? ctx.newNumber(v)
|
|
89
89
|
: typeof v === "string"
|
|
90
|
-
?
|
|
91
|
-
:
|
|
90
|
+
? ctx.newString(v)
|
|
91
|
+
: ctx.null
|
|
92
92
|
);
|
|
93
93
|
const preMarshal = vi.fn((_, a) => a);
|
|
94
94
|
|
|
95
|
-
const handle = marshalObject(
|
|
95
|
+
const handle = marshalObject(ctx, array, marshal, preMarshal);
|
|
96
96
|
if (!handle) throw new Error("handle is undefined");
|
|
97
97
|
|
|
98
|
-
expect(
|
|
99
|
-
expect(
|
|
100
|
-
expect(
|
|
101
|
-
expect(
|
|
98
|
+
expect(ctx.typeof(handle)).toBe("object");
|
|
99
|
+
expect(ctx.getNumber(ctx.getProp(handle, 0))).toBe(1);
|
|
100
|
+
expect(ctx.getString(ctx.getProp(handle, 1))).toBe("aa");
|
|
101
|
+
expect(ctx.getNumber(ctx.getProp(handle, "length"))).toBe(2);
|
|
102
102
|
expect(marshal.mock.calls).toEqual([
|
|
103
103
|
["0"],
|
|
104
104
|
[1],
|
|
@@ -111,33 +111,33 @@ test("array", async () => {
|
|
|
111
111
|
expect(preMarshal.mock.calls[0][0]).toBe(array);
|
|
112
112
|
expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
|
|
113
113
|
expect(
|
|
114
|
-
|
|
114
|
+
ctx.dump(ctx.unwrapResult(ctx.callFunction(isArray, ctx.undefined, handle)))
|
|
115
115
|
).toBe(true);
|
|
116
116
|
|
|
117
117
|
handle.dispose();
|
|
118
118
|
isArray.dispose();
|
|
119
|
-
|
|
119
|
+
ctx.dispose();
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
test("prototype", async () => {
|
|
123
|
-
const
|
|
123
|
+
const ctx = (await getQuickJS()).newContext();
|
|
124
124
|
|
|
125
125
|
const proto = { a: 100 };
|
|
126
|
-
const protoHandle =
|
|
127
|
-
|
|
126
|
+
const protoHandle = ctx.newObject();
|
|
127
|
+
ctx.setProp(protoHandle, "a", ctx.newNumber(100));
|
|
128
128
|
const preMarshal = vi.fn((_, a) => a);
|
|
129
129
|
|
|
130
130
|
const obj = Object.create(proto);
|
|
131
131
|
obj.b = "hoge";
|
|
132
132
|
const handle = marshalObject(
|
|
133
|
-
|
|
133
|
+
ctx,
|
|
134
134
|
obj,
|
|
135
135
|
(v) =>
|
|
136
136
|
v === proto
|
|
137
137
|
? protoHandle
|
|
138
138
|
: typeof v === "string"
|
|
139
|
-
?
|
|
140
|
-
:
|
|
139
|
+
? ctx.newString(v)
|
|
140
|
+
: ctx.null,
|
|
141
141
|
preMarshal
|
|
142
142
|
);
|
|
143
143
|
if (!handle) throw new Error("handle is undefined");
|
|
@@ -145,19 +145,24 @@ test("prototype", async () => {
|
|
|
145
145
|
expect(preMarshal).toBeCalledTimes(1);
|
|
146
146
|
expect(preMarshal.mock.calls[0][0]).toBe(obj);
|
|
147
147
|
expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
|
|
148
|
-
expect(
|
|
149
|
-
expect(
|
|
150
|
-
expect(
|
|
151
|
-
const e = call(
|
|
152
|
-
expect(
|
|
153
|
-
const protoHandle2 = call(
|
|
148
|
+
expect(ctx.typeof(handle)).toBe("object");
|
|
149
|
+
expect(ctx.getNumber(ctx.getProp(handle, "a"))).toBe(100);
|
|
150
|
+
expect(ctx.getString(ctx.getProp(handle, "b"))).toBe("hoge");
|
|
151
|
+
const e = call(ctx, "Object.entries", undefined, handle);
|
|
152
|
+
expect(ctx.dump(e)).toEqual([["b", "hoge"]]);
|
|
153
|
+
const protoHandle2 = call(
|
|
154
|
+
ctx,
|
|
155
|
+
"Object.getPrototypeOf",
|
|
156
|
+
ctx.undefined,
|
|
157
|
+
handle
|
|
158
|
+
);
|
|
154
159
|
expect(
|
|
155
|
-
|
|
160
|
+
ctx.dump(call(ctx, `Object.is`, undefined, protoHandle, protoHandle2))
|
|
156
161
|
).toBe(true);
|
|
157
162
|
|
|
158
163
|
protoHandle2.dispose();
|
|
159
164
|
e.dispose();
|
|
160
165
|
handle.dispose();
|
|
161
166
|
protoHandle.dispose();
|
|
162
|
-
|
|
167
|
+
ctx.dispose();
|
|
163
168
|
});
|
package/src/marshal/object.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
|
|
2
3
|
import { call } from "../vmutil";
|
|
3
4
|
import marshalProperties from "./properties";
|
|
4
5
|
|
|
5
6
|
export default function marshalObject(
|
|
6
|
-
|
|
7
|
+
ctx: QuickJSContext,
|
|
7
8
|
target: unknown,
|
|
8
9
|
marshal: (target: unknown) => QuickJSHandle,
|
|
9
10
|
preMarshal: (
|
|
@@ -13,7 +14,7 @@ export default function marshalObject(
|
|
|
13
14
|
): QuickJSHandle | undefined {
|
|
14
15
|
if (typeof target !== "object" || target === null) return;
|
|
15
16
|
|
|
16
|
-
const raw = Array.isArray(target) ?
|
|
17
|
+
const raw = Array.isArray(target) ? ctx.newArray() : ctx.newObject();
|
|
17
18
|
const handle = preMarshal(target, raw) ?? raw;
|
|
18
19
|
|
|
19
20
|
// prototype
|
|
@@ -24,7 +25,7 @@ export default function marshalObject(
|
|
|
24
25
|
: undefined;
|
|
25
26
|
if (prototypeHandle) {
|
|
26
27
|
call(
|
|
27
|
-
|
|
28
|
+
ctx,
|
|
28
29
|
"Object.setPrototypeOf",
|
|
29
30
|
undefined,
|
|
30
31
|
handle,
|
|
@@ -32,7 +33,7 @@ export default function marshalObject(
|
|
|
32
33
|
).dispose();
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
marshalProperties(
|
|
36
|
+
marshalProperties(ctx, target, raw, marshal);
|
|
36
37
|
|
|
37
38
|
return handle;
|
|
38
39
|
}
|
|
@@ -5,32 +5,36 @@ import { eq } from "../vmutil";
|
|
|
5
5
|
import marshalPrimitive from "./primitive";
|
|
6
6
|
|
|
7
7
|
test("works", async () => {
|
|
8
|
-
const
|
|
8
|
+
const ctx = (await getQuickJS()).newContext();
|
|
9
9
|
|
|
10
|
-
expect(marshalPrimitive(
|
|
11
|
-
expect(marshalPrimitive(
|
|
12
|
-
expect(marshalPrimitive(
|
|
13
|
-
expect(marshalPrimitive(
|
|
14
|
-
expect(eq(vm, marshalPrimitive(vm, 1) ?? vm.undefined, vm.newNumber(1))).toBe(
|
|
15
|
-
true
|
|
16
|
-
);
|
|
10
|
+
expect(marshalPrimitive(ctx, undefined)).toBe(ctx.undefined);
|
|
11
|
+
expect(marshalPrimitive(ctx, null)).toBe(ctx.null);
|
|
12
|
+
expect(marshalPrimitive(ctx, false)).toBe(ctx.false);
|
|
13
|
+
expect(marshalPrimitive(ctx, true)).toBe(ctx.true);
|
|
17
14
|
expect(
|
|
18
|
-
eq(
|
|
15
|
+
eq(ctx, marshalPrimitive(ctx, 1) ?? ctx.undefined, ctx.newNumber(1))
|
|
19
16
|
).toBe(true);
|
|
20
17
|
expect(
|
|
21
|
-
eq(
|
|
18
|
+
eq(ctx, marshalPrimitive(ctx, -100) ?? ctx.undefined, ctx.newNumber(-100))
|
|
19
|
+
).toBe(true);
|
|
20
|
+
expect(
|
|
21
|
+
eq(
|
|
22
|
+
ctx,
|
|
23
|
+
marshalPrimitive(ctx, "hoge") ?? ctx.undefined,
|
|
24
|
+
ctx.newString("hoge")
|
|
25
|
+
)
|
|
22
26
|
).toBe(true);
|
|
23
27
|
// expect(
|
|
24
28
|
// eq(
|
|
25
|
-
//
|
|
26
|
-
// marshalPrimitive(
|
|
27
|
-
//
|
|
29
|
+
// ctx,
|
|
30
|
+
// marshalPrimitive(ctx, BigInt(1)) ?? ctx.undefined,
|
|
31
|
+
// ctx.unwrapResult(ctx.evalCode("BigInt(1)"))
|
|
28
32
|
// )
|
|
29
33
|
// ).toBe(true);
|
|
30
34
|
|
|
31
|
-
expect(marshalPrimitive(
|
|
32
|
-
expect(marshalPrimitive(
|
|
33
|
-
expect(marshalPrimitive(
|
|
35
|
+
expect(marshalPrimitive(ctx, () => {})).toBe(undefined);
|
|
36
|
+
expect(marshalPrimitive(ctx, [])).toBe(undefined);
|
|
37
|
+
expect(marshalPrimitive(ctx, {})).toBe(undefined);
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
ctx.dispose();
|
|
36
40
|
});
|
package/src/marshal/primitive.ts
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
|
|
2
3
|
// import { call } from "../vmutil";
|
|
3
4
|
|
|
4
5
|
export default function marshalPrimitive(
|
|
5
|
-
|
|
6
|
+
ctx: QuickJSContext,
|
|
6
7
|
target: unknown
|
|
7
8
|
): QuickJSHandle | undefined {
|
|
8
9
|
switch (typeof target) {
|
|
9
10
|
case "undefined":
|
|
10
|
-
return
|
|
11
|
+
return ctx.undefined;
|
|
11
12
|
case "number":
|
|
12
|
-
return
|
|
13
|
+
return ctx.newNumber(target);
|
|
13
14
|
case "string":
|
|
14
|
-
return
|
|
15
|
+
return ctx.newString(target);
|
|
15
16
|
case "boolean":
|
|
16
|
-
return target ?
|
|
17
|
+
return target ? ctx.true : ctx.false;
|
|
17
18
|
case "object":
|
|
18
|
-
return target === null ?
|
|
19
|
+
return target === null ? ctx.null : undefined;
|
|
19
20
|
|
|
20
21
|
// BigInt is not supported by quickjs-emscripten
|
|
21
22
|
// case "bigint":
|
|
22
23
|
// return call(
|
|
23
|
-
//
|
|
24
|
+
// ctx,
|
|
24
25
|
// `s => BigInt(s)`,
|
|
25
26
|
// undefined,
|
|
26
|
-
//
|
|
27
|
+
// ctx.newString(target.toString())
|
|
27
28
|
// );
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -5,17 +5,17 @@ import {
|
|
|
5
5
|
type QuickJSHandle,
|
|
6
6
|
} from "quickjs-emscripten";
|
|
7
7
|
import { expect, test, vi } from "vitest";
|
|
8
|
-
import { newDeferred } from "../util";
|
|
9
8
|
|
|
10
|
-
import { fn, json } from "../vmutil";
|
|
11
9
|
import marshalPromise from "./promise";
|
|
10
|
+
import { newDeferred } from "../util";
|
|
11
|
+
import { fn, json } from "../vmutil";
|
|
12
12
|
|
|
13
13
|
const testPromise = (reject: boolean) => async () => {
|
|
14
|
-
const
|
|
14
|
+
const ctx = (await getQuickJS()).newContext();
|
|
15
15
|
|
|
16
16
|
const disposables: Disposable[] = [];
|
|
17
17
|
const marshal = vi.fn((v) => {
|
|
18
|
-
const handle = json(
|
|
18
|
+
const handle = json(ctx, v);
|
|
19
19
|
disposables.push(handle);
|
|
20
20
|
return handle;
|
|
21
21
|
});
|
|
@@ -27,15 +27,15 @@ const testPromise = (reject: boolean) => async () => {
|
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
const mockNotify = vi.fn();
|
|
30
|
-
const notify =
|
|
31
|
-
const arg1 =
|
|
32
|
-
const arg2 =
|
|
30
|
+
const notify = ctx.newFunction("notify", (handle1, handle2) => {
|
|
31
|
+
const arg1 = ctx.dump(handle1);
|
|
32
|
+
const arg2 = ctx.dump(handle2);
|
|
33
33
|
mockNotify(arg1, arg2);
|
|
34
34
|
});
|
|
35
35
|
disposables.push(notify);
|
|
36
36
|
|
|
37
37
|
const notifier = fn(
|
|
38
|
-
|
|
38
|
+
ctx,
|
|
39
39
|
`(notify, promise) => { promise.then(d => notify("resolved", d), d => notify("rejected", d)); }`
|
|
40
40
|
);
|
|
41
41
|
disposables.push(notifier);
|
|
@@ -44,7 +44,7 @@ const testPromise = (reject: boolean) => async () => {
|
|
|
44
44
|
if (reject) {
|
|
45
45
|
deferred.promise.catch(() => {});
|
|
46
46
|
}
|
|
47
|
-
const handle = marshalPromise(
|
|
47
|
+
const handle = marshalPromise(ctx, deferred.promise, marshal, preMarshal);
|
|
48
48
|
if (!handle) throw new Error("handle is undefined");
|
|
49
49
|
|
|
50
50
|
expect(marshal).toBeCalledTimes(0);
|
|
@@ -56,7 +56,7 @@ const testPromise = (reject: boolean) => async () => {
|
|
|
56
56
|
|
|
57
57
|
expect(mockNotify).toBeCalledTimes(0);
|
|
58
58
|
expect(deferred.resolve).not.toBeUndefined();
|
|
59
|
-
expect(
|
|
59
|
+
expect(ctx.runtime.hasPendingJob()).toBe(false);
|
|
60
60
|
|
|
61
61
|
if (reject) {
|
|
62
62
|
deferred.reject("hoge");
|
|
@@ -64,14 +64,14 @@ const testPromise = (reject: boolean) => async () => {
|
|
|
64
64
|
deferred.resolve("hoge");
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
expect(
|
|
67
|
+
expect(ctx.runtime.hasPendingJob()).toBe(false);
|
|
68
68
|
if (reject) {
|
|
69
69
|
await expect(deferred.promise).rejects.toBe("hoge");
|
|
70
70
|
} else {
|
|
71
71
|
await expect(deferred.promise).resolves.toBe("hoge");
|
|
72
72
|
}
|
|
73
|
-
expect(
|
|
74
|
-
const executed =
|
|
73
|
+
expect(ctx.runtime.hasPendingJob()).toBe(true);
|
|
74
|
+
const executed = ctx.unwrapResult(ctx.runtime.executePendingJobs());
|
|
75
75
|
expect(executed).toBe(1);
|
|
76
76
|
expect(mockNotify).toBeCalledTimes(1);
|
|
77
77
|
expect(mockNotify).toBeCalledWith(reject ? "rejected" : "resolved", "hoge");
|
|
@@ -79,7 +79,7 @@ const testPromise = (reject: boolean) => async () => {
|
|
|
79
79
|
expect(marshal.mock.calls).toEqual([["hoge"]]);
|
|
80
80
|
|
|
81
81
|
disposables.forEach((h) => h.dispose());
|
|
82
|
-
|
|
82
|
+
ctx.dispose();
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
test("resolve", testPromise(false));
|
package/src/marshal/promise.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
QuickJSDeferredPromise,
|
|
3
3
|
QuickJSHandle,
|
|
4
|
-
|
|
4
|
+
QuickJSContext,
|
|
5
5
|
} from "quickjs-emscripten";
|
|
6
6
|
|
|
7
7
|
export default function marshalPromise(
|
|
8
|
-
|
|
8
|
+
ctx: QuickJSContext,
|
|
9
9
|
target: unknown,
|
|
10
10
|
marshal: (target: unknown) => QuickJSHandle,
|
|
11
11
|
preMarshal: (
|
|
@@ -15,7 +15,7 @@ export default function marshalPromise(
|
|
|
15
15
|
) {
|
|
16
16
|
if (!(target instanceof Promise)) return;
|
|
17
17
|
|
|
18
|
-
const promise =
|
|
18
|
+
const promise = ctx.newPromise();
|
|
19
19
|
|
|
20
20
|
target.then(
|
|
21
21
|
(d) => promise.resolve(marshal(d)),
|
|
@@ -5,9 +5,9 @@ import { json } from "../vmutil";
|
|
|
5
5
|
import marshalProperties from "./properties";
|
|
6
6
|
|
|
7
7
|
test("works", async () => {
|
|
8
|
-
const
|
|
9
|
-
const descTester =
|
|
10
|
-
|
|
8
|
+
const ctx = (await getQuickJS()).newContext();
|
|
9
|
+
const descTester = ctx.unwrapResult(
|
|
10
|
+
ctx.evalCode(`(obj, expected) => {
|
|
11
11
|
const descs = Object.getOwnPropertyDescriptors(obj);
|
|
12
12
|
for (const [k, v] of Object.entries(expected)) {
|
|
13
13
|
const d = descs[k];
|
|
@@ -23,13 +23,13 @@ test("works", async () => {
|
|
|
23
23
|
|
|
24
24
|
const disposables: QuickJSHandle[] = [];
|
|
25
25
|
const marshal = vi.fn((t) => {
|
|
26
|
-
if (typeof t !== "function") return json(
|
|
27
|
-
const fn =
|
|
26
|
+
if (typeof t !== "function") return json(ctx, t);
|
|
27
|
+
const fn = ctx.newFunction("", () => {});
|
|
28
28
|
disposables.push(fn);
|
|
29
29
|
return fn;
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
const handle =
|
|
32
|
+
const handle = ctx.newObject();
|
|
33
33
|
const obj = {};
|
|
34
34
|
const bar = () => {};
|
|
35
35
|
const fooGet = () => {};
|
|
@@ -49,7 +49,7 @@ test("works", async () => {
|
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
marshalProperties(
|
|
52
|
+
marshalProperties(ctx, obj, handle, marshal);
|
|
53
53
|
expect(marshal.mock.calls).toEqual([
|
|
54
54
|
["bar"],
|
|
55
55
|
[bar],
|
|
@@ -58,30 +58,32 @@ test("works", async () => {
|
|
|
58
58
|
[fooSet],
|
|
59
59
|
]);
|
|
60
60
|
|
|
61
|
-
const expected =
|
|
62
|
-
|
|
61
|
+
const expected = ctx.unwrapResult(
|
|
62
|
+
ctx.evalCode(`({
|
|
63
63
|
bar: { valueType: "function", getType: "undefined", setType: "undefined", enumerable: true, configurable: true, writable: true },
|
|
64
64
|
foo: { valueType: "undefined", getType: "function", setType: "function", enumerable: false, configurable: true }
|
|
65
65
|
})`)
|
|
66
66
|
);
|
|
67
|
-
|
|
67
|
+
ctx.unwrapResult(
|
|
68
|
+
ctx.callFunction(descTester, ctx.undefined, handle, expected)
|
|
69
|
+
);
|
|
68
70
|
|
|
69
71
|
expected.dispose();
|
|
70
72
|
disposables.forEach((d) => d.dispose());
|
|
71
73
|
handle.dispose();
|
|
72
74
|
descTester.dispose();
|
|
73
|
-
|
|
75
|
+
ctx.dispose();
|
|
74
76
|
});
|
|
75
77
|
|
|
76
78
|
test("empty", async () => {
|
|
77
|
-
const
|
|
79
|
+
const ctx = (await getQuickJS()).newContext();
|
|
78
80
|
const marshal = vi.fn();
|
|
79
|
-
const handle =
|
|
81
|
+
const handle = ctx.newObject();
|
|
80
82
|
const obj = {};
|
|
81
83
|
|
|
82
|
-
marshalProperties(
|
|
84
|
+
marshalProperties(ctx, obj, handle, marshal);
|
|
83
85
|
expect(marshal).toHaveBeenCalledTimes(0);
|
|
84
86
|
|
|
85
87
|
handle.dispose();
|
|
86
|
-
|
|
88
|
+
ctx.dispose();
|
|
87
89
|
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
|
|
2
3
|
import { call } from "../vmutil";
|
|
3
4
|
|
|
4
5
|
export default function marshalProperties(
|
|
5
|
-
|
|
6
|
+
ctx: QuickJSContext,
|
|
6
7
|
target: object | Function,
|
|
7
8
|
handle: QuickJSHandle,
|
|
8
9
|
marshal: (target: unknown) => QuickJSHandle
|
|
9
10
|
): void {
|
|
10
|
-
const descs =
|
|
11
|
+
const descs = ctx.newObject();
|
|
11
12
|
const cb = (key: string | number | symbol, desc: PropertyDescriptor) => {
|
|
12
13
|
const keyHandle = marshal(key);
|
|
13
14
|
const valueHandle =
|
|
@@ -17,7 +18,7 @@ export default function marshalProperties(
|
|
|
17
18
|
const setHandle =
|
|
18
19
|
typeof desc.set === "undefined" ? undefined : marshal(desc.set);
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
ctx.newObject().consume((descObj) => {
|
|
21
22
|
Object.entries(desc).forEach(([k, v]) => {
|
|
22
23
|
const v2 =
|
|
23
24
|
k === "value"
|
|
@@ -27,13 +28,13 @@ export default function marshalProperties(
|
|
|
27
28
|
: k === "set"
|
|
28
29
|
? setHandle
|
|
29
30
|
: v
|
|
30
|
-
?
|
|
31
|
-
:
|
|
31
|
+
? ctx.true
|
|
32
|
+
: ctx.false;
|
|
32
33
|
if (v2) {
|
|
33
|
-
|
|
34
|
+
ctx.setProp(descObj, k, v2);
|
|
34
35
|
}
|
|
35
36
|
});
|
|
36
|
-
|
|
37
|
+
ctx.setProp(descs, keyHandle, descObj);
|
|
37
38
|
});
|
|
38
39
|
};
|
|
39
40
|
|
|
@@ -41,7 +42,7 @@ export default function marshalProperties(
|
|
|
41
42
|
Object.entries(desc).forEach(([k, v]) => cb(k, v));
|
|
42
43
|
Object.getOwnPropertySymbols(desc).forEach((k) => cb(k, (desc as any)[k]));
|
|
43
44
|
|
|
44
|
-
call(
|
|
45
|
+
call(ctx, `Object.defineProperties`, undefined, handle, descs).dispose();
|
|
45
46
|
|
|
46
47
|
descs.dispose();
|
|
47
48
|
}
|
|
@@ -4,21 +4,21 @@ import { expect, test, vi } from "vitest";
|
|
|
4
4
|
import marshalSymbol from "./symbol";
|
|
5
5
|
|
|
6
6
|
test("works", async () => {
|
|
7
|
-
const
|
|
7
|
+
const ctx = (await getQuickJS()).newContext();
|
|
8
8
|
const pre = vi.fn();
|
|
9
9
|
const sym = Symbol("foobar");
|
|
10
10
|
|
|
11
|
-
expect(marshalSymbol(
|
|
11
|
+
expect(marshalSymbol(ctx, {}, pre)).toBe(undefined);
|
|
12
12
|
expect(pre).toBeCalledTimes(0);
|
|
13
13
|
|
|
14
|
-
const handle = marshalSymbol(
|
|
14
|
+
const handle = marshalSymbol(ctx, sym, pre);
|
|
15
15
|
if (!handle) throw new Error("handle is undefined");
|
|
16
|
-
expect(
|
|
17
|
-
expect(
|
|
16
|
+
expect(ctx.typeof(handle)).toBe("symbol");
|
|
17
|
+
expect(ctx.getString(ctx.getProp(handle, "description"))).toBe("foobar");
|
|
18
18
|
expect(pre).toReturnTimes(1);
|
|
19
19
|
expect(pre.mock.calls[0][0]).toBe(sym);
|
|
20
20
|
expect(pre.mock.calls[0][1] === handle).toBe(true);
|
|
21
21
|
|
|
22
22
|
handle.dispose();
|
|
23
|
-
|
|
23
|
+
ctx.dispose();
|
|
24
24
|
});
|
package/src/marshal/symbol.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
|
|
2
3
|
import { call } from "../vmutil";
|
|
3
4
|
|
|
4
5
|
export default function marshalSymbol(
|
|
5
|
-
|
|
6
|
+
ctx: QuickJSContext,
|
|
6
7
|
target: unknown,
|
|
7
8
|
preMarshal: (
|
|
8
9
|
target: unknown,
|
|
@@ -11,10 +12,10 @@ export default function marshalSymbol(
|
|
|
11
12
|
): QuickJSHandle | undefined {
|
|
12
13
|
if (typeof target !== "symbol") return;
|
|
13
14
|
const handle = call(
|
|
14
|
-
|
|
15
|
+
ctx,
|
|
15
16
|
"d => Symbol(d)",
|
|
16
17
|
undefined,
|
|
17
|
-
target.description ?
|
|
18
|
+
target.description ? ctx.newString(target.description) : ctx.undefined
|
|
18
19
|
);
|
|
19
20
|
return preMarshal(target, handle) ?? handle;
|
|
20
21
|
}
|