| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- "use strict";
- // Runtime header offsets
- const ID_OFFSET = -8;
- const SIZE_OFFSET = -4;
- // Runtime ids
- const ARRAYBUFFER_ID = 0;
- const STRING_ID = 1;
- // const ARRAYBUFFERVIEW_ID = 2;
- // Runtime type information
- const ARRAYBUFFERVIEW = 1 << 0;
- const ARRAY = 1 << 1;
- const STATICARRAY = 1 << 2;
- // const SET = 1 << 3;
- // const MAP = 1 << 4;
- const VAL_ALIGN_OFFSET = 6;
- // const VAL_ALIGN = 1 << VAL_ALIGN_OFFSET;
- const VAL_SIGNED = 1 << 11;
- const VAL_FLOAT = 1 << 12;
- // const VAL_NULLABLE = 1 << 13;
- const VAL_MANAGED = 1 << 14;
- // const KEY_ALIGN_OFFSET = 15;
- // const KEY_ALIGN = 1 << KEY_ALIGN_OFFSET;
- // const KEY_SIGNED = 1 << 20;
- // const KEY_FLOAT = 1 << 21;
- // const KEY_NULLABLE = 1 << 22;
- // const KEY_MANAGED = 1 << 23;
- // Array(BufferView) layout
- const ARRAYBUFFERVIEW_BUFFER_OFFSET = 0;
- const ARRAYBUFFERVIEW_DATASTART_OFFSET = 4;
- const ARRAYBUFFERVIEW_DATALENGTH_OFFSET = 8;
- const ARRAYBUFFERVIEW_SIZE = 12;
- const ARRAY_LENGTH_OFFSET = 12;
- const ARRAY_SIZE = 16;
- const BIGINT = typeof BigUint64Array !== "undefined";
- const THIS = Symbol();
- const CHUNKSIZE = 1024;
- /** Gets a string from an U32 and an U16 view on a memory. */
- function getStringImpl(buffer, ptr) {
- const U32 = new Uint32Array(buffer);
- const U16 = new Uint16Array(buffer);
- let length = U32[(ptr + SIZE_OFFSET) >>> 2] >>> 1;
- let offset = ptr >>> 1;
- if (length <= CHUNKSIZE) return String.fromCharCode.apply(String, U16.subarray(offset, offset + length));
- const parts = [];
- do {
- const last = U16[offset + CHUNKSIZE - 1];
- const size = last >= 0xD800 && last < 0xDC00 ? CHUNKSIZE - 1 : CHUNKSIZE;
- parts.push(String.fromCharCode.apply(String, U16.subarray(offset, offset += size)));
- length -= size;
- } while (length > CHUNKSIZE);
- return parts.join("") + String.fromCharCode.apply(String, U16.subarray(offset, offset + length));
- }
- /** Prepares the base module prior to instantiation. */
- function preInstantiate(imports) {
- const extendedExports = {};
- function getString(memory, ptr) {
- if (!memory) return "<yet unknown>";
- return getStringImpl(memory.buffer, ptr);
- }
- // add common imports used by stdlib for convenience
- const env = (imports.env = imports.env || {});
- env.abort = env.abort || function abort(msg, file, line, colm) {
- const memory = extendedExports.memory || env.memory; // prefer exported, otherwise try imported
- throw Error("abort: " + getString(memory, msg) + " at " + getString(memory, file) + ":" + line + ":" + colm);
- };
- env.trace = env.trace || function trace(msg, n) {
- const memory = extendedExports.memory || env.memory;
- console.log("trace: " + getString(memory, msg) + (n ? " " : "") + Array.prototype.slice.call(arguments, 2, 2 + n).join(", "));
- };
- env.seed = env.seed || function seed() {
- return Date.now();
- };
- imports.Math = imports.Math || Math;
- imports.Date = imports.Date || Date;
- return extendedExports;
- }
- /** Prepares the final module once instantiation is complete. */
- function postInstantiate(extendedExports, instance) {
- const exports = instance.exports;
- const memory = exports.memory;
- const table = exports.table;
- const alloc = exports["__alloc"];
- const retain = exports["__retain"];
- const rttiBase = exports["__rtti_base"] || ~0; // oob if not present
- /** Gets the runtime type info for the given id. */
- function getInfo(id) {
- const U32 = new Uint32Array(memory.buffer);
- const count = U32[rttiBase >>> 2];
- if ((id >>>= 0) >= count) throw Error("invalid id: " + id);
- return U32[(rttiBase + 4 >>> 2) + id * 2];
- }
- /** Gets the runtime base id for the given id. */
- function getBase(id) {
- const U32 = new Uint32Array(memory.buffer);
- const count = U32[rttiBase >>> 2];
- if ((id >>>= 0) >= count) throw Error("invalid id: " + id);
- return U32[(rttiBase + 4 >>> 2) + id * 2 + 1];
- }
- /** Gets the runtime alignment of a collection's values. */
- function getValueAlign(info) {
- return 31 - Math.clz32((info >>> VAL_ALIGN_OFFSET) & 31); // -1 if none
- }
- /** Gets the runtime alignment of a collection's keys. */
- // function getKeyAlign(info) {
- // return 31 - Math.clz32((info >>> KEY_ALIGN_OFFSET) & 31); // -1 if none
- // }
- /** Allocates a new string in the module's memory and returns its retained pointer. */
- function __allocString(str) {
- const length = str.length;
- const ptr = alloc(length << 1, STRING_ID);
- const U16 = new Uint16Array(memory.buffer);
- for (var i = 0, p = ptr >>> 1; i < length; ++i) U16[p + i] = str.charCodeAt(i);
- return ptr;
- }
- extendedExports.__allocString = __allocString;
- /** Reads a string from the module's memory by its pointer. */
- function __getString(ptr) {
- const buffer = memory.buffer;
- const id = new Uint32Array(buffer)[ptr + ID_OFFSET >>> 2];
- if (id !== STRING_ID) throw Error("not a string: " + ptr);
- return getStringImpl(buffer, ptr);
- }
- extendedExports.__getString = __getString;
- /** Gets the view matching the specified alignment, signedness and floatness. */
- function getView(alignLog2, signed, float) {
- const buffer = memory.buffer;
- if (float) {
- switch (alignLog2) {
- case 2: return new Float32Array(buffer);
- case 3: return new Float64Array(buffer);
- }
- } else {
- switch (alignLog2) {
- case 0: return new (signed ? Int8Array : Uint8Array)(buffer);
- case 1: return new (signed ? Int16Array : Uint16Array)(buffer);
- case 2: return new (signed ? Int32Array : Uint32Array)(buffer);
- case 3: return new (signed ? BigInt64Array : BigUint64Array)(buffer);
- }
- }
- throw Error("unsupported align: " + alignLog2);
- }
- /** Allocates a new array in the module's memory and returns its retained pointer. */
- function __allocArray(id, values) {
- const info = getInfo(id);
- if (!(info & (ARRAYBUFFERVIEW | ARRAY | STATICARRAY))) throw Error("not an array: " + id + ", flags= " + info);
- const align = getValueAlign(info);
- const length = values.length;
- const buf = alloc(length << align, info & STATICARRAY ? id : ARRAYBUFFER_ID);
- let result;
- if (info & STATICARRAY) {
- result = buf;
- } else {
- const arr = alloc(info & ARRAY ? ARRAY_SIZE : ARRAYBUFFERVIEW_SIZE, id);
- const U32 = new Uint32Array(memory.buffer);
- U32[arr + ARRAYBUFFERVIEW_BUFFER_OFFSET >>> 2] = retain(buf);
- U32[arr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2] = buf;
- U32[arr + ARRAYBUFFERVIEW_DATALENGTH_OFFSET >>> 2] = length << align;
- if (info & ARRAY) U32[arr + ARRAY_LENGTH_OFFSET >>> 2] = length;
- result = arr;
- }
- const view = getView(align, info & VAL_SIGNED, info & VAL_FLOAT);
- if (info & VAL_MANAGED) {
- for (let i = 0; i < length; ++i) view[(buf >>> align) + i] = retain(values[i]);
- } else {
- view.set(values, buf >>> align);
- }
- return result;
- }
- extendedExports.__allocArray = __allocArray;
- /** Gets a live view on an array's values in the module's memory. Infers the array type from RTTI. */
- function __getArrayView(arr) {
- const U32 = new Uint32Array(memory.buffer);
- const id = U32[arr + ID_OFFSET >>> 2];
- const info = getInfo(id);
- if (!(info & (ARRAYBUFFERVIEW | ARRAY | STATICARRAY))) throw Error("not an array: " + id + ", flags=" + info);
- const align = getValueAlign(info);
- let buf = info & STATICARRAY
- ? arr
- : U32[arr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2];
- const length = info & ARRAY
- ? U32[arr + ARRAY_LENGTH_OFFSET >>> 2]
- : U32[buf + SIZE_OFFSET >>> 2] >>> align;
- return getView(align, info & VAL_SIGNED, info & VAL_FLOAT).subarray(buf >>>= align, buf + length);
- }
- extendedExports.__getArrayView = __getArrayView;
- /** Copies an array's values from the module's memory. Infers the array type from RTTI. */
- function __getArray(arr) {
- const input = __getArrayView(arr);
- const len = input.length;
- const out = new Array(len);
- for (let i = 0; i < len; i++) out[i] = input[i];
- return out;
- }
- extendedExports.__getArray = __getArray;
- /** Copies an ArrayBuffer's value from the module's memory. */
- function __getArrayBuffer(ptr) {
- const buffer = memory.buffer;
- const length = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2];
- return buffer.slice(ptr, ptr + length);
- }
- extendedExports.__getArrayBuffer = __getArrayBuffer;
- /** Copies a typed array's values from the module's memory. */
- function getTypedArray(Type, alignLog2, ptr) {
- return new Type(getTypedArrayView(Type, alignLog2, ptr));
- }
- /** Gets a live view on a typed array's values in the module's memory. */
- function getTypedArrayView(Type, alignLog2, ptr) {
- const buffer = memory.buffer;
- const U32 = new Uint32Array(buffer);
- const bufPtr = U32[ptr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2];
- return new Type(buffer, bufPtr, U32[bufPtr + SIZE_OFFSET >>> 2] >>> alignLog2);
- }
- /** Attach a set of get TypedArray and View functions to the exports. */
- function attachTypedArrayFunctions(ctor, name, align) {
- extendedExports["__get" + name] = getTypedArray.bind(null, ctor, align);
- extendedExports["__get" + name + "View"] = getTypedArrayView.bind(null, ctor, align);
- }
- [
- Int8Array,
- Uint8Array,
- Uint8ClampedArray,
- Int16Array,
- Uint16Array,
- Int32Array,
- Uint32Array,
- Float32Array,
- Float64Array
- ].forEach(ctor => {
- attachTypedArrayFunctions(ctor, ctor.name, 31 - Math.clz32(ctor.BYTES_PER_ELEMENT));
- });
- if (BIGINT) {
- [BigUint64Array, BigInt64Array].forEach(ctor => {
- attachTypedArrayFunctions(ctor, ctor.name.slice(3), 3);
- });
- }
- /** Tests whether an object is an instance of the class represented by the specified base id. */
- function __instanceof(ptr, baseId) {
- const U32 = new Uint32Array(memory.buffer);
- let id = U32[(ptr + ID_OFFSET) >>> 2];
- if (id <= U32[rttiBase >>> 2]) {
- do {
- if (id == baseId) return true;
- id = getBase(id);
- } while (id);
- }
- return false;
- }
- extendedExports.__instanceof = __instanceof;
- // Pull basic exports to extendedExports so code in preInstantiate can use them
- extendedExports.memory = extendedExports.memory || memory;
- extendedExports.table = extendedExports.table || table;
- // Demangle exports and provide the usual utility on the prototype
- return demangle(exports, extendedExports);
- }
- function isResponse(src) {
- return typeof Response !== "undefined" && src instanceof Response;
- }
- function isModule(src) {
- return src instanceof WebAssembly.Module;
- }
- /** Asynchronously instantiates an AssemblyScript module from anything that can be instantiated. */
- async function instantiate(source, imports = {}) {
- if (isResponse(source = await source)) return instantiateStreaming(source, imports);
- const module = isModule(source) ? source : await WebAssembly.compile(source);
- const extended = preInstantiate(imports);
- const instance = await WebAssembly.instantiate(module, imports);
- const exports = postInstantiate(extended, instance);
- return { module, instance, exports };
- }
- exports.instantiate = instantiate;
- /** Synchronously instantiates an AssemblyScript module from a WebAssembly.Module or binary buffer. */
- function instantiateSync(source, imports = {}) {
- const module = isModule(source) ? source : new WebAssembly.Module(source);
- const extended = preInstantiate(imports);
- const instance = new WebAssembly.Instance(module, imports);
- const exports = postInstantiate(extended, instance);
- return { module, instance, exports };
- }
- exports.instantiateSync = instantiateSync;
- /** Asynchronously instantiates an AssemblyScript module from a response, i.e. as obtained by `fetch`. */
- async function instantiateStreaming(source, imports = {}) {
- if (!WebAssembly.instantiateStreaming) {
- return instantiate(
- isResponse(source = await source)
- ? source.arrayBuffer()
- : source,
- imports
- );
- }
- const extended = preInstantiate(imports);
- const result = await WebAssembly.instantiateStreaming(source, imports);
- const exports = postInstantiate(extended, result.instance);
- return { ...result, exports };
- }
- exports.instantiateStreaming = instantiateStreaming;
- /** Demangles an AssemblyScript module's exports to a friendly object structure. */
- function demangle(exports, extendedExports = {}) {
- extendedExports = Object.create(extendedExports);
- const setArgumentsLength = exports["__argumentsLength"]
- ? length => { exports["__argumentsLength"].value = length; }
- : exports["__setArgumentsLength"] || exports["__setargc"] || (() => { /* nop */ });
- for (let internalName in exports) {
- if (!Object.prototype.hasOwnProperty.call(exports, internalName)) continue;
- const elem = exports[internalName];
- let parts = internalName.split(".");
- let curr = extendedExports;
- while (parts.length > 1) {
- let part = parts.shift();
- if (!Object.prototype.hasOwnProperty.call(curr, part)) curr[part] = {};
- curr = curr[part];
- }
- let name = parts[0];
- let hash = name.indexOf("#");
- if (hash >= 0) {
- const className = name.substring(0, hash);
- const classElem = curr[className];
- if (typeof classElem === "undefined" || !classElem.prototype) {
- const ctor = function(...args) {
- return ctor.wrap(ctor.prototype.constructor(0, ...args));
- };
- ctor.prototype = {
- valueOf: function valueOf() {
- return this[THIS];
- }
- };
- ctor.wrap = function(thisValue) {
- return Object.create(ctor.prototype, { [THIS]: { value: thisValue, writable: false } });
- };
- if (classElem) Object.getOwnPropertyNames(classElem).forEach(name =>
- Object.defineProperty(ctor, name, Object.getOwnPropertyDescriptor(classElem, name))
- );
- curr[className] = ctor;
- }
- name = name.substring(hash + 1);
- curr = curr[className].prototype;
- if (/^(get|set):/.test(name)) {
- if (!Object.prototype.hasOwnProperty.call(curr, name = name.substring(4))) {
- let getter = exports[internalName.replace("set:", "get:")];
- let setter = exports[internalName.replace("get:", "set:")];
- Object.defineProperty(curr, name, {
- get: function() { return getter(this[THIS]); },
- set: function(value) { setter(this[THIS], value); },
- enumerable: true
- });
- }
- } else {
- if (name === 'constructor') {
- (curr[name] = (...args) => {
- setArgumentsLength(args.length);
- return elem(...args);
- }).original = elem;
- } else { // instance method
- (curr[name] = function(...args) { // !
- setArgumentsLength(args.length);
- return elem(this[THIS], ...args);
- }).original = elem;
- }
- }
- } else {
- if (/^(get|set):/.test(name)) {
- if (!Object.prototype.hasOwnProperty.call(curr, name = name.substring(4))) {
- Object.defineProperty(curr, name, {
- get: exports[internalName.replace("set:", "get:")],
- set: exports[internalName.replace("get:", "set:")],
- enumerable: true
- });
- }
- } else if (typeof elem === "function" && elem !== setArgumentsLength) {
- (curr[name] = (...args) => {
- setArgumentsLength(args.length);
- return elem(...args);
- }).original = elem;
- } else {
- curr[name] = elem;
- }
- }
- }
- return extendedExports;
- }
- exports.demangle = demangle;
|