170 lines
4.3 KiB
JavaScript
170 lines
4.3 KiB
JavaScript
// 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;
|
|
},
|
|
};
|