// META: global=window,dedicatedworker,jsshell test(() => { const thisValues = [ undefined, null, true, "", Symbol(), 1, {}, WebAssembly.Global, WebAssembly.Global.prototype, ]; const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value"); assert_equals(typeof desc, "object"); const getter = desc.get; assert_equals(typeof getter, "function"); const setter = desc.set; assert_equals(typeof setter, "function"); for (const thisValue of thisValues) { assert_throws_js(TypeError, () => getter.call(thisValue), `getter with this=${format_value(thisValue)}`); assert_throws_js(TypeError, () => setter.call(thisValue, 1), `setter with this=${format_value(thisValue)}`); } }, "Branding"); for (const type of ["i32", "i64", "f32", "f64"]) { const [initial, value, invalid] = type === "i64" ? [0n, 1n, 2] : [0, 1, 2n]; const immutableOptions = [ [{}, "missing"], [{ "mutable": undefined }, "undefined"], [{ "mutable": null }, "null"], [{ "mutable": false }, "false"], [{ "mutable": "" }, "empty string"], [{ "mutable": 0 }, "zero"], ]; for (const [opts, name] of immutableOptions) { test(() => { opts.value = type; const global = new WebAssembly.Global(opts); assert_equals(global.value, initial, "initial value"); assert_equals(global.valueOf(), initial, "initial valueOf"); assert_throws_js(TypeError, () => global.value = value); assert_equals(global.value, initial, "post-set value"); assert_equals(global.valueOf(), initial, "post-set valueOf"); }, `Immutable ${type} (${name})`); test(t => { opts.value = type; const global = new WebAssembly.Global(opts); assert_equals(global.value, initial, "initial value"); assert_equals(global.valueOf(), initial, "initial valueOf"); const value = { valueOf: t.unreached_func("should not call valueOf"), toString: t.unreached_func("should not call toString"), }; assert_throws_js(TypeError, () => global.value = value); assert_equals(global.value, initial, "post-set value"); assert_equals(global.valueOf(), initial, "post-set valueOf"); }, `Immutable ${type} with ToNumber side-effects (${name})`); } const mutableOptions = [ [{ "mutable": true }, "true"], [{ "mutable": 1 }, "one"], [{ "mutable": "x" }, "string"], [Object.create({ "mutable": true }), "true on prototype"], ]; for (const [opts, name] of mutableOptions) { test(() => { opts.value = type; const global = new WebAssembly.Global(opts); assert_equals(global.value, initial, "initial value"); assert_equals(global.valueOf(), initial, "initial valueOf"); global.value = value; assert_throws_js(TypeError, () => global.value = invalid); assert_equals(global.value, value, "post-set value"); assert_equals(global.valueOf(), value, "post-set valueOf"); }, `Mutable ${type} (${name})`); } } test(() => { const argument = { "value": "i64", "mutable": true }; const global = new WebAssembly.Global(argument); assert_equals(global.value, 0n, "initial value using ToJSValue"); const valid = [ [123n, 123n], [2n ** 63n, - (2n ** 63n)], [true, 1n], [false, 0n], ["456", 456n], ]; for (const [input, output] of valid) { global.value = input; assert_equals(global.valueOf(), output, "post-set valueOf"); } const invalid = [ undefined, null, 0, 1, 4.2, Symbol(), ]; for (const input of invalid) { assert_throws_js(TypeError, () => global.value = input); } }, "i64 mutability"); test(() => { const argument = { "value": "i32", "mutable": true }; const global = new WebAssembly.Global(argument); const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value"); assert_equals(typeof desc, "object"); const setter = desc.set; assert_equals(typeof setter, "function"); assert_throws_js(TypeError, () => setter.call(global)); }, "Calling setter without argument"); test(() => { const argument = { "value": "i32", "mutable": true }; const global = new WebAssembly.Global(argument); const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value"); assert_equals(typeof desc, "object"); const getter = desc.get; assert_equals(typeof getter, "function"); const setter = desc.set; assert_equals(typeof setter, "function"); assert_equals(getter.call(global, {}), 0); assert_equals(setter.call(global, 1, {}), undefined); assert_equals(global.value, 1); }, "Stray argument");