quickjs-emscripten-sync 1.2.0 → 1.5.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.
Files changed (76) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +71 -44
  3. package/dist/index.d.ts +116 -23
  4. package/dist/quickjs-emscripten-sync.mjs +842 -0
  5. package/dist/quickjs-emscripten-sync.umd.js +64 -2
  6. package/package.json +22 -53
  7. package/src/default.ts +2 -2
  8. package/src/index.test.ts +223 -59
  9. package/src/index.ts +72 -66
  10. package/src/marshal/custom.test.ts +50 -0
  11. package/src/marshal/custom.ts +36 -0
  12. package/src/marshal/function.test.ts +64 -75
  13. package/src/marshal/function.ts +15 -18
  14. package/src/marshal/index.test.ts +122 -77
  15. package/src/marshal/index.ts +19 -15
  16. package/src/marshal/json.test.ts +37 -41
  17. package/src/marshal/json.ts +5 -7
  18. package/src/marshal/object.test.ts +59 -84
  19. package/src/marshal/object.ts +8 -15
  20. package/src/marshal/primitive.test.ts +18 -21
  21. package/src/marshal/primitive.ts +11 -10
  22. package/src/marshal/promise.test.ts +85 -0
  23. package/src/marshal/promise.ts +19 -0
  24. package/src/marshal/properties.test.ts +24 -27
  25. package/src/marshal/properties.ts +15 -17
  26. package/src/unmarshal/custom.test.ts +50 -0
  27. package/src/unmarshal/custom.ts +31 -0
  28. package/src/unmarshal/function.test.ts +63 -86
  29. package/src/unmarshal/function.ts +13 -22
  30. package/src/unmarshal/index.test.ts +114 -109
  31. package/src/unmarshal/index.ts +15 -14
  32. package/src/unmarshal/object.test.ts +42 -46
  33. package/src/unmarshal/object.ts +16 -20
  34. package/src/unmarshal/primitive.test.ts +17 -15
  35. package/src/unmarshal/primitive.ts +11 -18
  36. package/src/unmarshal/promise.test.ts +44 -0
  37. package/src/unmarshal/promise.ts +31 -0
  38. package/src/unmarshal/properties.test.ts +11 -9
  39. package/src/unmarshal/properties.ts +44 -45
  40. package/src/util.test.ts +14 -2
  41. package/src/util.ts +18 -8
  42. package/src/vmmap.test.ts +88 -82
  43. package/src/vmmap.ts +30 -44
  44. package/src/vmutil.test.ts +100 -75
  45. package/src/vmutil.ts +51 -34
  46. package/src/wrapper.test.ts +129 -167
  47. package/src/wrapper.ts +59 -62
  48. package/dist/default.d.ts +0 -4
  49. package/dist/marshal/function.d.ts +0 -2
  50. package/dist/marshal/index.d.ts +0 -11
  51. package/dist/marshal/json.d.ts +0 -2
  52. package/dist/marshal/object.d.ts +0 -2
  53. package/dist/marshal/primitive.d.ts +0 -2
  54. package/dist/marshal/properties.d.ts +0 -2
  55. package/dist/marshal/symbol.d.ts +0 -2
  56. package/dist/quickjs-emscripten-sync.cjs +0 -2
  57. package/dist/quickjs-emscripten-sync.cjs.map +0 -1
  58. package/dist/quickjs-emscripten-sync.modern.js +0 -2
  59. package/dist/quickjs-emscripten-sync.modern.js.map +0 -1
  60. package/dist/quickjs-emscripten-sync.module.js +0 -2
  61. package/dist/quickjs-emscripten-sync.module.js.map +0 -1
  62. package/dist/quickjs-emscripten-sync.umd.js.map +0 -1
  63. package/dist/unmarshal/function.d.ts +0 -2
  64. package/dist/unmarshal/index.d.ts +0 -9
  65. package/dist/unmarshal/object.d.ts +0 -2
  66. package/dist/unmarshal/primitive.d.ts +0 -2
  67. package/dist/unmarshal/properties.d.ts +0 -2
  68. package/dist/unmarshal/symbol.d.ts +0 -2
  69. package/dist/util.d.ts +0 -7
  70. package/dist/vmmap.d.ts +0 -35
  71. package/dist/vmutil.d.ts +0 -11
  72. package/dist/wrapper.d.ts +0 -11
  73. package/src/marshal/symbol.test.ts +0 -22
  74. package/src/marshal/symbol.ts +0 -20
  75. package/src/unmarshal/symbol.test.ts +0 -23
  76. package/src/unmarshal/symbol.ts +0 -12
@@ -1,16 +1,15 @@
1
1
  import { getQuickJS, QuickJSHandle } from "quickjs-emscripten";
2
+ import { expect, test, vi } from "vitest";
3
+
2
4
  import unmarshalObject from "./object";
3
5
 
4
6
  test("normal object", async () => {
5
- const vm = (await getQuickJS()).createVm();
6
- const unmarshal = jest.fn((v: QuickJSHandle): [unknown, boolean] => [
7
- vm.dump(v),
8
- false,
9
- ]);
10
- const preUnmarshal = jest.fn((a) => a);
7
+ const ctx = (await getQuickJS()).newContext();
8
+ const unmarshal = vi.fn((v: QuickJSHandle): [unknown, boolean] => [ctx.dump(v), false]);
9
+ const preUnmarshal = vi.fn(a => a);
11
10
 
12
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1, b: true })`));
13
- const obj = unmarshalObject(vm, handle, unmarshal, preUnmarshal);
11
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1, b: true })`));
12
+ const obj = unmarshalObject(ctx, handle, unmarshal, preUnmarshal);
14
13
  if (!obj) throw new Error("obj is undefined");
15
14
  expect(obj).toEqual({ a: 1, b: true });
16
15
  expect(unmarshal).toReturnTimes(4);
@@ -22,20 +21,20 @@ test("normal object", async () => {
22
21
  expect(preUnmarshal).toBeCalledWith(obj, handle);
23
22
 
24
23
  handle.dispose();
25
- vm.dispose();
24
+ ctx.dispose();
26
25
  });
27
26
 
28
27
  test("properties", async () => {
29
- const vm = (await getQuickJS()).createVm();
28
+ const ctx = (await getQuickJS()).newContext();
30
29
  const disposables: QuickJSHandle[] = [];
31
- const unmarshal = jest.fn((v: QuickJSHandle): [unknown, boolean] => {
30
+ const unmarshal = vi.fn((v: QuickJSHandle): [unknown, boolean] => {
32
31
  disposables.push(v);
33
- return [vm.typeof(v) === "function" ? () => {} : vm.dump(v), false];
32
+ return [ctx.typeof(v) === "function" ? () => {} : ctx.dump(v), false];
34
33
  });
35
- const preUnmarshal = jest.fn((a) => a);
34
+ const preUnmarshal = vi.fn(a => a);
36
35
 
37
- const handle = vm.unwrapResult(
38
- vm.evalCode(`{
36
+ const handle = ctx.unwrapResult(
37
+ ctx.evalCode(`{
39
38
  const obj = {};
40
39
  Object.defineProperties(obj, {
41
40
  a: { value: 1, writable: true, configurable: true, enumerable: true },
@@ -43,9 +42,9 @@ test("properties", async () => {
43
42
  c: { get: () => {}, set: () => {} },
44
43
  });
45
44
  obj
46
- }`)
45
+ }`),
47
46
  );
48
- const obj = unmarshalObject(vm, handle, unmarshal, preUnmarshal);
47
+ const obj = unmarshalObject(ctx, handle, unmarshal, preUnmarshal);
49
48
  if (!obj) throw new Error("obj is undefined");
50
49
  expect(obj).toEqual({
51
50
  a: 1,
@@ -70,21 +69,18 @@ test("properties", async () => {
70
69
  expect(preUnmarshal).toBeCalledTimes(1);
71
70
  expect(preUnmarshal).toBeCalledWith(obj, handle);
72
71
 
73
- disposables.forEach((d) => d.dispose());
72
+ disposables.forEach(d => d.dispose());
74
73
  handle.dispose();
75
- vm.dispose();
74
+ ctx.dispose();
76
75
  });
77
76
 
78
77
  test("array", async () => {
79
- const vm = (await getQuickJS()).createVm();
80
- const unmarshal = jest.fn((v: QuickJSHandle): [unknown, boolean] => [
81
- vm.dump(v),
82
- false,
83
- ]);
84
- const preUnmarshal = jest.fn((a) => a);
78
+ const ctx = (await getQuickJS()).newContext();
79
+ const unmarshal = vi.fn((v: QuickJSHandle): [unknown, boolean] => [ctx.dump(v), false]);
80
+ const preUnmarshal = vi.fn(a => a);
85
81
 
86
- const handle = vm.unwrapResult(vm.evalCode(`[1, true, "a"]`));
87
- const array = unmarshalObject(vm, handle, unmarshal, preUnmarshal);
82
+ const handle = ctx.unwrapResult(ctx.evalCode(`[1, true, "a"]`));
83
+ const array = unmarshalObject(ctx, handle, unmarshal, preUnmarshal);
88
84
  expect((array as any)[0]).toEqual(1);
89
85
  expect(Array.isArray(array)).toBe(true);
90
86
  expect(unmarshal.mock.results[0].value).toEqual(["0", false]);
@@ -98,19 +94,19 @@ test("array", async () => {
98
94
  expect(preUnmarshal).toBeCalledWith(array, handle);
99
95
 
100
96
  handle.dispose();
101
- vm.dispose();
97
+ ctx.dispose();
102
98
  });
103
99
 
104
100
  test("prototype", async () => {
105
- const vm = (await getQuickJS()).createVm();
106
- const unmarshal = jest.fn((v: QuickJSHandle): [unknown, boolean] => [
107
- vm.typeof(v) === "object" ? { a: () => 1 } : vm.dump(v),
101
+ const ctx = (await getQuickJS()).newContext();
102
+ const unmarshal = vi.fn((v: QuickJSHandle): [unknown, boolean] => [
103
+ ctx.typeof(v) === "object" ? { a: () => 1 } : ctx.dump(v),
108
104
  false,
109
105
  ]);
110
- const preUnmarshal = jest.fn((a) => a);
106
+ const preUnmarshal = vi.fn(a => a);
111
107
 
112
- const handle = vm.unwrapResult(vm.evalCode(`Object.create({ a: () => 1 })`));
113
- const obj = unmarshalObject(vm, handle, unmarshal, preUnmarshal) as any;
108
+ const handle = ctx.unwrapResult(ctx.evalCode(`Object.create({ a: () => 1 })`));
109
+ const obj = unmarshalObject(ctx, handle, unmarshal, preUnmarshal) as any;
114
110
  if (!obj) throw new Error("obj is undefined");
115
111
  expect(Object.getPrototypeOf(obj)).toEqual({ a: expect.any(Function) });
116
112
  expect(obj.a()).toBe(1);
@@ -120,25 +116,25 @@ test("prototype", async () => {
120
116
  expect(preUnmarshal).toBeCalledWith(obj, handle);
121
117
 
122
118
  handle.dispose();
123
- vm.dispose();
119
+ ctx.dispose();
124
120
  });
125
121
 
126
122
  test("undefined", async () => {
127
- const vm = (await getQuickJS()).createVm();
128
- const f = jest.fn();
123
+ const ctx = (await getQuickJS()).newContext();
124
+ const f = vi.fn();
129
125
 
130
- expect(unmarshalObject(vm, vm.undefined, f, f)).toEqual(undefined);
131
- expect(unmarshalObject(vm, vm.true, f, f)).toEqual(undefined);
132
- expect(unmarshalObject(vm, vm.false, f, f)).toEqual(undefined);
133
- expect(unmarshalObject(vm, vm.null, f, f)).toEqual(undefined);
134
- expect(unmarshalObject(vm, vm.newString("hoge"), f, f)).toEqual(undefined);
135
- expect(unmarshalObject(vm, vm.newNumber(-10), f, f)).toEqual(undefined);
126
+ expect(unmarshalObject(ctx, ctx.undefined, f, f)).toEqual(undefined);
127
+ expect(unmarshalObject(ctx, ctx.true, f, f)).toEqual(undefined);
128
+ expect(unmarshalObject(ctx, ctx.false, f, f)).toEqual(undefined);
129
+ expect(unmarshalObject(ctx, ctx.null, f, f)).toEqual(undefined);
130
+ expect(unmarshalObject(ctx, ctx.newString("hoge"), f, f)).toEqual(undefined);
131
+ expect(unmarshalObject(ctx, ctx.newNumber(-10), f, f)).toEqual(undefined);
136
132
 
137
- const func = vm.newFunction("", () => {});
138
- expect(unmarshalObject(vm, func, f, f)).toEqual(undefined);
133
+ const func = ctx.newFunction("", () => {});
134
+ expect(unmarshalObject(ctx, func, f, f)).toEqual(undefined);
139
135
 
140
136
  expect(f).toBeCalledTimes(0);
141
137
 
142
138
  func.dispose();
143
- vm.dispose();
139
+ ctx.dispose();
144
140
  });
@@ -1,41 +1,37 @@
1
- import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
2
- import unmarshalProperties from "./properties";
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+
3
3
  import { call } from "../vmutil";
4
4
 
5
+ import unmarshalProperties from "./properties";
6
+
5
7
  export default function unmarshalObject(
6
- vm: QuickJSVm,
8
+ ctx: QuickJSContext,
7
9
  handle: QuickJSHandle,
8
10
  unmarshal: (handle: QuickJSHandle) => [unknown, boolean],
9
- preUnmarshal: <T>(target: T, handle: QuickJSHandle) => T | undefined
11
+ preUnmarshal: <T>(target: T, handle: QuickJSHandle) => T | undefined,
10
12
  ): object | undefined {
11
13
  if (
12
- vm.typeof(handle) !== "object" ||
14
+ ctx.typeof(handle) !== "object" ||
13
15
  // null check
14
- vm
15
- .unwrapResult(vm.evalCode("o => o === null"))
16
- .consume((n) =>
17
- vm.dump(vm.unwrapResult(vm.callFunction(n, vm.undefined, handle)))
18
- )
16
+ ctx
17
+ .unwrapResult(ctx.evalCode("o => o === null"))
18
+ .consume(n => ctx.dump(ctx.unwrapResult(ctx.callFunction(n, ctx.undefined, handle))))
19
19
  )
20
20
  return;
21
21
 
22
- const raw = call(vm, "Array.isArray", undefined, handle).consume((r) =>
23
- vm.dump(r)
24
- )
25
- ? []
26
- : {};
22
+ const raw = call(ctx, "Array.isArray", undefined, handle).consume(r => ctx.dump(r)) ? [] : {};
27
23
  const obj = preUnmarshal(raw, handle) ?? raw;
28
24
 
29
25
  const prototype = call(
30
- vm,
26
+ ctx,
31
27
  `o => {
32
28
  const p = Object.getPrototypeOf(o);
33
29
  return !p || p === Object.prototype || p === Array.prototype ? undefined : p;
34
30
  }`,
35
31
  undefined,
36
- handle
37
- ).consume((prototype) => {
38
- if (vm.typeof(prototype) === "undefined") return;
32
+ handle,
33
+ ).consume(prototype => {
34
+ if (ctx.typeof(prototype) === "undefined") return;
39
35
  const [proto] = unmarshal(prototype);
40
36
  return proto;
41
37
  });
@@ -43,7 +39,7 @@ export default function unmarshalObject(
43
39
  Object.setPrototypeOf(obj, prototype);
44
40
  }
45
41
 
46
- unmarshalProperties(vm, handle, raw, unmarshal);
42
+ unmarshalProperties(ctx, handle, raw, unmarshal);
47
43
 
48
44
  return obj;
49
45
  }
@@ -1,28 +1,30 @@
1
1
  import { getQuickJS } from "quickjs-emscripten";
2
+ import { expect, test } from "vitest";
3
+
2
4
  import unmarshalPrimitive from "./primitive";
3
5
 
4
6
  test("works", async () => {
5
- const vm = (await getQuickJS()).createVm();
7
+ const ctx = (await getQuickJS()).newContext();
6
8
 
7
- expect(unmarshalPrimitive(vm, vm.undefined)).toEqual([undefined, true]);
8
- expect(unmarshalPrimitive(vm, vm.true)).toEqual([true, true]);
9
- expect(unmarshalPrimitive(vm, vm.false)).toEqual([false, true]);
10
- expect(unmarshalPrimitive(vm, vm.null)).toEqual([null, true]);
11
- expect(unmarshalPrimitive(vm, vm.newString("hoge"))).toEqual(["hoge", true]);
12
- expect(unmarshalPrimitive(vm, vm.newNumber(-10))).toEqual([-10, true]);
9
+ expect(unmarshalPrimitive(ctx, ctx.undefined)).toEqual([undefined, true]);
10
+ expect(unmarshalPrimitive(ctx, ctx.true)).toEqual([true, true]);
11
+ expect(unmarshalPrimitive(ctx, ctx.false)).toEqual([false, true]);
12
+ expect(unmarshalPrimitive(ctx, ctx.null)).toEqual([null, true]);
13
+ expect(unmarshalPrimitive(ctx, ctx.newString("hoge"))).toEqual(["hoge", true]);
14
+ expect(unmarshalPrimitive(ctx, ctx.newNumber(-10))).toEqual([-10, true]);
13
15
  // expect(
14
- // unmarshalPrimitive(vm, vm.unwrapResult(vm.evalCode(`BigInt(1)`)))
16
+ // unmarshalPrimitive(ctx, ctx.unwrapResult(vm.evalCode(`BigInt(1)`)))
15
17
  // ).toEqual([BigInt(1), true]);
16
18
 
17
- const obj = vm.newObject();
18
- expect(unmarshalPrimitive(vm, obj)).toEqual([undefined, false]);
19
- const array = vm.newArray();
20
- expect(unmarshalPrimitive(vm, array)).toEqual([undefined, false]);
21
- const func = vm.newFunction("", () => {});
22
- expect(unmarshalPrimitive(vm, func)).toEqual([undefined, false]);
19
+ const obj = ctx.newObject();
20
+ expect(unmarshalPrimitive(ctx, obj)).toEqual([undefined, false]);
21
+ const array = ctx.newArray();
22
+ expect(unmarshalPrimitive(ctx, array)).toEqual([undefined, false]);
23
+ const func = ctx.newFunction("", () => {});
24
+ expect(unmarshalPrimitive(ctx, func)).toEqual([undefined, false]);
23
25
 
24
26
  obj.dispose();
25
27
  array.dispose();
26
28
  func.dispose();
27
- vm.dispose();
29
+ ctx.dispose();
28
30
  });
@@ -1,23 +1,16 @@
1
- import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
2
 
3
3
  export default function unmarshalPrimitive(
4
- vm: QuickJSVm,
5
- handle: QuickJSHandle
4
+ ctx: QuickJSContext,
5
+ handle: QuickJSHandle,
6
6
  ): [any, boolean] {
7
- const ty = vm.typeof(handle);
8
- if (
9
- ty === "undefined" ||
10
- ty === "number" ||
11
- ty === "string" ||
12
- ty === "boolean"
13
- ) {
14
- return [vm.dump(handle), true];
7
+ const ty = ctx.typeof(handle);
8
+ if (ty === "undefined" || ty === "number" || ty === "string" || ty === "boolean") {
9
+ return [ctx.dump(handle), true];
15
10
  } else if (ty === "object") {
16
- const isNull = vm
17
- .unwrapResult(vm.evalCode("a => a === null"))
18
- .consume((n) =>
19
- vm.dump(vm.unwrapResult(vm.callFunction(n, vm.undefined, handle)))
20
- );
11
+ const isNull = ctx
12
+ .unwrapResult(ctx.evalCode("a => a === null"))
13
+ .consume(n => ctx.dump(ctx.unwrapResult(ctx.callFunction(n, ctx.undefined, handle))));
21
14
  if (isNull) {
22
15
  return [null, true];
23
16
  }
@@ -25,10 +18,10 @@ export default function unmarshalPrimitive(
25
18
 
26
19
  // BigInt is not supported by quickjs-emscripten
27
20
  // if (ty === "bigint") {
28
- // const str = vm
21
+ // const str = ctx
29
22
  // .getProp(handle, "toString")
30
23
  // .consume(toString => vm.unwrapResult(vm.callFunction(toString, handle)))
31
- // .consume(str => vm.getString(str));
24
+ // .consume(str => ctx.getString(str));
32
25
  // const bi = BigInt(str);
33
26
  // return [bi, true];
34
27
  // }
@@ -0,0 +1,44 @@
1
+ import { Disposable, getQuickJS, type QuickJSHandle } from "quickjs-emscripten";
2
+ import { expect, test, vi } from "vitest";
3
+
4
+ import unmarshalPromise from "./promise";
5
+
6
+ const testPromise = (reject: boolean) => async () => {
7
+ const ctx = (await getQuickJS()).newContext();
8
+ const disposables: Disposable[] = [];
9
+ const marshal = vi.fn((v): [QuickJSHandle, boolean] => {
10
+ const f = ctx.newFunction(v.name, h => {
11
+ v(ctx.dump(h));
12
+ });
13
+ disposables.push(f);
14
+ return [f, false];
15
+ });
16
+ const preUnmarshal = vi.fn(a => a);
17
+
18
+ const deferred = ctx.newPromise();
19
+ disposables.push(deferred);
20
+ const promise = unmarshalPromise(ctx, deferred.handle, marshal, preUnmarshal);
21
+
22
+ expect(marshal).toBeCalledTimes(2);
23
+ expect(preUnmarshal).toBeCalledTimes(1);
24
+ expect(ctx.runtime.hasPendingJob()).toBe(false);
25
+
26
+ if (reject) {
27
+ deferred.reject(ctx.newString("hoge"));
28
+ } else {
29
+ deferred.resolve(ctx.newString("hoge"));
30
+ }
31
+ expect(ctx.runtime.hasPendingJob()).toBe(true);
32
+ expect(ctx.unwrapResult(ctx.runtime.executePendingJobs())).toBe(1);
33
+ if (reject) {
34
+ expect(promise).rejects.toThrow("hoge");
35
+ } else {
36
+ expect(promise).resolves.toBe("hoge");
37
+ }
38
+
39
+ disposables.forEach(d => d.dispose());
40
+ ctx.dispose();
41
+ };
42
+
43
+ test("resolve", testPromise(false));
44
+ test("reject", testPromise(true));
@@ -0,0 +1,31 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+
3
+ import { newDeferred } from "../util";
4
+ import { call, instanceOf } from "../vmutil";
5
+
6
+ export default function unmarshalPromise<T = unknown>(
7
+ ctx: QuickJSContext,
8
+ handle: QuickJSHandle,
9
+ /** marshal returns handle and boolean indicates that the handle should be disposed after use */
10
+ marshal: (value: unknown) => [QuickJSHandle, boolean],
11
+ preUnmarshal: <T>(target: T, handle: QuickJSHandle) => T | undefined,
12
+ ): Promise<T> | undefined {
13
+ if (!isPromiseHandle(ctx, handle)) return;
14
+
15
+ const deferred = newDeferred<T>();
16
+ const [resHandle, resShouldBeDisposed] = marshal(deferred.resolve);
17
+ const [rejHandle, rejShouldBeDisposed] = marshal(deferred.reject);
18
+ call(ctx, "(p, res, rej) => { p.then(res, rej); }", undefined, handle, resHandle, rejHandle);
19
+ if (resShouldBeDisposed) resHandle.dispose();
20
+ if (rejShouldBeDisposed) rejHandle.dispose();
21
+
22
+ return preUnmarshal(deferred.promise, handle) ?? deferred.promise;
23
+ }
24
+
25
+ function isPromiseHandle(ctx: QuickJSContext, handle: QuickJSHandle): boolean {
26
+ if (!handle.owner) return false;
27
+ return ctx.unwrapResult(ctx.evalCode("Promise")).consume(promise => {
28
+ if (!handle.owner) return false;
29
+ return instanceOf(ctx, handle, promise);
30
+ });
31
+ }
@@ -1,17 +1,19 @@
1
1
  import { getQuickJS, QuickJSHandle } from "quickjs-emscripten";
2
+ import { expect, test, vi } from "vitest";
3
+
2
4
  import unmarshalProperties from "./properties";
3
5
 
4
6
  test("works", async () => {
5
- const vm = (await getQuickJS()).createVm();
7
+ const ctx = (await getQuickJS()).newContext();
6
8
  const disposables: QuickJSHandle[] = [];
7
- const unmarshal = jest.fn((v: QuickJSHandle): [unknown, boolean] => {
9
+ const unmarshal = vi.fn((v: QuickJSHandle): [unknown, boolean] => {
8
10
  disposables.push(v);
9
- return [vm.typeof(v) === "function" ? () => {} : vm.dump(v), false];
11
+ return [ctx.typeof(v) === "function" ? () => {} : ctx.dump(v), false];
10
12
  });
11
13
  const obj = {};
12
14
 
13
- const handle = vm.unwrapResult(
14
- vm.evalCode(`{
15
+ const handle = ctx.unwrapResult(
16
+ ctx.evalCode(`{
15
17
  const obj = {};
16
18
  Object.defineProperties(obj, {
17
19
  a: { value: 1, writable: true, configurable: true, enumerable: true },
@@ -19,10 +21,10 @@ test("works", async () => {
19
21
  c: { get: () => {}, set: () => {} },
20
22
  });
21
23
  obj
22
- }`)
24
+ }`),
23
25
  );
24
26
 
25
- unmarshalProperties(vm, handle, obj, unmarshal);
27
+ unmarshalProperties(ctx, handle, obj, unmarshal);
26
28
 
27
29
  expect(obj).toEqual({
28
30
  a: 1,
@@ -45,7 +47,7 @@ test("works", async () => {
45
47
  expect(unmarshal).toReturnWith(["c", false]);
46
48
  expect(unmarshal).toReturnWith([expect.any(Function), false]); // get, set
47
49
 
48
- disposables.forEach((d) => d.dispose());
50
+ disposables.forEach(d => d.dispose());
49
51
  handle.dispose();
50
- vm.dispose();
52
+ ctx.dispose();
51
53
  });
@@ -1,61 +1,60 @@
1
- import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+
2
3
  import { call } from "../vmutil";
3
4
 
4
5
  export default function unmarshalProperties(
5
- vm: QuickJSVm,
6
+ ctx: QuickJSContext,
6
7
  handle: QuickJSHandle,
7
8
  target: object | Function,
8
- unmarshal: (handle: QuickJSHandle) => [unknown, boolean]
9
+ unmarshal: (handle: QuickJSHandle) => [unknown, boolean],
9
10
  ) {
10
- vm.newFunction("", (key, value) => {
11
- const [keyName] = unmarshal(key);
12
- if (
13
- typeof keyName !== "string" &&
14
- typeof keyName !== "number" &&
15
- typeof keyName !== "symbol"
16
- )
17
- return;
11
+ ctx
12
+ .newFunction("", (key, value) => {
13
+ const [keyName] = unmarshal(key);
14
+ if (typeof keyName !== "string" && typeof keyName !== "number" && typeof keyName !== "symbol")
15
+ return;
18
16
 
19
- const desc = (
20
- [
21
- ["value", true],
22
- ["get", true],
23
- ["set", true],
24
- ["configurable", false],
25
- ["enumerable", false],
26
- ["writable", false],
27
- ] as const
28
- ).reduce<PropertyDescriptor>((desc, [key, unmarshable]) => {
29
- const h = vm.getProp(value, key);
30
- const ty = vm.typeof(h);
17
+ const desc = (
18
+ [
19
+ ["value", true],
20
+ ["get", true],
21
+ ["set", true],
22
+ ["configurable", false],
23
+ ["enumerable", false],
24
+ ["writable", false],
25
+ ] as const
26
+ ).reduce<PropertyDescriptor>((desc, [key, unmarshable]) => {
27
+ const h = ctx.getProp(value, key);
28
+ const ty = ctx.typeof(h);
31
29
 
32
- if (ty === "undefined") return desc;
33
- if (!unmarshable && ty === "boolean") {
34
- desc[key] = vm.dump(vm.getProp(value, key));
35
- return desc;
36
- }
30
+ if (ty === "undefined") return desc;
31
+ if (!unmarshable && ty === "boolean") {
32
+ desc[key] = ctx.dump(ctx.getProp(value, key));
33
+ return desc;
34
+ }
37
35
 
38
- const [v, alreadyExists] = unmarshal(h);
39
- if (alreadyExists) {
40
- h.dispose();
41
- }
42
- desc[key] = v;
36
+ const [v, alreadyExists] = unmarshal(h);
37
+ if (alreadyExists) {
38
+ h.dispose();
39
+ }
40
+ desc[key] = v;
43
41
 
44
- return desc;
45
- }, {});
42
+ return desc;
43
+ }, {});
46
44
 
47
- Object.defineProperty(target, keyName, desc);
48
- }).consume((fn) => {
49
- call(
50
- vm,
51
- `(o, fn) => {
45
+ Object.defineProperty(target, keyName, desc);
46
+ })
47
+ .consume(fn => {
48
+ call(
49
+ ctx,
50
+ `(o, fn) => {
52
51
  const descs = Object.getOwnPropertyDescriptors(o);
53
52
  Object.entries(descs).forEach(([k, v]) => fn(k, v));
54
53
  Object.getOwnPropertySymbols(descs).forEach(k => fn(k, descs[k]));
55
54
  }`,
56
- undefined,
57
- handle,
58
- fn
59
- ).dispose();
60
- });
55
+ undefined,
56
+ handle,
57
+ fn,
58
+ ).dispose();
59
+ });
61
60
  }
package/src/util.test.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { isES2015Class, isObject, walkObject, complexity } from "./util";
1
+ import { expect, test, vi } from "vitest";
2
+
3
+ import { isES2015Class, isObject, walkObject, complexity, newDeferred } from "./util";
2
4
 
3
5
  test("isES2015Class", () => {
4
6
  expect(isES2015Class(class {})).toBe(true);
@@ -25,7 +27,7 @@ test("isObject", () => {
25
27
  });
26
28
 
27
29
  test("walkObject", () => {
28
- const cb = jest.fn();
30
+ const cb = vi.fn();
29
31
  const obj = { a: { b: 1, c: () => {} } };
30
32
  const set = new Set<any>([obj, obj.a, obj.a.c]);
31
33
  expect(walkObject(obj, cb)).toEqual(set);
@@ -52,3 +54,13 @@ test("complexity", () => {
52
54
  expect(complexity({ a: {} })).toBe(2);
53
55
  expect(complexity({ a: {} }, 1)).toBe(1);
54
56
  });
57
+
58
+ test("newDeferred", () => {
59
+ const deferred = newDeferred();
60
+ deferred.resolve("foo");
61
+ expect(deferred.promise).resolves.toBe("foo");
62
+
63
+ const deferred2 = newDeferred();
64
+ deferred2.reject("bar");
65
+ expect(deferred2.promise).rejects.toBe("bar");
66
+ });
package/src/util.ts CHANGED
@@ -1,19 +1,14 @@
1
1
  export function isES2015Class(cls: any): cls is new (...args: any[]) => any {
2
- return (
3
- typeof cls === "function" &&
4
- /^class\s/.test(Function.prototype.toString.call(cls))
5
- );
2
+ return typeof cls === "function" && /^class\s/.test(Function.prototype.toString.call(cls));
6
3
  }
7
4
 
8
5
  export function isObject(value: any): value is object | Function {
9
- return (
10
- typeof value === "function" || (typeof value === "object" && value !== null)
11
- );
6
+ return typeof value === "function" || (typeof value === "object" && value !== null);
12
7
  }
13
8
 
14
9
  export function walkObject(
15
10
  value: any,
16
- callback?: (target: any, set: Set<any>) => boolean | void
11
+ callback?: (target: any, set: Set<any>) => boolean | void,
17
12
  ): Set<any> {
18
13
  const set = new Set<any>();
19
14
  const walk = (v: any) => {
@@ -51,3 +46,18 @@ export function walkObject(
51
46
  export function complexity(value: any, max?: number): number {
52
47
  return walkObject(value, max ? (_, set) => set.size < max : undefined).size;
53
48
  }
49
+
50
+ export function newDeferred<T = unknown>() {
51
+ let res: (v: T | PromiseLike<T>) => void = () => {};
52
+ let rej: (v: T | PromiseLike<T>) => void = () => {};
53
+ const promise = new Promise<T>((resolve, reject) => {
54
+ res = resolve;
55
+ rej = reject;
56
+ });
57
+
58
+ return {
59
+ promise,
60
+ resolve: res,
61
+ reject: rej,
62
+ };
63
+ }