---
# System prepended metadata

title: Minimum Viable Module Source

---

# Minimum Viable Module Source

_**Concept:** Specify an absolute minimum `ModuleSource` implementation as part of the Import Reflection Proposal, so that source reflection can be fully specified to return an ECMA-262-defined object._

## ModuleSource Intrinsic

**Intrinsic**, not a global:

```javascript
class AbstractModuleSource {
  get [Symbol.toStringTag] () {
    throw new TypeError(`unimplemented`);
  }
  constructor () {
    throw new TypeError(`unimplemented`);
  }
}
```

## AbstractModuleSource Record

The `AbstractModuleSource` JS object has an internal slot pointing to its own `AbstractModuleSource Record`.

| Field            | Description                   | Default Value |
| ---------------- | ----------------------------- | ------------- |
| [[HostMetadata]] | Host-defined source metadata, used to host-default module resolution and initial value of `import.meta` (e.g. including `import.meta.url`) | _Empty_. The _Empty_ value is initially specified for `WebAssembly.Module`. |
| [[ModuleSourceObj]] | When directly exposed to JS, the JS object wrapper created by the host (a subclass of `ModuleSource`), which is then cached | _Empty_ |

### JavaScript Module Source

The JavaScript Module Source extension would be defined:

```javascript
class ModuleSource extends AbstractModuleSource {
  get [Symbol.toStringTag] () {
    if (this instanceof ModuleSource)
      return 'ModuleSource';
    return null;
  }
}
```

Defined as a **global**.

The `ModuleSource` constructor (`new ModuleSource('export function f () { ... }')`) could be defined at a later point to permit dynamic module creation (per https://github.com/tc39/proposal-compartments/blob/master/0-module-and-module-source.md).

### WebAssembly.Module Inheritance

Retroactively define

```javascript
WebAssembly.Module.prototype = Object.create(AbstractModuleSource);
```

as the base class of `WebAssembly.Module`, with the existing `WebAssembly.Module` `toStringTag` value.

```javascript
const mod = await WebAssembly.compileStreaming(await fetch('./mod.wasm'));
mod instanceof WebAssembly.Module // true
mod instanceof ModuleSource // true
mod[Symbol.toStringTag] === 'WebAssembly.Module' // true
```

This specification change in the WebAssembly JS API would be a minor subclassing change.

Web compat should not be affected since there would be no change to existing API functions. Only very specific checks like `wasmMod.__proto__ === Object` would be affected, which likely have no real world reliance.

## Instancing

When creating an instance from an `ModuleSource`, `[[HostMetadata]]` from the associated module source record can be used to inform the host-defined resolution and population of `import.meta`.

Instancing operations are left out of the initial implementation, to rather be provided by future specification work.

For example, for `WebAssembly.Module`, `WebAssembly.instantiate` provides the instancing function.

There may be a number of instancing approaches specified:

1. `new ModuleInstance(moduleSource, importHook)`
2. `import(moduleSource)` could be specified to correspond to the global canonical host instance phase of the provided source module, since they are globally identifiable and relatable to their module phase record.
3. `moduleSource.instantiate(importHook)` could be a defined-method for instance generation to create a `ModuleInstance` as a class method.

Of all of the above, specifying `import(moduleSource)` _may_ be possible within the current import reflection proposal as it does not depend on the `ModuleInstance` object. It would require as a specification detail, the definition of a weak global module asset registry along with their associated phase records.

## Binding APIs

The bindings API is left out of the initial minimal implementation.

In future, module source functions can be provided to enable dynamic binding lookups to determine the imported and exported specifier information for a source.

There may be a single unified bindings API such as `ModuleSource.prototype.getImports()` which can work for all module formats. Alternatively, binding inspection may be provided by external functions that are host-specific operating on specific Module Source subclasses, (e.g WebAssembly provides a `WebAssembly.exports(module)` function).

## Transfer

Module Sources are transferrable between agents via the Structured Clone algorithm, following how WebAssembly already supports this - https://webassembly.github.io/spec/web-api/index.html#serialization.

## CSP Integration

The CSP integration for module source would follow the same policy as a normal module import.

That is, the ability to obtain a module source through the module system is already guarded by CSP for the ES module system.

In future, if the constructor were permitted to allow explicit module source creation, this API would itself be a new CSP guard, for example requiring `unsafe-eval` or `wasm-unsafe-eval` for JS and Wasm respectively in order to be constructed.

## Security

There are three "gates" at which security policies may apply:

1. Module Source creation
2. Module Source transfer
3. Module Source instantiation

Hosts may implement whatever security policies they deem appropriate at these gates.

(1) correspond to CSP policies today, as described above, and would be fully handled by directly following the ESM integration and Wasm CSP policies.

Chrome implements some restrictions in (2) around same-origin, for example transferring a `WebAssembly.Module` object between frames with different origins will deny the transfer.

Other JS platforms such as Deno may integrate their own checks during (2) and/or (3).
