summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/exceptions/reftypes.js
blob: efd577dec834bd811cc136a88d19f476cb2603dc (plain)
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Exception tests that use reference types.

load(libdir + "eqArrayHelper.js");

assertEq(
  wasmEvalText(
    `(module
       (tag $exn (param externref))
       (func (export "f") (result externref)
         try (result externref)
           ref.null extern
           throw $exn
         catch $exn
         end))`
  ).exports.f(),
  null
);

{
  let f = wasmEvalText(
    `(module
       (tag $exn (param funcref))
       (func $f (export "f") (result funcref)
         try (result funcref)
           ref.func $f
           throw $exn
         catch $exn
         end))`
  ).exports.f;
  assertEq(f(), f);
}

{
  let f = wasmEvalText(
    `(module
       (tag $exn (param externref))
       (func (export "f") (param externref) (result externref)
         try (result externref)
           local.get 0
           throw $exn
         catch $exn
         end))`
  ).exports.f;

  for (v of WasmExternrefValues) {
    assertEq(f(v), v);
  }
}

assertEqArray(
  wasmEvalText(
    `(module
       (tag $exn (param externref externref))
       (func (export "f") (param externref externref)
             (result externref externref)
         try (result externref externref)
           local.get 0
           local.get 1
           throw $exn
         catch $exn
         end))`
  ).exports.f("foo", "bar"),
  ["foo", "bar"]
);

assertEqArray(
  wasmEvalText(
    `(module
       (tag $exn (param i32 i32 externref f32))
       (func (export "f") (param externref)
             (result i32 i32 externref f32)
         try (result i32 i32 externref f32)
           i32.const 0
           i32.const 1
           local.get 0
           f32.const 2.0
           throw $exn
         catch $exn
         end))`
  ).exports.f("foo"),
  [0, 1, "foo", 2.0]
);

assertEqArray(
  wasmEvalText(
    `(module
       (tag $exn (param i32 i32 externref f32 externref f64))
       (func (export "f") (param externref externref)
             (result i32 i32 externref f32 externref f64)
         try (result i32 i32 externref f32 externref f64)
           i32.const 0
           i32.const 1
           local.get 0
           f32.const 2.0
           local.get 1
           f64.const 3.0
           throw $exn
         catch $exn
         end))`
  ).exports.f("foo", "bar"),
  [0, 1, "foo", 2.0, "bar", 3.0]
);

// Test to ensure that reference typed values are tracked correctly by
// the GC within exception objects.
{
  gczeal(2, 1); // Collect on every allocation.

  var thrower;
  let exports = wasmEvalText(
    `(module
       (tag $exn (param externref))
       (import "m" "f" (func $f (result externref)))
       (func (export "thrower") (param externref)
         (local.get 0)
         (throw $exn))
       (func (export "catcher") (result externref)
         try (result externref)
           (call $f)
         catch $exn
         end))`,
    {
      m: {
        f: () => {
          // The purpose of this intermediate try-catch in JS is to force
          // some allocation to occur after Wasm's `throw`, triggering GC, and
          // then rethrow back to Wasm to observe any errors.
          try {
            thrower("foo");
          } catch (e) {
            let v = { x: 5 };
            throw e;
          }
        },
      },
    }
  ).exports;

  thrower = exports.thrower;
  assertEq(exports.catcher(), "foo");
}