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