summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/globals.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/globals.js')
-rw-r--r--js/src/jit-test/tests/wasm/globals.js248
1 files changed, 248 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/globals.js b/js/src/jit-test/tests/wasm/globals.js
new file mode 100644
index 000000000..1d37d0d38
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/globals.js
@@ -0,0 +1,248 @@
+load(libdir + "wasm.js");
+
+const { Instance, Module } = WebAssembly;
+
+// Locally-defined globals
+assertErrorMessage(() => wasmEvalText(`(module (global))`), SyntaxError, /parsing/);
+assertErrorMessage(() => wasmEvalText(`(module (global i32))`), SyntaxError, /parsing/);
+assertErrorMessage(() => wasmEvalText(`(module (global (mut i32)))`), SyntaxError, /parsing/);
+
+// Initializer expressions.
+wasmFailValidateText(`(module (global i32 (f32.const 13.37)))`, /type mismatch/);
+wasmFailValidateText(`(module (global f64 (f32.const 13.37)))`, /type mismatch/);
+wasmFailValidateText(`(module (global i32 (i32.add (i32.const 13) (i32.const 37))))`, /failed to read end/);
+
+wasmFailValidateText(`(module (global i32 (get_global 0)))`, /out of range/);
+wasmFailValidateText(`(module (global i32 (get_global 1)) (global i32 (i32.const 1)))`, /out of range/);
+
+// Test a well-defined global section.
+function testInner(type, initialValue, nextValue, coercion, assertFunc = assertEq)
+{
+ var module = wasmEvalText(`(module
+ (global (mut ${type}) (${type}.const ${initialValue}))
+ (global ${type} (${type}.const ${initialValue}))
+
+ (func $get (result ${type}) (get_global 0))
+ (func $set (param ${type}) (set_global 0 (get_local 0)))
+
+ (func $get_cst (result ${type}) (get_global 1))
+
+ (export "get" $get)
+ (export "get_cst" $get_cst)
+
+ (export "set" $set)
+ )`).exports;
+
+ assertFunc(module.get(), coercion(initialValue));
+ assertEq(module.set(coercion(nextValue)), undefined);
+ assertFunc(module.get(), coercion(nextValue));
+
+ assertFunc(module.get_cst(), coercion(initialValue));
+}
+
+testInner('i32', 13, 37, x => x|0);
+testInner('f32', 13.37, 0.1989, Math.fround);
+testInner('f64', 13.37, 0.1989, x => +x);
+
+// Semantic errors.
+wasmFailValidateText(`(module (global (mut i32) (i32.const 1337)) (func (set_global 1 (i32.const 0))))`, /out of range/);
+wasmFailValidateText(`(module (global i32 (i32.const 1337)) (func (set_global 0 (i32.const 0))))`, /can't write an immutable global/);
+
+// Big module with many variables: test that setting one doesn't overwrite the
+// other ones.
+function get_set(i, type) {
+ return `
+ (func $get_${i} (result ${type}) (get_global ${i}))
+ (func $set_${i} (param ${type}) (set_global ${i} (get_local 0)))
+ `;
+}
+
+var module = wasmEvalText(`(module
+ (global (mut i32) (i32.const 42))
+ (global (mut i32) (i32.const 10))
+ (global (mut f32) (f32.const 13.37))
+ (global (mut f64) (f64.const 13.37))
+ (global (mut i32) (i32.const -18))
+
+ ${get_set(0, 'i32')}
+ ${get_set(1, 'i32')}
+ ${get_set(2, 'f32')}
+ ${get_set(3, 'f64')}
+ ${get_set(4, 'i32')}
+
+ (export "get0" $get_0) (export "set0" $set_0)
+ (export "get1" $get_1) (export "set1" $set_1)
+ (export "get2" $get_2) (export "set2" $set_2)
+ (export "get3" $get_3) (export "set3" $set_3)
+ (export "get4" $get_4) (export "set4" $set_4)
+)`).exports;
+
+let values = [42, 10, Math.fround(13.37), 13.37, -18];
+let nextValues = [13, 37, Math.fround(-17.89), 9.3, -13];
+for (let i = 0; i < 5; i++) {
+ assertEq(module[`get${i}`](), values[i]);
+ assertEq(module[`set${i}`](nextValues[i]), undefined);
+ assertEq(module[`get${i}`](), nextValues[i]);
+ for (let j = 0; j < 5; j++) {
+ if (i === j)
+ continue;
+ assertEq(module[`get${j}`](), values[j]);
+ }
+ assertEq(module[`set${i}`](values[i]), undefined);
+ assertEq(module[`get${i}`](), values[i]);
+}
+
+// Initializer expressions can also be used in elem section initializers.
+wasmFailValidateText(`(module (import "globals" "a" (global f32)) (table 4 anyfunc) (elem (get_global 0) $f) (func $f))`, /type mismatch/);
+
+module = wasmEvalText(`(module
+ (import "globals" "a" (global i32))
+ (table (export "tbl") 4 anyfunc)
+ (elem (get_global 0) $f)
+ (func $f)
+ (export "f" $f)
+)`, {
+ globals: {
+ a: 1
+ }
+}).exports;
+assertEq(module.f, module.tbl.get(1));
+
+// Import/export rules.
+wasmFailValidateText(`(module (import "globals" "x" (global (mut i32))))`, /can't import.* mutable globals in the MVP/);
+wasmFailValidateText(`(module (global (mut i32) (i32.const 42)) (export "" global 0))`, /can't .*export mutable globals in the MVP/);
+
+// Import/export semantics.
+module = wasmEvalText(`(module
+ (import $g "globals" "x" (global i32))
+ (func $get (result i32) (get_global $g))
+ (export "getter" $get)
+ (export "value" global 0)
+)`, { globals: {x: 42} }).exports;
+
+assertEq(module.getter(), 42);
+assertEq(module.value, 42);
+
+// Can only import numbers (no implicit coercions).
+module = new WebAssembly.Module(wasmTextToBinary(`(module
+ (global (import "globs" "i32") i32)
+ (global (import "globs" "f32") f32)
+ (global (import "globs" "f64") f32)
+)`));
+
+const assertLinkFails = (m, imp, err) => {
+ assertErrorMessage(() => new WebAssembly.Instance(m, imp), TypeError, err);
+}
+
+var imp = {
+ globs: {
+ i32: 0,
+ f32: Infinity,
+ f64: NaN
+ }
+};
+
+let i = new WebAssembly.Instance(module, imp);
+
+for (let v of [
+ null,
+ {},
+ "42",
+ /not a number/,
+ false,
+ undefined,
+ Symbol(),
+ { valueOf() { return 42; } }
+]) {
+ imp.globs.i32 = v;
+ assertLinkFails(module, imp, /not a number/);
+
+ imp.globs.i32 = 0;
+ imp.globs.f32 = v;
+ assertLinkFails(module, imp, /not a number/);
+
+ imp.globs.f32 = Math.fround(13.37);
+ imp.globs.f64 = v;
+ assertLinkFails(module, imp, /not a number/);
+
+ imp.globs.f64 = 13.37;
+}
+
+// Imported globals and locally defined globals use the same index space.
+module = wasmEvalText(`(module
+ (import "globals" "x" (global i32))
+ (global i32 (i32.const 1337))
+ (export "imported" global 0)
+ (export "defined" global 1)
+)`, { globals: {x: 42} }).exports;
+
+assertEq(module.imported, 42);
+assertEq(module.defined, 1337);
+
+// Initializer expressions can reference an imported immutable global.
+wasmFailValidateText(`(module (global f32 (f32.const 13.37)) (global i32 (get_global 0)))`, /must reference a global immutable import/);
+wasmFailValidateText(`(module (global (mut f32) (f32.const 13.37)) (global i32 (get_global 0)))`, /must reference a global immutable import/);
+wasmFailValidateText(`(module (global (mut i32) (i32.const 0)) (global i32 (get_global 0)))`, /must reference a global immutable import/);
+
+wasmFailValidateText(`(module (import "globals" "a" (global f32)) (global i32 (get_global 0)))`, /type mismatch/);
+
+function testInitExpr(type, initialValue, nextValue, coercion, assertFunc = assertEq) {
+ var module = wasmEvalText(`(module
+ (import "globals" "a" (global ${type}))
+
+ (global (mut ${type}) (get_global 0))
+ (global ${type} (get_global 0))
+
+ (func $get0 (result ${type}) (get_global 0))
+
+ (func $get1 (result ${type}) (get_global 1))
+ (func $set1 (param ${type}) (set_global 1 (get_local 0)))
+
+ (func $get_cst (result ${type}) (get_global 2))
+
+ (export "get0" $get0)
+ (export "get1" $get1)
+ (export "get_cst" $get_cst)
+
+ (export "set1" $set1)
+ )`, {
+ globals: {
+ a: coercion(initialValue)
+ }
+ }).exports;
+
+ assertFunc(module.get0(), coercion(initialValue));
+ assertFunc(module.get1(), coercion(initialValue));
+
+ assertEq(module.set1(coercion(nextValue)), undefined);
+ assertFunc(module.get1(), coercion(nextValue));
+ assertFunc(module.get0(), coercion(initialValue));
+
+ assertFunc(module.get_cst(), coercion(initialValue));
+}
+
+testInitExpr('i32', 13, 37, x => x|0);
+testInitExpr('f32', 13.37, 0.1989, Math.fround);
+testInitExpr('f64', 13.37, 0.1989, x => +x);
+
+// Int64.
+{
+ wasmFailValidateText(`(module (import "globals" "x" (global i64)))`, /can't import.* an Int64 global/);
+ wasmFailValidateText(`(module (global i64 (i64.const 42)) (export "" global 0))`, /can't .*export an Int64 global/);
+
+ setJitCompilerOption('wasm.test-mode', 1);
+ testInner('i64', '0x531642753864975F', '0x123456789abcdef0', createI64, assertEqI64);
+ testInitExpr('i64', '0x531642753864975F', '0x123456789abcdef0', createI64, assertEqI64);
+
+ module = wasmEvalText(`(module
+ (import "globals" "x" (global i64))
+ (global i64 (i64.const 0xFAFADADABABA))
+ (export "imported" global 0)
+ (export "defined" global 1)
+ )`, { globals: {x: createI64('0x1234567887654321')} }).exports;
+
+ assertEqI64(module.imported, createI64('0x1234567887654321'));
+ assertEqI64(module.defined, createI64('0xFAFADADABABA'));
+
+ setJitCompilerOption('wasm.test-mode', 0);
+}