@isolated-vm/experimental 0.0.9 → 0.0.11
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/addon/CMakeLists.txt +1 -1
- package/addon/handle/local_of.cc +149 -0
- package/addon/handle/types.cc +8 -137
- package/addon/handle/value_of.cc +82 -27
- package/addon/support/callback_info.cc +5 -5
- package/addon/support/callback_storage.cc +2 -2
- package/addon/support/free_function.cc +3 -3
- package/addon/support/initialize.cc +5 -5
- package/addon/transfer/accept.cc +104 -72
- package/addon/transfer/visit.cc +97 -54
- package/addon/value/array.cc +6 -6
- package/addon/value/array_buffer.cc +27 -18
- package/addon/value/function.cc +5 -5
- package/addon/value/function.h.cc +5 -5
- package/addon/value/object.cc +3 -3
- package/addon/value/primitive.cc +36 -36
- package/addon/value/prototype.cc +7 -7
- package/addon/value/record.cc +20 -20
- package/addon/value/value.cc +1 -1
- package/addon/value/vector.cc +9 -9
- package/backend/backend.d.cts +9 -9
- package/dist/frontend/agent.d.ts +1 -0
- package/dist/frontend/agent.d.ts.map +1 -1
- package/dist/frontend/agent.js.map +1 -1
- package/dist/frontend/module.d.ts +1 -1
- package/dist/frontend/module.d.ts.map +1 -1
- package/dist/frontend/module.js.map +1 -1
- package/dist/frontend/realm.d.ts +1 -1
- package/dist/frontend/realm.d.ts.map +1 -1
- package/dist/frontend/reference.d.ts +3 -3
- package/dist/frontend/reference.d.ts.map +1 -1
- package/dist/test/00.agent/00.prerequisites.d.ts +2 -0
- package/dist/test/00.agent/00.prerequisites.d.ts.map +1 -0
- package/dist/test/00.agent/00.prerequisites.js +25 -0
- package/dist/test/00.agent/00.prerequisites.js.map +1 -0
- package/dist/test/00.agent/10.clock.d.ts +2 -0
- package/dist/test/00.agent/10.clock.d.ts.map +1 -0
- package/dist/test/{00.datetime.js → 00.agent/10.clock.js} +8 -8
- package/dist/test/00.agent/10.clock.js.map +1 -0
- package/dist/test/00.agent/10.random.d.ts +2 -0
- package/dist/test/00.agent/10.random.d.ts.map +1 -0
- package/dist/test/{00.random.js → 00.agent/10.random.js} +4 -4
- package/dist/test/00.agent/10.random.js.map +1 -0
- package/dist/test/10.transfer/00.primitives.d.ts +2 -0
- package/dist/test/10.transfer/00.primitives.d.ts.map +1 -0
- package/dist/test/10.transfer/00.primitives.js +54 -0
- package/dist/test/10.transfer/00.primitives.js.map +1 -0
- package/dist/test/10.transfer/10.array_buffer.d.ts +2 -0
- package/dist/test/10.transfer/10.array_buffer.d.ts.map +1 -0
- package/dist/test/{20.array_buffer.js → 10.transfer/10.array_buffer.js} +69 -64
- package/dist/test/10.transfer/10.array_buffer.js.map +1 -0
- package/dist/test/10.transfer/90.regressions.d.ts +2 -0
- package/dist/test/10.transfer/90.regressions.d.ts.map +1 -0
- package/dist/test/10.transfer/90.regressions.js +72 -0
- package/dist/test/10.transfer/90.regressions.js.map +1 -0
- package/dist/test/20.intrinsics/00.script.d.ts +2 -0
- package/dist/test/20.intrinsics/00.script.d.ts.map +1 -0
- package/dist/test/{10.script.js → 20.intrinsics/00.script.js} +32 -7
- package/dist/test/20.intrinsics/00.script.js.map +1 -0
- package/dist/test/20.intrinsics/05.global.d.ts.map +1 -0
- package/dist/test/{05.global.js → 20.intrinsics/05.global.js} +5 -5
- package/dist/test/20.intrinsics/05.global.js.map +1 -0
- package/dist/test/20.intrinsics/10.reference.d.ts.map +1 -0
- package/dist/test/{10.reference.js → 20.intrinsics/10.reference.js} +73 -27
- package/dist/test/20.intrinsics/10.reference.js.map +1 -0
- package/dist/test/20.intrinsics/20.module.d.ts +2 -0
- package/dist/test/20.intrinsics/20.module.d.ts.map +1 -0
- package/dist/test/{10.module.js → 20.intrinsics/20.module.js} +70 -39
- package/dist/test/20.intrinsics/20.module.js.map +1 -0
- package/dist/test/50.features/50.timers.d.ts.map +1 -0
- package/dist/test/{50.timers.js → 50.features/50.timers.js} +8 -8
- package/dist/test/50.features/50.timers.js.map +1 -0
- package/dist/test/50.features/90.i18n.d.ts +2 -0
- package/dist/test/50.features/90.i18n.d.ts.map +1 -0
- package/dist/test/{99.i18n.js → 50.features/90.i18n.js} +6 -6
- package/dist/test/50.features/90.i18n.js.map +1 -0
- package/dist/test/90.isolation/00.dispose.d.ts +1 -1
- package/dist/test/90.isolation/00.dispose.d.ts.map +1 -1
- package/dist/test/90.isolation/00.dispose.js +23 -5
- package/dist/test/90.isolation/00.dispose.js.map +1 -1
- package/dist/test/90.isolation/10.memory.d.ts +2 -0
- package/dist/test/90.isolation/10.memory.d.ts.map +1 -0
- package/dist/test/90.isolation/10.memory.js +51 -0
- package/dist/test/90.isolation/10.memory.js.map +1 -0
- package/dist/test/fixtures.js +2 -2
- package/dist/test/fixtures.js.map +1 -1
- package/dist/test/glob.d.ts +2 -0
- package/dist/test/glob.d.ts.map +1 -0
- package/dist/test/glob.js +11 -0
- package/dist/test/glob.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility/completion.d.ts +2 -1
- package/dist/utility/completion.d.ts.map +1 -1
- package/dist/utility/completion.js +4 -0
- package/dist/utility/completion.js.map +1 -1
- package/frontend/agent.ts +1 -0
- package/frontend/module.ts +1 -1
- package/frontend/realm.ts +4 -1
- package/frontend/reference.ts +3 -3
- package/package.json +13 -13
- package/test/00.agent/00.prerequisites.ts +12 -0
- package/test/{00.datetime.ts → 00.agent/10.clock.ts} +7 -7
- package/test/{00.random.ts → 00.agent/10.random.ts} +3 -3
- package/test/10.transfer/00.primitives.ts +47 -0
- package/test/{20.array_buffer.ts → 10.transfer/10.array_buffer.ts} +40 -35
- package/test/10.transfer/90.regressions.ts +38 -0
- package/test/{10.script.ts → 20.intrinsics/00.script.ts} +21 -6
- package/test/{05.global.ts → 20.intrinsics/05.global.ts} +5 -5
- package/test/20.intrinsics/10.reference.ts +111 -0
- package/test/{10.module.ts → 20.intrinsics/20.module.ts} +39 -17
- package/test/{50.timers.ts → 50.features/50.timers.ts} +8 -8
- package/test/{99.i18n.ts → 50.features/90.i18n.ts} +5 -5
- package/test/90.isolation/00.dispose.ts +12 -5
- package/test/90.isolation/10.memory.ts +28 -0
- package/test/fixtures.ts +4 -4
- package/test/glob.ts +11 -0
- package/utility/completion.ts +6 -1
- package/addon/handle/bound_value.cc +0 -45
- package/dist/test/00.datetime.d.ts +0 -2
- package/dist/test/00.datetime.d.ts.map +0 -1
- package/dist/test/00.datetime.js.map +0 -1
- package/dist/test/00.random.d.ts +0 -2
- package/dist/test/00.random.d.ts.map +0 -1
- package/dist/test/00.random.js.map +0 -1
- package/dist/test/00.transfer.d.ts +0 -2
- package/dist/test/00.transfer.d.ts.map +0 -1
- package/dist/test/00.transfer.js +0 -168
- package/dist/test/00.transfer.js.map +0 -1
- package/dist/test/05.global.d.ts.map +0 -1
- package/dist/test/05.global.js.map +0 -1
- package/dist/test/10.module.d.ts +0 -2
- package/dist/test/10.module.d.ts.map +0 -1
- package/dist/test/10.module.js.map +0 -1
- package/dist/test/10.reference.d.ts.map +0 -1
- package/dist/test/10.reference.js.map +0 -1
- package/dist/test/10.script.d.ts +0 -2
- package/dist/test/10.script.d.ts.map +0 -1
- package/dist/test/10.script.js.map +0 -1
- package/dist/test/20.array_buffer.d.ts +0 -2
- package/dist/test/20.array_buffer.d.ts.map +0 -1
- package/dist/test/20.array_buffer.js.map +0 -1
- package/dist/test/50.timers.d.ts.map +0 -1
- package/dist/test/50.timers.js.map +0 -1
- package/dist/test/99.i18n.d.ts +0 -2
- package/dist/test/99.i18n.d.ts.map +0 -1
- package/dist/test/99.i18n.js.map +0 -1
- package/test/00.transfer.ts +0 -134
- package/test/10.reference.ts +0 -82
- /package/dist/test/{05.global.d.ts → 20.intrinsics/05.global.d.ts} +0 -0
- /package/dist/test/{10.reference.d.ts → 20.intrinsics/10.reference.d.ts} +0 -0
- /package/dist/test/{50.timers.d.ts → 50.features/50.timers.d.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import { injectAssert, unsafeEvalAsString, unsafeEvalAsStringInRealm } from "
|
|
3
|
+
import { Agent, expect } from "@isolated-vm/experimental";
|
|
4
|
+
import { injectAssert, unsafeEvalAsString, unsafeEvalAsStringInRealm } from "@isolated-vm/experimental/test/fixtures";
|
|
5
5
|
|
|
6
6
|
const hostSupportsSharedArraySupport =
|
|
7
7
|
// @ts-expect-error
|
|
@@ -9,7 +9,7 @@ const hostSupportsSharedArraySupport =
|
|
|
9
9
|
|
|
10
10
|
await describe("array buffer", async () => {
|
|
11
11
|
await describe("transfer out", async () => {
|
|
12
|
-
await using agent = await
|
|
12
|
+
await using agent = await Agent.create();
|
|
13
13
|
const ab = await unsafeEvalAsString(agent, () => {
|
|
14
14
|
const uint8 = new Uint8Array([ 1, 2, 3 ]);
|
|
15
15
|
return uint8.buffer;
|
|
@@ -20,7 +20,7 @@ await describe("array buffer", async () => {
|
|
|
20
20
|
|
|
21
21
|
if (hostSupportsSharedArraySupport) {
|
|
22
22
|
await test("transfer out same reference", async () => {
|
|
23
|
-
await using agent = await
|
|
23
|
+
await using agent = await Agent.create();
|
|
24
24
|
const ab = await unsafeEvalAsString(agent, () => {
|
|
25
25
|
// nb: also tests zero-length buffer
|
|
26
26
|
const ab = new ArrayBuffer(0);
|
|
@@ -30,38 +30,43 @@ await describe("array buffer", async () => {
|
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
// These tests work individually in Deno but something about the test runner is choking when run
|
|
34
|
+
// in the suite.
|
|
35
|
+
if (process.versions.deno === undefined) {
|
|
36
|
+
await test("transfer in", async () => {
|
|
37
|
+
await using agent = await Agent.create();
|
|
38
|
+
const realm = expect(await agent.createRealm());
|
|
39
|
+
await injectAssert(agent, realm);
|
|
40
|
+
const global = await realm.acquireGlobalObject();
|
|
41
|
+
await global.set("ab", new Uint8Array([ 1, 2, 3 ]).buffer);
|
|
42
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
43
|
+
// @ts-expect-error
|
|
44
|
+
const uint8 = new Uint8Array(ab);
|
|
45
|
+
assert.deepStrictEqual([ ...uint8 ], [ 1, 2, 3 ]);
|
|
46
|
+
});
|
|
47
|
+
await agent.disposeAsync();
|
|
43
48
|
});
|
|
44
|
-
});
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
await test("transfer in same reference", async () => {
|
|
51
|
+
await using agent = await Agent.create();
|
|
52
|
+
const realm = expect(await agent.createRealm());
|
|
53
|
+
await injectAssert(agent, realm);
|
|
54
|
+
const global = await realm.acquireGlobalObject();
|
|
55
|
+
const ab = new ArrayBuffer(0);
|
|
56
|
+
await global.set("abs", [ ab, ab ]);
|
|
57
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
54
58
|
// @ts-expect-error
|
|
55
59
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
56
|
-
|
|
60
|
+
assert.strictEqual(abs[0], abs[1]);
|
|
61
|
+
});
|
|
57
62
|
});
|
|
58
|
-
}
|
|
63
|
+
}
|
|
59
64
|
});
|
|
60
65
|
|
|
61
66
|
await describe("shared array buffer", async () => {
|
|
62
67
|
if (hostSupportsSharedArraySupport) {
|
|
63
68
|
await describe("transfer out", async () => {
|
|
64
|
-
await using agent = await
|
|
69
|
+
await using agent = await Agent.create();
|
|
65
70
|
const realm = await agent.createRealm();
|
|
66
71
|
const sab = await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
67
72
|
const sab = new SharedArrayBuffer(3);
|
|
@@ -85,7 +90,7 @@ await describe("shared array buffer", async () => {
|
|
|
85
90
|
});
|
|
86
91
|
|
|
87
92
|
await test("transfer out same reference", async () => {
|
|
88
|
-
await using agent = await
|
|
93
|
+
await using agent = await Agent.create();
|
|
89
94
|
const ab = await unsafeEvalAsString(agent, () => {
|
|
90
95
|
// nb: also tests zero-length buffer
|
|
91
96
|
const sab = new SharedArrayBuffer(0);
|
|
@@ -95,8 +100,8 @@ await describe("shared array buffer", async () => {
|
|
|
95
100
|
});
|
|
96
101
|
|
|
97
102
|
await test("transfer in", async () => {
|
|
98
|
-
await using agent = await
|
|
99
|
-
const realm = await agent.createRealm();
|
|
103
|
+
await using agent = await Agent.create();
|
|
104
|
+
const realm = expect(await agent.createRealm());
|
|
100
105
|
await injectAssert(agent, realm);
|
|
101
106
|
const global = await realm.acquireGlobalObject();
|
|
102
107
|
const sab = new SharedArrayBuffer(3);
|
|
@@ -113,8 +118,8 @@ await describe("shared array buffer", async () => {
|
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
await test("transfer in same reference", async () => {
|
|
116
|
-
await using agent = await
|
|
117
|
-
const realm = await agent.createRealm();
|
|
121
|
+
await using agent = await Agent.create();
|
|
122
|
+
const realm = expect(await agent.createRealm());
|
|
118
123
|
await injectAssert(agent, realm);
|
|
119
124
|
const global = await realm.acquireGlobalObject();
|
|
120
125
|
const ab = new ArrayBuffer(0);
|
|
@@ -132,7 +137,7 @@ await describe("shared array buffer", async () => {
|
|
|
132
137
|
|
|
133
138
|
// TODO: deno fails when this is in the `describe` (??)
|
|
134
139
|
await test("transfer out", async () => {
|
|
135
|
-
await using agent = await
|
|
140
|
+
await using agent = await Agent.create();
|
|
136
141
|
const [ uint8, uint8_copy ] = await unsafeEvalAsString(agent, () => {
|
|
137
142
|
const uint8 = new Uint8Array([ 1, 2, 3 ]);
|
|
138
143
|
return [ uint8, new Uint8Array(uint8.buffer) ];
|
|
@@ -143,8 +148,8 @@ await test("transfer out", async () => {
|
|
|
143
148
|
|
|
144
149
|
await describe("typed array", async () => {
|
|
145
150
|
await test("transfer in", async () => {
|
|
146
|
-
await using agent = await
|
|
147
|
-
const realm = await agent.createRealm();
|
|
151
|
+
await using agent = await Agent.create();
|
|
152
|
+
const realm = expect(await agent.createRealm());
|
|
148
153
|
await injectAssert(agent, realm);
|
|
149
154
|
const global = await realm.acquireGlobalObject();
|
|
150
155
|
const uint8 = new Uint8Array([ 1, 2, 3 ]);
|
|
@@ -159,7 +164,7 @@ await describe("typed array", async () => {
|
|
|
159
164
|
|
|
160
165
|
if (hostSupportsSharedArraySupport) {
|
|
161
166
|
await test("shared transfer out", async () => {
|
|
162
|
-
await using agent = await
|
|
167
|
+
await using agent = await Agent.create();
|
|
163
168
|
const [ shared_uint8, shared_uint8_copy ] = await unsafeEvalAsString(agent, () => {
|
|
164
169
|
const sab = new SharedArrayBuffer(3);
|
|
165
170
|
const uint8 = new Uint8Array(sab);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { Agent, expect } from "@isolated-vm/experimental";
|
|
3
|
+
import "@isolated-vm/experimental/test/fixtures";
|
|
4
|
+
|
|
5
|
+
const hostSupportsSharedArraySupport =
|
|
6
|
+
// @ts-expect-error
|
|
7
|
+
process.isBun === undefined && process.versions.deno === undefined;
|
|
8
|
+
|
|
9
|
+
// TODO: deno fails when this is in the `describe` (??)
|
|
10
|
+
await test("numeric references", async () => {
|
|
11
|
+
await using agent = await Agent.create();
|
|
12
|
+
const realm = expect(await agent.createRealm());
|
|
13
|
+
const global = await realm.acquireGlobalObject();
|
|
14
|
+
// doubles are stored as references in `value_t`, because they are bigger than 32-bit. there was
|
|
15
|
+
// a failure with more than one of them in the same transfer operation.
|
|
16
|
+
expect(await global.set("xx", { zero: 0.1, one: 0.2 }));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
await test("numeric indices", async () => {
|
|
20
|
+
await using agent = await Agent.create();
|
|
21
|
+
const realm = expect(await agent.createRealm());
|
|
22
|
+
const global = await realm.acquireGlobalObject();
|
|
23
|
+
// numeric array indices broke as part of a double to int32_t change.
|
|
24
|
+
expect(await global.set("xx", [ false, true ]));
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (hostSupportsSharedArraySupport) {
|
|
28
|
+
await test("seen index type", async () => {
|
|
29
|
+
await using agent = await Agent.create();
|
|
30
|
+
const realm = expect(await agent.createRealm());
|
|
31
|
+
const global = await realm.acquireGlobalObject();
|
|
32
|
+
const payload = {
|
|
33
|
+
number: 0,
|
|
34
|
+
buffer: [ new Uint8Array(new SharedArrayBuffer(0)) ],
|
|
35
|
+
};
|
|
36
|
+
expect(await global.set("xx", [ payload ]));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import { expectComplete, expectThrow, unsafeEvalAsStringInRealm, unsafeIIFEAsString } from "
|
|
3
|
+
import { Agent } from "@isolated-vm/experimental";
|
|
4
|
+
import { expectComplete, expectThrow, unsafeEvalAsStringInRealm, unsafeIIFEAsString } from "@isolated-vm/experimental/test/fixtures";
|
|
5
|
+
|
|
6
|
+
const illegalAccess = new Error("illegal access");
|
|
5
7
|
|
|
6
8
|
await test("script source origin", async () => {
|
|
7
|
-
await using agent = await
|
|
9
|
+
await using agent = await Agent.create();
|
|
8
10
|
const script = expectComplete(await agent.compileScript(
|
|
9
11
|
unsafeIIFEAsString(() => {
|
|
10
12
|
try {
|
|
@@ -28,7 +30,7 @@ await test("script source origin", async () => {
|
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
await test("script which throws", async () => {
|
|
31
|
-
await using agent = await
|
|
33
|
+
await using agent = await Agent.create();
|
|
32
34
|
const realm = await agent.createRealm();
|
|
33
35
|
const script = expectComplete(await agent.compileScript("throw new Error('wow');", { origin: { name: "test:script" } }));
|
|
34
36
|
const error = expectThrow(await script.run(realm)) as Error;
|
|
@@ -37,7 +39,7 @@ await test("script which throws", async () => {
|
|
|
37
39
|
});
|
|
38
40
|
|
|
39
41
|
await test("script with syntax error", async () => {
|
|
40
|
-
await using agent = await
|
|
42
|
+
await using agent = await Agent.create();
|
|
41
43
|
const error = expectThrow(await agent.compileScript("}"));
|
|
42
44
|
// @ts-expect-error
|
|
43
45
|
const message: unknown = error.message;
|
|
@@ -46,7 +48,7 @@ await test("script with syntax error", async () => {
|
|
|
46
48
|
});
|
|
47
49
|
|
|
48
50
|
await test("script which returns a circular object", async () => {
|
|
49
|
-
await using agent = await
|
|
51
|
+
await using agent = await Agent.create();
|
|
50
52
|
const realm = await agent.createRealm();
|
|
51
53
|
const result = await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
52
54
|
const date = new Date();
|
|
@@ -61,3 +63,16 @@ await test("script which returns a circular object", async () => {
|
|
|
61
63
|
assert.strictEqual(result.date1, result.date2);
|
|
62
64
|
assert.strictEqual(result.object, result);
|
|
63
65
|
});
|
|
66
|
+
|
|
67
|
+
await test("script result should not invoke interceptors", async () => {
|
|
68
|
+
await using agent = await Agent.create();
|
|
69
|
+
const realm = await agent.createRealm();
|
|
70
|
+
const script = expectComplete(await agent.compileScript(unsafeIIFEAsString(() => {
|
|
71
|
+
const object = Object.defineProperty({ name: "value" }, "name", {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
get() { throw new Error("interceptor invoked"); },
|
|
74
|
+
});
|
|
75
|
+
return object;
|
|
76
|
+
})));
|
|
77
|
+
await assert.rejects(async () => expectComplete(await script.run(realm)), illegalAccess);
|
|
78
|
+
});
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import { unsafeEvalAsStringInRealm } from "
|
|
3
|
+
import { Agent, expect } from "@isolated-vm/experimental";
|
|
4
|
+
import { unsafeEvalAsStringInRealm } from "@isolated-vm/experimental/test/fixtures";
|
|
5
5
|
|
|
6
6
|
await test("realm global reference", async () => {
|
|
7
|
-
await using agent = await
|
|
8
|
-
const realm = await agent.createRealm();
|
|
7
|
+
await using agent = await Agent.create();
|
|
8
|
+
const realm = expect(await agent.createRealm());
|
|
9
9
|
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
10
10
|
// @ts-expect-error
|
|
11
11
|
globalThis.test = 123;
|
|
12
12
|
});
|
|
13
13
|
const global = await realm.acquireGlobalObject();
|
|
14
|
-
const property = await global.get("test");
|
|
14
|
+
const property = expect(await global.get("test"));
|
|
15
15
|
const value = await property.copy();
|
|
16
16
|
assert.equal(value, 123);
|
|
17
17
|
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Reference } from "@isolated-vm/experimental";
|
|
2
|
+
import * as assert from "node:assert/strict";
|
|
3
|
+
import { test } from "node:test";
|
|
4
|
+
import { Agent, expect } from "@isolated-vm/experimental";
|
|
5
|
+
import { expectComplete, unsafeEvalAsStringInRealm } from "@isolated-vm/experimental/test/fixtures";
|
|
6
|
+
|
|
7
|
+
const illegalAccess = new Error("illegal access");
|
|
8
|
+
|
|
9
|
+
await test("function reference invoke", async () => {
|
|
10
|
+
await using agent = await Agent.create();
|
|
11
|
+
const realm = expect(await agent.createRealm());
|
|
12
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
13
|
+
// @ts-expect-error
|
|
14
|
+
globalThis.fn = () => "wow";
|
|
15
|
+
});
|
|
16
|
+
const global = await realm.acquireGlobalObject();
|
|
17
|
+
const property = (await global.get("fn")) as Reference<() => unknown>;
|
|
18
|
+
const value = expectComplete(await property.invoke([]));
|
|
19
|
+
assert.equal(value, "wow");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await test("invoke function cross-param reference", async () => {
|
|
23
|
+
await using agent = await Agent.create();
|
|
24
|
+
const realm = expect(await agent.createRealm());
|
|
25
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
26
|
+
// @ts-expect-error
|
|
27
|
+
globalThis.fn = (...values: unknown[]) => values;
|
|
28
|
+
});
|
|
29
|
+
const global = await realm.acquireGlobalObject();
|
|
30
|
+
const fn = await global.get("fn");
|
|
31
|
+
const object = {};
|
|
32
|
+
// @ts-expect-error
|
|
33
|
+
const [ left, right ] = expectComplete(await fn.invoke([ object, object ]));
|
|
34
|
+
assert.strictEqual(left, right);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await test("invoke function reference with circular object", async () => {
|
|
38
|
+
await using agent = await Agent.create();
|
|
39
|
+
const realm = expect(await agent.createRealm());
|
|
40
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
41
|
+
// @ts-expect-error
|
|
42
|
+
globalThis.fn = (value: unknown) => value;
|
|
43
|
+
});
|
|
44
|
+
const global = await realm.acquireGlobalObject();
|
|
45
|
+
const fn = (await global.get("fn")) as Reference<(value: unknown) => unknown>;
|
|
46
|
+
const date = new Date();
|
|
47
|
+
const object: Record<string, any> = {
|
|
48
|
+
record: {},
|
|
49
|
+
date1: date,
|
|
50
|
+
date2: date,
|
|
51
|
+
};
|
|
52
|
+
object.object = object;
|
|
53
|
+
const result = expectComplete(await fn.invoke([ object ]));
|
|
54
|
+
// @ts-expect-error
|
|
55
|
+
assert.strictEqual(result.date1, result.date2);
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
assert.strictEqual(result.object, result);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await test("get & set should not invoke proxies", async () => {
|
|
61
|
+
await using agent = await Agent.create();
|
|
62
|
+
const realm = expect(await agent.createRealm());
|
|
63
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
64
|
+
const proxy = new Proxy({}, {
|
|
65
|
+
get() { throw new Error("interceptor invoked"); },
|
|
66
|
+
set() { throw new Error("interceptor invoked"); },
|
|
67
|
+
});
|
|
68
|
+
// @ts-expect-error
|
|
69
|
+
globalThis.proxy = proxy;
|
|
70
|
+
});
|
|
71
|
+
const global = await realm.acquireGlobalObject();
|
|
72
|
+
const proxy = expect(await global.get("proxy"));
|
|
73
|
+
expect(await proxy.get("name"));
|
|
74
|
+
expect(await proxy.set("name", undefined));
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await test("copy should not invoke interceptors", async () => {
|
|
78
|
+
await using agent = await Agent.create();
|
|
79
|
+
const realm = await agent.createRealm();
|
|
80
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
81
|
+
const object =
|
|
82
|
+
Object.defineProperty({}, "name", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get() { throw new Error("interceptor invoked"); },
|
|
85
|
+
});
|
|
86
|
+
// @ts-expect-error
|
|
87
|
+
globalThis.object = object;
|
|
88
|
+
});
|
|
89
|
+
const global = await realm?.acquireGlobalObject();
|
|
90
|
+
const object = await global?.get("object");
|
|
91
|
+
await assert.rejects(async () => object?.copy(), illegalAccess);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await test("invoke should not invoke interceptors", async () => {
|
|
95
|
+
await using agent = await Agent.create();
|
|
96
|
+
const realm = await agent.createRealm();
|
|
97
|
+
await unsafeEvalAsStringInRealm(agent, realm, () => {
|
|
98
|
+
// @ts-expect-error
|
|
99
|
+
globalThis.fn = () => {};
|
|
100
|
+
// eslint-disable-next-line no-extend-native
|
|
101
|
+
Object.defineProperty(Object.prototype, "name", {
|
|
102
|
+
set() { throw new Error("interceptor invoked"); },
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
const global = await realm?.acquireGlobalObject();
|
|
106
|
+
const fn = await global?.get("fn") as Reference<(...args: unknown[]) => unknown> | null;
|
|
107
|
+
await assert.rejects(
|
|
108
|
+
async () => expectComplete(await fn?.invoke([ { name: "value" } ])),
|
|
109
|
+
illegalAccess,
|
|
110
|
+
);
|
|
111
|
+
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { Agent, expect } from "@isolated-vm/experimental";
|
|
4
|
+
import { expectComplete, expectThrow } from "@isolated-vm/experimental/test/fixtures";
|
|
5
|
+
import { makeNullLinker } from "@isolated-vm/experimental/utility/linker";
|
|
6
6
|
|
|
7
7
|
await test("module linker", async () => {
|
|
8
|
-
await using agent = await
|
|
8
|
+
await using agent = await Agent.create();
|
|
9
9
|
const realm = await agent.createRealm();
|
|
10
10
|
const left = expectComplete(await agent.compileModule('import { right } from "right"; globalThis.right = right;'));
|
|
11
11
|
const right = expectComplete(await agent.compileModule('export function right() { return "hello"; }'));
|
|
@@ -20,18 +20,18 @@ await test("module linker", async () => {
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
await test("nested compilation in module linker", async () => {
|
|
23
|
-
await using agent = await
|
|
23
|
+
await using agent = await Agent.create();
|
|
24
24
|
const realm = await agent.createRealm();
|
|
25
25
|
const left = expectComplete(await agent.compileModule('import "right";'));
|
|
26
26
|
await left.link(realm, async () => expectComplete(await agent.compileModule("export {};")));
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
await test("synthetic module capability", async () => {
|
|
30
|
-
await using agent = await
|
|
30
|
+
await using agent = await Agent.create();
|
|
31
31
|
const capabilityName = "isolated-vm:///capability";
|
|
32
32
|
let didInvoke = false;
|
|
33
|
-
const realm = await agent.createRealm();
|
|
34
|
-
const capability = await realm.createCapability(
|
|
33
|
+
const realm = expect(await agent.createRealm());
|
|
34
|
+
const capability = expect(await realm.createCapability(
|
|
35
35
|
() => ({
|
|
36
36
|
default: (value1: unknown, value2: unknown) => {
|
|
37
37
|
didInvoke = true;
|
|
@@ -39,7 +39,7 @@ await test("synthetic module capability", async () => {
|
|
|
39
39
|
assert.equal(value2, "world");
|
|
40
40
|
},
|
|
41
41
|
}),
|
|
42
|
-
{ origin: capabilityName });
|
|
42
|
+
{ origin: capabilityName }));
|
|
43
43
|
const left = expectComplete(await agent.compileModule(`
|
|
44
44
|
import capability from ${JSON.stringify(capabilityName)};
|
|
45
45
|
capability("hello", "world");
|
|
@@ -53,10 +53,10 @@ await test("synthetic module capability", async () => {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
await test("synthetic module with circular reference", async () => {
|
|
56
|
-
await using agent = await
|
|
56
|
+
await using agent = await Agent.create();
|
|
57
57
|
const capabilityName = "isolated-vm:///capability";
|
|
58
|
-
const realm = await agent.createRealm();
|
|
59
|
-
const capability = await realm.createCapability(
|
|
58
|
+
const realm = expect(await agent.createRealm());
|
|
59
|
+
const capability = expect(await realm.createCapability(
|
|
60
60
|
() => ({
|
|
61
61
|
default: (value1: unknown) => {
|
|
62
62
|
// @ts-expect-error
|
|
@@ -65,7 +65,7 @@ await test("synthetic module with circular reference", async () => {
|
|
|
65
65
|
assert.strictEqual(value1.object, value1);
|
|
66
66
|
},
|
|
67
67
|
}),
|
|
68
|
-
{ origin: capabilityName });
|
|
68
|
+
{ origin: capabilityName }));
|
|
69
69
|
const left = expectComplete(await agent.compileModule(`
|
|
70
70
|
import capability from ${JSON.stringify(capabilityName)};
|
|
71
71
|
const date = new Date();
|
|
@@ -84,10 +84,32 @@ await test("synthetic module with circular reference", async () => {
|
|
|
84
84
|
await left.evaluate(realm);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
await test("synthetic module with data templates", async () => {
|
|
88
|
+
await using agent = await Agent.create();
|
|
89
|
+
const capabilityName = "isolated-vm:///capability";
|
|
90
|
+
const realm = expect(await agent.createRealm());
|
|
91
|
+
const capability = expect(await realm.createCapability(
|
|
92
|
+
() => ({
|
|
93
|
+
string: "string",
|
|
94
|
+
}),
|
|
95
|
+
{ origin: capabilityName }));
|
|
96
|
+
const entry = expectComplete(await agent.compileModule(`
|
|
97
|
+
import { string } from ${JSON.stringify(capabilityName)};
|
|
98
|
+
globalThis.result = JSON.stringify({ string });
|
|
99
|
+
`));
|
|
100
|
+
await entry.link(realm, () => capability);
|
|
101
|
+
await entry.evaluate(realm);
|
|
102
|
+
const global = expect(await realm.acquireGlobalObject());
|
|
103
|
+
const result = expect(await global.get("result"));
|
|
104
|
+
assert.equal(await result.copy(), JSON.stringify({
|
|
105
|
+
string: "string",
|
|
106
|
+
}));
|
|
107
|
+
});
|
|
108
|
+
|
|
87
109
|
// TODO: This terminates the process. It should probably raise an async error, because there is no
|
|
88
110
|
// promise.
|
|
89
111
|
// await test("throw from synthetic module", async () => {
|
|
90
|
-
// await using agent = await
|
|
112
|
+
// await using agent = await Agent.create();
|
|
91
113
|
// const capabilityName = "isolated-vm:///capability";
|
|
92
114
|
// const realm = await agent.createRealm();
|
|
93
115
|
// const capability = await realm.createCapability(
|
|
@@ -109,7 +131,7 @@ await test("synthetic module with circular reference", async () => {
|
|
|
109
131
|
// });
|
|
110
132
|
|
|
111
133
|
await test("throw from linker", async () => {
|
|
112
|
-
await using agent = await
|
|
134
|
+
await using agent = await Agent.create();
|
|
113
135
|
const realm = await agent.createRealm();
|
|
114
136
|
const left = expectComplete(await agent.compileModule('import "right";'));
|
|
115
137
|
await assert.rejects(left.link(realm, () => {
|
|
@@ -118,7 +140,7 @@ await test("throw from linker", async () => {
|
|
|
118
140
|
});
|
|
119
141
|
|
|
120
142
|
await test("throw from evaluation", async () => {
|
|
121
|
-
await using agent = await
|
|
143
|
+
await using agent = await Agent.create();
|
|
122
144
|
const realm = await agent.createRealm();
|
|
123
145
|
const module = expectComplete(await agent.compileModule('throw new Error("wow");', { origin: { name: "test:module" } }));
|
|
124
146
|
await module.link(realm, makeNullLinker());
|
|
@@ -128,7 +150,7 @@ await test("throw from evaluation", async () => {
|
|
|
128
150
|
});
|
|
129
151
|
|
|
130
152
|
await test("missing imports", async () => {
|
|
131
|
-
await using agent = await
|
|
153
|
+
await using agent = await Agent.create();
|
|
132
154
|
const realm = await agent.createRealm();
|
|
133
155
|
const left = expectComplete(await agent.compileModule('import { nothing } from "right";'));
|
|
134
156
|
await assert.rejects(left.link(realm, async () =>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { test } from "node:test";
|
|
3
|
-
import
|
|
3
|
+
import { Agent, expect } from "@isolated-vm/experimental";
|
|
4
|
+
import { expectComplete } from "@isolated-vm/experimental/test/fixtures";
|
|
4
5
|
import { makeCompositeLinker, makeDirectResolver, makeFileSystemCompilationLoader, makeLinker, makeLocalResolver, makeStaticLoader } from "@isolated-vm/experimental/utility/linker";
|
|
5
|
-
import { expectComplete } from "./fixtures.js";
|
|
6
6
|
|
|
7
7
|
await test("setTimeout capability", async () => {
|
|
8
|
-
await using agent = await
|
|
9
|
-
const realm = await agent.createRealm();
|
|
8
|
+
await using agent = await Agent.create();
|
|
9
|
+
const realm = expect(await agent.createRealm());
|
|
10
10
|
const runTimers = expectComplete(await agent.compileScript("runTimers()"));
|
|
11
11
|
const resolvers = Promise.withResolvers();
|
|
12
12
|
const capabilities = makeStaticLoader({
|
|
13
|
-
"isolated-vm:capability/timers": await realm.createCapability(
|
|
13
|
+
"isolated-vm:capability/timers": expect(await realm.createCapability(
|
|
14
14
|
() => ({
|
|
15
15
|
default: (/*timeout*/) => {
|
|
16
16
|
void async function() {
|
|
@@ -18,12 +18,12 @@ await test("setTimeout capability", async () => {
|
|
|
18
18
|
}();
|
|
19
19
|
},
|
|
20
20
|
}),
|
|
21
|
-
{ origin: "isolated-vm:capability/timers" }),
|
|
22
|
-
"notify-test": await realm.createCapability(
|
|
21
|
+
{ origin: "isolated-vm:capability/timers" })),
|
|
22
|
+
"notify-test": expect(await realm.createCapability(
|
|
23
23
|
() => ({
|
|
24
24
|
default: (message: unknown) => { resolvers.resolve(message); },
|
|
25
25
|
}),
|
|
26
|
-
{ origin: "notify-test" }),
|
|
26
|
+
{ origin: "notify-test" })),
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
const runtime = makeFileSystemCompilationLoader(agent);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import { unsafeEvalAsString } from "
|
|
3
|
+
import { Agent } from "@isolated-vm/experimental";
|
|
4
|
+
import { unsafeEvalAsString } from "@isolated-vm/experimental/test/fixtures";
|
|
5
5
|
|
|
6
6
|
await test("localCompare", async () => {
|
|
7
|
-
await using agent = await
|
|
7
|
+
await using agent = await Agent.create();
|
|
8
8
|
const result = await unsafeEvalAsString(agent, () => "a".localeCompare("b"));
|
|
9
9
|
assert.equal(result, -1);
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
await test("i18n locales", async () => {
|
|
13
|
-
await using agent = await
|
|
13
|
+
await using agent = await Agent.create();
|
|
14
14
|
const supported = await unsafeEvalAsString(agent, () =>
|
|
15
15
|
Intl.NumberFormat.supportedLocalesOf([ "ar-EG", "fa-IR", "zh-Hans", "hi-IN", "th-TH", "km-KH" ]));
|
|
16
16
|
// no "km-KH"
|
|
@@ -18,7 +18,7 @@ await test("i18n locales", async () => {
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
await test("i18n format", async () => {
|
|
21
|
-
await using agent = await
|
|
21
|
+
await using agent = await Agent.create();
|
|
22
22
|
const german = await unsafeEvalAsString(agent, () => new Intl.NumberFormat("de-DE").format(1234567.89));
|
|
23
23
|
assert.equal(german, "1.234.567,89");
|
|
24
24
|
});
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import * as assert from "node:assert/strict";
|
|
2
2
|
import { test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import { Agent, expectComplete } from "@isolated-vm/experimental";
|
|
4
|
+
import "@isolated-vm/experimental/test/fixtures";
|
|
5
5
|
|
|
6
6
|
await test("dispose while running", async () => {
|
|
7
7
|
const result = async function() {
|
|
8
|
-
await using agent = await
|
|
8
|
+
await using agent = await Agent.create();
|
|
9
9
|
const realm = await agent.createRealm();
|
|
10
|
-
const script =
|
|
10
|
+
const script = expectComplete(await agent.compileScript("for(;;);"));
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/return-await
|
|
12
12
|
return script.run(realm);
|
|
13
13
|
}();
|
|
14
|
-
assert.strictEqual(await result,
|
|
14
|
+
assert.strictEqual(await result, null);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
await test("busy dispose", async () => {
|
|
18
|
+
await using agent = await Agent.create();
|
|
19
|
+
const [ dispose, realm ] = await Promise.all([ agent.disposeAsync(), agent.createRealm() ]);
|
|
20
|
+
assert.strictEqual(dispose, undefined);
|
|
21
|
+
assert.strictEqual(realm, null);
|
|
15
22
|
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { Agent, expectComplete } from "@isolated-vm/experimental";
|
|
4
|
+
import "@isolated-vm/experimental/test/fixtures";
|
|
5
|
+
|
|
6
|
+
await test("memory limit", async () => {
|
|
7
|
+
await using agent = await Agent.create({ memoryLimitBytes: 128 << 20 });
|
|
8
|
+
const realm = await agent.createRealm();
|
|
9
|
+
const sourceText =
|
|
10
|
+
`const x = [];
|
|
11
|
+
for (;;) {
|
|
12
|
+
let a = 'a';
|
|
13
|
+
for(; a.length < 2**28;) a += a;
|
|
14
|
+
x.push(a);
|
|
15
|
+
}`;
|
|
16
|
+
const script = expectComplete(await agent.compileScript(sourceText));
|
|
17
|
+
const result = await script.run(realm);
|
|
18
|
+
assert.strictEqual(result, null);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await test("array spread", async () => {
|
|
22
|
+
await using agent = await Agent.create({ memoryLimitBytes: 128 << 20 });
|
|
23
|
+
const realm = await agent.createRealm();
|
|
24
|
+
const sourceText = "[...'.'.repeat(5e7)]; undefined";
|
|
25
|
+
const script = expectComplete(await agent.compileScript(sourceText));
|
|
26
|
+
const result = await script.run(realm);
|
|
27
|
+
assert.strictEqual(result, null);
|
|
28
|
+
});
|