diff --git a/.eslintrc.js b/.eslintrc.js index 8dc670e2d4..52ee9b47de 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -87,13 +87,18 @@ module.exports = { "es6": true }, files: [ - "**/*.js" + "**/*.js", + "**/*.mjs", + "**/*.cjs" ], rules: { // Node's support for ESM is still not great, but this rule is likely - // to become activated once compatibility doesn't suck anymore. + // to become activated once ESM-by-default becomes generally usable. "@typescript-eslint/no-var-requires": "off", + // There are no types in JavaScript + "@typescript-eslint/explicit-module-boundary-types": "off", + // Enforcing to remove function parameters on stubs makes code less // maintainable, so we instead allow unused function parameters. "no-unused-vars": [ diff --git a/lib/loader/index.d.ts b/lib/loader/index.d.ts index bc6854277a..3eab599587 100644 --- a/lib/loader/index.d.ts +++ b/lib/loader/index.d.ts @@ -5,7 +5,6 @@ export interface ResultObject { instance: WebAssembly.Instance; } - /** WebAssembly imports with an optional env object and two levels of nesting. */ export type Imports = { [key: string]: Record; diff --git a/lib/loader/index.js b/lib/loader/index.js index f29d445fab..8ed271f39e 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -1,5 +1,3 @@ -"use strict"; - // Runtime header offsets const ID_OFFSET = -8; const SIZE_OFFSET = -4; @@ -7,26 +5,15 @@ 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; @@ -299,7 +286,7 @@ function isModule(src) { } /** Asynchronously instantiates an AssemblyScript module from anything that can be instantiated. */ -async function instantiate(source, imports = {}) { +export 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); @@ -308,10 +295,8 @@ async function instantiate(source, imports = {}) { return { module, instance, exports }; } -exports.instantiate = instantiate; - /** Synchronously instantiates an AssemblyScript module from a WebAssembly.Module or binary buffer. */ -function instantiateSync(source, imports = {}) { +export function instantiateSync(source, imports = {}) { const module = isModule(source) ? source : new WebAssembly.Module(source); const extended = preInstantiate(imports); const instance = new WebAssembly.Instance(module, imports); @@ -319,10 +304,8 @@ function instantiateSync(source, imports = {}) { 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 = {}) { +export async function instantiateStreaming(source, imports = {}) { if (!WebAssembly.instantiateStreaming) { return instantiate( isResponse(source = await source) @@ -337,10 +320,8 @@ async function instantiateStreaming(source, imports = {}) { return { ...result, exports }; } -exports.instantiateStreaming = instantiateStreaming; - /** Demangles an AssemblyScript module's exports to a friendly object structure. */ -function demangle(exports, extendedExports = {}) { +export function demangle(exports, extendedExports = {}) { extendedExports = Object.create(extendedExports); const setArgumentsLength = exports["__argumentsLength"] ? length => { exports["__argumentsLength"].value = length; } @@ -424,4 +405,9 @@ function demangle(exports, extendedExports = {}) { return extendedExports; } -exports.demangle = demangle; +export default { + instantiate, + instantiateSync, + instantiateStreaming, + demangle +}; diff --git a/lib/loader/package.json b/lib/loader/package.json index ea9e7f2af0..4d5f0a213d 100644 --- a/lib/loader/package.json +++ b/lib/loader/package.json @@ -21,18 +21,30 @@ "bugs": { "url": "https://github.com/AssemblyScript/assemblyscript/issues" }, - "main": "index.js", - "types": "index.d.ts", + "type": "module", + "main": "./umd/index.js", + "exports": { + ".": { + "require": "./umd/index.js", + "import": "./index.js" + } + }, + "types": "./index.d.ts", + "module": "./index.js", "scripts": { "asbuild": "npm run asbuild:default && npm run asbuild:legacy", "asbuild:default": "node ../../bin/asc tests/assembly/index.ts -b tests/build/default.wasm", "asbuild:legacy": "node ../../bin/asc tests/assembly/index.ts --disable mutable-globals -b tests/build/legacy.wasm", - "test": "node tests" + "test": "node tests", + "build": "npx esm2umd loader index.js > umd/index.js", + "prepublishOnly": "npm run build" }, "files": [ - "index.d.ts", "index.js", + "index.d.ts", "package.json", - "README.md" + "README.md", + "umd/index.js", + "umd/package.json" ] } diff --git a/lib/loader/tests/index.js b/lib/loader/tests/index.js index 72dc1996c6..b3daa5272a 100644 --- a/lib/loader/tests/index.js +++ b/lib/loader/tests/index.js @@ -1,8 +1,12 @@ -var fs = require("fs"); -var assert = require("assert"); -var inspect = require("util").inspect; +import fs from "fs"; +import assert from "assert"; +import { inspect } from "util"; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; -var loader = require(".."); +import loader from "../index.js"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); test("default.wasm"); test("legacy.wasm"); @@ -11,9 +15,8 @@ testInstantiate("default.wasm"); testInstantiate("legacy.wasm"); function test(file) { - var buffer = fs.readFileSync(__dirname + "/build/" + file); - var result = loader.instantiateSync(buffer, {}); - const exports = result.exports; + const buffer = fs.readFileSync(__dirname + "/build/" + file); + const exports = loader.instantiateSync(buffer, {}).exports; console.log(inspect(exports, true, 100, true)); diff --git a/lib/loader/umd/index.js b/lib/loader/umd/index.js new file mode 100644 index 0000000000..e8865970d5 --- /dev/null +++ b/lib/loader/umd/index.js @@ -0,0 +1,481 @@ +// GENERATED FILE. DO NOT EDIT. +var loader = (function(exports) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.instantiate = instantiate; + exports.instantiateSync = instantiateSync; + exports.instantiateStreaming = instantiateStreaming; + exports.demangle = demangle; + exports.default = void 0; + // Runtime header offsets + const ID_OFFSET = -8; + const SIZE_OFFSET = -4; // Runtime ids + + const ARRAYBUFFER_ID = 0; + const STRING_ID = 1; // Runtime type information + + const ARRAYBUFFERVIEW = 1 << 0; + const ARRAY = 1 << 1; + const STATICARRAY = 1 << 2; + const VAL_ALIGN_OFFSET = 6; + const VAL_SIGNED = 1 << 11; + const VAL_FLOAT = 1 << 12; + const VAL_MANAGED = 1 << 14; // 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 ""; + 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 + }; + } + /** 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 + }; + } + /** 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 + }; + } + /** 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; + } + + var _default = { + instantiate, + instantiateSync, + instantiateStreaming, + demangle + }; + exports.default = _default; + return exports; +})({}); +if (typeof define === 'function' && define.amd) define([], function() { return loader; }); +else if (typeof module === 'object' && typeof exports==='object') module.exports = loader; diff --git a/lib/loader/umd/package.json b/lib/loader/umd/package.json new file mode 100644 index 0000000000..5bbefffbab --- /dev/null +++ b/lib/loader/umd/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/package.json b/package.json index f3e802907c..9ede897259 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "webpack": "^4.43.0", "webpack-cli": "^3.3.11" }, + "type": "commonjs", "main": "index.js", "types": "index.d.ts", "bin": { @@ -71,7 +72,7 @@ "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized", "asbuild:untouched": "node bin/asc src/glue/wasm/index.ts src/index.ts -t out/assemblyscript.untouched.wat -b out/assemblyscript.untouched.wasm -d out/assemblyscript.d.ts --debug --measure --runtime stub", "asbuild:optimized": "node bin/asc src/glue/wasm/index.ts src/index.ts -t out/assemblyscript.optimized.wat -b out/assemblyscript.optimized.wasm -O3 --measure --runtime stub", - "astest": "ts-node tests/bootstrap" + "astest": "node tests/bootstrap/index.js" }, "releaseFiles": [ "lib/rtrace/index.d.ts", diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.js similarity index 80% rename from tests/bootstrap/index.ts rename to tests/bootstrap/index.js index 098b8c0dd6..8dcb35c754 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.js @@ -1,38 +1,41 @@ -import * as fs from "fs"; -import * as path from "path"; -import * as binaryen from "binaryen"; -import * as util from "util"; -import * as loader from "../../lib/loader"; -import * as find from "../../cli/util/find"; -import AssemblyScript from "../../out/assemblyscript"; +import fs from "fs"; +import path from "path"; +import util from "util"; +import { fileURLToPath } from 'url'; +import find from "../../cli/util/find.js"; + +import binaryen from "binaryen"; +import loader from "../../lib/loader/index.js"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); Error.stackTraceLimit = Infinity; // Load stdlib const libDir = path.join(__dirname, "..", "..", "std", "assembly"); const libraryFiles = {}; -find.files(libDir, /^(?!.*\.d\.ts$).*\.ts$/).forEach((file: string) => { +find.files(libDir, /^(?!.*\.d\.ts$).*\.ts$/).forEach(file => { libraryFiles[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" ); }); -async function test(build: string): Promise { +async function test(build) { await binaryen.ready; - const { exports: asc } = await loader.instantiate( + const { exports: asc } = await loader.instantiate( fs.promises.readFile(`${ __dirname }/../../out/assemblyscript.${ build }.wasm`), { binaryen } ); console.log(util.inspect(asc, true)); - const cachedStrings = new Map(); - function cachedString(text: string): number { + const cachedStrings = new Map(); + function cachedString(text) { if (cachedStrings.has(text)) return cachedStrings.get(text); var ptr = asc.__retain(asc.__allocString(text)); cachedStrings.set(text, ptr); return ptr; } - const programPtr = ((): number => { + const programPtr = (() => { const optionsPtr = asc.newOptions(); const ptr = asc.newProgram(optionsPtr); asc.__release(optionsPtr); @@ -40,7 +43,7 @@ async function test(build: string): Promise { })(); console.log("\nParsing standard library ..."); - Object.keys(libraryFiles).forEach((libPath: string) => { + Object.keys(libraryFiles).forEach((libPath) => { if (libPath.indexOf("/") >= 0) return; const textPtr = cachedString(libraryFiles[libPath]); const pathPtr = cachedString("~lib/" + libPath + ".ts"); diff --git a/tests/bootstrap/package.json b/tests/bootstrap/package.json new file mode 100644 index 0000000000..aead43de36 --- /dev/null +++ b/tests/bootstrap/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file