Skip to content

Commit ff80a4e

Browse files
authored
feat: Make loader ESM by default, with UMD fallback (#1513)
BREAKING CHANGE: The loader is now an ES module by default so it works out of the box on the web. Users of older node.js versions may have to switch to `require("@assemblyscript/loader/umd")`.
1 parent 6ed4f74 commit ff80a4e

File tree

16 files changed

+564
-44
lines changed

16 files changed

+564
-44
lines changed

.eslintrc.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,12 @@ module.exports = {
9292
"bin/*"
9393
],
9494
rules: {
95-
// Node's support for ESM is still not great, but this rule is likely
96-
// to become activated once compatibility doesn't suck anymore.
95+
// We are testing both ESM and UMD, so don't limit us.
9796
"@typescript-eslint/no-var-requires": "off",
9897

98+
// This rule does not behave well in JS files.
99+
"@typescript-eslint/explicit-module-boundary-types": "off",
100+
99101
// Enforcing to remove function parameters on stubs makes code less
100102
// maintainable, so we instead allow unused function parameters.
101103
"no-unused-vars": [

.github/workflows/publish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
node node_modules/semantic-release/bin/semantic-release.js --unstable
3434
cd lib/loader
3535
if [ $(node -pe "require('./package.json').version") != "0.0.0" ]; then
36+
npm run build
3637
npm config set "//registry.npmjs.org/:_authToken=${NPM_TOKEN}"
3738
npm publish --access public
3839
fi

.github/workflows/test.yml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,11 @@ jobs:
5353
- name: Check sources
5454
run: npm run check
5555
- name: Test sources
56-
run: |
57-
if [[ `node bin/asc --version` != *"-dev" ]]; then
58-
echo "ERROR: Not testing sources"
59-
exit 1
60-
fi
61-
npm test
56+
run: npm test
6257
- name: Build distribution files
6358
run: npm run build
6459
- name: Test distribution
65-
run: |
66-
if [[ `node bin/asc --version` == *"-dev" ]]; then
67-
echo "ERROR: Not testing distribution"
68-
exit 1
69-
fi
70-
npm test
60+
run: npm test
7161
- name: Test browser build
7262
run: node tests/browser-asc
7363
test-windows:

cli/asc.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
* Uses the low-level API exported from src/index.ts so it works with the compiler compiled to
2424
* JavaScript as well as the compiler compiled to WebAssembly (eventually). Runs the sources
25-
* directly through ts-node if distribution files are not present (indicated by a `-dev` version).
25+
* directly through ts-node if distribution files are not present.
2626
*
2727
* Can also be packaged as a bundle suitable for in-browser use with the standard library injected
2828
* in the build step. See dist/asc.js for the bundle and webpack.config.js for building details.
@@ -75,23 +75,23 @@ if (process.removeAllListeners) process.removeAllListeners("uncaughtException");
7575

7676
// Use distribution files if present, otherwise run the sources directly.
7777
var assemblyscript;
78-
var isDev = false;
7978
(function loadAssemblyScript() {
8079
try {
80+
// note that this case will always trigger in recent node.js versions for typical installs
81+
// see: https://nodejs.org/api/packages.html#packages_self_referencing_a_package_using_its_name
8182
assemblyscript = require("assemblyscript");
8283
} catch (e) {
83-
try { // `asc` on the command line
84+
try { // `asc` on the command line (unnecessary in recent node)
8485
assemblyscript = dynrequire("../dist/assemblyscript.js");
8586
} catch (e) {
86-
try { // `asc` on the command line without dist files
87+
try { // `asc` on the command line without dist files (unnecessary in recent node)
8788
dynrequire("ts-node").register({
8889
project: path.join(__dirname, "..", "src", "tsconfig.json"),
8990
skipIgnore: true,
9091
compilerOptions: { target: "ES2016" }
9192
});
9293
dynrequire("../src/glue/js");
9394
assemblyscript = dynrequire("../src");
94-
isDev = true;
9595
} catch (e_ts) {
9696
try { // `require("dist/asc.js")` in explicit browser tests
9797
assemblyscript = dynrequire("./assemblyscript");
@@ -106,9 +106,6 @@ var isDev = false;
106106
/** Whether this is a webpack bundle or not. */
107107
exports.isBundle = typeof BUNDLE_VERSION === "string";
108108

109-
/** Whether asc runs the sources directly or not. */
110-
exports.isDev = isDev;
111-
112109
/** AssemblyScript version. */
113110
exports.version = exports.isBundle ? BUNDLE_VERSION : dynrequire("../package.json").version;
114111

@@ -241,7 +238,7 @@ exports.main = function main(argv, options, callback) {
241238

242239
// Just print the version if requested
243240
if (opts.version) {
244-
stdout.write("Version " + exports.version + (isDev ? "-dev" : "") + EOL);
241+
stdout.write("Version " + exports.version + EOL);
245242
return callback(null);
246243
}
247244

lib/loader/index.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
"use strict";
2-
31
// Runtime header offsets
42
const ID_OFFSET = -8;
53
const SIZE_OFFSET = -4;
@@ -297,7 +295,7 @@ function isModule(src) {
297295
}
298296

299297
/** Asynchronously instantiates an AssemblyScript module from anything that can be instantiated. */
300-
async function instantiate(source, imports = {}) {
298+
export async function instantiate(source, imports = {}) {
301299
if (isResponse(source = await source)) return instantiateStreaming(source, imports);
302300
const module = isModule(source) ? source : await WebAssembly.compile(source);
303301
const extended = preInstantiate(imports);
@@ -306,21 +304,17 @@ async function instantiate(source, imports = {}) {
306304
return { module, instance, exports };
307305
}
308306

309-
exports.instantiate = instantiate;
310-
311307
/** Synchronously instantiates an AssemblyScript module from a WebAssembly.Module or binary buffer. */
312-
function instantiateSync(source, imports = {}) {
308+
export function instantiateSync(source, imports = {}) {
313309
const module = isModule(source) ? source : new WebAssembly.Module(source);
314310
const extended = preInstantiate(imports);
315311
const instance = new WebAssembly.Instance(module, imports);
316312
const exports = postInstantiate(extended, instance);
317313
return { module, instance, exports };
318314
}
319315

320-
exports.instantiateSync = instantiateSync;
321-
322316
/** Asynchronously instantiates an AssemblyScript module from a response, i.e. as obtained by `fetch`. */
323-
async function instantiateStreaming(source, imports = {}) {
317+
export async function instantiateStreaming(source, imports = {}) {
324318
if (!WebAssembly.instantiateStreaming) {
325319
return instantiate(
326320
isResponse(source = await source)
@@ -335,10 +329,8 @@ async function instantiateStreaming(source, imports = {}) {
335329
return { ...result, exports };
336330
}
337331

338-
exports.instantiateStreaming = instantiateStreaming;
339-
340332
/** Demangles an AssemblyScript module's exports to a friendly object structure. */
341-
function demangle(exports, extendedExports = {}) {
333+
export function demangle(exports, extendedExports = {}) {
342334
extendedExports = Object.create(extendedExports);
343335
const setArgumentsLength = exports["__argumentsLength"]
344336
? length => { exports["__argumentsLength"].value = length; }
@@ -420,4 +412,9 @@ function demangle(exports, extendedExports = {}) {
420412
return extendedExports;
421413
}
422414

423-
exports.demangle = demangle;
415+
export default {
416+
instantiate,
417+
instantiateSync,
418+
instantiateStreaming,
419+
demangle
420+
};

lib/loader/package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,27 @@
2121
"bugs": {
2222
"url": "https://github.com/AssemblyScript/assemblyscript/issues"
2323
},
24+
"type": "module",
2425
"main": "index.js",
2526
"types": "index.d.ts",
27+
"exports": {
28+
"import": "./index.js",
29+
"require": "./umd/index.js"
30+
},
2631
"scripts": {
2732
"asbuild": "npm run asbuild:default && npm run asbuild:legacy",
2833
"asbuild:default": "node ../../bin/asc tests/assembly/index.ts -b tests/build/default.wasm",
2934
"asbuild:legacy": "node ../../bin/asc tests/assembly/index.ts --disable mutable-globals -b tests/build/legacy.wasm",
30-
"test": "node tests"
35+
"build": "npx esm2umd loader index.js > umd/index.js",
36+
"test": "node tests && node tests/umd"
3137
},
3238
"files": [
3339
"index.d.ts",
3440
"index.js",
3541
"package.json",
42+
"umd/index.d.ts",
43+
"umd/index.js",
44+
"umd/package.json",
3645
"README.md"
3746
]
3847
}

lib/loader/tests/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
var fs = require("fs");
2-
var assert = require("assert");
3-
var inspect = require("util").inspect;
4-
5-
var loader = require("..");
1+
import fs from "fs";
2+
import assert from "assert";
3+
import { inspect } from "util";
4+
import loader from "../index.js";
5+
import { dirname } from "path";
6+
import { fileURLToPath } from "url";
7+
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = dirname(__filename);
610

711
test("default.wasm");
812
test("legacy.wasm");

lib/loader/tests/umd/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const assert = require("assert");
2+
const loader = require("../../umd");
3+
4+
assert(typeof loader.instantiate === "function");

lib/loader/tests/umd/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "commonjs"
3+
}

lib/loader/umd/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "..";

0 commit comments

Comments
 (0)