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.
Files changed (44) hide show
  1. package/README.md +36 -34
  2. package/dist/index.d.ts +17 -15
  3. package/dist/quickjs-emscripten-sync.es.js +146 -135
  4. package/dist/quickjs-emscripten-sync.umd.js +6 -6
  5. package/package.json +3 -3
  6. package/src/index.test.ts +146 -60
  7. package/src/index.ts +40 -26
  8. package/src/marshal/function.test.ts +61 -53
  9. package/src/marshal/function.ts +7 -6
  10. package/src/marshal/index.test.ts +73 -65
  11. package/src/marshal/index.ts +12 -11
  12. package/src/marshal/json.test.ts +30 -30
  13. package/src/marshal/json.ts +4 -3
  14. package/src/marshal/object.test.ts +55 -50
  15. package/src/marshal/object.ts +6 -5
  16. package/src/marshal/primitive.test.ts +21 -17
  17. package/src/marshal/primitive.ts +10 -9
  18. package/src/marshal/promise.test.ts +14 -14
  19. package/src/marshal/promise.ts +3 -3
  20. package/src/marshal/properties.test.ts +17 -15
  21. package/src/marshal/properties.ts +10 -9
  22. package/src/marshal/symbol.test.ts +6 -6
  23. package/src/marshal/symbol.ts +5 -4
  24. package/src/unmarshal/function.test.ts +45 -43
  25. package/src/unmarshal/function.ts +9 -8
  26. package/src/unmarshal/index.test.ts +41 -40
  27. package/src/unmarshal/index.ts +9 -8
  28. package/src/unmarshal/object.test.ts +33 -31
  29. package/src/unmarshal/object.ts +12 -11
  30. package/src/unmarshal/primitive.test.ts +18 -15
  31. package/src/unmarshal/primitive.ts +9 -9
  32. package/src/unmarshal/promise.test.ts +11 -11
  33. package/src/unmarshal/promise.ts +9 -11
  34. package/src/unmarshal/properties.test.ts +6 -6
  35. package/src/unmarshal/properties.ts +47 -44
  36. package/src/unmarshal/symbol.test.ts +6 -6
  37. package/src/unmarshal/symbol.ts +4 -4
  38. package/src/util.test.ts +1 -0
  39. package/src/vmmap.test.ts +72 -88
  40. package/src/vmmap.ts +16 -16
  41. package/src/vmutil.test.ts +71 -73
  42. package/src/vmutil.ts +22 -18
  43. package/src/wrapper.test.ts +111 -88
  44. package/src/wrapper.ts +31 -27
@@ -13,11 +13,11 @@ import {
13
13
  import { call, eq, json } from "./vmutil";
14
14
 
15
15
  test("wrap, unwrap, isWrapped", async () => {
16
- const vm = (await getQuickJS()).createVm();
16
+ const ctx = (await getQuickJS()).newContext();
17
17
  const target = { a: 1 };
18
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
18
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
19
19
  const proxyKeySymbol = Symbol();
20
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
20
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
21
21
  const marshal = vi.fn();
22
22
  const syncMode = vi.fn();
23
23
 
@@ -25,7 +25,7 @@ test("wrap, unwrap, isWrapped", async () => {
25
25
  expect(unwrap(target, proxyKeySymbol)).toBe(target);
26
26
 
27
27
  const wrapped = wrap(
28
- vm,
28
+ ctx,
29
29
  target,
30
30
  proxyKeySymbol,
31
31
  proxyKeySymbolHandle,
@@ -39,25 +39,37 @@ test("wrap, unwrap, isWrapped", async () => {
39
39
  expect(unwrap(wrapped, proxyKeySymbol)).toBe(target);
40
40
 
41
41
  expect(
42
- wrap(vm, wrapped, proxyKeySymbol, proxyKeySymbolHandle, marshal, syncMode)
42
+ wrap(ctx, wrapped, proxyKeySymbol, proxyKeySymbolHandle, marshal, syncMode)
43
43
  ).toBe(wrapped);
44
44
 
45
+ // promise cannot be wrapped
46
+ expect(
47
+ wrap(
48
+ ctx,
49
+ Promise.resolve(1),
50
+ proxyKeySymbol,
51
+ proxyKeySymbolHandle,
52
+ marshal,
53
+ syncMode
54
+ )
55
+ ).toBeUndefined();
56
+
45
57
  proxyKeySymbolHandle.dispose();
46
58
  handle.dispose();
47
- vm.dispose();
59
+ ctx.dispose();
48
60
  });
49
61
 
50
62
  test("wrap without sync", async () => {
51
- const vm = (await getQuickJS()).createVm();
63
+ const ctx = (await getQuickJS()).newContext();
52
64
  const target = { a: 1 };
53
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
65
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
54
66
  const proxyKeySymbol = Symbol();
55
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
67
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
56
68
  const marshal = vi.fn();
57
69
  const syncMode = vi.fn();
58
70
 
59
71
  const wrapped = wrap(
60
- vm,
72
+ ctx,
61
73
  target,
62
74
  proxyKeySymbol,
63
75
  proxyKeySymbolHandle,
@@ -72,33 +84,33 @@ test("wrap without sync", async () => {
72
84
  wrapped.a = 2;
73
85
 
74
86
  expect(target.a).toBe(2);
75
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(1); // not synced
87
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(1); // not synced
76
88
  expect(marshal).toBeCalledTimes(0);
77
89
  expect(syncMode).toBeCalledTimes(1);
78
90
  expect(syncMode).toBeCalledWith(wrapped);
79
91
 
80
92
  proxyKeySymbolHandle.dispose();
81
93
  handle.dispose();
82
- vm.dispose();
94
+ ctx.dispose();
83
95
 
84
96
  wrapped.a = 3; // no error even if vm is disposed
85
97
  expect(wrapped.a).toBe(3);
86
98
  });
87
99
 
88
100
  test("wrap with both sync", async () => {
89
- const vm = (await getQuickJS()).createVm();
101
+ const ctx = (await getQuickJS()).newContext();
90
102
  const target = { a: 1 } as { a?: number };
91
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
103
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
92
104
  const proxyKeySymbol = Symbol();
93
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
105
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
94
106
  const marshal = vi.fn((t: any): [QuickJSHandle, boolean] => [
95
- t === wrapped ? handle : json(vm, t),
107
+ t === wrapped ? handle : json(ctx, t),
96
108
  false,
97
109
  ]);
98
110
  const syncMode = vi.fn((): SyncMode => "both");
99
111
 
100
112
  const wrapped = wrap(
101
- vm,
113
+ ctx,
102
114
  target,
103
115
  proxyKeySymbol,
104
116
  proxyKeySymbolHandle,
@@ -113,7 +125,7 @@ test("wrap with both sync", async () => {
113
125
  wrapped.a = 2;
114
126
 
115
127
  expect(target.a).toBe(2);
116
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(2); // synced
128
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(2); // synced
117
129
  expect(marshal).toBeCalledTimes(3);
118
130
  expect(marshal).toBeCalledWith(2);
119
131
  expect(marshal).toBeCalledWith("a");
@@ -122,30 +134,30 @@ test("wrap with both sync", async () => {
122
134
 
123
135
  delete wrapped.a;
124
136
  expect(target.a).toBe(undefined);
125
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(undefined); // synced
137
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(undefined); // synced
126
138
 
127
139
  proxyKeySymbolHandle.dispose();
128
140
  handle.dispose();
129
- vm.dispose();
141
+ ctx.dispose();
130
142
 
131
143
  wrapped.a = 3; // no error even if vm is disposed
132
144
  expect(wrapped.a).toBe(3);
133
145
  });
134
146
 
135
147
  test("wrap with vm sync", async () => {
136
- const vm = (await getQuickJS()).createVm();
148
+ const ctx = (await getQuickJS()).newContext();
137
149
  const target = { a: 1 } as { a?: number };
138
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
150
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
139
151
  const proxyKeySymbol = Symbol();
140
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
152
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
141
153
  const marshal = vi.fn((t: any): [QuickJSHandle, boolean] => [
142
- t === wrapped ? handle : json(vm, t),
154
+ t === wrapped ? handle : json(ctx, t),
143
155
  false,
144
156
  ]);
145
157
  const syncMode = vi.fn((): SyncMode => "vm");
146
158
 
147
159
  const wrapped = wrap(
148
- vm,
160
+ ctx,
149
161
  target,
150
162
  proxyKeySymbol,
151
163
  proxyKeySymbolHandle,
@@ -160,7 +172,7 @@ test("wrap with vm sync", async () => {
160
172
  wrapped.a = 2;
161
173
 
162
174
  expect(target.a).toBe(1); // not set
163
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(2); // synced
175
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(2); // synced
164
176
  expect(marshal).toBeCalledTimes(3);
165
177
  expect(marshal).toBeCalledWith(2);
166
178
  expect(marshal).toBeCalledWith("a");
@@ -169,33 +181,33 @@ test("wrap with vm sync", async () => {
169
181
 
170
182
  delete wrapped.a;
171
183
  expect(target.a).toBe(1); // not deleted
172
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(undefined); // synced
184
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(undefined); // synced
173
185
 
174
186
  proxyKeySymbolHandle.dispose();
175
187
  handle.dispose();
176
- vm.dispose();
188
+ ctx.dispose();
177
189
 
178
190
  wrapped.a = 3; // no error even after vm is disposed
179
191
  expect(wrapped.a).toBe(1); // vm mode cannot modify obj in host
180
192
  });
181
193
 
182
194
  test("wrapHandle, unwrapHandle, isHandleWrapped", async () => {
183
- const vm = (await getQuickJS()).createVm();
195
+ const ctx = (await getQuickJS()).newContext();
184
196
  const target = { a: 1 };
185
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
197
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
186
198
  const proxyKeySymbol = Symbol();
187
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
199
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
188
200
  const unmarshal = vi.fn();
189
201
  const syncMode = vi.fn();
190
202
 
191
- expect(isHandleWrapped(vm, handle, proxyKeySymbolHandle)).toBe(false);
192
- expect(unwrapHandle(vm, handle, proxyKeySymbolHandle)).toEqual([
203
+ expect(isHandleWrapped(ctx, handle, proxyKeySymbolHandle)).toBe(false);
204
+ expect(unwrapHandle(ctx, handle, proxyKeySymbolHandle)).toEqual([
193
205
  handle,
194
206
  false,
195
207
  ]);
196
208
 
197
209
  const [wrapped, w] = wrapHandle(
198
- vm,
210
+ ctx,
199
211
  handle,
200
212
  proxyKeySymbol,
201
213
  proxyKeySymbolHandle,
@@ -204,18 +216,22 @@ test("wrapHandle, unwrapHandle, isHandleWrapped", async () => {
204
216
  );
205
217
  if (!wrapped || !w) throw new Error("wrapped is undefined");
206
218
 
207
- expect(vm.dump(wrapped)).toEqual(target); // vm.dump does not support proxies
208
- expect(vm.dump(vm.getProp(wrapped, "a"))).toBe(1);
209
- expect(isHandleWrapped(vm, wrapped, proxyKeySymbolHandle)).toBe(true);
219
+ expect(ctx.dump(wrapped)).toEqual(target); // vm.dump does not support proxies
220
+ expect(ctx.dump(ctx.getProp(wrapped, "a"))).toBe(1);
221
+ expect(isHandleWrapped(ctx, wrapped, proxyKeySymbolHandle)).toBe(true);
210
222
 
211
- const [handle2, unwrapped2] = unwrapHandle(vm, wrapped, proxyKeySymbolHandle);
223
+ const [handle2, unwrapped2] = unwrapHandle(
224
+ ctx,
225
+ wrapped,
226
+ proxyKeySymbolHandle
227
+ );
212
228
  expect(unwrapped2).toBe(true);
213
229
  handle2.consume((h) => {
214
- expect(eq(vm, handle, h)).toBe(true);
230
+ expect(eq(ctx, handle, h)).toBe(true);
215
231
  });
216
232
 
217
233
  const [wrapped2] = wrapHandle(
218
- vm,
234
+ ctx,
219
235
  wrapped,
220
236
  proxyKeySymbol,
221
237
  proxyKeySymbolHandle,
@@ -224,25 +240,32 @@ test("wrapHandle, unwrapHandle, isHandleWrapped", async () => {
224
240
  );
225
241
  expect(wrapped2 === wrapped).toBe(true);
226
242
 
243
+ // promise cannot be wrapped
244
+ const deferred = ctx.newPromise();
245
+ expect(isHandleWrapped(ctx, deferred.handle, proxyKeySymbolHandle)).toBe(
246
+ true
247
+ );
248
+
249
+ deferred.dispose();
227
250
  wrapped.dispose();
228
251
  handle.dispose();
229
252
  proxyKeySymbolHandle.dispose();
230
- vm.dispose();
253
+ ctx.dispose();
231
254
  });
232
255
 
233
256
  test("wrapHandle without sync", async () => {
234
- const vm = (await getQuickJS()).createVm();
257
+ const ctx = (await getQuickJS()).newContext();
235
258
  const target = { a: 1 };
236
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
259
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
237
260
  const proxyKeySymbol = Symbol();
238
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
261
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
239
262
  const unmarshal = vi.fn((h: QuickJSHandle) =>
240
- wrapped && eq(vm, h, wrapped) ? target : vm.dump(h)
263
+ wrapped && eq(ctx, h, wrapped) ? target : ctx.dump(h)
241
264
  );
242
265
  const syncMode = vi.fn();
243
266
 
244
267
  const [wrapped, w] = wrapHandle(
245
- vm,
268
+ ctx,
246
269
  handle,
247
270
  proxyKeySymbol,
248
271
  proxyKeySymbolHandle,
@@ -254,9 +277,9 @@ test("wrapHandle without sync", async () => {
254
277
  expect(unmarshal).toBeCalledTimes(0);
255
278
  expect(syncMode).toBeCalledTimes(0);
256
279
 
257
- call(vm, `a => a.a = 2`, undefined, wrapped);
280
+ call(ctx, `a => a.a = 2`, undefined, wrapped);
258
281
 
259
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(2);
282
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(2);
260
283
  expect(target.a).toBe(1); // not synced
261
284
  expect(unmarshal).toBeCalledTimes(1);
262
285
  expect(unmarshal).toReturnWith(target);
@@ -266,22 +289,22 @@ test("wrapHandle without sync", async () => {
266
289
  wrapped.dispose();
267
290
  handle.dispose();
268
291
  proxyKeySymbolHandle.dispose();
269
- vm.dispose();
292
+ ctx.dispose();
270
293
  });
271
294
 
272
295
  test("wrapHandle with both sync", async () => {
273
- const vm = (await getQuickJS()).createVm();
296
+ const ctx = (await getQuickJS()).newContext();
274
297
  const target = { a: 1 };
275
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
298
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
276
299
  const proxyKeySymbol = Symbol();
277
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
300
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
278
301
  const unmarshal = vi.fn((h: QuickJSHandle) => {
279
- return wrapped && eq(vm, h, wrapped) ? target : vm.dump(h);
302
+ return wrapped && eq(ctx, h, wrapped) ? target : ctx.dump(h);
280
303
  });
281
304
  const syncMode = vi.fn((): SyncMode => "both");
282
305
 
283
306
  const [wrapped, w] = wrapHandle(
284
- vm,
307
+ ctx,
285
308
  handle,
286
309
  proxyKeySymbol,
287
310
  proxyKeySymbolHandle,
@@ -293,9 +316,9 @@ test("wrapHandle with both sync", async () => {
293
316
  expect(unmarshal).toBeCalledTimes(0);
294
317
  expect(syncMode).toBeCalledTimes(0);
295
318
 
296
- call(vm, `a => a.a = 2`, undefined, wrapped);
319
+ call(ctx, `a => a.a = 2`, undefined, wrapped);
297
320
 
298
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(2);
321
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(2);
299
322
  expect(target.a).toBe(2); // synced
300
323
  expect(unmarshal).toBeCalledTimes(4);
301
324
  expect(unmarshal).toReturnWith(target); // twice
@@ -304,13 +327,13 @@ test("wrapHandle with both sync", async () => {
304
327
  expect(syncMode).toBeCalledTimes(1);
305
328
  expect(syncMode).toBeCalledWith(target);
306
329
 
307
- call(vm, `a => { delete a.a; }`, undefined, wrapped);
308
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(undefined);
330
+ call(ctx, `a => { delete a.a; }`, undefined, wrapped);
331
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(undefined);
309
332
  expect(target.a).toBe(undefined); // synced
310
333
 
311
334
  // changing __proto__ will be blocked
312
- call(vm, `a => { a.__proto__ = null; }`, undefined, wrapped);
313
- expect(vm.dump(call(vm, `Object.getPrototypeOf`, undefined, handle))).toBe(
335
+ call(ctx, `a => { a.__proto__ = null; }`, undefined, wrapped);
336
+ expect(ctx.dump(call(ctx, `Object.getPrototypeOf`, undefined, handle))).toBe(
314
337
  null
315
338
  );
316
339
  expect(Object.getPrototypeOf(target)).toBe(Object.prototype); // not changed
@@ -318,22 +341,22 @@ test("wrapHandle with both sync", async () => {
318
341
  wrapped.dispose();
319
342
  handle.dispose();
320
343
  proxyKeySymbolHandle.dispose();
321
- vm.dispose();
344
+ ctx.dispose();
322
345
  });
323
346
 
324
347
  test("wrapHandle with host sync", async () => {
325
- const vm = (await getQuickJS()).createVm();
348
+ const ctx = (await getQuickJS()).newContext();
326
349
  const target = { a: 1 };
327
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
350
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
328
351
  const proxyKeySymbol = Symbol();
329
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
352
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
330
353
  const unmarshal = vi.fn((handle: QuickJSHandle) =>
331
- wrapped && eq(vm, handle, wrapped) ? target : vm.dump(handle)
354
+ wrapped && eq(ctx, handle, wrapped) ? target : ctx.dump(handle)
332
355
  );
333
356
  const syncMode = vi.fn((): SyncMode => "host");
334
357
 
335
358
  const [wrapped, w] = wrapHandle(
336
- vm,
359
+ ctx,
337
360
  handle,
338
361
  proxyKeySymbol,
339
362
  proxyKeySymbolHandle,
@@ -345,9 +368,9 @@ test("wrapHandle with host sync", async () => {
345
368
  expect(unmarshal).toBeCalledTimes(0);
346
369
  expect(syncMode).toBeCalledTimes(0);
347
370
 
348
- call(vm, `a => a.a = 2`, undefined, wrapped);
371
+ call(ctx, `a => a.a = 2`, undefined, wrapped);
349
372
 
350
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(1); // not set
373
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(1); // not set
351
374
  expect(target.a).toBe(2); // synced
352
375
  expect(unmarshal).toBeCalledTimes(4);
353
376
  expect(unmarshal).toReturnWith(target); // twice
@@ -356,33 +379,33 @@ test("wrapHandle with host sync", async () => {
356
379
  expect(syncMode).toBeCalledTimes(1);
357
380
  expect(syncMode).toBeCalledWith(target);
358
381
 
359
- call(vm, `a => delete a.a`, undefined, handle);
360
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(undefined);
382
+ call(ctx, `a => delete a.a`, undefined, handle);
383
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(undefined);
361
384
  expect(target.a).toBe(2); // not synced
362
385
 
363
386
  wrapped.dispose();
364
387
  handle.dispose();
365
388
  proxyKeySymbolHandle.dispose();
366
- vm.dispose();
389
+ ctx.dispose();
367
390
  });
368
391
 
369
392
  test("wrap and wrapHandle", async () => {
370
- const vm = (await getQuickJS()).createVm();
393
+ const ctx = (await getQuickJS()).newContext();
371
394
  const target = { a: 1 };
372
- const handle = vm.unwrapResult(vm.evalCode(`({ a: 1 })`));
395
+ const handle = ctx.unwrapResult(ctx.evalCode(`({ a: 1 })`));
373
396
  const proxyKeySymbol = Symbol();
374
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
397
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
375
398
  const marshal = vi.fn((t: any): [QuickJSHandle, boolean] => [
376
- wrappedHandle && t === wrapped ? wrappedHandle : json(vm, t),
399
+ wrappedHandle && t === wrapped ? wrappedHandle : json(ctx, t),
377
400
  false,
378
401
  ]);
379
402
  const unmarshal = vi.fn((handle: QuickJSHandle) =>
380
- wrappedHandle && eq(vm, handle, wrappedHandle) ? wrapped : vm.dump(handle)
403
+ wrappedHandle && eq(ctx, handle, wrappedHandle) ? wrapped : ctx.dump(handle)
381
404
  );
382
405
  const syncMode = vi.fn((): SyncMode => "both");
383
406
 
384
407
  const wrapped = wrap(
385
- vm,
408
+ ctx,
386
409
  target,
387
410
  proxyKeySymbol,
388
411
  proxyKeySymbolHandle,
@@ -391,7 +414,7 @@ test("wrap and wrapHandle", async () => {
391
414
  );
392
415
  if (!wrapped) throw new Error("wrapped is undefined");
393
416
  const [wrappedHandle, w] = wrapHandle(
394
- vm,
417
+ ctx,
395
418
  handle,
396
419
  proxyKeySymbol,
397
420
  proxyKeySymbolHandle,
@@ -400,9 +423,9 @@ test("wrap and wrapHandle", async () => {
400
423
  );
401
424
  if (!wrappedHandle || !w) throw new Error("wrappedHandle is undefined");
402
425
 
403
- call(vm, `a => a.a = 2`, undefined, wrappedHandle);
426
+ call(ctx, `a => a.a = 2`, undefined, wrappedHandle);
404
427
 
405
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(2);
428
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(2);
406
429
  expect(target.a).toBe(2);
407
430
  expect(marshal).toBeCalledTimes(0);
408
431
  expect(unmarshal).toBeCalledTimes(4);
@@ -415,7 +438,7 @@ test("wrap and wrapHandle", async () => {
415
438
 
416
439
  wrapped.a = 3;
417
440
 
418
- expect(vm.dump(vm.getProp(handle, "a"))).toBe(3);
441
+ expect(ctx.dump(ctx.getProp(handle, "a"))).toBe(3);
419
442
  expect(target.a).toBe(3);
420
443
  expect(marshal).toBeCalledTimes(3);
421
444
  expect(marshal).toBeCalledWith(wrapped);
@@ -426,23 +449,23 @@ test("wrap and wrapHandle", async () => {
426
449
  wrappedHandle.dispose();
427
450
  handle.dispose();
428
451
  proxyKeySymbolHandle.dispose();
429
- vm.dispose();
452
+ ctx.dispose();
430
453
  });
431
454
 
432
455
  test("non object", async () => {
433
- const vm = (await getQuickJS()).createVm();
456
+ const ctx = (await getQuickJS()).newContext();
434
457
  const target = 1;
435
- const handle = vm.newNumber(1);
458
+ const handle = ctx.newNumber(1);
436
459
  const proxyKeySymbol = Symbol();
437
- const proxyKeySymbolHandle = vm.unwrapResult(vm.evalCode(`Symbol()`));
460
+ const proxyKeySymbolHandle = ctx.unwrapResult(ctx.evalCode(`Symbol()`));
438
461
 
439
462
  expect(
440
- wrap(vm, target, proxyKeySymbol, proxyKeySymbolHandle, vi.fn(), vi.fn())
463
+ wrap(ctx, target, proxyKeySymbol, proxyKeySymbolHandle, vi.fn(), vi.fn())
441
464
  ).toBe(undefined);
442
465
 
443
466
  expect(
444
467
  wrapHandle(
445
- vm,
468
+ ctx,
446
469
  handle,
447
470
  proxyKeySymbol,
448
471
  proxyKeySymbolHandle,
@@ -452,5 +475,5 @@ test("non object", async () => {
452
475
  ).toEqual([undefined, false]);
453
476
 
454
477
  proxyKeySymbolHandle.dispose();
455
- vm.dispose();
478
+ ctx.dispose();
456
479
  });
package/src/wrapper.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { QuickJSVm, QuickJSHandle } from "quickjs-emscripten";
1
+ import type { QuickJSHandle, QuickJSContext } from "quickjs-emscripten";
2
+
2
3
  import { isObject } from "./util";
3
4
  import { call, isHandleObject, consumeAll, mayConsumeAll } from "./vmutil";
4
5
 
@@ -7,14 +8,15 @@ export type SyncMode = "both" | "vm" | "host";
7
8
  export type Wrapped<T> = T & { __qes_wrapped: never };
8
9
 
9
10
  export function wrap<T = any>(
10
- vm: QuickJSVm,
11
+ ctx: QuickJSContext,
11
12
  target: T,
12
13
  proxyKeySymbol: symbol,
13
14
  proxyKeySymbolHandle: QuickJSHandle,
14
15
  marshal: (target: any) => [QuickJSHandle, boolean],
15
16
  syncMode?: (target: T) => SyncMode | undefined
16
17
  ): Wrapped<T> | undefined {
17
- if (!isObject(target)) return undefined;
18
+ // promise cannot be wrapped
19
+ if (!isObject(target) || target instanceof Promise) return undefined;
18
20
  if (isWrapped(target, proxyKeySymbol)) return target;
19
21
 
20
22
  const rec = new Proxy(target as any, {
@@ -27,7 +29,7 @@ export function wrap<T = any>(
27
29
  if (
28
30
  (sync !== "vm" && !Reflect.set(obj, key, v, receiver)) ||
29
31
  sync === "host" ||
30
- !vm.alive
32
+ !ctx.alive
31
33
  )
32
34
  return true;
33
35
 
@@ -35,14 +37,14 @@ export function wrap<T = any>(
35
37
  [marshal(receiver), marshal(key), marshal(v)],
36
38
  (receiverHandle, keyHandle, valueHandle) => {
37
39
  const [handle2, unwrapped] = unwrapHandle(
38
- vm,
40
+ ctx,
39
41
  receiverHandle,
40
42
  proxyKeySymbolHandle
41
43
  );
42
44
  if (unwrapped) {
43
- handle2.consume((h) => vm.setProp(h, keyHandle, valueHandle));
45
+ handle2.consume((h) => ctx.setProp(h, keyHandle, valueHandle));
44
46
  } else {
45
- vm.setProp(handle2, keyHandle, valueHandle);
47
+ ctx.setProp(handle2, keyHandle, valueHandle);
46
48
  }
47
49
  }
48
50
  );
@@ -55,20 +57,20 @@ export function wrap<T = any>(
55
57
  [marshal(rec), marshal(key)],
56
58
  (recHandle, keyHandle) => {
57
59
  const [handle2, unwrapped] = unwrapHandle(
58
- vm,
60
+ ctx,
59
61
  recHandle,
60
62
  proxyKeySymbolHandle
61
63
  );
62
64
 
63
65
  if (sync === "vm" || Reflect.deleteProperty(obj, key)) {
64
- if (sync === "host" || !vm.alive) return true;
66
+ if (sync === "host" || !ctx.alive) return true;
65
67
 
66
68
  if (unwrapped) {
67
69
  handle2.consume((h) =>
68
- call(vm, `(a, b) => delete a[b]`, undefined, h, keyHandle)
70
+ call(ctx, `(a, b) => delete a[b]`, undefined, h, keyHandle)
69
71
  );
70
72
  } else {
71
- call(vm, `(a, b) => delete a[b]`, undefined, handle2, keyHandle);
73
+ call(ctx, `(a, b) => delete a[b]`, undefined, handle2, keyHandle);
72
74
  }
73
75
  }
74
76
  return true;
@@ -80,24 +82,25 @@ export function wrap<T = any>(
80
82
  }
81
83
 
82
84
  export function wrapHandle(
83
- vm: QuickJSVm,
85
+ ctx: QuickJSContext,
84
86
  handle: QuickJSHandle,
85
87
  proxyKeySymbol: symbol,
86
88
  proxyKeySymbolHandle: QuickJSHandle,
87
89
  unmarshal: (handle: QuickJSHandle) => any,
88
90
  syncMode?: (target: QuickJSHandle) => SyncMode | undefined
89
91
  ): [Wrapped<QuickJSHandle> | undefined, boolean] {
90
- if (!isHandleObject(vm, handle)) return [undefined, false];
91
- if (isHandleWrapped(vm, handle, proxyKeySymbolHandle)) return [handle, false];
92
+ if (!isHandleObject(ctx, handle)) return [undefined, false];
93
+ if (isHandleWrapped(ctx, handle, proxyKeySymbolHandle))
94
+ return [handle, false];
92
95
 
93
96
  return consumeAll(
94
97
  [
95
- vm.newFunction("getSyncMode", (h) => {
98
+ ctx.newFunction("getSyncMode", (h) => {
96
99
  const res = syncMode?.(unmarshal(h));
97
- if (typeof res === "string") return vm.newString(res);
98
- return vm.undefined;
100
+ if (typeof res === "string") return ctx.newString(res);
101
+ return ctx.undefined;
99
102
  }),
100
- vm.newFunction("setter", (h, keyHandle, valueHandle) => {
103
+ ctx.newFunction("setter", (h, keyHandle, valueHandle) => {
101
104
  const target = unmarshal(h);
102
105
  if (!target) return;
103
106
  const key = unmarshal(keyHandle);
@@ -105,7 +108,7 @@ export function wrapHandle(
105
108
  const value = unmarshal(valueHandle);
106
109
  unwrap(target, proxyKeySymbol)[key] = value;
107
110
  }),
108
- vm.newFunction("deleter", (h, keyHandle) => {
111
+ ctx.newFunction("deleter", (h, keyHandle) => {
109
112
  const target = unmarshal(h);
110
113
  if (!target) return;
111
114
  const key = unmarshal(keyHandle);
@@ -114,7 +117,7 @@ export function wrapHandle(
114
117
  ],
115
118
  (args) => [
116
119
  call(
117
- vm,
120
+ ctx,
118
121
  `(target, sym, getSyncMode, setter, deleter) => {
119
122
  const rec = new Proxy(target, {
120
123
  get(obj, key, receiver) {
@@ -159,12 +162,12 @@ export function unwrap<T>(obj: T, key: string | symbol): T {
159
162
  }
160
163
 
161
164
  export function unwrapHandle(
162
- vm: QuickJSVm,
165
+ ctx: QuickJSContext,
163
166
  handle: QuickJSHandle,
164
167
  key: QuickJSHandle
165
168
  ): [QuickJSHandle, boolean] {
166
- if (!isHandleWrapped(vm, handle, key)) return [handle, false];
167
- return [vm.getProp(handle, key), true];
169
+ if (!isHandleWrapped(ctx, handle, key)) return [handle, false];
170
+ return [ctx.getProp(handle, key), true];
168
171
  }
169
172
 
170
173
  export function isWrapped<T>(obj: T, key: string | symbol): obj is Wrapped<T> {
@@ -172,14 +175,15 @@ export function isWrapped<T>(obj: T, key: string | symbol): obj is Wrapped<T> {
172
175
  }
173
176
 
174
177
  export function isHandleWrapped(
175
- vm: QuickJSVm,
178
+ ctx: QuickJSContext,
176
179
  handle: QuickJSHandle,
177
180
  key: QuickJSHandle
178
181
  ): handle is Wrapped<QuickJSHandle> {
179
- return !!vm.dump(
182
+ return !!ctx.dump(
180
183
  call(
181
- vm,
182
- `(a, s) => (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]`,
184
+ ctx,
185
+ // promise cannot be wrapped
186
+ `(a, s) => (a instanceof Promise) || (typeof a === "object" && a !== null || typeof a === "function") && !!a[s]`,
183
187
  undefined,
184
188
  handle,
185
189
  key