1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
// New API experiments.
// Example from the proposal.
var compute_delta = async (i) => Promise.resolve(i / 100 || 1);
var suspending_compute_delta = new WebAssembly.Suspending(
compute_delta
);
var ins = wasmEvalText(`(module
(import "js" "init_state" (func $init_state (result f64)))
(import "js" "compute_delta"
(func $compute_delta (param i32) (result f64)))
(global $suspender (mut externref) (ref.null extern))
(global $state (mut f64) (f64.const nan))
(func $init (global.set $state (call $init_state)))
(start $init)
(func $get_state (export "get_state") (result f64) (global.get $state))
(func (export "update_state_export") (param i32) (result f64)
(global.set $state (f64.add
(global.get $state) (call $compute_delta (local.get 0))))
(global.get $state)
)
)`, {
js: {
init_state() { return 0; },
compute_delta: suspending_compute_delta,
},
});
var update_state = WebAssembly.promising(
ins.exports.update_state_export
);
var res = update_state(4);
var tasks = res.then((r) => {
print(r);
assertEq(ins.exports.get_state(), .04);
});
assertEq(ins.exports.get_state(), 0);
// Also test with exceptions/traps.
async function test(c) {
var compute_delta = (i) => Promise.resolve(i/100 || 1);
if (c == 1) compute_delta = async (i) => {throw "ff"};
if (c == 2) compute_delta = () => {throw "ff";}
var suspending_compute_delta = new WebAssembly.Suspending(
compute_delta
);
var ins = wasmEvalText(`(module
(import "js" "init_state" (func $init_state (result f64)))
(import "js" "compute_delta"
(func $compute_delta (param i32) (result f64)))
(global $suspender (mut externref) (ref.null extern))
(global $state (mut f64) (f64.const nan))
(func $init (global.set $state (call $init_state)))
(start $init)
(func $get_state (export "get_state") (result f64) (global.get $state))
(func (export "update_state_export") (param i32) (result f64)
${c == 3 ? "(unreachable)" : ""}
(global.set $state (f64.add
(global.get $state) (call $compute_delta (local.get 0))))
${c == 4 ? "(unreachable)" : ""}
(global.get $state)
)
)`, {
js: {
init_state() { return 0; },
compute_delta: suspending_compute_delta,
},
});
var update_state = WebAssembly.promising(
ins.exports.update_state_export
);
var res = update_state(4);
var p = res.then((r) => {
assertEq(c, 0);
assertEq(ins.exports.get_state(), .04);
}).catch(_ => {
assertEq(c > 0, true);
});
assertEq(ins.exports.get_state(), 0);
await p;
}
for (let c = 0; c < 5; c++) {
tasks = tasks.then(() => test(c));
}
|