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
|
@@ -4,27 +4,30 @@ import { expect, test } from "vitest";
|
|
|
4
4
|
import unmarshalPrimitive from "./primitive";
|
|
5
5
|
|
|
6
6
|
test("works", async () => {
|
|
7
|
-
const
|
|
7
|
+
const ctx = (await getQuickJS()).newContext();
|
|
8
8
|
|
|
9
|
-
expect(unmarshalPrimitive(
|
|
10
|
-
expect(unmarshalPrimitive(
|
|
11
|
-
expect(unmarshalPrimitive(
|
|
12
|
-
expect(unmarshalPrimitive(
|
|
13
|
-
expect(unmarshalPrimitive(
|
|
14
|
-
|
|
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([
|
|
14
|
+
"hoge",
|
|
15
|
+
true,
|
|
16
|
+
]);
|
|
17
|
+
expect(unmarshalPrimitive(ctx, ctx.newNumber(-10))).toEqual([-10, true]);
|
|
15
18
|
// expect(
|
|
16
|
-
// unmarshalPrimitive(
|
|
19
|
+
// unmarshalPrimitive(ctx, ctx.unwrapResult(vm.evalCode(`BigInt(1)`)))
|
|
17
20
|
// ).toEqual([BigInt(1), true]);
|
|
18
21
|
|
|
19
|
-
const obj =
|
|
20
|
-
expect(unmarshalPrimitive(
|
|
21
|
-
const array =
|
|
22
|
-
expect(unmarshalPrimitive(
|
|
23
|
-
const func =
|
|
24
|
-
expect(unmarshalPrimitive(
|
|
22
|
+
const obj = ctx.newObject();
|
|
23
|
+
expect(unmarshalPrimitive(ctx, obj)).toEqual([undefined, false]);
|
|
24
|
+
const array = ctx.newArray();
|
|
25
|
+
expect(unmarshalPrimitive(ctx, array)).toEqual([undefined, false]);
|
|
26
|
+
const func = ctx.newFunction("", () => {});
|
|
27
|
+
expect(unmarshalPrimitive(ctx, func)).toEqual([undefined, false]);
|
|
25
28
|
|
|
26
29
|
obj.dispose();
|
|
27
30
|
array.dispose();
|
|
28
31
|
func.dispose();
|
|
29
|
-
|
|
32
|
+
ctx.dispose();
|
|
30
33
|
});
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
2
|
|
|
3
3
|
export default function unmarshalPrimitive(
|
|
4
|
-
|
|
4
|
+
ctx: QuickJSContext,
|
|
5
5
|
handle: QuickJSHandle
|
|
6
6
|
): [any, boolean] {
|
|
7
|
-
const ty =
|
|
7
|
+
const ty = ctx.typeof(handle);
|
|
8
8
|
if (
|
|
9
9
|
ty === "undefined" ||
|
|
10
10
|
ty === "number" ||
|
|
11
11
|
ty === "string" ||
|
|
12
12
|
ty === "boolean"
|
|
13
13
|
) {
|
|
14
|
-
return [
|
|
14
|
+
return [ctx.dump(handle), true];
|
|
15
15
|
} else if (ty === "object") {
|
|
16
|
-
const isNull =
|
|
17
|
-
.unwrapResult(
|
|
16
|
+
const isNull = ctx
|
|
17
|
+
.unwrapResult(ctx.evalCode("a => a === null"))
|
|
18
18
|
.consume((n) =>
|
|
19
|
-
|
|
19
|
+
ctx.dump(ctx.unwrapResult(ctx.callFunction(n, ctx.undefined, handle)))
|
|
20
20
|
);
|
|
21
21
|
if (isNull) {
|
|
22
22
|
return [null, true];
|
|
@@ -25,10 +25,10 @@ export default function unmarshalPrimitive(
|
|
|
25
25
|
|
|
26
26
|
// BigInt is not supported by quickjs-emscripten
|
|
27
27
|
// if (ty === "bigint") {
|
|
28
|
-
// const str =
|
|
28
|
+
// const str = ctx
|
|
29
29
|
// .getProp(handle, "toString")
|
|
30
30
|
// .consume(toString => vm.unwrapResult(vm.callFunction(toString, handle)))
|
|
31
|
-
// .consume(str =>
|
|
31
|
+
// .consume(str => ctx.getString(str));
|
|
32
32
|
// const bi = BigInt(str);
|
|
33
33
|
// return [bi, true];
|
|
34
34
|
// }
|
|
@@ -4,32 +4,32 @@ import { expect, test, vi } from "vitest";
|
|
|
4
4
|
import unmarshalPromise from "./promise";
|
|
5
5
|
|
|
6
6
|
const testPromise = (reject: boolean) => async () => {
|
|
7
|
-
const
|
|
7
|
+
const ctx = (await getQuickJS()).newContext();
|
|
8
8
|
const disposables: Disposable[] = [];
|
|
9
9
|
const marshal = vi.fn((v): [QuickJSHandle, boolean] => {
|
|
10
|
-
const f =
|
|
11
|
-
v(
|
|
10
|
+
const f = ctx.newFunction(v.name, (h) => {
|
|
11
|
+
v(ctx.dump(h));
|
|
12
12
|
});
|
|
13
13
|
disposables.push(f);
|
|
14
14
|
return [f, false];
|
|
15
15
|
});
|
|
16
16
|
const preUnmarshal = vi.fn((a) => a);
|
|
17
17
|
|
|
18
|
-
const deferred =
|
|
18
|
+
const deferred = ctx.newPromise();
|
|
19
19
|
disposables.push(deferred);
|
|
20
|
-
const promise = unmarshalPromise(
|
|
20
|
+
const promise = unmarshalPromise(ctx, deferred.handle, marshal, preUnmarshal);
|
|
21
21
|
|
|
22
22
|
expect(marshal).toBeCalledTimes(2);
|
|
23
23
|
expect(preUnmarshal).toBeCalledTimes(1);
|
|
24
|
-
expect(
|
|
24
|
+
expect(ctx.runtime.hasPendingJob()).toBe(false);
|
|
25
25
|
|
|
26
26
|
if (reject) {
|
|
27
|
-
deferred.reject(
|
|
27
|
+
deferred.reject(ctx.newString("hoge"));
|
|
28
28
|
} else {
|
|
29
|
-
deferred.resolve(
|
|
29
|
+
deferred.resolve(ctx.newString("hoge"));
|
|
30
30
|
}
|
|
31
|
-
expect(
|
|
32
|
-
expect(
|
|
31
|
+
expect(ctx.runtime.hasPendingJob()).toBe(true);
|
|
32
|
+
expect(ctx.unwrapResult(ctx.runtime.executePendingJobs())).toBe(1);
|
|
33
33
|
if (reject) {
|
|
34
34
|
expect(promise).rejects.toThrow("hoge");
|
|
35
35
|
} else {
|
|
@@ -37,7 +37,7 @@ const testPromise = (reject: boolean) => async () => {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
disposables.forEach((d) => d.dispose());
|
|
40
|
-
|
|
40
|
+
ctx.dispose();
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
test("resolve", testPromise(false));
|
package/src/unmarshal/promise.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
2
|
|
|
3
3
|
import { newDeferred } from "../util";
|
|
4
4
|
import { call, instanceOf } from "../vmutil";
|
|
5
5
|
|
|
6
6
|
export default function unmarshalPromise<T = unknown>(
|
|
7
|
-
|
|
7
|
+
ctx: QuickJSContext,
|
|
8
8
|
handle: QuickJSHandle,
|
|
9
9
|
/** marshal returns handle and boolean indicates that the handle should be disposed after use */
|
|
10
10
|
marshal: (value: unknown) => [QuickJSHandle, boolean],
|
|
11
11
|
preUnmarshal: <T>(target: T, handle: QuickJSHandle) => T | undefined
|
|
12
12
|
): Promise<T> | undefined {
|
|
13
|
-
if (!isPromiseHandle(handle)) return;
|
|
13
|
+
if (!isPromiseHandle(ctx, handle)) return;
|
|
14
14
|
|
|
15
15
|
const deferred = newDeferred<T>();
|
|
16
16
|
const [resHandle, resShouldBeDisposed] = marshal(deferred.resolve);
|
|
17
17
|
const [rejHandle, rejShouldBeDisposed] = marshal(deferred.reject);
|
|
18
18
|
call(
|
|
19
|
-
|
|
19
|
+
ctx,
|
|
20
20
|
"(p, res, rej) => { p.then(res, rej); }",
|
|
21
21
|
undefined,
|
|
22
22
|
handle,
|
|
@@ -29,12 +29,10 @@ export default function unmarshalPromise<T = unknown>(
|
|
|
29
29
|
return preUnmarshal(deferred.promise, handle) ?? deferred.promise;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function isPromiseHandle(handle: QuickJSHandle): boolean {
|
|
32
|
+
function isPromiseHandle(ctx: QuickJSContext, handle: QuickJSHandle): boolean {
|
|
33
33
|
if (!handle.owner) return false;
|
|
34
|
-
return
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return instanceOf(handle.owner, handle, promise);
|
|
39
|
-
});
|
|
34
|
+
return ctx.unwrapResult(ctx.evalCode("Promise")).consume((promise) => {
|
|
35
|
+
if (!handle.owner) return false;
|
|
36
|
+
return instanceOf(ctx, handle, promise);
|
|
37
|
+
});
|
|
40
38
|
}
|
|
@@ -4,16 +4,16 @@ import { expect, test, vi } from "vitest";
|
|
|
4
4
|
import unmarshalProperties from "./properties";
|
|
5
5
|
|
|
6
6
|
test("works", async () => {
|
|
7
|
-
const
|
|
7
|
+
const ctx = (await getQuickJS()).newContext();
|
|
8
8
|
const disposables: QuickJSHandle[] = [];
|
|
9
9
|
const unmarshal = vi.fn((v: QuickJSHandle): [unknown, boolean] => {
|
|
10
10
|
disposables.push(v);
|
|
11
|
-
return [
|
|
11
|
+
return [ctx.typeof(v) === "function" ? () => {} : ctx.dump(v), false];
|
|
12
12
|
});
|
|
13
13
|
const obj = {};
|
|
14
14
|
|
|
15
|
-
const handle =
|
|
16
|
-
|
|
15
|
+
const handle = ctx.unwrapResult(
|
|
16
|
+
ctx.evalCode(`{
|
|
17
17
|
const obj = {};
|
|
18
18
|
Object.defineProperties(obj, {
|
|
19
19
|
a: { value: 1, writable: true, configurable: true, enumerable: true },
|
|
@@ -24,7 +24,7 @@ test("works", async () => {
|
|
|
24
24
|
}`)
|
|
25
25
|
);
|
|
26
26
|
|
|
27
|
-
unmarshalProperties(
|
|
27
|
+
unmarshalProperties(ctx, handle, obj, unmarshal);
|
|
28
28
|
|
|
29
29
|
expect(obj).toEqual({
|
|
30
30
|
a: 1,
|
|
@@ -49,5 +49,5 @@ test("works", async () => {
|
|
|
49
49
|
|
|
50
50
|
disposables.forEach((d) => d.dispose());
|
|
51
51
|
handle.dispose();
|
|
52
|
-
|
|
52
|
+
ctx.dispose();
|
|
53
53
|
});
|
|
@@ -1,61 +1,64 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
|
+
|
|
2
3
|
import { call } from "../vmutil";
|
|
3
4
|
|
|
4
5
|
export default function unmarshalProperties(
|
|
5
|
-
|
|
6
|
+
ctx: QuickJSContext,
|
|
6
7
|
handle: QuickJSHandle,
|
|
7
8
|
target: object | Function,
|
|
8
9
|
unmarshal: (handle: QuickJSHandle) => [unknown, boolean]
|
|
9
10
|
) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
ctx
|
|
12
|
+
.newFunction("", (key, value) => {
|
|
13
|
+
const [keyName] = unmarshal(key);
|
|
14
|
+
if (
|
|
15
|
+
typeof keyName !== "string" &&
|
|
16
|
+
typeof keyName !== "number" &&
|
|
17
|
+
typeof keyName !== "symbol"
|
|
18
|
+
)
|
|
19
|
+
return;
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
const desc = (
|
|
22
|
+
[
|
|
23
|
+
["value", true],
|
|
24
|
+
["get", true],
|
|
25
|
+
["set", true],
|
|
26
|
+
["configurable", false],
|
|
27
|
+
["enumerable", false],
|
|
28
|
+
["writable", false],
|
|
29
|
+
] as const
|
|
30
|
+
).reduce<PropertyDescriptor>((desc, [key, unmarshable]) => {
|
|
31
|
+
const h = ctx.getProp(value, key);
|
|
32
|
+
const ty = ctx.typeof(h);
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (ty === "undefined") return desc;
|
|
35
|
+
if (!unmarshable && ty === "boolean") {
|
|
36
|
+
desc[key] = ctx.dump(ctx.getProp(value, key));
|
|
37
|
+
return desc;
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const [v, alreadyExists] = unmarshal(h);
|
|
41
|
+
if (alreadyExists) {
|
|
42
|
+
h.dispose();
|
|
43
|
+
}
|
|
44
|
+
desc[key] = v;
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
return desc;
|
|
47
|
+
}, {});
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
Object.defineProperty(target, keyName, desc);
|
|
50
|
+
})
|
|
51
|
+
.consume((fn) => {
|
|
52
|
+
call(
|
|
53
|
+
ctx,
|
|
54
|
+
`(o, fn) => {
|
|
52
55
|
const descs = Object.getOwnPropertyDescriptors(o);
|
|
53
56
|
Object.entries(descs).forEach(([k, v]) => fn(k, v));
|
|
54
57
|
Object.getOwnPropertySymbols(descs).forEach(k => fn(k, descs[k]));
|
|
55
58
|
}`,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
undefined,
|
|
60
|
+
handle,
|
|
61
|
+
fn
|
|
62
|
+
).dispose();
|
|
63
|
+
});
|
|
61
64
|
}
|
|
@@ -4,15 +4,15 @@ import { expect, test, vi } from "vitest";
|
|
|
4
4
|
import unmarshalSymbol from "./symbol";
|
|
5
5
|
|
|
6
6
|
test("works", async () => {
|
|
7
|
-
const
|
|
7
|
+
const ctx = (await getQuickJS()).newContext();
|
|
8
8
|
const pre = vi.fn();
|
|
9
|
-
const obj =
|
|
10
|
-
const handle =
|
|
9
|
+
const obj = ctx.newObject();
|
|
10
|
+
const handle = ctx.unwrapResult(ctx.evalCode(`Symbol("foobar")`));
|
|
11
11
|
|
|
12
|
-
expect(unmarshalSymbol(
|
|
12
|
+
expect(unmarshalSymbol(ctx, obj, pre)).toBe(undefined);
|
|
13
13
|
expect(pre).toBeCalledTimes(0);
|
|
14
14
|
|
|
15
|
-
const sym = unmarshalSymbol(
|
|
15
|
+
const sym = unmarshalSymbol(ctx, handle, pre);
|
|
16
16
|
expect(typeof sym).toBe("symbol");
|
|
17
17
|
expect((sym as any).description).toBe("foobar");
|
|
18
18
|
expect(pre).toReturnTimes(1);
|
|
@@ -21,5 +21,5 @@ test("works", async () => {
|
|
|
21
21
|
|
|
22
22
|
handle.dispose();
|
|
23
23
|
obj.dispose();
|
|
24
|
-
|
|
24
|
+
ctx.dispose();
|
|
25
25
|
});
|
package/src/unmarshal/symbol.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
|
|
2
2
|
|
|
3
3
|
export default function unmarshalSymbol(
|
|
4
|
-
|
|
4
|
+
ctx: QuickJSContext,
|
|
5
5
|
handle: QuickJSHandle,
|
|
6
6
|
preUnmarshal: <T>(target: T, handle: QuickJSHandle) => T | undefined
|
|
7
7
|
): symbol | undefined {
|
|
8
|
-
if (
|
|
9
|
-
const desc =
|
|
8
|
+
if (ctx.typeof(handle) !== "symbol") return;
|
|
9
|
+
const desc = ctx.getString(ctx.getProp(handle, "description"));
|
|
10
10
|
const sym = Symbol(desc);
|
|
11
11
|
return preUnmarshal(sym, handle) ?? sym;
|
|
12
12
|
}
|