class ClassEmitter extends AnyRef

Linear Supertypes
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. ClassEmitter
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Instance Constructors

  1. new ClassEmitter(coreSpec: CoreSpec)

Value Members

  1. def genClassDef(clazz: LinkedClass)(implicit ctx: WasmContext): Unit
  2. def genGlobalArrayClassItable()(implicit ctx: WasmContext): Unit

    Generate common itable global for all array classes.

  3. def genTopLevelExport(topLevelExport: LinkedTopLevelExport)(implicit ctx: WasmContext): Unit

    Generates code for a top-level export.

    Generates code for a top-level export.

    It is tempting to use Wasm exports for top-level exports. However, that does not work in several situations:

    • for values, an exported global is visible in JS as an instance of WebAssembly.Global, of which we need to extract the .value field anyway
    • this in turn causes issues for mutable static fields, since we need to republish changes
    • we cannot distinguish mutable static fields from immutable ones, so we have to use the same strategy for both
    • exported top-level defs must be seen by JS as function functions, but exported funcs are JS arrow functions

    Overall, the only things for which exports would work are for exported JS classes and objects.

    Instead, we uniformly use the following strategy for all top-level exports:

    • the JS code declares a non-initialized let for every top-level export, and exports it from the module with an ECMAScript export
    • the JS code provides a setter function that we import into a Wasm, which allows to set the value of that let
    • the Wasm code "publishes" every update to top-level exports to the JS code via this setter; this happens once in the start function for every kind of top-level export (see Emitter.genStartFunction), and in addition upon each reassignment of a top-level exported field (see FunctionEmitter.genAssign).

    This method declares the import of the setter on the Wasm side, for all kinds of top-level exports. In addition, for exported *methods*, it generates the implementation of the method as a Wasm function.

    The JS code is generated by Emitter.buildJSFileContent. Note that for fields, the JS lets are only "mirrors" of the state. The source of truth for the state remains in the Wasm Global for the static field. This is fine because, by spec of ECMAScript modules, JavaScript code that *uses* the export cannot mutate it; it can only read it.

    The calls to the setters, which actually initialize all the exported lets, are performed:

    • in the start function for all kinds of exports, and
    • in addition on every assignment to an exported mutable static field.