// Generate some helper functions for manipulating (array (mut i16)) from JS let helperExports; { const builder = new WasmModuleBuilder(); const arrayIndex = builder.addArray(kWasmI16, true, kNoSuperType, true); builder .addFunction("createArrayMutI16", { params: [kWasmI32], results: [kWasmAnyRef] }) .addBody([ kExprLocalGet, ...wasmSignedLeb(0), ...GCInstr(kExprArrayNewDefault), ...wasmSignedLeb(arrayIndex) ]) .exportFunc(); builder .addFunction("arrayLength", { params: [kWasmArrayRef], results: [kWasmI32] }) .addBody([ kExprLocalGet, ...wasmSignedLeb(0), ...GCInstr(kExprArrayLen) ]) .exportFunc(); builder .addFunction("arraySet", { params: [wasmRefNullType(arrayIndex), kWasmI32, kWasmI32], results: [] }) .addBody([ kExprLocalGet, ...wasmSignedLeb(0), kExprLocalGet, ...wasmSignedLeb(1), kExprLocalGet, ...wasmSignedLeb(2), ...GCInstr(kExprArraySet), ...wasmSignedLeb(arrayIndex) ]) .exportFunc(); builder .addFunction("arrayGet", { params: [wasmRefNullType(arrayIndex), kWasmI32], results: [kWasmI32] }) .addBody([ kExprLocalGet, ...wasmSignedLeb(0), kExprLocalGet, ...wasmSignedLeb(1), ...GCInstr(kExprArrayGetU), ...wasmSignedLeb(arrayIndex) ]) .exportFunc(); let bytes = builder.toBuffer(); let module = new WebAssembly.Module(bytes); let instance = new WebAssembly.Instance(module); helperExports = instance.exports; } function throwIfNotString(a) { if (typeof a !== "string") { throw new WebAssembly.RuntimeError(); } } this.polyfillImports = { test: (string) => { if (string === null || typeof string !== "string") { return 0; } return 1; }, cast: (string) => { throwIfNotString(string); return string; }, fromCharCodeArray: (array, arrayStart, arrayCount) => { arrayStart >>>= 0; arrayCount >>>= 0; let length = helperExports.arrayLength(array); if (BigInt(arrayStart) + BigInt(arrayCount) > BigInt(length)) { throw new WebAssembly.RuntimeError(); } let result = ''; for (let i = arrayStart; i < arrayStart + arrayCount; i++) { result += String.fromCharCode(helperExports.arrayGet(array, i)); } return result; }, intoCharCodeArray: (string, arr, arrayStart) => { arrayStart >>>= 0; throwIfNotString(string); let arrLength = helperExports.arrayLength(arr); let stringLength = string.length; if (BigInt(arrayStart) + BigInt(stringLength) > BigInt(arrLength)) { throw new WebAssembly.RuntimeError(); } for (let i = 0; i < stringLength; i++) { helperExports.arraySet(arr, arrayStart + i, string[i].charCodeAt(0)); } return stringLength; }, fromCharCode: (charCode) => { charCode >>>= 0; return String.fromCharCode(charCode); }, fromCodePoint: (codePoint) => { codePoint >>>= 0; return String.fromCodePoint(codePoint); }, charCodeAt: (string, stringIndex) => { stringIndex >>>= 0; throwIfNotString(string); if (stringIndex >= string.length) throw new WebAssembly.RuntimeError(); return string.charCodeAt(stringIndex); }, codePointAt: (string, stringIndex) => { stringIndex >>>= 0; throwIfNotString(string); if (stringIndex >= string.length) throw new WebAssembly.RuntimeError(); return string.codePointAt(stringIndex); }, length: (string) => { throwIfNotString(string); return string.length; }, concat: (stringA, stringB) => { throwIfNotString(stringA); throwIfNotString(stringB); return stringA + stringB; }, substring: (string, startIndex, endIndex) => { startIndex >>>= 0; endIndex >>>= 0; throwIfNotString(string); if (startIndex > string.length, endIndex > string.length, endIndex < startIndex) { return ""; } return string.substring(startIndex, endIndex); }, equals: (stringA, stringB) => { if (stringA !== null) throwIfNotString(stringA); if (stringB !== null) throwIfNotString(stringB); return stringA === stringB; }, compare: (stringA, stringB) => { throwIfNotString(stringA); throwIfNotString(stringB); if (stringA < stringB) { return -1; } return stringA === stringB ? 0 : 1; }, };