jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 1 | import * as assert from '../assert.js'; |
| 2 | import * as utilities from '../utilities.js'; |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 3 | |
jfbastien@apple.com | 5d26c89 | 2017-02-23 21:36:13 +0000 | [diff] [blame] | 4 | const version = 0x01; |
jfbastien@apple.com | c498854 | 2016-10-27 02:18:51 +0000 | [diff] [blame] | 5 | const emptyModuleArray = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, version, 0x00, 0x00, 0x00); |
| 6 | const invalidConstructorInputs = [undefined, null, "", 1, {}, []]; |
| 7 | const invalidInstanceImports = [null, "", 1]; |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 8 | |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 9 | const checkOwnPropertyDescriptor = (obj, prop, expect) => { |
| 10 | const descriptor = Object.getOwnPropertyDescriptor(obj, prop); |
| 11 | assert.eq(typeof descriptor.value, expect.typeofvalue); |
| 12 | assert.eq(descriptor.writable, expect.writable); |
| 13 | assert.eq(descriptor.configurable, expect.configurable); |
| 14 | assert.eq(descriptor.enumerable, expect.enumerable); |
| 15 | }; |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 16 | |
jfbastien@apple.com | 71d1e86 | 2017-05-19 05:27:28 +0000 | [diff] [blame] | 17 | const checkAccessorOwnPropertyDescriptor = (obj, prop, expect) => { |
| 18 | const descriptor = Object.getOwnPropertyDescriptor(obj, prop); |
| 19 | assert.eq(typeof descriptor.value, "undefined"); |
| 20 | assert.eq(typeof descriptor.writable, "undefined"); |
| 21 | assert.eq(descriptor.configurable, expect.configurable); |
| 22 | assert.eq(descriptor.enumerable, expect.enumerable); |
| 23 | }; |
| 24 | |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 25 | const functionProperties = { |
| 26 | "validate": { length: 1 }, |
| 27 | "compile": { length: 1 }, |
| 28 | }; |
| 29 | const constructorProperties = { |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 30 | "Module": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
| 31 | "Instance": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
| 32 | "Memory": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
| 33 | "Table": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
| 34 | "CompileError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
jfbastien@apple.com | 5d2a7e3 | 2016-12-20 20:20:05 +0000 | [diff] [blame] | 35 | "LinkError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 36 | "RuntimeError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 }, |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 37 | }; |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 38 | |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 39 | |
jfbastien@apple.com | 97a32c1 | 2016-11-04 22:12:12 +0000 | [diff] [blame] | 40 | assert.isNotUndef(WebAssembly); |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 41 | checkOwnPropertyDescriptor(utilities.global, "WebAssembly", { typeofvalue: "object", writable: true, configurable: true, enumerable: false }); |
| 42 | assert.eq(String(WebAssembly), "[object WebAssembly]"); |
| 43 | assert.isUndef(WebAssembly.length); |
jfbastien@apple.com | e7640f3 | 2016-10-21 01:19:24 +0000 | [diff] [blame] | 44 | assert.eq(WebAssembly instanceof Object, true); |
| 45 | assert.throws(() => WebAssembly(), TypeError, `WebAssembly is not a function. (In 'WebAssembly()', 'WebAssembly' is an instance of WebAssembly)`); |
| 46 | assert.throws(() => new WebAssembly(), TypeError, `WebAssembly is not a constructor (evaluating 'new WebAssembly()')`); |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 47 | |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 48 | for (const f in functionProperties) { |
jfbastien@apple.com | 97a32c1 | 2016-11-04 22:12:12 +0000 | [diff] [blame] | 49 | assert.isNotUndef(WebAssembly[f]); |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 50 | assert.eq(WebAssembly[f].name, f); |
| 51 | assert.eq(WebAssembly[f].length, functionProperties[f].length); |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 52 | } |
| 53 | |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 54 | for (const c in constructorProperties) { |
jfbastien@apple.com | 97a32c1 | 2016-11-04 22:12:12 +0000 | [diff] [blame] | 55 | assert.isNotUndef(WebAssembly[c]); |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 56 | assert.eq(WebAssembly[c].name, c); |
| 57 | assert.eq(WebAssembly[c].length, constructorProperties[c].length); |
| 58 | checkOwnPropertyDescriptor(WebAssembly, c, constructorProperties[c]); |
jfbastien@apple.com | 2872147 | 2016-10-19 22:11:11 +0000 | [diff] [blame] | 59 | checkOwnPropertyDescriptor(WebAssembly[c], "prototype", { typeofvalue: "object", writable: false, configurable: false, enumerable: false }); |
jfbastien@apple.com | 7172d5d | 2017-03-22 17:52:55 +0000 | [diff] [blame] | 60 | if (["CompileError", "LinkError", "RuntimeError"].indexOf(c) >= 0) |
| 61 | WebAssembly[c](); // Per spec, the WebAssembly.*Error types match ye olden JavaScript NativeError behavior: they can be constructed without `new`. |
| 62 | else |
| 63 | assert.throws(() => WebAssembly[c](), TypeError, `calling WebAssembly.${c} constructor without new is invalid`); |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 64 | switch (c) { |
| 65 | case "Module": |
jfbastien@apple.com | c498854 | 2016-10-27 02:18:51 +0000 | [diff] [blame] | 66 | for (const invalid of invalidConstructorInputs) |
sbarati@apple.com | 7fbb1b2 | 2016-12-19 07:22:42 +0000 | [diff] [blame] | 67 | assert.throws(() => new WebAssembly[c](invalid), TypeError, `first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'new WebAssembly[c](invalid)')`); |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 68 | for (const buffer of [new ArrayBuffer(), new DataView(new ArrayBuffer()), new Int8Array(), new Uint8Array(), new Uint8ClampedArray(), new Int16Array(), new Uint16Array(), new Int32Array(), new Uint32Array(), new Float32Array(), new Float64Array()]) |
| 69 | // FIXME the following should be WebAssembly.CompileError. https://bugs.webkit.org/show_bug.cgi?id=163768 |
yusukesuzuki@slowstart.org | 184dd1f | 2018-08-28 06:38:29 +0000 | [diff] [blame] | 70 | assert.throws(() => new WebAssembly[c](buffer), Error, `WebAssembly.Module doesn't parse at byte 0: expected a module of at least 8 bytes (evaluating 'new WebAssembly[c](buffer)')`); |
jfbastien@apple.com | c498854 | 2016-10-27 02:18:51 +0000 | [diff] [blame] | 71 | assert.instanceof(new WebAssembly[c](emptyModuleArray), WebAssembly.Module); |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 72 | break; |
| 73 | case "Instance": |
jfbastien@apple.com | c498854 | 2016-10-27 02:18:51 +0000 | [diff] [blame] | 74 | for (const invalid of invalidConstructorInputs) |
| 75 | assert.throws(() => new WebAssembly[c](invalid), TypeError, `first argument to WebAssembly.Instance must be a WebAssembly.Module (evaluating 'new WebAssembly[c](invalid)')`); |
| 76 | const instance = new WebAssembly[c](new WebAssembly.Module(emptyModuleArray)); |
| 77 | assert.instanceof(instance, WebAssembly.Instance); |
| 78 | for (const invalid of invalidInstanceImports) |
| 79 | assert.throws(() => new WebAssembly[c](new WebAssembly.Module(emptyModuleArray), invalid), TypeError, `second argument to WebAssembly.Instance must be undefined or an Object (evaluating 'new WebAssembly[c](new WebAssembly.Module(emptyModuleArray), invalid)')`); |
jfbastien@apple.com | 97a32c1 | 2016-11-04 22:12:12 +0000 | [diff] [blame] | 80 | assert.isNotUndef(instance.exports); |
ysuzuki@apple.com | 3640d4e | 2019-07-15 22:41:54 +0000 | [diff] [blame] | 81 | checkAccessorOwnPropertyDescriptor(WebAssembly.Instance.prototype, "exports", { configurable: true, enumerable: true }); |
jfbastien@apple.com | 71d1e86 | 2017-05-19 05:27:28 +0000 | [diff] [blame] | 82 | assert.throws(() => WebAssembly.Instance.prototype.exports = undefined, TypeError, `Attempted to assign to readonly property.`); |
| 83 | assert.throws(() => WebAssembly.Instance.prototype.exports, TypeError, `expected |this| value to be an instance of WebAssembly.Instance`); |
jfbastien@apple.com | 0a1b73d | 2017-03-22 17:54:36 +0000 | [diff] [blame] | 84 | assert.isUndef(instance.exports.__proto__); |
| 85 | assert.eq(Reflect.isExtensible(instance.exports), false); |
| 86 | assert.eq(Symbol.iterator in instance.exports, false); |
| 87 | assert.eq(Symbol.toStringTag in instance.exports, true); |
| 88 | assert.eq(Object.getOwnPropertySymbols(instance.exports).length, 1); |
| 89 | assert.eq(Object.getOwnPropertySymbols(instance.exports)[0], Symbol.toStringTag); |
| 90 | assert.throws(() => instance.exports[Symbol.toStringTag] = 42, TypeError, `Attempted to assign to readonly property.`); |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 91 | break; |
| 92 | case "Memory": |
sbarati@apple.com | 73916bb | 2016-12-09 22:38:39 +0000 | [diff] [blame] | 93 | new WebAssembly.Memory({initial: 20}); |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 94 | break; |
| 95 | case "Table": |
justin_michaud@apple.com | 4453412 | 2019-06-19 15:36:46 +0000 | [diff] [blame] | 96 | new WebAssembly.Table({initial: 20, element: "funcref"}); |
| 97 | new WebAssembly.Table({initial: 20, maximum: 20, element: "funcref"}); |
| 98 | new WebAssembly.Table({initial: 20, maximum: 25, element: "funcref"}); |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 99 | break; |
| 100 | case "CompileError": |
jfbastien@apple.com | 5d2a7e3 | 2016-12-20 20:20:05 +0000 | [diff] [blame] | 101 | case "LinkError": |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 102 | case "RuntimeError": { |
jfbastien@apple.com | 7172d5d | 2017-03-22 17:52:55 +0000 | [diff] [blame] | 103 | { |
| 104 | const e = new WebAssembly[c]; |
| 105 | assert.eq(e instanceof WebAssembly[c], true); |
| 106 | assert.eq(e instanceof Error, true); |
| 107 | assert.eq(e instanceof TypeError, false); |
| 108 | assert.eq(e.message, ""); |
| 109 | assert.eq(typeof e.stack, "string"); |
| 110 | const sillyString = "uh-oh!"; |
| 111 | const e2 = new WebAssembly[c](sillyString); |
| 112 | assert.eq(e2.message, sillyString + " (evaluating 'new WebAssembly[c](sillyString)')"); |
| 113 | } |
| 114 | { |
| 115 | const e = WebAssembly[c](); |
| 116 | assert.eq(e instanceof WebAssembly[c], true); |
| 117 | assert.eq(e instanceof Error, true); |
| 118 | assert.eq(e instanceof TypeError, false); |
| 119 | assert.eq(e.message, ""); |
| 120 | assert.eq(typeof e.stack, "string"); |
| 121 | const sillyString = "uh-oh!"; |
| 122 | const e2 = WebAssembly[c](sillyString); |
| 123 | assert.eq(e2.message, sillyString); |
| 124 | } |
jfbastien@apple.com | 7e51cf3 | 2016-10-25 17:23:53 +0000 | [diff] [blame] | 125 | } break; |
| 126 | default: throw new Error(`Implementation error: unexpected constructor property "${c}"`); |
jfbastien@apple.com | e7640f3 | 2016-10-21 01:19:24 +0000 | [diff] [blame] | 127 | } |
jfbastien@apple.com | d2c6b7a | 2016-10-17 21:36:05 +0000 | [diff] [blame] | 128 | } |