polyfill.js (4451B)
1 // Generate some helper functions for manipulating (array (mut i16)) from JS 2 let helperExports; 3 { 4 const builder = new WasmModuleBuilder(); 5 const arrayIndex = builder.addArray(kWasmI16, true, kNoSuperType, true); 6 7 builder 8 .addFunction("createArrayMutI16", { 9 params: [kWasmI32], 10 results: [kWasmAnyRef] 11 }) 12 .addBody([ 13 kExprLocalGet, 14 ...wasmSignedLeb(0), 15 ...GCInstr(kExprArrayNewDefault), 16 ...wasmSignedLeb(arrayIndex) 17 ]) 18 .exportFunc(); 19 20 builder 21 .addFunction("arrayLength", { 22 params: [kWasmArrayRef], 23 results: [kWasmI32] 24 }) 25 .addBody([ 26 kExprLocalGet, 27 ...wasmSignedLeb(0), 28 ...GCInstr(kExprArrayLen) 29 ]) 30 .exportFunc(); 31 32 builder 33 .addFunction("arraySet", { 34 params: [wasmRefNullType(arrayIndex), kWasmI32, kWasmI32], 35 results: [] 36 }) 37 .addBody([ 38 kExprLocalGet, 39 ...wasmSignedLeb(0), 40 kExprLocalGet, 41 ...wasmSignedLeb(1), 42 kExprLocalGet, 43 ...wasmSignedLeb(2), 44 ...GCInstr(kExprArraySet), 45 ...wasmSignedLeb(arrayIndex) 46 ]) 47 .exportFunc(); 48 49 builder 50 .addFunction("arrayGet", { 51 params: [wasmRefNullType(arrayIndex), kWasmI32], 52 results: [kWasmI32] 53 }) 54 .addBody([ 55 kExprLocalGet, 56 ...wasmSignedLeb(0), 57 kExprLocalGet, 58 ...wasmSignedLeb(1), 59 ...GCInstr(kExprArrayGetU), 60 ...wasmSignedLeb(arrayIndex) 61 ]) 62 .exportFunc(); 63 64 let bytes = builder.toBuffer(); 65 let module = new WebAssembly.Module(bytes); 66 let instance = new WebAssembly.Instance(module); 67 68 helperExports = instance.exports; 69 } 70 71 function throwIfNotString(a) { 72 if (typeof a !== "string") { 73 throw new WebAssembly.RuntimeError(); 74 } 75 } 76 77 this.polyfillImports = { 78 test: (string) => { 79 if (string === null || 80 typeof string !== "string") { 81 return 0; 82 } 83 return 1; 84 }, 85 cast: (string) => { 86 throwIfNotString(string); 87 return string; 88 }, 89 fromCharCodeArray: (array, arrayStart, arrayCount) => { 90 arrayStart >>>= 0; 91 arrayCount >>>= 0; 92 let length = helperExports.arrayLength(array); 93 if (BigInt(arrayStart) + BigInt(arrayCount) > BigInt(length)) { 94 throw new WebAssembly.RuntimeError(); 95 } 96 let result = ''; 97 for (let i = arrayStart; i < arrayStart + arrayCount; i++) { 98 result += String.fromCharCode(helperExports.arrayGet(array, i)); 99 } 100 return result; 101 }, 102 intoCharCodeArray: (string, arr, arrayStart) => { 103 arrayStart >>>= 0; 104 throwIfNotString(string); 105 let arrLength = helperExports.arrayLength(arr); 106 let stringLength = string.length; 107 if (BigInt(arrayStart) + BigInt(stringLength) > BigInt(arrLength)) { 108 throw new WebAssembly.RuntimeError(); 109 } 110 for (let i = 0; i < stringLength; i++) { 111 helperExports.arraySet(arr, arrayStart + i, string[i].charCodeAt(0)); 112 } 113 return stringLength; 114 }, 115 fromCharCode: (charCode) => { 116 charCode >>>= 0; 117 return String.fromCharCode(charCode); 118 }, 119 fromCodePoint: (codePoint) => { 120 codePoint >>>= 0; 121 return String.fromCodePoint(codePoint); 122 }, 123 charCodeAt: (string, stringIndex) => { 124 stringIndex >>>= 0; 125 throwIfNotString(string); 126 if (stringIndex >= string.length) 127 throw new WebAssembly.RuntimeError(); 128 return string.charCodeAt(stringIndex); 129 }, 130 codePointAt: (string, stringIndex) => { 131 stringIndex >>>= 0; 132 throwIfNotString(string); 133 if (stringIndex >= string.length) 134 throw new WebAssembly.RuntimeError(); 135 return string.codePointAt(stringIndex); 136 }, 137 length: (string) => { 138 throwIfNotString(string); 139 return string.length; 140 }, 141 concat: (stringA, stringB) => { 142 throwIfNotString(stringA); 143 throwIfNotString(stringB); 144 return stringA + stringB; 145 }, 146 substring: (string, startIndex, endIndex) => { 147 startIndex >>>= 0; 148 endIndex >>>= 0; 149 throwIfNotString(string); 150 if (startIndex > string.length, 151 endIndex > string.length, 152 endIndex < startIndex) { 153 return ""; 154 } 155 return string.substring(startIndex, endIndex); 156 }, 157 equals: (stringA, stringB) => { 158 if (stringA !== null) throwIfNotString(stringA); 159 if (stringB !== null) throwIfNotString(stringB); 160 return stringA === stringB; 161 }, 162 compare: (stringA, stringB) => { 163 throwIfNotString(stringA); 164 throwIfNotString(stringB); 165 if (stringA < stringB) { 166 return -1; 167 } 168 return stringA === stringB ? 0 : 1; 169 }, 170 };