summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/function-references/non-nullable.js
blob: afe1d3cb43c0542416c05bf822502f0b076fcfe5 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// |jit-test| skip-if: !wasmFunctionReferencesEnabled()

// non-null values are subtype of null values
wasmValidateText(`(module
  (func (param $a (ref extern))
    local.get $a
    (block (param (ref null extern))
      drop
    )
  )
)`);

// null values are not subtype of non-null values
wasmFailValidateText(`(module
  (func (param $a (ref null extern))
    local.get $a
    (block (param (ref extern))
      drop
    )
  )
)`, /expression has type externref but expected \(ref extern\)/);

// can have non-defaultable local, but not use/get if unset.
wasmValidateText(`(module
  (func (local (ref extern)))
)`);
wasmFailValidateText(`(module
  (func (local (ref extern))
    local.get 0
    drop
  )
)`, /local\.get read from unset local/);
wasmFailValidateText(`(module
  (func
    (local (ref extern))
    unreachable
    block
      local.get 0
      drop
    end
  )
)`, /local\.get read from unset local/);
wasmFailValidateText(`(module
  (func (param funcref) (result funcref) (local (ref func))
    block
      local.get 0
      ref.as_non_null
      local.set 1
    end
    local.get 1
  )
)`, /local\.get read from unset local/);
wasmValidateText(`(module
  (func (param $r (ref extern))
    (local $var (ref extern))
    local.get $r
    ref.as_non_null
    local.set $var
    block block block
    local.get $var
    drop
    end end end
  )
  (func
    (param (ref null func) (ref null func) (ref func))
    (result funcref)
    (local (ref func) i32 (ref func) (ref null func))
    local.get 0
    ref.as_non_null
    local.tee 3
    block
      local.get 6
      ref.as_non_null
      local.set 5 
    end
    local.get 2
    drop
    local.tee 5
  )  
)`);
wasmFailValidateText(`(module
  (elem declare func 0)
  (func
    (local (ref func))
    i32.const 0
    if
      ref.func 0
      local.set 0
    else
      local.get 0
      drop
    end
  )
)`, /local\.get read from unset local/);
wasmValidateText(`(module
  (elem declare func 0)
  (func (result funcref)
    (local (ref func) (ref func))
    i32.const 0
    if (result funcref)
      ref.func 0
      local.set 0
      local.get 0
    else
      ref.func 0
      local.tee 1
      local.get 1
      drop
    end
  )
)`);

// exported funcs can't take null in non-nullable params
let {a} = wasmEvalText(`(module
  (func (export "a") (param (ref extern)))
)`).exports;
assertErrorMessage(() => a(null), TypeError, /cannot pass null to non-nullable/);
for (let val of WasmNonNullExternrefValues) {
  a(val);
}

// imported funcs can't return null in non-nullable results
function returnNull() {
  return null;
}
function returnMultiNullReg() {
  return [null, null];
}
function returnMultiNullStack() {
  return [1, 2, 3, 4, 5, 6, 7, 8, null];
}
let {runNull, runMultiNullReg, runMultiNullStack} = wasmEvalText(`(module
  (func $returnNull (import "" "returnNull") (result (ref extern)))
  (func $returnMultiNullReg (import "" "returnMultiNullReg") (result (ref extern) (ref extern)))
  (func $returnMultiNullStack (import "" "returnMultiNullStack") (result (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern)))
  (func (export "runNull")
    call $returnNull
    unreachable
  )
  (func (export "runMultiNullReg")
    call $returnMultiNullReg
    unreachable
  )
  (func (export "runMultiNullStack")
    call $returnMultiNullStack
    unreachable
  )
)`, { "": { returnNull, returnMultiNullReg, returnMultiNullStack } }).exports;
assertErrorMessage(() => runNull(), TypeError, /cannot pass null to non-nullable/);
assertErrorMessage(() => runMultiNullReg(), TypeError, /cannot pass null to non-nullable/);
assertErrorMessage(() => runMultiNullStack(), TypeError, /cannot pass null to non-nullable/);

{
  // can have non-nullable globals
  wasmEvalText(`(module
    (func $f)
    (elem declare func $f)
    (global (ref func) ref.func $f)
  )`);
}

// cannot have non-nullable tables without initializer
wasmFailValidateText(`(module
  (table (ref extern) (elem))
)`, /table with non-nullable references requires initializer/);

// Testing internal wasmLosslessInvoke to pass non-nullable as params and arguments.
let {t} = wasmEvalText(`(module
  (func (export "t") (param (ref extern)) (result (ref extern))
    (local (ref extern))
    (local.set 1 (local.get 0))
    (local.get 1)
  )
)`).exports;
const ret = wasmLosslessInvoke(t, {test: 1});
assertEq(ret.value.test, 1);