summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/ref-types/funcref.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/jit-test/tests/wasm/ref-types/funcref.js
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/wasm/ref-types/funcref.js')
-rw-r--r--js/src/jit-test/tests/wasm/ref-types/funcref.js135
1 files changed, 135 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/ref-types/funcref.js b/js/src/jit-test/tests/wasm/ref-types/funcref.js
new file mode 100644
index 0000000000..21ce95c0cb
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/ref-types/funcref.js
@@ -0,0 +1,135 @@
+const {Module,Instance,Global,RuntimeError} = WebAssembly;
+
+const badWasmFunc = /can only pass WebAssembly exported functions to funcref/;
+const typeErr = /type mismatch/;
+
+
+// Validation:
+
+wasmFailValidateText(`(module (func (local externref funcref) (local.set 0 (local.get 1))))`, typeErr);
+wasmEvalText(`(module (func (local funcref funcref) (local.set 0 (local.get 1))))`);
+wasmEvalText(`(module (func (local funcref) (local.set 0 (ref.null func))))`);
+wasmFailValidateText(`(module (func (local funcref externref) (local.set 0 (local.get 1))))`, typeErr);
+wasmEvalText(`(module (global (mut funcref) (ref.null func)) (func (param funcref) (global.set 0 (local.get 0))))`);
+wasmFailValidateText(`(module (global (mut externref) (ref.null extern)) (func (param funcref) (global.set 0 (local.get 0))))`, typeErr);
+wasmFailValidateText(`(module (global (mut funcref) (ref.null func)) (func (param externref) (global.set 0 (local.get 0))))`, typeErr);
+wasmEvalText(`(module (func (param funcref)) (func (param funcref) (call 0 (local.get 0))))`);
+wasmFailValidateText(`(module (func (param externref)) (func (param funcref) (call 0 (local.get 0))))`, typeErr);
+wasmFailValidateText(`(module (func (param funcref)) (func (param externref) (call 0 (local.get 0))))`, typeErr);
+wasmEvalText(`(module (func (param funcref) (result funcref) (block (result funcref) (local.get 0) (br 0))))`);
+wasmFailValidateText(`(module (func (param funcref) (result externref) (block (result externref) (local.get 0) (br 0))))`, typeErr);
+wasmFailValidateText(`(module (func (param externref) (result externref) (block (result funcref) (local.get 0) (br 0))))`, typeErr);
+wasmEvalText(`(module (func (param funcref funcref) (result funcref) (select (result funcref) (local.get 0) (local.get 1) (i32.const 0))))`);
+wasmFailValidateText(`(module (func (param externref funcref) (result externref) (select (result externref) (local.get 0) (local.get 1) (i32.const 0))))`, typeErr);
+wasmFailValidateText(`(module (func (param funcref externref) (result externref) (select (result externref)(local.get 0) (local.get 1) (i32.const 0))))`, typeErr);
+wasmFailValidateText(`(module (func (param externref funcref) (result funcref) (select (result funcref) (local.get 0) (local.get 1) (i32.const 0))))`, typeErr);
+wasmFailValidateText(`(module (func (param funcref externref) (result funcref) (select (result funcref) (local.get 0) (local.get 1) (i32.const 0))))`, typeErr);
+
+
+// Runtime:
+
+var m = new Module(wasmTextToBinary(`(module (func (export "wasmFun")))`));
+const wasmFun1 = new Instance(m).exports.wasmFun;
+const wasmFun2 = new Instance(m).exports.wasmFun;
+const wasmFun3 = new Instance(m).exports.wasmFun;
+
+var run = wasmEvalText(`(module
+ (global (mut funcref) (ref.null func))
+ (func (param $x funcref) (param $test i32) (result funcref)
+ local.get $x
+ global.get 0
+ local.get $test
+ select (result funcref)
+ )
+ (func (export "run") (param $a funcref) (param $b funcref) (param $c funcref) (param $test1 i32) (param $test2 i32) (result funcref)
+ local.get $a
+ global.set 0
+ block (result funcref)
+ local.get $b
+ local.get $test1
+ br_if 0
+ drop
+ local.get $c
+ end
+ local.get $test2
+ call 0
+ )
+)`).exports.run;
+assertEq(run(wasmFun1, wasmFun2, wasmFun3, false, false), wasmFun1);
+assertEq(run(wasmFun1, wasmFun2, wasmFun3, true, false), wasmFun1);
+assertEq(run(wasmFun1, wasmFun2, wasmFun3, true, true), wasmFun2);
+assertEq(run(wasmFun1, wasmFun2, wasmFun3, false, true), wasmFun3);
+
+var run = wasmEvalText(`(module
+ (type $t0 (func (param externref) (result externref)))
+ (type $t1 (func (param funcref) (result externref)))
+ (type $t2 (func (param funcref funcref) (result externref)))
+ (func $f0 (type $t0) ref.null extern)
+ (func $f1 (type $t1) ref.null extern)
+ (func $f2 (type $t2) ref.null extern)
+ (table funcref (elem $f0 $f1 $f2))
+ (func (export "run") (param i32 i32) (result externref)
+ block $b2 block $b1 block $b0
+ local.get 0
+ br_table $b0 $b1 $b2
+ end $b0
+ ref.null extern
+ local.get 1
+ call_indirect (type $t0)
+ return
+ end $b1
+ ref.null func
+ local.get 1
+ call_indirect (type $t1)
+ return
+ end $b2
+ ref.null func
+ ref.null func
+ local.get 1
+ call_indirect (type $t2)
+ return
+ )
+)`).exports.run;
+
+for (var i = 0; i < 3; i++) {
+ for (var j = 0; j < 3; j++) {
+ if (i == j)
+ assertEq(run(i, j), null);
+ else
+ assertErrorMessage(() => run(i, j), RuntimeError, /indirect call signature mismatch/);
+ }
+}
+
+
+// JS API:
+
+const wasmFun = wasmEvalText(`(module (func (export "x")))`).exports.x;
+
+var run = wasmEvalText(`(module (func (export "run") (param funcref) (result funcref) (local.get 0)))`).exports.run;
+assertEq(run(wasmFun), wasmFun);
+assertEq(run(null), null);
+assertErrorMessage(() => run(() => {}), TypeError, badWasmFunc);
+
+var importReturnValue;
+var importFun = () => importReturnValue;
+var run = wasmEvalText(`(module (func (import "" "i") (result funcref)) (func (export "run") (result funcref) (call 0)))`, {'':{i:importFun}}).exports.run;
+importReturnValue = wasmFun;
+assertEq(run(), wasmFun);
+importReturnValue = null;
+assertEq(run(), null);
+importReturnValue = undefined;
+assertErrorMessage(() => run(), TypeError, badWasmFunc);
+importReturnValue = () => {};
+assertErrorMessage(() => run(), TypeError, badWasmFunc);
+
+var g = new Global({value:'anyfunc', mutable:true}, wasmFun);
+assertEq(g.value, wasmFun);
+g.value = null;
+assertEq(g.value, null);
+Math.sin();
+assertErrorMessage(() => g.value = () => {}, TypeError, badWasmFunc);
+var g = new Global({value:'anyfunc', mutable:true}, null);
+assertEq(g.value, null);
+g.value = wasmFun;
+assertEq(g.value, wasmFun);
+assertErrorMessage(() => new Global({value:'anyfunc'}, () => {}), TypeError, badWasmFunc);