Skip to content

v0.20.0

Compare
Choose a tag to compare
@github-actions github-actions released this 21 Mar 01:24
a7c87e6

ECMAScript modules

Fixes #1306. Migrating our dependencies to ESM made it possible to migrate the compiler and frontend as well, alongside internal utility and scripts. This is a breaking change for consumers of the compiler API (i.e. transforms), but not for command line usage. Viable strategies to account for the changes are:

  1. Migrate any code utilizing compiler APIs to ESM as well:

    import assemblyscript from "assemblyscript";
    ...
  2. Utilize a dynamic import while consuming code remains in its current module format:

    const assemblyscript = (await import("assemblyscript")).default;
    ...
    // or
    import("assemblyscript").then(({ default: assemblyscript }) => { ... });

Due to this change, older versions of Node.js may need to be upgraded (LTS v16 or stable v17 are recommended).

Running the compiler on the Web with ESM

Prior, we provided a browser SDK that made use of the AMD module format to load the components necessary to run the compiler on the Web. With the switch to ESM, it is not necessary anymore to provide a separate SDK, but native browser functionality can now be used to utilize the compiler in browsers. To ease the transition, the build system outputs an example dist/web.html template with all the right versions in <script ...> tags. Alongside, it also sets up es-module-shims for import maps support as is currently necessary to support browsers other than those based on Chromium. General outline is:

<script async src="url/to/es-module-shims"></script>
<script type="importmap">
{
  "imports": {
    "binaryen": "url/to/binaryen",
    "long": "url/to/long",
    "assemblyscript": "url/to/assemblyscript"
  }
}
</script>
<script type="module">
import asc from "url/to/asc";
...
</script>

Asynchronous compiler APIs

Prior, programmatically executing for example asc.main was synchronous despite accepting a callback. The relevant APIs are now asynchronous, making use of the opportunity to perform asynchronous I/O under the hood, and as such return a promise with the compilation result instead of accepting a callback.

const { error, stdout, stderr } = await asc.main([ ... ], { ... });
...

It is no longer necessary to override stdout and stderr, since the default has been switched to return a memory stream. If binding to the Node.js console is desired, which is rare, the behavior can be overridden to the previous by specifying { stdout: process.stdout, stderr: process.stderr } in API options.

In addition, transform hooks gained the ability to evaluate asynchronously when being async / returning a promise.

Unification of === and ==

Fixes #856. Closes #1111. The semantics of === and !== are redundant in AssemblyScript since comparing two values of different types is not permitted anyhow. In the early days of the compiler we hence repurposed the operator to perform what seemed like a useful operation, that is test for identity equality (the exact same object). Doing so, however, introduced a subtle footgun into the language for those coming from TypeScript, and now has been removed.

Means: === is now the same as ==, !== is now the same as !=, largely matching intuition.

Deprecation of the loader

The loader was a stopgap solution intended to keep glue code minimal until WebAssembly integrates natively with the rest of the Web platform. Sadly, we made a bet there that didn't materialize, and the loader has now been deprecated with the compiler now supporting static generation of glue code with the --bindings option.

Available bindings are:

  --bindings, -b        Specifies the bindings to generate (.js + .d.ts).

                          esm  JavaScript bindings & typings with ESM integration.
                          raw  Like esm, but exports just the instantiate function.
                               Useful where modules are meant to be instantiated
                               multiple times or non-ESM imports must be provided.

Generated JavaScript bindings support the data types

Type Strategy Description
Number By value Basic types except 64-bit integers
BigInt By value 64-bit integers via js-bigint-integration
String Copy
ArrayBuffer Copy
TypedArray Copy Any kind
Array Copy Any kind
StaticArray Copy Any kind
Object Copy Plain objects (no constructor or non-public fields).
Can opt-out by providing an empty constructor.
Internref By value Reference counted pointer via FinalizationRegistry.
Essentially anything that isn't a plain object.
Externref By value Via reference-types

For now, only top-level functions, globals and enums receive bindings. Classes do not (yet). Bindings automagically utilize exported runtime helpers so users don't have to.

Preserving side-effects in static type checks

Fixes #531. The static type checks isInteger, isFloat, isBoolean, isSigned, isReference, isString, isArray, isArrayLike, isFunction, isNullable, isConstant, isManaged, isVoid, lengthof, nameof and idof accept either a type argument, an argument or both. In the uncommon case of providing an argument, that is not solely operating on a type, these builtins now preserve side-effects of the argument which is safer but may prevent compile-time branch elimination in such cases.

Unified consumption of the assemblyscript package

Entrypoints for the various components are now:

  • assemblyscript as before
  • assemblyscript/asc to obtain the compiler frontend
  • assemblyscript/transform to obtain the transform base class
  • assemblyscript/binaryen to obtain the exact instance of Binaryen used
  • assemblyscript/util/*.js to obtain various utility, i.e. for configuration parsing

Removal of ascMain in package.json

Fixes #1954. As it turned out, specifying an alternative entry point in package.json led to more issues than it solved, often not finding files and types because existing tooling does not recognize it. As such, this mechanism has been removed in favor of plain node-style resolution, i.e. import { x } from "myPackage/assembly", which is not susceptible to these problems.

Removal of experimental --extension CLI option

See #1003. While it is likely that discussion about using another file extension will continue in the future, the CLI option was meant for experimentation, had various issues and lately became stale. Hence it has been removed to simplify matters on common ground.

Replaced --explicitStart CLI option with --exportStart NAME

Fixes #2099. The new option is more general in that it also accepts the desired export name to use for the start function. Typical options are:

  • --exportStart _start for a WASI command. This is equivalent to the former --explicitStart.
  • --exportStart _initialize for a WASI reactor.
  • --exportStart myCustomStartFunctionName for anything else.

Note that the start function, no matter how it is named, must always be called before any other exports to initialize the module.

Renamed untouched/optimized to debug/release

Default compilation targets (generated) for projects are now named debug and release to better fit their purpose and to have only one set of names to remember.

Enabled various WebAssembly features

Some meanwhile standardized features have been enabled by default:

  • Nontrapping float to int conversions brings additional conversion operations.
  • Bulk Memory replaces fallback implementations of memory.fill and memory.copy.

Note that we are still holding back on enabling SIMD by default as it is not yet supported in Safari, but one can already play with it using --enable simd.

Reworked development workflow

Prior, AssemblyScript utilized ts-node in development to lessen overhead from recompilation on changes. This approach turned out to be not viable anymore due to various issues with modern language features and has been dropped, alongside webpack for final builds, and replaced with esbuild. The new development workflow is to execute npm run watch which will automatically and quickly produce builds. As a side effect, workarounds and dependencies to support the prior development workflow could be dropped.

And the kitchen sink

  • Various clean ups have been performed, with no longer needed files and long deprecated APIs being removed
  • Support for older Node.js versions not supporting ECMAScript modules has been dropped
  • The WebIDL and Asm.js targets have been dropped as they were of little use and largely unmaintained
  • The --listFiles (not Wasm-target compatible) and --traceResolution (now tested programmatically) CLI options have been removed.
  • The Binaryen dependency now uses Wasm builds and has been significantly sped up by enabling more optimizations. Optimizing the AssemblyScript compiler itself now only takes about a third of the time.