# Implementation status

AssemblyScript both aims to be a thin and efficient layer on top of WebAssembly, as well as a language with familiar syntax for developers coming from TypeScript. These two goals are sometimes in conflict, since not all features are equally viable to implement on top of WebAssembly's capabilities right now, respectively applicable in general in ahead-of-time compilation. As such the focus is to implement what's feasible first, and where possible to delay features that are better served by one of the future WebAssembly proposals to avoid otherwise duplicate work. In a sense, the approach is similar to the MVP model used in WebAssembly specification. Some features are critical to make AssemblyScript work right now of course, so there are some exceptions to this rule.

# WebAssembly features

Some crucial language features rely on future WebAssembly functionality (opens new window) to be efficient. The following table aims to give an overview from a WebAssembly perspective:

WebAssembly spec Engines AssemblyScript (flag) Perspective
✔️ Finished proposal
Import/export of mutable globals (opens new window) ✔️ good Interop
JS BigInt integration (opens new window)1 ✔️ good Interop
Sign-extension operations (opens new window) ✔️ good Efficiency
Non-trapping float-to-int conversions (opens new window) ✔️ good Efficiency
Bulk memory operations (opens new window) ✔️ good Efficiency
Fixed-width SIMD (opens new window) 🏁 simd good Feature
Reference types (opens new window) 🔨 reference-types good Interop
Multi-value (opens new window) uncertain
🏁 Standardize the feature
🔨 Implementation phase
Exception handling (opens new window) 🔨 exception-handling good Feature
Tail call (opens new window) uncertain
Multiple memories (opens new window) uncertain
Memory64 (opens new window) 🔨 uncertain
Branch hinting (opens new window) good Efficiency
Relaxed SIMD (opens new window) good Feature
Extended constant expressions (opens new window) 🔨 good Efficiency
📖 Spec text available
Threads (opens new window) 🔨 threads uncertain
ECMAScript module integration (opens new window) good Interop
Typed function references (opens new window) good Feature
Instrument and tracing (opens new window) good Debugging
Garbage collection (opens new window) good Efficiency / Interop
JS Promise integration (opens new window) uncertain
💡 Feature proposal
Type imports (opens new window) good Interop
Feature detection (opens new window) uncertain
Extended name section (opens new window) 🔨 good Debugging
Flexible vectors (opens new window) good Feature
Call tags (opens new window) uncertain
Stack switching (opens new window) good Feature / Interop
Constant time (opens new window) good Security
Memory control (opens new window) uncertain
Reference-typed strings (opens new window) good Interop
Component model (opens new window)2 harmful
Quasi proposal
WASI (opens new window)3 🔨 harmful
Chrome   Firefox   Safari   Node.js   Wasmtime   Wasmer   (1 native support in non-JS hosts)

2 Supersedes Interface types (opens new window), simultaneously deciding (opens new window) that compatibility with JavaScript (strings) is out of scope.
3 WASI is not a good fit for the Web embedding and it is disallowed (opens new window) to discuss or mitigate the risks of its approach.

Perspective Description
good This specification is conceptually good and worth looking into
uncertain AssemblyScript is uncertain about this specification and not in a hurry to implement it
harmful AssemblyScript considers this specification to be harmful in its current state

# Language features

As such, certain higher-level language features still have their limitations or are not yet available. From a language perspective:

Feature What to expect?
🐤 Functional
Bootstrap The compiler can compile itself to WebAssembly, passing the test suite. Note that the compiler is not technically "self hosted" in WebAssembly yet, as it currently uses a JavaScript frontend for I/O and links to Binaryen (C++ compiled with Emscripten), which again requires some amount of JS glue code.
OOP Largely implemented in linear memory. Access modifiers like private and protected are not currently enforced. There is rudimentary support for interfaces. Interfaces must specify getters instead of fields.
Standard library Largely implemented in linear memory. Some APIs function a little different than in JavaScript due to differences introduced by static typing or not yet available future features. There is a separate status document (opens new window) specific to the standard library.
Generics Generics are compiled as monomorphized templates for now and can be specialized with static type checks. Constraining extends XY clauses are not yet enforced.
Garbage collection Implemented in linear memory for the time being, independent of the host GC.
Host integration Enabled by generated host bindings, respectively the runtime interface for integration into non-Web environments.
🐣 Limited
Union types Union types are not supported by design, except for nullable class types. There is no any type. A viable alternative is to use generics specialized with static type checks to achieve a similar effect.
Symbols Symbols are implemented in the standard library, but don't have deep compiler integration yet.
Object literals Object literals can be used in places where the current type is a bare class, then corresponding to an instantiation of the class.
JSON JSON is not strictly typed in nature, so we haven't settled on a standard yet. Solutions developed by the community: assemblyscript-json (opens new window)
RegExp Regular expressions need quite a lot of supporting code with many quirks, and we haven't decided on an implementation yet. Solutions developed by the community: assemblyscript-regex (opens new window)
Date There is initial support for the UTC parts, but WebAssembly lacks access to the system's time zone data. In general the Temporal proposal could be more feasible to adopt. Solutions developed by the community: assemblyscript-temporal (opens new window).
🥚 Not implemented
Closures Captures of local variables are not yet supported and would be best implemented on top of future WebAssembly features, also to avoid inventing a custom ABI. Can be worked around by using a global variable instead (does not need to be captured), or passing an argument with the relevant values.
Iterators Iterators and for..of loops are not supported yet. APIs that would return an iterator return an array of keys or values for now instead.
Rest parameters Rest parameters are not supported yet. Would benefit from a WebAssembly proposal to avoid a custom ABI, but there is none yet. Optional parameters with a default value are supported and can often be used as an alterantive.
Exceptions Exceptions require support from the WebAssembly engine first. Throwing currently aborts the program.
Promises There is no concept of async/await yet due to the lack of an event loop. Future WebAssembly proposals might help with the stack switching parts (pause and resume execution).
BigInt Instead of BigInts, AssemblyScript has opted to utilize WebAssembly's 64-bit integers. It is currently unclear how both concepts could mix.
🕳️ Not supported
Dynamicness AssemblyScript avoids overly dynamic JavaScript features by design and focuses on static compilation.

# On closures

Closures (functions with a captured environment) are not yet supported and we are waiting for the Function References 🦄 and Garbage collection 🦄 (captured environments are GC'ed) proposals to land. However, since this is a crucial language feature, we may end up with a filler implementation using linear memory. Not available yet, though.

In the meantime we recommend to restructure code so closures are not necessary, i.e. instead of writing

function computeSum(arr: i32[]): i32 {
  var sum = 0
  arr.forEach(value => {
    sum += value // fails
  })
  return sum
}

restructure to

var sum: i32 // becomes a WebAssembly Global
function computeSum(arr: i32[]): i32 {
  sum = 0
  arr.forEach(value => {
    sum += value // works
  })
  return sum
}

or to

function computeSum(arr: i32[]): i32 {
  var sum = 0
  for (let i = 0, k = arr.length; i < k; ++i) {
    sum += arr[i] // works
  }
  return sum
}

# On dynamicness

AssemblyScript intentionally avoids very dynamic JavaScript features that cannot be compiled efficiently, like for example:

  • Assigning any value to any variable.
  • Compare values of incompatible types.
  • Implicitly convert from a non-string to a string without using x.toString().
  • Assign a new property, that has not been statically declared, to a class or object.
  • Assign a class to a variable (e.g. var clazz = MyClass) since classes are static constructs without a runtime representation.
  • Patch class .prototypes since there are none.
  • Access arguments to dynamically obtain function arguments.
  • Dynamically obtain the name of a function at runtime or otherwise use reflection.

Some of these restrictions, like implicit conversion to strings when concatenating with a string, may be lifted in the future, while others, like prototypes, may never be viable in ahead-of-time compilation. For instance, some features would work in an interpreter and may become efficient with a JIT compiler, yet going down that rabbit hole runs counter to WebAssembly's, and by definition AssemblyScript's, goals.

# Tooling features

Feature What to expect?
🐤 Functional
Debugging There is support for debug information and source maps. See also.
Testing Unopinionated with simple assertions. Solutions developed by the community: as-pect (opens new window)
🐣 Limited
Linting AssemblyScript re-uses TypeScript tooling with a // @ts-ignore here or there but would benefit from a dedicated language server eventually. Solutions developed by the community: asls (opens new window)