quickjs-emscripten-sync 1.3.0 → 1.5.1

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.
Files changed (51) hide show
  1. package/README.md +60 -37
  2. package/dist/index.d.ts +29 -22
  3. package/dist/quickjs-emscripten-sync.mjs +842 -0
  4. package/dist/quickjs-emscripten-sync.umd.js +15 -15
  5. package/package.json +12 -21
  6. package/src/default.ts +2 -2
  7. package/src/index.test.ts +159 -65
  8. package/src/index.ts +67 -66
  9. package/src/marshal/custom.test.ts +50 -0
  10. package/src/marshal/custom.ts +36 -0
  11. package/src/marshal/function.test.ts +60 -72
  12. package/src/marshal/function.ts +15 -18
  13. package/src/marshal/index.test.ts +88 -84
  14. package/src/marshal/index.ts +16 -18
  15. package/src/marshal/json.test.ts +32 -38
  16. package/src/marshal/json.ts +5 -7
  17. package/src/marshal/object.test.ts +52 -79
  18. package/src/marshal/object.ts +8 -15
  19. package/src/marshal/primitive.test.ts +16 -21
  20. package/src/marshal/primitive.ts +11 -10
  21. package/src/marshal/promise.test.ts +21 -22
  22. package/src/marshal/promise.ts +6 -13
  23. package/src/marshal/properties.test.ts +21 -26
  24. package/src/marshal/properties.ts +15 -17
  25. package/src/unmarshal/custom.test.ts +50 -0
  26. package/src/unmarshal/custom.ts +31 -0
  27. package/src/unmarshal/function.test.ts +52 -74
  28. package/src/unmarshal/function.ts +13 -22
  29. package/src/unmarshal/index.test.ts +58 -50
  30. package/src/unmarshal/index.ts +12 -13
  31. package/src/unmarshal/object.test.ts +37 -43
  32. package/src/unmarshal/object.ts +16 -20
  33. package/src/unmarshal/primitive.test.ts +15 -15
  34. package/src/unmarshal/primitive.ts +11 -18
  35. package/src/unmarshal/promise.test.ts +13 -13
  36. package/src/unmarshal/promise.ts +10 -19
  37. package/src/unmarshal/properties.test.ts +8 -8
  38. package/src/unmarshal/properties.ts +44 -45
  39. package/src/util.test.ts +2 -7
  40. package/src/util.ts +3 -8
  41. package/src/vmmap.test.ts +72 -88
  42. package/src/vmmap.ts +26 -44
  43. package/src/vmutil.test.ts +73 -89
  44. package/src/vmutil.ts +24 -47
  45. package/src/wrapper.test.ts +108 -148
  46. package/src/wrapper.ts +59 -62
  47. package/dist/quickjs-emscripten-sync.es.js +0 -951
  48. package/src/marshal/symbol.test.ts +0 -24
  49. package/src/marshal/symbol.ts +0 -20
  50. package/src/unmarshal/symbol.test.ts +0 -25
  51. package/src/unmarshal/symbol.ts +0 -12
@@ -1,43 +1,40 @@
1
- import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+
2
3
  import { isES2015Class, isObject } from "../util";
3
4
  import { call } from "../vmutil";
5
+
4
6
  import marshalProperties from "./properties";
5
7
 
6
8
  export default function marshalFunction(
7
- vm: QuickJSVm,
9
+ ctx: QuickJSContext,
8
10
  target: unknown,
9
11
  marshal: (target: unknown) => QuickJSHandle,
10
12
  unmarshal: (handle: QuickJSHandle) => unknown,
11
- preMarshal: (
12
- target: unknown,
13
- handle: QuickJSHandle
14
- ) => QuickJSHandle | undefined,
15
- preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any
13
+ preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined,
14
+ preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any,
16
15
  ): QuickJSHandle | undefined {
17
16
  if (typeof target !== "function") return;
18
17
 
19
- const raw = vm
18
+ const raw = ctx
20
19
  .newFunction(target.name, function (...argHandles) {
21
20
  const that = unmarshal(this);
22
- const args = argHandles.map((a) => unmarshal(a));
21
+ const args = argHandles.map(a => unmarshal(a));
23
22
 
24
23
  if (isES2015Class(target) && isObject(that)) {
25
24
  // Class constructors cannot be invoked without new expression, and new.target is not changed
26
25
  const result = new target(...args);
27
26
  Object.entries(result).forEach(([key, value]) => {
28
- vm.setProp(this, key, marshal(value));
27
+ ctx.setProp(this, key, marshal(value));
29
28
  });
30
29
  return this;
31
30
  }
32
31
 
33
- return marshal(
34
- preApply ? preApply(target, that, args) : target.apply(that, args)
35
- );
32
+ return marshal(preApply ? preApply(target, that, args) : target.apply(that, args));
36
33
  })
37
- .consume((handle2) =>
34
+ .consume(handle2 =>
38
35
  // fucntions created by vm.newFunction are not callable as a class constrcutor
39
36
  call(
40
- vm,
37
+ ctx,
41
38
  `Cls => {
42
39
  const fn = function(...args) { return Cls.apply(this, args); };
43
40
  fn.name = Cls.name;
@@ -45,12 +42,12 @@ export default function marshalFunction(
45
42
  return fn;
46
43
  }`,
47
44
  undefined,
48
- handle2
49
- )
45
+ handle2,
46
+ ),
50
47
  );
51
48
 
52
49
  const handle = preMarshal(target, raw) ?? raw;
53
- marshalProperties(vm, target, raw, marshal);
50
+ marshalProperties(ctx, target, raw, marshal);
54
51
 
55
52
  return handle;
56
53
  }
@@ -1,13 +1,14 @@
1
1
  import { getQuickJS } from "quickjs-emscripten";
2
2
  import { expect, test, vi } from "vitest";
3
3
 
4
+ import { newDeferred } from "../util";
4
5
  import VMMap from "../vmmap";
5
6
  import { instanceOf, call, handleFrom, fn } from "../vmutil";
7
+
6
8
  import marshal from ".";
7
- import { newDeferred } from "../util";
8
9
 
9
10
  test("primitive, array, object", async () => {
10
- const { vm, map, marshal, dispose } = await setup();
11
+ const { ctx, map, marshal, dispose } = await setup();
11
12
 
12
13
  const target = {
13
14
  hoge: "foo",
@@ -17,7 +18,7 @@ test("primitive, array, object", async () => {
17
18
  };
18
19
  const handle = marshal(target);
19
20
 
20
- expect(vm.dump(handle)).toEqual(target);
21
+ expect(ctx.dump(handle)).toEqual(target);
21
22
  expect(map.size).toBe(4);
22
23
  expect(map.get(target)).toBe(handle);
23
24
  expect(map.has(target.aaa)).toBe(true);
@@ -28,37 +29,33 @@ test("primitive, array, object", async () => {
28
29
  });
29
30
 
30
31
  test("object with symbol key", async () => {
31
- const { vm, marshal, dispose } = await setup();
32
+ const { ctx, marshal, dispose } = await setup();
32
33
 
33
34
  const target = {
34
35
  foo: "hoge",
35
36
  [Symbol("a")]: 1,
36
37
  };
37
38
  const handle = marshal(target);
38
- expect(vm.dump(call(vm, `a => a.foo`, undefined, handle))).toBe("hoge");
39
- expect(
40
- vm.dump(
41
- call(vm, `a => a[Object.getOwnPropertySymbols(a)[0]]`, undefined, handle)
42
- )
43
- ).toBe(1);
39
+ expect(ctx.dump(call(ctx, `a => a.foo`, undefined, handle))).toBe("hoge");
40
+ expect(ctx.dump(call(ctx, `a => a[Object.getOwnPropertySymbols(a)[0]]`, undefined, handle))).toBe(
41
+ 1,
42
+ );
44
43
 
45
44
  dispose();
46
45
  });
47
46
 
48
47
  test("arrow function", async () => {
49
- const { vm, map, marshal, dispose } = await setup();
48
+ const { ctx, map, marshal, dispose } = await setup();
50
49
  const hoge = () => "foo";
51
50
  hoge.foo = { bar: 1 };
52
51
  const handle = marshal(hoge);
53
52
 
54
- expect(vm.typeof(handle)).toBe("function");
55
- expect(vm.dump(vm.getProp(handle, "length"))).toBe(0);
56
- expect(vm.dump(vm.getProp(handle, "name"))).toBe("hoge");
57
- const foo = vm.getProp(handle, "foo");
58
- expect(vm.dump(foo)).toEqual({ bar: 1 });
59
- expect(vm.dump(vm.unwrapResult(vm.callFunction(handle, vm.undefined)))).toBe(
60
- "foo"
61
- );
53
+ expect(ctx.typeof(handle)).toBe("function");
54
+ expect(ctx.dump(ctx.getProp(handle, "length"))).toBe(0);
55
+ expect(ctx.dump(ctx.getProp(handle, "name"))).toBe("hoge");
56
+ const foo = ctx.getProp(handle, "foo");
57
+ expect(ctx.dump(foo)).toEqual({ bar: 1 });
58
+ expect(ctx.dump(ctx.unwrapResult(ctx.callFunction(handle, ctx.undefined)))).toBe("foo");
62
59
  expect(map.size).toBe(2);
63
60
  expect(map.get(hoge)).toBe(handle);
64
61
  expect(map.has(hoge.foo)).toBe(true);
@@ -68,25 +65,23 @@ test("arrow function", async () => {
68
65
  });
69
66
 
70
67
  test("function", async () => {
71
- const { vm, map, marshal, dispose } = await setup();
68
+ const { ctx, map, marshal, dispose } = await setup();
72
69
 
73
70
  const bar = function (a: number, b: { hoge: number }) {
74
71
  return a + b.hoge;
75
72
  };
76
73
  const handle = marshal(bar);
77
74
 
78
- expect(vm.typeof(handle)).toBe("function");
79
- expect(vm.dump(vm.getProp(handle, "length"))).toBe(2);
80
- expect(vm.dump(vm.getProp(handle, "name"))).toBe("bar");
75
+ expect(ctx.typeof(handle)).toBe("function");
76
+ expect(ctx.dump(ctx.getProp(handle, "length"))).toBe(2);
77
+ expect(ctx.dump(ctx.getProp(handle, "name"))).toBe("bar");
81
78
  expect(map.size).toBe(2);
82
79
  expect(map.get(bar)).toBe(handle);
83
80
  expect(map.has(bar.prototype)).toBe(true);
84
81
 
85
- const b = vm.unwrapResult(vm.evalCode(`({ hoge: 2 })`));
82
+ const b = ctx.unwrapResult(ctx.evalCode(`({ hoge: 2 })`));
86
83
  expect(
87
- vm.dump(
88
- vm.unwrapResult(vm.callFunction(handle, vm.undefined, vm.newNumber(1), b))
89
- )
84
+ ctx.dump(ctx.unwrapResult(ctx.callFunction(handle, ctx.undefined, ctx.newNumber(1), b))),
90
85
  ).toBe(3);
91
86
 
92
87
  b.dispose();
@@ -94,18 +89,20 @@ test("function", async () => {
94
89
  });
95
90
 
96
91
  test("promise", async () => {
97
- const { vm, marshal, dispose } = await setup();
92
+ const { ctx, marshal, dispose } = await setup();
98
93
  const register = fn(
99
- vm,
100
- `promise => { promise.then(d => notify("resolve", d), d => notify("reject", d)); }`
94
+ ctx,
95
+ `promise => { promise.then(d => notify("resolve", d), d => notify("reject", d)); }`,
101
96
  );
102
97
 
103
98
  let notified: any;
104
- vm.newFunction("notify", (...handles) => {
105
- notified = handles.map((h) => vm.dump(h));
106
- }).consume((h) => {
107
- vm.setProp(vm.global, "notify", h);
108
- });
99
+ ctx
100
+ .newFunction("notify", (...handles) => {
101
+ notified = handles.map(h => ctx.dump(h));
102
+ })
103
+ .consume(h => {
104
+ ctx.setProp(ctx.global, "notify", h);
105
+ });
109
106
 
110
107
  const deferred = newDeferred();
111
108
  const handle = marshal(deferred.promise);
@@ -113,7 +110,7 @@ test("promise", async () => {
113
110
 
114
111
  deferred.resolve("foo");
115
112
  await deferred.promise;
116
- expect(vm.unwrapResult(vm.executePendingJobs())).toBe(1);
113
+ expect(ctx.unwrapResult(ctx.runtime.executePendingJobs())).toBe(1);
117
114
  expect(notified).toEqual(["resolve", "foo"]);
118
115
 
119
116
  const deferred2 = newDeferred();
@@ -122,7 +119,7 @@ test("promise", async () => {
122
119
 
123
120
  deferred2.reject("bar");
124
121
  await expect(deferred2.promise).rejects.toBe("bar");
125
- expect(vm.unwrapResult(vm.executePendingJobs())).toBe(1);
122
+ expect(ctx.unwrapResult(ctx.runtime.executePendingJobs())).toBe(1);
126
123
  expect(notified).toEqual(["reject", "bar"]);
127
124
 
128
125
  register.dispose();
@@ -130,7 +127,7 @@ test("promise", async () => {
130
127
  });
131
128
 
132
129
  test("class", async () => {
133
- const { vm, map, marshal, dispose } = await setup();
130
+ const { ctx, map, marshal, dispose } = await setup();
134
131
 
135
132
  class A {
136
133
  a: number;
@@ -165,41 +162,33 @@ test("class", async () => {
165
162
  expect(map.has(A.prototype)).toBe(true);
166
163
  expect(map.has(A.a)).toBe(true);
167
164
  expect(map.has(A.prototype.hoge)).toBe(true);
168
- expect(
169
- map.has(Object.getOwnPropertyDescriptor(A.prototype, "foo")?.get)
170
- ).toBe(true);
171
- expect(
172
- map.has(Object.getOwnPropertyDescriptor(A.prototype, "foo")?.set)
173
- ).toBe(true);
174
-
175
- expect(vm.typeof(handle)).toBe("function");
176
- expect(vm.dump(vm.getProp(handle, "length"))).toBe(1);
177
- expect(vm.dump(vm.getProp(handle, "name"))).toBe("_A");
178
- const staticA = vm.getProp(handle, "a");
179
- expect(instanceOf(vm, staticA, handle)).toBe(true);
180
- expect(vm.dump(vm.getProp(staticA, "a"))).toBe(100);
181
- expect(vm.dump(vm.getProp(staticA, "b"))).toBe("a!");
182
-
183
- const newA = vm.unwrapResult(vm.evalCode(`A => new A("foo")`));
184
- const instance = vm.unwrapResult(vm.callFunction(newA, vm.undefined, handle));
185
- expect(instanceOf(vm, instance, handle)).toBe(true);
186
- expect(vm.dump(vm.getProp(instance, "a"))).toBe(100);
187
- expect(vm.dump(vm.getProp(instance, "b"))).toBe("foo!");
188
- const methodHoge = vm.getProp(instance, "hoge");
189
- expect(vm.dump(vm.unwrapResult(vm.callFunction(methodHoge, instance)))).toBe(
190
- 101
191
- );
192
- expect(vm.dump(vm.getProp(instance, "a"))).toBe(100); // not synced
193
-
194
- const getter = vm.unwrapResult(vm.evalCode(`a => a.foo`));
195
- const setter = vm.unwrapResult(vm.evalCode(`(a, b) => a.foo = b`));
196
- expect(
197
- vm.dump(vm.unwrapResult(vm.callFunction(getter, vm.undefined, instance)))
198
- ).toBe("foo!");
199
- vm.unwrapResult(
200
- vm.callFunction(setter, vm.undefined, instance, vm.newString("b"))
165
+ expect(map.has(Object.getOwnPropertyDescriptor(A.prototype, "foo")?.get)).toBe(true);
166
+ expect(map.has(Object.getOwnPropertyDescriptor(A.prototype, "foo")?.set)).toBe(true);
167
+
168
+ expect(ctx.typeof(handle)).toBe("function");
169
+ expect(ctx.dump(ctx.getProp(handle, "length"))).toBe(1);
170
+ expect(ctx.dump(ctx.getProp(handle, "name"))).toBe("_A");
171
+ const staticA = ctx.getProp(handle, "a");
172
+ expect(instanceOf(ctx, staticA, handle)).toBe(true);
173
+ expect(ctx.dump(ctx.getProp(staticA, "a"))).toBe(100);
174
+ expect(ctx.dump(ctx.getProp(staticA, "b"))).toBe("a!");
175
+
176
+ const newA = ctx.unwrapResult(ctx.evalCode(`A => new A("foo")`));
177
+ const instance = ctx.unwrapResult(ctx.callFunction(newA, ctx.undefined, handle));
178
+ expect(instanceOf(ctx, instance, handle)).toBe(true);
179
+ expect(ctx.dump(ctx.getProp(instance, "a"))).toBe(100);
180
+ expect(ctx.dump(ctx.getProp(instance, "b"))).toBe("foo!");
181
+ const methodHoge = ctx.getProp(instance, "hoge");
182
+ expect(ctx.dump(ctx.unwrapResult(ctx.callFunction(methodHoge, instance)))).toBe(101);
183
+ expect(ctx.dump(ctx.getProp(instance, "a"))).toBe(100); // not synced
184
+
185
+ const getter = ctx.unwrapResult(ctx.evalCode(`a => a.foo`));
186
+ const setter = ctx.unwrapResult(ctx.evalCode(`(a, b) => a.foo = b`));
187
+ expect(ctx.dump(ctx.unwrapResult(ctx.callFunction(getter, ctx.undefined, instance)))).toBe(
188
+ "foo!",
201
189
  );
202
- expect(vm.dump(vm.getProp(instance, "b"))).toBe("foo!"); // not synced
190
+ ctx.unwrapResult(ctx.callFunction(setter, ctx.undefined, instance, ctx.newString("b")));
191
+ expect(ctx.dump(ctx.getProp(instance, "b"))).toBe("foo!"); // not synced
203
192
 
204
193
  staticA.dispose();
205
194
  newA.dispose();
@@ -207,19 +196,34 @@ test("class", async () => {
207
196
  methodHoge.dispose();
208
197
  getter.dispose();
209
198
  setter.dispose();
210
- map.dispose();
199
+ dispose();
200
+ });
201
+
202
+ test("date", async () => {
203
+ const { ctx, map, marshal, dispose } = await setup();
204
+
205
+ const date = new Date(2022, 7, 26);
206
+ const handle = marshal(date);
207
+ if (!map) throw new Error("map is undefined");
208
+
209
+ expect(map.size).toBe(1);
210
+ expect(map.get(date)).toBe(handle);
211
+
212
+ expect(ctx.dump(call(ctx, "d => d instanceof Date", undefined, handle))).toBe(true);
213
+ expect(ctx.dump(call(ctx, "d => d.getTime()", undefined, handle))).toBe(date.getTime());
214
+
211
215
  dispose();
212
216
  });
213
217
 
214
218
  test("marshalable", async () => {
215
219
  const isMarshalable = vi.fn((a: any) => a !== globalThis);
216
- const { vm, marshal, dispose } = await setup({
220
+ const { ctx, marshal, dispose } = await setup({
217
221
  isMarshalable,
218
222
  });
219
223
 
220
224
  const handle = marshal({ a: globalThis, b: 1 });
221
225
 
222
- expect(vm.dump(handle)).toEqual({ a: undefined, b: 1 });
226
+ expect(ctx.dump(handle)).toEqual({ a: undefined, b: 1 });
223
227
  expect(isMarshalable).toBeCalledWith(globalThis);
224
228
  expect(isMarshalable).toReturnWith(false);
225
229
 
@@ -228,7 +232,7 @@ test("marshalable", async () => {
228
232
 
229
233
  test("marshalable json", async () => {
230
234
  const isMarshalable = vi.fn(() => "json" as const);
231
- const { vm, marshal, dispose } = await setup({
235
+ const { ctx, marshal, dispose } = await setup({
232
236
  isMarshalable,
233
237
  });
234
238
 
@@ -239,7 +243,7 @@ test("marshalable json", async () => {
239
243
  };
240
244
  const handle = marshal(target);
241
245
 
242
- expect(vm.dump(handle)).toEqual({
246
+ expect(ctx.dump(handle)).toEqual({
243
247
  a: { d: target.a.d.toISOString(), e: [null, 1, {}] },
244
248
  b: 1,
245
249
  });
@@ -255,26 +259,26 @@ const setup = async ({
255
259
  }: {
256
260
  isMarshalable?: (target: any) => boolean | "json";
257
261
  } = {}) => {
258
- const vm = (await getQuickJS()).createVm();
259
- const map = new VMMap(vm);
262
+ const ctx = (await getQuickJS()).newContext();
263
+ const map = new VMMap(ctx);
260
264
  return {
261
- vm,
265
+ ctx,
262
266
  map,
263
267
  marshal: (v: any) =>
264
268
  marshal(v, {
265
- vm,
266
- unmarshal: (h) => map.getByHandle(h) ?? vm.dump(h),
269
+ ctx: ctx,
270
+ unmarshal: h => map.getByHandle(h) ?? ctx.dump(h),
267
271
  isMarshalable,
268
272
  pre: (t, d) => {
269
273
  const h = handleFrom(d);
270
274
  map.set(t, h);
271
275
  return h;
272
276
  },
273
- find: (t) => map.get(t),
277
+ find: t => map.get(t),
274
278
  }),
275
279
  dispose: () => {
276
280
  map.dispose();
277
- vm.dispose();
281
+ ctx.dispose();
278
282
  },
279
283
  };
280
284
  };
@@ -1,33 +1,31 @@
1
- import type {
2
- QuickJSDeferredPromise,
3
- QuickJSHandle,
4
- QuickJSVm,
5
- } from "quickjs-emscripten";
1
+ import type { QuickJSDeferredPromise, QuickJSHandle, QuickJSContext } from "quickjs-emscripten";
2
+
3
+ import marshalCustom, { defaultCustom } from "./custom";
6
4
  import marshalFunction from "./function";
5
+ import marshalJSON from "./json";
7
6
  import marshalObject from "./object";
8
7
  import marshalPrimitive from "./primitive";
9
- import marshalSymbol from "./symbol";
10
- import marshalJSON from "./json";
11
8
  import marshalPromise from "./promise";
12
9
 
13
10
  export type Options = {
14
- vm: QuickJSVm;
11
+ ctx: QuickJSContext;
15
12
  unmarshal: (handle: QuickJSHandle) => unknown;
16
13
  isMarshalable?: (target: unknown) => boolean | "json";
17
14
  find: (target: unknown) => QuickJSHandle | undefined;
18
15
  pre: (
19
16
  target: unknown,
20
17
  handle: QuickJSHandle | QuickJSDeferredPromise,
21
- mode: true | "json" | undefined
18
+ mode: true | "json" | undefined,
22
19
  ) => QuickJSHandle | undefined;
23
20
  preApply?: (target: Function, thisArg: unknown, args: unknown[]) => any;
21
+ custom?: Iterable<(obj: unknown, ctx: QuickJSContext) => QuickJSHandle | undefined>;
24
22
  };
25
23
 
26
24
  export function marshal(target: unknown, options: Options): QuickJSHandle {
27
- const { vm, unmarshal, isMarshalable, find, pre } = options;
25
+ const { ctx, unmarshal, isMarshalable, find, pre } = options;
28
26
 
29
27
  {
30
- const primitive = marshalPrimitive(vm, target);
28
+ const primitive = marshalPrimitive(ctx, target);
31
29
  if (primitive) {
32
30
  return primitive;
33
31
  }
@@ -40,22 +38,22 @@ export function marshal(target: unknown, options: Options): QuickJSHandle {
40
38
 
41
39
  const marshalable = isMarshalable?.(target);
42
40
  if (marshalable === false) {
43
- return vm.undefined;
41
+ return ctx.undefined;
44
42
  }
45
43
 
46
44
  const pre2 = (target: any, handle: QuickJSHandle | QuickJSDeferredPromise) =>
47
45
  pre(target, handle, marshalable);
48
46
  if (marshalable === "json") {
49
- return marshalJSON(vm, target, pre2);
47
+ return marshalJSON(ctx, target, pre2);
50
48
  }
51
49
 
52
50
  const marshal2 = (t: unknown) => marshal(t, options);
53
51
  return (
54
- marshalSymbol(vm, target, pre2) ??
55
- marshalPromise(vm, target, marshal2, pre2) ??
56
- marshalFunction(vm, target, marshal2, unmarshal, pre2, options.preApply) ??
57
- marshalObject(vm, target, marshal2, pre2) ??
58
- vm.undefined
52
+ marshalCustom(ctx, target, pre2, [...defaultCustom, ...(options.custom ?? [])]) ??
53
+ marshalPromise(ctx, target, marshal2, pre2) ??
54
+ marshalFunction(ctx, target, marshal2, unmarshal, pre2, options.preApply) ??
55
+ marshalObject(ctx, target, marshal2, pre2) ??
56
+ ctx.undefined
59
57
  );
60
58
  }
61
59
 
@@ -4,58 +4,54 @@ import { expect, test, vi } from "vitest";
4
4
  import marshalJSON from "./json";
5
5
 
6
6
  test("empty object", async () => {
7
- const vm = (await getQuickJS()).createVm();
8
- const prototypeCheck = vm.unwrapResult(
9
- vm.evalCode(`o => Object.getPrototypeOf(o) === Object.prototype`)
7
+ const ctx = (await getQuickJS()).newContext();
8
+ const prototypeCheck = ctx.unwrapResult(
9
+ ctx.evalCode(`o => Object.getPrototypeOf(o) === Object.prototype`),
10
10
  );
11
11
 
12
12
  const obj = {};
13
13
  const preMarshal = vi.fn((_, a) => a);
14
14
 
15
- const handle = marshalJSON(vm, obj, preMarshal);
15
+ const handle = marshalJSON(ctx, obj, preMarshal);
16
16
  if (!handle) throw new Error("handle is undefined");
17
17
 
18
- expect(vm.typeof(handle)).toBe("object");
18
+ expect(ctx.typeof(handle)).toBe("object");
19
19
  expect(preMarshal).toBeCalledTimes(1);
20
20
  expect(preMarshal.mock.calls[0][0]).toBe(obj);
21
21
  expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
22
- expect(
23
- vm.dump(
24
- vm.unwrapResult(vm.callFunction(prototypeCheck, vm.undefined, handle))
25
- )
26
- ).toBe(true);
22
+ expect(ctx.dump(ctx.unwrapResult(ctx.callFunction(prototypeCheck, ctx.undefined, handle)))).toBe(
23
+ true,
24
+ );
27
25
 
28
26
  handle.dispose();
29
27
  prototypeCheck.dispose();
30
- vm.dispose();
28
+ ctx.dispose();
31
29
  });
32
30
 
33
31
  test("normal object", async () => {
34
- const vm = (await getQuickJS()).createVm();
35
- const prototypeCheck = vm.unwrapResult(
36
- vm.evalCode(`o => Object.getPrototypeOf(o) === Object.prototype`)
32
+ const ctx = (await getQuickJS()).newContext();
33
+ const prototypeCheck = ctx.unwrapResult(
34
+ ctx.evalCode(`o => Object.getPrototypeOf(o) === Object.prototype`),
37
35
  );
38
- const entries = vm.unwrapResult(vm.evalCode(`Object.entries`));
36
+ const entries = ctx.unwrapResult(ctx.evalCode(`Object.entries`));
39
37
 
40
38
  const obj = { a: 100, b: "hoge" };
41
39
  const preMarshal = vi.fn((_, a) => a);
42
40
 
43
- const handle = marshalJSON(vm, obj, preMarshal);
41
+ const handle = marshalJSON(ctx, obj, preMarshal);
44
42
  if (!handle) throw new Error("handle is undefined");
45
43
 
46
- expect(vm.typeof(handle)).toBe("object");
47
- expect(vm.getNumber(vm.getProp(handle, "a"))).toBe(100);
48
- expect(vm.getString(vm.getProp(handle, "b"))).toBe("hoge");
44
+ expect(ctx.typeof(handle)).toBe("object");
45
+ expect(ctx.getNumber(ctx.getProp(handle, "a"))).toBe(100);
46
+ expect(ctx.getString(ctx.getProp(handle, "b"))).toBe("hoge");
49
47
  expect(preMarshal).toBeCalledTimes(1);
50
48
  expect(preMarshal.mock.calls[0][0]).toBe(obj);
51
49
  expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
52
- expect(
53
- vm.dump(
54
- vm.unwrapResult(vm.callFunction(prototypeCheck, vm.undefined, handle))
55
- )
56
- ).toBe(true);
57
- const e = vm.unwrapResult(vm.callFunction(entries, vm.undefined, handle));
58
- expect(vm.dump(e)).toEqual([
50
+ expect(ctx.dump(ctx.unwrapResult(ctx.callFunction(prototypeCheck, ctx.undefined, handle)))).toBe(
51
+ true,
52
+ );
53
+ const e = ctx.unwrapResult(ctx.callFunction(entries, ctx.undefined, handle));
54
+ expect(ctx.dump(e)).toEqual([
59
55
  ["a", 100],
60
56
  ["b", "hoge"],
61
57
  ]);
@@ -64,31 +60,29 @@ test("normal object", async () => {
64
60
  handle.dispose();
65
61
  prototypeCheck.dispose();
66
62
  entries.dispose();
67
- vm.dispose();
63
+ ctx.dispose();
68
64
  });
69
65
 
70
66
  test("array", async () => {
71
- const vm = (await getQuickJS()).createVm();
72
- const isArray = vm.unwrapResult(vm.evalCode(`Array.isArray`));
67
+ const ctx = (await getQuickJS()).newContext();
68
+ const isArray = ctx.unwrapResult(ctx.evalCode(`Array.isArray`));
73
69
 
74
70
  const array = [1, "aa"];
75
71
  const preMarshal = vi.fn((_, a) => a);
76
72
 
77
- const handle = marshalJSON(vm, array, preMarshal);
73
+ const handle = marshalJSON(ctx, array, preMarshal);
78
74
  if (!handle) throw new Error("handle is undefined");
79
75
 
80
- expect(vm.typeof(handle)).toBe("object");
81
- expect(vm.getNumber(vm.getProp(handle, 0))).toBe(1);
82
- expect(vm.getString(vm.getProp(handle, 1))).toBe("aa");
83
- expect(vm.getNumber(vm.getProp(handle, "length"))).toBe(2);
76
+ expect(ctx.typeof(handle)).toBe("object");
77
+ expect(ctx.getNumber(ctx.getProp(handle, 0))).toBe(1);
78
+ expect(ctx.getString(ctx.getProp(handle, 1))).toBe("aa");
79
+ expect(ctx.getNumber(ctx.getProp(handle, "length"))).toBe(2);
84
80
  expect(preMarshal).toBeCalledTimes(1);
85
81
  expect(preMarshal.mock.calls[0][0]).toBe(array);
86
82
  expect(preMarshal.mock.calls[0][1] === handle).toBe(true); // avoid freeze
87
- expect(
88
- vm.dump(vm.unwrapResult(vm.callFunction(isArray, vm.undefined, handle)))
89
- ).toBe(true);
83
+ expect(ctx.dump(ctx.unwrapResult(ctx.callFunction(isArray, ctx.undefined, handle)))).toBe(true);
90
84
 
91
85
  handle.dispose();
92
86
  isArray.dispose();
93
- vm.dispose();
87
+ ctx.dispose();
94
88
  });
@@ -1,15 +1,13 @@
1
- import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+
2
3
  import { json } from "../vmutil";
3
4
 
4
5
  export default function marshalJSON(
5
- vm: QuickJSVm,
6
+ ctx: QuickJSContext,
6
7
  target: unknown,
7
- preMarshal: (
8
- target: unknown,
9
- handle: QuickJSHandle
10
- ) => QuickJSHandle | undefined
8
+ preMarshal: (target: unknown, handle: QuickJSHandle) => QuickJSHandle | undefined,
11
9
  ): QuickJSHandle {
12
- const raw = json(vm, target);
10
+ const raw = json(ctx, target);
13
11
  const handle = preMarshal(target, raw) ?? raw;
14
12
  return handle;
15
13
  }