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.
- package/LICENSE +2 -2
- package/README.md +71 -44
- package/dist/index.d.ts +116 -23
- package/dist/quickjs-emscripten-sync.mjs +842 -0
- package/dist/quickjs-emscripten-sync.umd.js +64 -2
- package/package.json +22 -53
- package/src/default.ts +2 -2
- package/src/index.test.ts +223 -59
- package/src/index.ts +72 -66
- package/src/marshal/custom.test.ts +50 -0
- package/src/marshal/custom.ts +36 -0
- package/src/marshal/function.test.ts +64 -75
- package/src/marshal/function.ts +15 -18
- package/src/marshal/index.test.ts +122 -77
- package/src/marshal/index.ts +19 -15
- package/src/marshal/json.test.ts +37 -41
- package/src/marshal/json.ts +5 -7
- package/src/marshal/object.test.ts +59 -84
- package/src/marshal/object.ts +8 -15
- package/src/marshal/primitive.test.ts +18 -21
- package/src/marshal/primitive.ts +11 -10
- package/src/marshal/promise.test.ts +85 -0
- package/src/marshal/promise.ts +19 -0
- package/src/marshal/properties.test.ts +24 -27
- package/src/marshal/properties.ts +15 -17
- package/src/unmarshal/custom.test.ts +50 -0
- package/src/unmarshal/custom.ts +31 -0
- package/src/unmarshal/function.test.ts +63 -86
- package/src/unmarshal/function.ts +13 -22
- package/src/unmarshal/index.test.ts +114 -109
- package/src/unmarshal/index.ts +15 -14
- package/src/unmarshal/object.test.ts +42 -46
- package/src/unmarshal/object.ts +16 -20
- package/src/unmarshal/primitive.test.ts +17 -15
- package/src/unmarshal/primitive.ts +11 -18
- package/src/unmarshal/promise.test.ts +44 -0
- package/src/unmarshal/promise.ts +31 -0
- package/src/unmarshal/properties.test.ts +11 -9
- package/src/unmarshal/properties.ts +44 -45
- package/src/util.test.ts +14 -2
- package/src/util.ts +18 -8
- package/src/vmmap.test.ts +88 -82
- package/src/vmmap.ts +30 -44
- package/src/vmutil.test.ts +100 -75
- package/src/vmutil.ts +51 -34
- package/src/wrapper.test.ts +129 -167
- package/src/wrapper.ts +59 -62
- package/dist/default.d.ts +0 -4
- package/dist/marshal/function.d.ts +0 -2
- package/dist/marshal/index.d.ts +0 -11
- package/dist/marshal/json.d.ts +0 -2
- 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 +0 -2
- package/dist/quickjs-emscripten-sync.cjs.map +0 -1
- package/dist/quickjs-emscripten-sync.modern.js +0 -2
- package/dist/quickjs-emscripten-sync.modern.js.map +0 -1
- package/dist/quickjs-emscripten-sync.module.js +0 -2
- package/dist/quickjs-emscripten-sync.module.js.map +0 -1
- package/dist/quickjs-emscripten-sync.umd.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 -11
- package/dist/wrapper.d.ts +0 -11
- package/src/marshal/symbol.test.ts +0 -22
- package/src/marshal/symbol.ts +0 -20
- package/src/unmarshal/symbol.test.ts +0 -23
- package/src/unmarshal/symbol.ts +0 -12
package/src/index.test.ts
CHANGED
|
@@ -1,10 +1,82 @@
|
|
|
1
1
|
import { getQuickJS } from "quickjs-emscripten";
|
|
2
|
+
import { describe, expect, test, vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { isWrapped } from "./wrapper";
|
|
5
|
+
|
|
2
6
|
import { Arena } from ".";
|
|
3
7
|
|
|
8
|
+
describe("readme", () => {
|
|
9
|
+
test("first", async () => {
|
|
10
|
+
class Cls {
|
|
11
|
+
field = 0;
|
|
12
|
+
|
|
13
|
+
method() {
|
|
14
|
+
return ++this.field;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ctx = (await getQuickJS()).newContext();
|
|
19
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
20
|
+
|
|
21
|
+
// We can pass objects to the VM and run code safely
|
|
22
|
+
const exposed = {
|
|
23
|
+
Cls,
|
|
24
|
+
cls: new Cls(),
|
|
25
|
+
syncedCls: arena.sync(new Cls()),
|
|
26
|
+
};
|
|
27
|
+
arena.expose(exposed);
|
|
28
|
+
|
|
29
|
+
expect(arena.evalCode(`cls instanceof Cls`)).toBe(true);
|
|
30
|
+
expect(arena.evalCode(`cls.field`)).toBe(0);
|
|
31
|
+
expect(arena.evalCode(`cls.method()`)).toBe(1);
|
|
32
|
+
expect(arena.evalCode(`cls.field`)).toBe(1);
|
|
33
|
+
|
|
34
|
+
expect(arena.evalCode(`syncedCls.field`)).toBe(0);
|
|
35
|
+
expect(exposed.syncedCls.method()).toBe(1);
|
|
36
|
+
expect(arena.evalCode(`syncedCls.field`)).toBe(1);
|
|
37
|
+
|
|
38
|
+
arena.dispose();
|
|
39
|
+
ctx.dispose();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("usage", async () => {
|
|
43
|
+
const quickjs = await getQuickJS();
|
|
44
|
+
const ctx = quickjs.newContext();
|
|
45
|
+
|
|
46
|
+
// init Arena
|
|
47
|
+
// ⚠️ Marshaling is opt-in for security reasons.
|
|
48
|
+
// ⚠️ Be careful when activating marshalling.
|
|
49
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
50
|
+
|
|
51
|
+
// expose objects as global objects in QuickJS VM
|
|
52
|
+
const log = vi.fn();
|
|
53
|
+
arena.expose({
|
|
54
|
+
console: { log },
|
|
55
|
+
});
|
|
56
|
+
arena.evalCode(`console.log("hello, world");`); // run console.log
|
|
57
|
+
expect(log).toBeCalledWith("hello, world");
|
|
58
|
+
arena.evalCode(`1 + 1`); // 2
|
|
59
|
+
|
|
60
|
+
// expose objects but also enable sync
|
|
61
|
+
const data = arena.sync({ hoge: "foo" });
|
|
62
|
+
arena.expose({ data });
|
|
63
|
+
|
|
64
|
+
arena.evalCode(`data.hoge = "bar"`);
|
|
65
|
+
// eval code and operations to exposed objects are automatically synced
|
|
66
|
+
expect(data.hoge).toBe("bar");
|
|
67
|
+
data.hoge = "changed!";
|
|
68
|
+
expect(arena.evalCode(`data.hoge`)).toBe("changed!");
|
|
69
|
+
|
|
70
|
+
// Don't forget calling arena.dispose() before disposing QuickJS VM!
|
|
71
|
+
arena.dispose();
|
|
72
|
+
ctx.dispose();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
4
76
|
describe("evalCode", () => {
|
|
5
77
|
test("simple object and function", async () => {
|
|
6
|
-
const
|
|
7
|
-
const arena = new Arena(
|
|
78
|
+
const ctx = (await getQuickJS()).newContext();
|
|
79
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
8
80
|
|
|
9
81
|
const result = arena.evalCode(
|
|
10
82
|
`({
|
|
@@ -18,7 +90,7 @@ describe("evalCode", () => {
|
|
|
18
90
|
get e() {
|
|
19
91
|
return { a: 1 };
|
|
20
92
|
}
|
|
21
|
-
})
|
|
93
|
+
})`,
|
|
22
94
|
);
|
|
23
95
|
expect(result).toEqual({
|
|
24
96
|
a: 1,
|
|
@@ -36,23 +108,36 @@ describe("evalCode", () => {
|
|
|
36
108
|
expect(result.e).toStrictEqual({ a: 1 });
|
|
37
109
|
|
|
38
110
|
arena.dispose();
|
|
39
|
-
|
|
111
|
+
ctx.dispose();
|
|
40
112
|
});
|
|
41
113
|
|
|
42
114
|
test("Math", async () => {
|
|
43
|
-
const
|
|
44
|
-
const arena = new Arena(
|
|
115
|
+
const ctx = (await getQuickJS()).newContext();
|
|
116
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
45
117
|
|
|
46
118
|
const VMMath = arena.evalCode(`Math`) as Math;
|
|
47
119
|
expect(VMMath.floor(1.1)).toBe(1);
|
|
48
120
|
|
|
49
121
|
arena.dispose();
|
|
50
|
-
|
|
122
|
+
ctx.dispose();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("Date", async () => {
|
|
126
|
+
const ctx = (await getQuickJS()).newContext();
|
|
127
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
128
|
+
|
|
129
|
+
const date = new Date(2022, 7, 26);
|
|
130
|
+
expect(arena.evalCode("new Date(2022, 7, 26)")).toEqual(date);
|
|
131
|
+
expect(arena.evalCode("d => d instanceof Date")(date)).toBe(true);
|
|
132
|
+
expect(arena.evalCode("d => d.getTime()")(date)).toBe(date.getTime());
|
|
133
|
+
|
|
134
|
+
arena.dispose();
|
|
135
|
+
ctx.dispose();
|
|
51
136
|
});
|
|
52
137
|
|
|
53
138
|
test("class", async () => {
|
|
54
|
-
const
|
|
55
|
-
const arena = new Arena(
|
|
139
|
+
const ctx = (await getQuickJS()).newContext();
|
|
140
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
56
141
|
|
|
57
142
|
const instance = arena.evalCode(`{
|
|
58
143
|
globalThis.Cls = class D {
|
|
@@ -73,12 +158,12 @@ describe("evalCode", () => {
|
|
|
73
158
|
expect(instance.a).toBe(102);
|
|
74
159
|
|
|
75
160
|
arena.dispose();
|
|
76
|
-
|
|
161
|
+
ctx.dispose();
|
|
77
162
|
});
|
|
78
163
|
|
|
79
164
|
test("obj", async () => {
|
|
80
|
-
const
|
|
81
|
-
const arena = new Arena(
|
|
165
|
+
const ctx = (await getQuickJS()).newContext();
|
|
166
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
82
167
|
|
|
83
168
|
const obj = arena.evalCode(`globalThis.AAA = { a: 1 }`);
|
|
84
169
|
|
|
@@ -89,14 +174,56 @@ describe("evalCode", () => {
|
|
|
89
174
|
expect(arena.evalCode(`AAA.a`)).toBe(2);
|
|
90
175
|
|
|
91
176
|
arena.dispose();
|
|
92
|
-
|
|
177
|
+
ctx.dispose();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("promise", async () => {
|
|
181
|
+
const ctx = (await getQuickJS()).newContext();
|
|
182
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
183
|
+
|
|
184
|
+
const [promise, resolve] = arena.evalCode<[Promise<string>, (d: string) => void]>(`
|
|
185
|
+
let resolve;
|
|
186
|
+
const promise = new Promise(r => {
|
|
187
|
+
resolve = r;
|
|
188
|
+
}).then(d => d + "!");
|
|
189
|
+
[promise, resolve]
|
|
190
|
+
`);
|
|
191
|
+
expect(promise).instanceOf(Promise);
|
|
192
|
+
expect(isWrapped(arena._unwrapIfNotSynced(promise), arena._symbol)).toBe(false);
|
|
193
|
+
|
|
194
|
+
resolve("hoge");
|
|
195
|
+
expect(arena.executePendingJobs()).toBe(2);
|
|
196
|
+
expect(await promise).toBe("hoge!");
|
|
197
|
+
|
|
198
|
+
arena.dispose();
|
|
199
|
+
ctx.dispose();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("promise2", async () => {
|
|
203
|
+
const ctx = (await getQuickJS()).newContext();
|
|
204
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
205
|
+
|
|
206
|
+
const deferred: { resolve?: (s: string) => void } = {};
|
|
207
|
+
const promise = new Promise(resolve => {
|
|
208
|
+
deferred.resolve = resolve;
|
|
209
|
+
});
|
|
210
|
+
const res = vi.fn();
|
|
211
|
+
arena.evalCode(`(p, r) => { p.then(d => { r(d + "!"); }); }`)(promise, res);
|
|
212
|
+
|
|
213
|
+
deferred.resolve?.("hoge");
|
|
214
|
+
await promise;
|
|
215
|
+
expect(arena.executePendingJobs()).toBe(1);
|
|
216
|
+
expect(res).toBeCalledWith("hoge!");
|
|
217
|
+
|
|
218
|
+
arena.dispose();
|
|
219
|
+
ctx.dispose();
|
|
93
220
|
});
|
|
94
221
|
});
|
|
95
222
|
|
|
96
223
|
describe("expose without sync", () => {
|
|
97
224
|
test("simple object and function", async () => {
|
|
98
|
-
const
|
|
99
|
-
const arena = new Arena(
|
|
225
|
+
const ctx = (await getQuickJS()).newContext();
|
|
226
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
100
227
|
|
|
101
228
|
const obj = {
|
|
102
229
|
a: 1,
|
|
@@ -127,12 +254,12 @@ describe("expose without sync", () => {
|
|
|
127
254
|
expect(arena.evalCode(`obj.e`)).toStrictEqual({ a: 1 });
|
|
128
255
|
|
|
129
256
|
arena.dispose();
|
|
130
|
-
|
|
257
|
+
ctx.dispose();
|
|
131
258
|
});
|
|
132
259
|
|
|
133
260
|
test("Math", async () => {
|
|
134
|
-
const
|
|
135
|
-
const arena = new Arena(
|
|
261
|
+
const ctx = (await getQuickJS()).newContext();
|
|
262
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
136
263
|
|
|
137
264
|
arena.expose({ Math2: Math });
|
|
138
265
|
expect(arena.evalCode(`Math`)).not.toBe(Math);
|
|
@@ -140,12 +267,12 @@ describe("expose without sync", () => {
|
|
|
140
267
|
expect(arena.evalCode(`Math2.floor(1.1)`)).toBe(1);
|
|
141
268
|
|
|
142
269
|
arena.dispose();
|
|
143
|
-
|
|
270
|
+
ctx.dispose();
|
|
144
271
|
});
|
|
145
272
|
|
|
146
273
|
test("class", async () => {
|
|
147
|
-
const
|
|
148
|
-
const arena = new Arena(
|
|
274
|
+
const ctx = (await getQuickJS()).newContext();
|
|
275
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
149
276
|
|
|
150
277
|
class D {
|
|
151
278
|
a: number;
|
|
@@ -169,12 +296,12 @@ describe("expose without sync", () => {
|
|
|
169
296
|
expect(arena.evalCode(`d.a`)).toBe(102);
|
|
170
297
|
|
|
171
298
|
arena.dispose();
|
|
172
|
-
|
|
299
|
+
ctx.dispose();
|
|
173
300
|
});
|
|
174
301
|
|
|
175
302
|
test("object and function", async () => {
|
|
176
|
-
const
|
|
177
|
-
const arena = new Arena(
|
|
303
|
+
const ctx = (await getQuickJS()).newContext();
|
|
304
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
178
305
|
|
|
179
306
|
const obj = {
|
|
180
307
|
a: 1,
|
|
@@ -206,14 +333,14 @@ describe("expose without sync", () => {
|
|
|
206
333
|
expect(arena.evalCode(`obj.a`)).toBe(100);
|
|
207
334
|
|
|
208
335
|
arena.dispose();
|
|
209
|
-
|
|
336
|
+
ctx.dispose();
|
|
210
337
|
});
|
|
211
338
|
});
|
|
212
339
|
|
|
213
340
|
describe("expose with sync", () => {
|
|
214
341
|
test("sync before expose", async () => {
|
|
215
|
-
const
|
|
216
|
-
const arena = new Arena(
|
|
342
|
+
const ctx = (await getQuickJS()).newContext();
|
|
343
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
217
344
|
|
|
218
345
|
const obj = {
|
|
219
346
|
a: 1,
|
|
@@ -252,12 +379,12 @@ describe("expose with sync", () => {
|
|
|
252
379
|
expect(arena.evalCode(`obj.a`)).toBe(100);
|
|
253
380
|
|
|
254
381
|
arena.dispose();
|
|
255
|
-
|
|
382
|
+
ctx.dispose();
|
|
256
383
|
});
|
|
257
384
|
|
|
258
385
|
test("sync after expose", async () => {
|
|
259
|
-
const
|
|
260
|
-
const arena = new Arena(
|
|
386
|
+
const ctx = (await getQuickJS()).newContext();
|
|
387
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
261
388
|
|
|
262
389
|
const obj = {
|
|
263
390
|
a: 1,
|
|
@@ -297,13 +424,13 @@ describe("expose with sync", () => {
|
|
|
297
424
|
expect(arena.evalCode(`obj.a`)).toBe(100);
|
|
298
425
|
|
|
299
426
|
arena.dispose();
|
|
300
|
-
|
|
427
|
+
ctx.dispose();
|
|
301
428
|
});
|
|
302
429
|
});
|
|
303
430
|
|
|
304
431
|
test("evalCode -> expose", async () => {
|
|
305
|
-
const
|
|
306
|
-
const arena = new Arena(
|
|
432
|
+
const ctx = (await getQuickJS()).newContext();
|
|
433
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
307
434
|
|
|
308
435
|
const obj = arena.evalCode(`({ a: 1, b: 1 })`);
|
|
309
436
|
arena.expose({ obj });
|
|
@@ -329,12 +456,12 @@ test("evalCode -> expose", async () => {
|
|
|
329
456
|
expect(arena.evalCode(`obj.b`)).toBe(2);
|
|
330
457
|
|
|
331
458
|
arena.dispose();
|
|
332
|
-
|
|
459
|
+
ctx.dispose();
|
|
333
460
|
});
|
|
334
461
|
|
|
335
462
|
test("expose -> evalCode", async () => {
|
|
336
|
-
const
|
|
337
|
-
const arena = new Arena(
|
|
463
|
+
const ctx = (await getQuickJS()).newContext();
|
|
464
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
338
465
|
|
|
339
466
|
const obj = { a: 1 };
|
|
340
467
|
arena.expose({ obj });
|
|
@@ -351,12 +478,12 @@ test("expose -> evalCode", async () => {
|
|
|
351
478
|
expect(arena.evalCode(`obj.a`)).toBe(3);
|
|
352
479
|
|
|
353
480
|
arena.dispose();
|
|
354
|
-
|
|
481
|
+
ctx.dispose();
|
|
355
482
|
});
|
|
356
483
|
|
|
357
484
|
test("evalCode -> expose -> evalCode", async () => {
|
|
358
|
-
const
|
|
359
|
-
const arena = new Arena(
|
|
485
|
+
const ctx = (await getQuickJS()).newContext();
|
|
486
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
360
487
|
|
|
361
488
|
const obj = [1];
|
|
362
489
|
expect(arena.evalCode("a => a[0] + 10")(obj)).toBe(11);
|
|
@@ -364,12 +491,12 @@ test("evalCode -> expose -> evalCode", async () => {
|
|
|
364
491
|
expect(arena.evalCode("obj")).toBe(obj);
|
|
365
492
|
|
|
366
493
|
arena.dispose();
|
|
367
|
-
|
|
494
|
+
ctx.dispose();
|
|
368
495
|
});
|
|
369
496
|
|
|
370
497
|
test("register and unregister", async () => {
|
|
371
|
-
const
|
|
372
|
-
const arena = new Arena(
|
|
498
|
+
const ctx = (await getQuickJS()).newContext();
|
|
499
|
+
const arena = new Arena(ctx, { isMarshalable: true, registeredObjects: [] });
|
|
373
500
|
|
|
374
501
|
arena.register(Math, `Math`);
|
|
375
502
|
expect(arena.evalCode(`Math`)).toBe(Math);
|
|
@@ -384,29 +511,27 @@ test("register and unregister", async () => {
|
|
|
384
511
|
expect(arena.evalCode(`new Error()`)).toBeInstanceOf(Error);
|
|
385
512
|
|
|
386
513
|
arena.dispose();
|
|
387
|
-
|
|
514
|
+
ctx.dispose();
|
|
388
515
|
});
|
|
389
516
|
|
|
390
517
|
test("registeredObjects option", async () => {
|
|
391
|
-
const
|
|
392
|
-
const arena = new Arena(
|
|
518
|
+
const ctx = (await getQuickJS()).newContext();
|
|
519
|
+
const arena = new Arena(ctx, {
|
|
393
520
|
isMarshalable: true,
|
|
394
521
|
registeredObjects: [[Symbol.iterator, "Symbol.iterator"]],
|
|
395
522
|
});
|
|
396
523
|
|
|
397
524
|
expect(arena.evalCode(`Symbol.iterator`)).toBe(Symbol.iterator);
|
|
398
|
-
expect(arena.evalCode(`s => s === Symbol.iterator`)(Symbol.iterator)).toBe(
|
|
399
|
-
true
|
|
400
|
-
);
|
|
525
|
+
expect(arena.evalCode(`s => s === Symbol.iterator`)(Symbol.iterator)).toBe(true);
|
|
401
526
|
|
|
402
527
|
arena.dispose();
|
|
403
|
-
|
|
528
|
+
ctx.dispose();
|
|
404
529
|
});
|
|
405
530
|
|
|
406
531
|
describe("isMarshalable option", () => {
|
|
407
532
|
test("false", async () => {
|
|
408
|
-
const
|
|
409
|
-
const arena = new Arena(
|
|
533
|
+
const ctx = (await getQuickJS()).newContext();
|
|
534
|
+
const arena = new Arena(ctx, { isMarshalable: false });
|
|
410
535
|
|
|
411
536
|
expect(arena.evalCode(`s => s === undefined`)(globalThis)).toBe(true);
|
|
412
537
|
expect(arena.evalCode(`s => s === undefined`)({})).toBe(true);
|
|
@@ -414,12 +539,12 @@ describe("isMarshalable option", () => {
|
|
|
414
539
|
expect(arena.evalCode(`aaa`)).toBeUndefined();
|
|
415
540
|
|
|
416
541
|
arena.dispose();
|
|
417
|
-
|
|
542
|
+
ctx.dispose();
|
|
418
543
|
});
|
|
419
544
|
|
|
420
545
|
test("json", async () => {
|
|
421
|
-
const
|
|
422
|
-
const arena = new Arena(
|
|
546
|
+
const ctx = (await getQuickJS()).newContext();
|
|
547
|
+
const arena = new Arena(ctx, { isMarshalable: "json" });
|
|
423
548
|
|
|
424
549
|
const obj = { a: () => {}, b: new Date(), c: [() => {}, 1] };
|
|
425
550
|
const objJSON = { b: obj.b.toISOString(), c: [null, 1] };
|
|
@@ -431,13 +556,13 @@ describe("isMarshalable option", () => {
|
|
|
431
556
|
expect(exposedObj).not.toBe(objJSON2);
|
|
432
557
|
|
|
433
558
|
arena.dispose();
|
|
434
|
-
|
|
559
|
+
ctx.dispose();
|
|
435
560
|
});
|
|
436
561
|
|
|
437
562
|
test("conditional", async () => {
|
|
438
|
-
const
|
|
439
|
-
const arena = new Arena(
|
|
440
|
-
isMarshalable:
|
|
563
|
+
const ctx = (await getQuickJS()).newContext();
|
|
564
|
+
const arena = new Arena(ctx, {
|
|
565
|
+
isMarshalable: o => o !== globalThis,
|
|
441
566
|
});
|
|
442
567
|
|
|
443
568
|
const obj = { a: 1 };
|
|
@@ -448,6 +573,45 @@ describe("isMarshalable option", () => {
|
|
|
448
573
|
expect(arena.evalCode(`bbb`)).toBe(obj);
|
|
449
574
|
|
|
450
575
|
arena.dispose();
|
|
451
|
-
|
|
576
|
+
ctx.dispose();
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
describe("edge cases", () => {
|
|
581
|
+
test("getter", async () => {
|
|
582
|
+
const ctx = (await getQuickJS()).newContext();
|
|
583
|
+
const arena = new Arena(ctx, { isMarshalable: true });
|
|
584
|
+
|
|
585
|
+
const called: string[] = [];
|
|
586
|
+
const obj = { c: 0 };
|
|
587
|
+
const exposed = {
|
|
588
|
+
get a() {
|
|
589
|
+
called.push("a");
|
|
590
|
+
return {
|
|
591
|
+
get b() {
|
|
592
|
+
called.push("b");
|
|
593
|
+
return obj;
|
|
594
|
+
},
|
|
595
|
+
};
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
const cb: { current?: () => any } = {};
|
|
599
|
+
const register = (fn: () => any) => {
|
|
600
|
+
cb.current = fn;
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
arena.expose({ exposed, register });
|
|
604
|
+
expect(called).toEqual([]);
|
|
605
|
+
|
|
606
|
+
arena.evalCode(`register(() => exposed.a.b.c);`);
|
|
607
|
+
expect(cb.current?.()).toBe(0);
|
|
608
|
+
expect(called).toEqual(["a", "b"]);
|
|
609
|
+
|
|
610
|
+
obj.c = 1;
|
|
611
|
+
expect(cb.current?.()).toBe(1); // this line causes an error when context is disposed
|
|
612
|
+
expect(called).toEqual(["a", "b", "a", "b"]);
|
|
613
|
+
|
|
614
|
+
arena.dispose();
|
|
615
|
+
// ctx.dispose(); // reports an error
|
|
452
616
|
});
|
|
453
617
|
});
|