diff --git a/design/high-level/FAQ.md b/design/high-level/FAQ.md
index 7318c0761..f2316c991 100644
--- a/design/high-level/FAQ.md
+++ b/design/high-level/FAQ.md
@@ -1,5 +1,11 @@
# FAQ
+### How do WebAssembly Components relate to Web Components
+
+[Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) are a collection of technologies for creating reusable DOM custom elements. WebAssembly Components are a technology for creating reusable software interfaces (not tied to a single language or UI framework). See these [slides](https://docs.google.com/presentation/d/1PSC3Q5oFsJEaYyV5lNJvVgh-SNxhySWUqZ6puyojMi8/edit?slide=id.gced688a2b6_0_9#slide=id.gced688a2b6_0_9) for a rationale for this naming.
+
+Whenever there is a chance of ambiguity, the full WebAssembly (or Wasm) Component name should be used.
+
### How does WASI relate to the Component Model?
[WASI] is layered on top of the Component Model, with the Component Model
diff --git a/design/mvp/Explainer.md b/design/mvp/Explainer.md
index b0cee058f..55a3c2e22 100644
--- a/design/mvp/Explainer.md
+++ b/design/mvp/Explainer.md
@@ -3082,227 +3082,7 @@ In particular, the Component Model maintains the following invariants:
## JavaScript Embedding
-### JS API
-
-The [JS API] currently provides `WebAssembly.compile(Streaming)` which take
-raw bytes from an `ArrayBuffer` or `Response` object and produces
-`WebAssembly.Module` objects that represent decoded and validated modules. To
-natively support the Component Model, the JS API would be extended to allow
-these same JS API functions to accept component binaries and produce new
-`WebAssembly.Component` objects that represent decoded and validated
-components. The [binary format of components](Binary.md) is designed to allow
-modules and components to be distinguished by the first 8 bytes of the binary
-(splitting the 32-bit [`core:version`] field into a 16-bit `version` field and
-a 16-bit `layer` field with `0` for modules and `1` for components).
-
-Once compiled, a `WebAssembly.Component` could be instantiated using the
-existing JS API `WebAssembly.instantiate(Streaming)`. Since components have the
-same basic import/export structure as modules, this means extending the [*read
-the imports*] logic to support single-level imports as well as imports of
-modules, components and instances. Since the results of instantiating a
-component is a record of JavaScript values, just like an instantiated module,
-`WebAssembly.instantiate` would always produce a `WebAssembly.Instance` object
-for both module and component arguments.
-
-Types are a new sort of definition that are not ([yet][type-imports]) present
-in Core WebAssembly and so the [*read the imports*] and [*create an exports
-object*] steps need to be expanded to cover them:
-
-For type exports, each type definition would export a JS constructor function.
-This function would be callable iff a `[constructor]`-annotated function was
-also exported. All `[method]`- and `[static]`-annotated functions would be
-dynamically installed on the constructor's prototype chain, making sure to
-register `[get]` and `[set]` functions as getters and setters. In the case of
-re-exports and multiple exports of the same definition, the same constructor
-function object would be exported (following the same rules as WebAssembly
-Exported Functions today). In pathological cases (which, importantly, don't
-concern the global namespace, but involve the same actual type definition being
-imported and re-exported by multiple components), there can be collisions when
-installing constructors, methods and statics on the same constructor function
-object. In such cases, a conservative option is to undo the initial
-installation and require all clients to instead use the full explicit names
-as normal instance exports.
-
-For type imports, the constructors created by type exports would naturally
-be importable. Additionally, certain JS- and Web-defined objects that correspond
-to types (e.g., the `RegExp` and `ArrayBuffer` constructors or any Web IDL
-[interface object]) could be imported. The `ToWebAssemblyValue` checks on
-handle values mentioned below can then be defined to perform the associated
-[internal slot] type test, thereby providing static type guarantees for
-outgoing handles that can avoid runtime dynamic type tests.
-
-Lastly, when given a component binary, the compile-then-instantiate overloads
-of `WebAssembly.instantiate(Streaming)` would inherit the compound behavior of
-the abovementioned functions (again, using the `layer` field to eagerly
-distinguish between modules and components).
-
-For example, the following component:
-```wat
-;; a.wasm
-(component
- (import "one" (func))
- (import "two" (value string)) ๐ช
- (import "three" (instance
- (export "four" (instance
- (export "five" (core module
- (import "six" "a" (func))
- (import "six" "b" (func))
- ))
- ))
- ))
- ...
-)
-```
-and module:
-```wat
-;; b.wasm
-(module
- (import "six" "a" (func))
- (import "six" "b" (func))
- ...
-)
-```
-could be successfully instantiated via:
-```js
-WebAssembly.instantiateStreaming(fetch('./a.wasm'), {
- one: () => (),
- two: "hi", ๐ช
- three: {
- four: {
- five: await WebAssembly.compileStreaming(fetch('./b.wasm'))
- }
- }
-});
-```
-
-The other significant addition to the JS API would be the expansion of the set
-of WebAssembly types coerced to and from JavaScript values (by [`ToJSValue`]
-and [`ToWebAssemblyValue`]) to include all of [`valtype`](#type-definitions).
-At a high level, the additional coercions would be:
-
-| Type | `ToJSValue` | `ToWebAssemblyValue` |
-| ---- | ----------- | -------------------- |
-| `bool` | `true` or `false` | `ToBoolean` |
-| `s8`, `s16`, `s32` | as a Number value | `ToInt8`, `ToInt16`, `ToInt32` |
-| `u8`, `u16`, `u32` | as a Number value | `ToUint8`, `ToUint16`, `ToUint32` |
-| `s64` | as a BigInt value | `ToBigInt64` |
-| `u64` | as a BigInt value | `ToBigUint64` |
-| `f32`, `f64` | as a Number value | `ToNumber` |
-| `char` | same as [`USVString`] | same as [`USVString`], throw if the USV length is not 1 |
-| `record` | TBD: maybe a [JS Record]? | same as [`dictionary`] |
-| `variant` | see below | see below |
-| `list` | create a typed array copy for number types; otherwise produce a JS array (like [`sequence`]) | same as [`sequence`] |
-| `string` | same as [`USVString`] | same as [`USVString`] |
-| `tuple` | TBD: maybe a [JS Tuple]? | TBD |
-| `flags` | TBD: maybe a [JS Record]? | same as [`dictionary`] of optional `boolean` fields with default values of `false` |
-| `enum` | same as [`enum`] | same as [`enum`] |
-| `option` | same as [`T?`] | same as [`T?`] |
-| `result` | same as `variant`, but coerce a top-level `error` return value to a thrown exception | same as `variant`, but coerce uncaught exceptions to top-level `error` return values |
-| `map` | `new Map(_)` | `Map`s directly or other objects via `Object.entries(_)` |
-| `own`, `borrow` | see below | see below |
-| `future` | to a `Promise` | from a `Promise` |
-| `stream` | to a `ReadableStream` | from a `ReadableStream` |
-
-Notes:
-* Function parameter names are ignored since JavaScript doesn't have named
- parameters.
-* If a function's result type list is empty, the JavaScript function returns
- `undefined`. If the result type list contains a single unnamed result, then
- the return value is specified by `ToJSValue` above. Otherwise, the function
- result is wrapped into a JS object whose field names are taken from the result
- names and whose field values are specified by `ToJSValue` above.
-* In lieu of an existing standard JS representation for `variant`, the JS API
- would need to define its own custom binding built from objects. As a sketch,
- the JS values accepted by `(variant (case "a" u32) (case "b" string))` could
- include `{ tag: 'a', value: 42 }` and `{ tag: 'b', value: "hi" }`.
-* For `option`, when Web IDL doesn't support particular type
- combinations (e.g., `(option (option u32))`), the JS API would fall back to
- the JS API of the unspecialized `variant` (e.g.,
- `(variant (case "some" (option u32)) (case "none"))`, despecializing only
- the problematic outer `option`).
-* When coercing `ToWebAssemblyValue`, `own` and `borrow` handle types would
- dynamically guard that the incoming JS value's dynamic type was compatible
- with the imported resource type referenced by the handle type. For example,
- if a component contains `(import "Object" (type $Object (sub resource)))` and
- is instantiated with the JS `Object` constructor, then `(own $Object)` and
- `(borrow $Object)` could accept JS `object` values.
-* When coercing `ToJSValue`, handle values would be wrapped with JS objects
- that are instances of the handles' resource type's exported constructor
- (described above). For `own` handles, a [`FinalizationRegistry`] would be
- used to drop the `own` handle (thereby calling the resource destructor) when
- its wrapper object was unreachable from JS. For `borrow` handles, the wrapper
- object would become dynamically invalid (throwing on any access) at the end
- of the export call.
-* When an imported JavaScript function is a built-in function wrapping a Web
- IDL function, the specified behavior should allow the intermediate JavaScript
- call to be optimized away when the types are sufficiently compatible, falling
- back to a plain call through JavaScript when the types are incompatible or
- when the engine does not provide a separate optimized call path.
-
-
-### ESM-integration
-
-Like the JS API, [ESM-integration] can be extended to load components in all
-the same places where modules can be loaded today, branching on the `layer`
-field in the binary format to determine whether to decode as a module or a
-component.
-
-When present, the [`external-id`](#import-and-export-definitions) attribute of
-an `import` would be used as the [Module Specifier], thereby giving components
-the same naming expressivity as JavaScript (in particular, for importing URLs).
-In the absence of an `external-id`, the always-present, but syntactically-
-restrictive, `externname` of the import would be used instead.
-
-The main remaining question is how to deal with component imports having a
-single string as well as the new importable component, module and instance
-types. Going through these one by one:
-
-For component imports of module type, we need a new way to request that the ESM
-loader parse or decode a module without *also* instantiating that module.
-Recognizing this same need from JavaScript, there is a TC39 proposal called
-[Import Reflection] that adds the ability to write, in JavaScript:
-```js
-import Foo from "./foo.wasm" as "wasm-module";
-assert(Foo instanceof WebAssembly.Module);
-```
-With this extension to JavaScript and the ESM loader, a component import
-of module type can be treated the same as `import ... as "wasm-module"`.
-
-Component imports of component type would work the same way as modules,
-potentially replacing `"wasm-module"` with `"wasm-component"`.
-
-In all other cases, the (single) string imported by a component is first
-resolved to a [Module Record] using the same process as resolving the
-[Module Specifier] of a JavaScript `import`. After this, the handling of the
-imported Module Record is determined by the import type:
-
-For imports of instance type, the ESM loader would treat the exports of the
-instance type as if they were the [Named Imports] of a JavaScript `import`.
-Thus, single-level imports of instance type act like the two-level imports
-of Core WebAssembly modules where the first-level has been factored out. Since
-the exports of an instance type can themselves be instance types, this process
-must be performed recursively.
-
-Otherwise, function or value imports are treated like an [Imported Default Binding]
-and the Module Record is converted to its default value. This allows the following
-component:
-```wat
-;; bar.wasm
-(component
- (import "./foo.js" (func (result string)))
- ...
-)
-```
-to be satisfied by a JavaScript module via ESM-integration:
-```js
-// foo.js
-export default () => "hi";
-```
-when `bar.wasm` is loaded as an ESM:
-```html
-
-```
-
+This has been moved to [JS-Overview.md](JS-Overview.md) and [JS-Reference.md](JS-Reference.md).
## Examples
diff --git a/design/mvp/JS-Explainer.md b/design/mvp/JS-Explainer.md
new file mode 100644
index 000000000..38036f335
--- /dev/null
+++ b/design/mvp/JS-Explainer.md
@@ -0,0 +1,352 @@
+# WebAssembly Components JS-API Explainer
+
+This explainer describes how WebAssembly Components (hereafter 'components' and _not_ [web components](../high-level/FAQ.md#how-do-webassembly-components-relate-to-web-components)) can be used from JS in supported runtimes.
+
+See the [reference](./JS-Reference.md) for an in-depth walkthrough.
+
+**This is a draft and is not complete.**
+
+## Walkthrough
+
+### Components that export a function
+
+Let's start with a component that imports nothing:
+
+```wat
+(component
+ ...
+ (export "greet"
+ (func (param "who" string) (result string))
+ )
+)
+```
+
+Given the above component (compiled from the WAT text format to the [binary](./Binary.md) format), you can execute it with:
+
+```js
+const { instance } = await WebAssembly.instantiate(bytes);
+
+instance.exports.greet("world"); // "hello, world"
+```
+
+The `exports` property of an instance holds one property per export and `greet` is an ordinary JS function
+
+Component names are kebab-case and JS function names are [camelCase](./JS-Reference.md#names), so a function export named `greet-loudly` would be `greetLoudly`.
+
+Arguments are coerced to their expected type, and if that fails a `TypeError` is thrown:
+
+```js
+instance.exports.greet(42); // "hello, 42"
+instance.exports.greet(); // TypeError
+```
+
+`undefined` is substituted for missing arguments, and extra arguments are ignored, just as in JS.
+
+### Components that import a function
+
+Now a component that imports:
+
+```wat
+(component
+ (import "log"
+ (func (param "message" string))
+ )
+ ...
+ (export "run" (func))
+)
+```
+
+The import `log` must be a JS callable object, and will be called with a JS String.
+
+We can provide the `console.log` builtin as here:
+
+```js
+const imports = { log: console.log };
+
+const { instance } =
+ await WebAssembly.instantiate(bytes, imports);
+
+instance.exports.run(); // logs "hello"
+```
+
+Or provide a custom implementation:
+
+```js
+const lines = [];
+const log = (message) => { lines.push(message); };
+const imports = { log };
+
+const { instance } =
+ await WebAssembly.instantiate(bytes, imports);
+```
+
+### Values at a glance
+
+Components and JS maintain separate type/value systems, so any value crossing the boundary needs a defined translation in both directions.
+
+The following table describes how a component value is converted into a JS value.
+
+| Component type | JS type |
+|---|---|
+| `bool` | Boolean |
+| `s8`-`s32`, `u8`-`u32` | Number, an exact integer |
+| `s64`, `u64` | BigInt |
+| `f32`, `f64` | Number, including NaN and infinities |
+| `char` | String of exactly one Unicode scalar value |
+| `string` | String, well formed |
+| `list` | `Uint8Array` |
+| `list`, `list`, `tuple` | Array |
+| `record { field-name: T, ... }` | null-prototype object, `{ fieldName: T, ... }` |
+| `flags "flag-a" "flag-b"` | null-prototype object of Booleans, `{ flagA: bool, flagB: bool }` |
+| `enum "case-a" "case-b"` | String, the case label verbatim |
+| `option` (if `T` is not `option`) | `null`, or the payload |
+| `option>` | treated as variant, see below |
+| `result` (if in return position of function) | if `E` { thrown as a `WebAssembly.ComponentError` } else { `T` } |
+| `variant` | `{ kind: string, value: T }` |
+| `map` | `Map` |
+| `own`, `borrow` | the original JS value for an imported resource type, an instance of its class for an exported one |
+| `future`, `stream`, `error-context` | not yet specified |
+
+Converting a JS value to a component value accepts all of the above, but also has additional coercions. See [ToJSValue](./JS-Reference.md#tojsvalue) and [ToComponentValue](./JS-Reference.md#tocomponentvalue) for detailed algorithms.
+
+### Loading with ESM
+
+[ESM-integration](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration) extends to components. The loader branches on the `layer` field of the binary, so a component loads anywhere a core module does today.
+
+Each component import becomes a JS import, and its module specifier is the import's [`external-id`](Explainer.md#import-and-export-definitions) if it has one and its name otherwise:
+
+```wat
+(component
+ (import "slugify"
+ (external-id
+ "https://esm.unpkg.com/slugify@1.6.6")
+ (func (param "text" string) (result string))
+ )
+ ...
+ (export "run" (func))
+)
+```
+
+```html
+
+```
+
+### Handling expected errors using `result`
+
+Component functions signal failure using a `result` value:
+ 1. Exported component functions that return an error `result` throw JS exceptions.
+ 1. Imported JS functions that throw JS exceptions are captured as a `result`.
+
+An imported JS function that throws where the component asked for a plain return type results in a trap.
+
+```wat
+(component
+ (import "lookup"
+ (func (param "key" string) (result string (error string)))
+ )
+ ...
+ (export "parse"
+ (func (param "text" string) (result u32 (error string)))
+ )
+)
+```
+
+`parse` tries to parse its `text` argument as an integer, and if that fails performs a fallible lookup.
+
+```js
+const imports = {
+ lookup: (key) => { throw `no such key: ${key}`; },
+};
+const { instance } =
+ await WebAssembly.instantiate(bytes, imports);
+
+instance.exports.parse("42"); // 42
+
+try {
+ instance.exports.parse("$name");
+} catch (e) {
+ e instanceof WebAssembly.ComponentError; // true
+ e.data; // "no such key: $name"
+}
+```
+
+In the second call, parsing fails and leads to a call to `lookup` which throws a JS exception. This is converted to a `result` and consumed by the component. The component then propagates it to the original JS caller as a thrown `ComponentError` carrying the original message.
+
+### Handling unexpected failures with lockdown
+
+In the case a component is executing and traps, the trap is surfaced as a `WebAssembly.RuntimeError` (as in core wasm), and then the component is locked down to prevent future execution. If an exported function from the component is invoked again, it immediately results in another trap.
+
+```js
+import { buggyFunction, normalFunction } from "component.wasm"
+
+// normalFunction doesn't trap
+normalFunction();
+
+try {
+ // Calling buggyFunction traps and locks down the component.
+ buggyFunction()
+} catch (err) {
+ assert(err instanceof WebAssembly.RuntimeError);
+ try {
+ // Calling normalFunction again leads to a lockdown trap.
+ normalFunction();
+ } catch (err) {
+ assert(err instanceof WebAssembly.RuntimeError);
+ }
+}
+```
+
+### Importing JS values as resource types
+
+Components can also accept JS values as resources. A resource type import is satisfied by passing a constructor function.
+
+Whenever a JS value must be converted to a resource type, an `instanceof` check is performed against the imported constructor. If the constructor is a [WebIDL interface object](https://webidl.spec.whatwg.org/#interface-object) or an [exported component resource constructor](#exporting-a-resource), a precise [brand check](./JS-Reference.md#brand-checks) is performed.
+
+Any imported function whose name is tagged `[constructor]`, `[method]`, or `[static]` is looked up on the imported constructor instead of the imports object:
+
+| name | import lookup |
+|---|---|
+| `[constructor]R` | `R` |
+| `[method]R.M` | `R.prototype.M` |
+| `[static]R.S` | `R.S` |
+
+The above allows most JS classes to be imported as a resource by just passing the constructor function:
+
+```wat
+(component
+ (import "element"
+ (type $element (sub resource))
+ )
+ (import
+ "[method]element.query-selector"
+ (func
+ (param "self" (borrow $element))
+ (param "selectors" string)
+ (result (option (own $element)))
+ )
+ )
+ (import "[method]element.get-attribute"
+ (func
+ (param "self" (borrow $element))
+ (param "name" string)
+ (result (option string))
+ )
+ )
+ ...
+ (export "find"
+ (func
+ (param "root" (borrow $element))
+ (param "selectors" string)
+ (result (option string))
+ )
+ )
+)
+```
+
+```js
+const imports = { element: Element };
+const { instance } =
+ await WebAssembly.instantiate(bytes, imports);
+
+instance.exports.find(document.body, "h1"); // "page-title" or null
+```
+
+Component [`plainnames`](./Explainer.md#import-and-export-definitions) as used in imports/exports are converted to idiomatic JS names ([rules here](./JS-Reference.md#names)). Type names are converted to pascal case, and everything else is converted to camel case. This allows the component imports of `element` and `get-attribute` to be satisfied with `Element` and `getAttribute` respectively.
+
+### Importing from the JS global
+
+The example above still needs someone to write `{ element: Element }`. A component can skip that and take its imports straight from the global object by importing `wasm:js/global`:
+
+```wat
+(component
+ (import "wasm:js/global"
+ (instance $g
+ (export "btoa"
+ (func (param "data" string) (result string))
+ )
+
+ (export "element" (type $element (sub resource)))
+ (export "[method]element.get-attribute"
+ (func
+ (param "self" (borrow $element))
+ (param "name" string)
+ (result (option string))
+ )
+ )
+ )
+ )
+ (alias export $g "element" (type $el))
+
+ ...
+
+ (export "encode-id"
+ (func
+ (param "el" (borrow $el))
+ (result (option string))
+ )
+ )
+)
+```
+
+```js
+const exports =
+ await WebAssembly.instantiate(bytes, { builtins: ["js/global"] }).exports;
+
+exports.encodeId(document.body);
+```
+
+Importing from `wasm:js/global` is equivalent to an imports object with: `{ "wasm:js/global": globalThis }`. The normal rules for reading from the imports object still apply.
+
+ESM-integration defaults to enabling `js/global` in the compile options (the `wasm:` prefix is implicit) which allows a component to import and use web APIs without any glue code:
+
+```html
+
+```
+
+### Exporting a resource
+
+A resource type exported from a component becomes a JS class:
+
+```wat
+(component
+ ...
+
+ (export "counter" (type $counter (sub resource)))
+ (export "[constructor]counter"
+ (func (result (own $counter)))
+ )
+ (export "[method]counter.increment-once"
+ (func
+ (param "self" (borrow $counter))
+ (result u32)
+ )
+ )
+)
+```
+
+```js
+const { instance } = await WebAssembly.instantiate(bytes);
+const { Counter } = instance.exports;
+
+let c = new Counter();
+c.incrementOnce(); // 1
+c.incrementOnce(); // 2
+```
+
+As in the importing a resource case above, component names are converted to JS names. This allows an export of `counter` to become a JS class named `Counter`, and `increment-once` to become `incrementOnce`.
+
+## Status
+
+The following have no binding yet:
+- Component model async features such as `async` functions, `future`, `stream`.
+- `error-context`.
+
+Everything else we know to be open is collected in the reference's [follow ups](./JS-Reference.md#follow-ups).
diff --git a/design/mvp/JS-Reference.md b/design/mvp/JS-Reference.md
new file mode 100644
index 000000000..d78cef10b
--- /dev/null
+++ b/design/mvp/JS-Reference.md
@@ -0,0 +1,1107 @@
+# WebAssembly Components JS-API Reference
+
+This is the in-depth reference for the WebAssembly Component JS-API. See the [component model explainer](./Explainer.md) for an in-depth explanation of WebAssembly Components (hereafter 'components'). See the [JS-API explainer](./JS-Explainer.md) for a higher-level introduction to the JS-API.
+
+**This is a draft and is not complete. Major details are unresolved, and there are bugs.**
+
+## Goals
+
+1. Components can import and use most web and JS APIs
+2. Components can export an API usable by JS
+3. Components interact with the web platform in similar ways to JS:
+ 1. Components can feature test whether APIs are present
+ 1. Components work whether they are importing a web API, or a JS polyfill, or a component polyfill
+ 1. Components are tolerant of web API evolution
+ 1. Component misuse of a web API results in failure at that call-site, not a link time error
+4. Components have better web API performance than WebAssembly modules today
+
+## Non-goals
+
+1. Components importing every kind of web API
+1. Components exporting any kind of JS API
+
+The gaps ideally will narrow over time after a v1.0 release, but may not ever fully close.
+
+## The WebAssembly namespace
+
+We extend the imperative WebAssembly JS-API interfaces to also allow validation, compilation, and instantiation of components in addition to modules.
+
+```webidl
+[LegacyNamespace=WebAssembly, Exposed=*]
+interface Component {
+ constructor([AllowResizable] AllowSharedBufferSource bytes, optional WebAssemblyCompileOptions options = {});
+};
+
+[LegacyNamespace=WebAssembly, Exposed=*]
+interface ComponentInstance {
+ constructor(Component component, optional object importsObject);
+ readonly attribute object exports;
+};
+
+typedef (Component or Module) InstantiateSource;
+
+dictionary WebAssemblyInstantiatedComponentSource {
+ required Component component;
+ required ComponentInstance instance;
+};
+
+[Exposed=*]
+namespace WebAssembly {
+ // Same as before, but now will detect if the bytes are a component or module and dispatch differently.
+ boolean validate([AllowResizable] AllowSharedBufferSource bytes, optional WebAssemblyCompileOptions options = {});
+ Promise compile([AllowResizable] AllowSharedBufferSource bytes, optional WebAssemblyCompileOptions options = {});
+ Promise<(WebAssemblyInstantiatedSource or WebAssemblyInstantiatedComponentSource)> instantiate(
+ [AllowResizable] AllowSharedBufferSource bytes, optional object importObject, optional WebAssemblyCompileOptions options = {});
+
+ // Now takes an InstantiateSource instead of just a Module, and returns a
+ // ComponentInstance for a Component.
+ Promise<(Instance or ComponentInstance)> instantiate(
+ InstantiateSource moduleOrComponentObject, optional object importObject);
+};
+```
+
+We also add an error type for component functions that return `result<_, E>` to JS:
+
+```webidl
+[LegacyNamespace=WebAssembly, Exposed=*]
+interface ComponentError : Error {
+ constructor(optional DOMString message = "", optional any data);
+ readonly attribute any data;
+};
+```
+
+`data` is the converted `E` value. See [Create the exports object](#create-the-exports-object).
+
+## Validation/compilation
+
+Validation and compilation of components defer to the underlying component embedding interface. This reference adds nothing to it.
+
+## Component store
+
+A component store is defined by the [canonical ABI](./CanonicalABI.md#component-instances) and is analogous to the core wasm store. It contains a set of component instances and tasks. A store is also a unit of failure where a trap can trigger a lockdown which prevents further execution within the store.
+
+In contrast with core wasm, every component instantiated by the JS-API or ESM (i.e. 'top level') is partitioned to its own store. This means that all top-level component interaction is mediated by the JS-API. A component export imported by another component is treated the same as any other JS import.
+
+This ensures that whether an ESM is implemented as a component or with JS is an implementation detail that can change over time. This also means that a failure within a top-level component instance that triggers a lockdown affects only that component instance.
+
+Nested components share a common store and directly link following the normal component rules. This should be sufficient for most cases where you want to directly link components. In the future, we could consider an extension to instantiate two components within the same store.
+
+## Entry points
+
+A `Component` has the following slots:
+ 1. [[Component]] - the compiled component.
+ 1. [[EnabledBuiltins]] - the enabled builtins.
+
+A `ComponentInstance` has the following slots:
+ 1. [[Store]] - the component store.
+ 1. [[ComponentInstance]] - the component instance.
+ 1. [[Exports]] - the [exports object](#create-the-exports-object).
+ 1. [[HostResourceTypes]] - map from [abstract type key](#abstract-and-transparent-types) to [host resource type](#host-resource-types-and-values).
+ 1. [[GuestResourceClasses]] - map from [abstract type key](#abstract-and-transparent-types) to [guest resource class](#guest-resource-classes).
+
+To `trap` given a component instance |instance|:
+1. Invoke |instance|.[[Store]].lock_down().
+1. Throw a `WebAssembly.RuntimeError`.
+
+A trapped instance is locked down: every later call into it traps again before running any code.
+
+A call has *entered the guest* once the canonical ABI has, on the call's behalf, invoked any function of the component instance (such as `realloc`) or modified one of its handle tables. A conversion that throws after that point leaves guest state the guest never sees, so the instance is locked down as if the call had trapped, while the original exception still propagates. A conversion that throws before that point leaves the instance untouched.
+
+To `construct a Component` given |bytes| and |options|:
+1. Let |stableBytes| be a copy of the bytes held by |bytes|.
+1. Let |enabledBuiltins| be the result of parsing [`builtins`](#builtin-imports) from |options|.
+1. Let |component| be the result of compiling |stableBytes| as a component, per the embedding interface.
+1. If compilation fails:
+ 1. Throw a `WebAssembly.CompileError`.
+1. Set **this**.[[Component]] to |component|.
+1. Set **this**.[[EnabledBuiltins]] to |enabledBuiltins|.
+
+To `construct a ComponentInstance` given a `Component` |component|, and |importsObject|:
+1. Let |enabledBuiltins| be |component|.[[EnabledBuiltins]].
+1. Let |result| be ? [`instantiate a component from an imports object`](#instantiation) given |component|.[[Component]], |importsObject|, |enabledBuiltins|.
+1. Set **this**.[[Store]] to |result|.[[Store]].
+1. Set **this**.[[ComponentInstance]] to |result|.[[ComponentInstance]].
+1. Set **this**.[[Exports]] to |result|.[[Exports]].
+1. Set **this**.[[HostResourceTypes]] to |result|.[[HostResourceTypes]].
+1. Set **this**.[[GuestResourceClasses]] to |result|.[[GuestResourceClasses]].
+
+The `exports` getter returns **this**.[[Exports]].
+
+`validate` is modified to validate the bytes as a component if the `layer` field of the binary indicates a component.
+`compile`/`instantiate` are modified to asynchronously compile/instantiate the bytes as a component if the `layer` field indicates a component.
+
+## Names
+
+Component import/export `plainname`s contain [`label`s](Explainer.md#import-and-export-definitions) that must be transformed into an identifier for use with JS.
+
+Fully qualified component import/export `interfacename`s (such as `wasi:http/handler@1.0.0`) are used as-is when converted to JS strings or as [module specifiers](#webassembly-esm-integration).
+
+We define `PascalCase(label)` and `CamelCase(label)` below.
+
+| `label` | `PascalCase` | `CamelCase` |
+|---|---|---|
+| `element` | `Element` | `element` |
+| `query-selector` | `QuerySelector` | `querySelector` |
+| `inner-HTML` | `InnerHTML` | `innerHTML` |
+| `XML-http-request` | `XMLHttpRequest` | `xmlHttpRequest` |
+| `URL` | `URL` | `url` |
+| `a1-2-3` | `A123` | `a123` |
+
+Every `plainname` matches exactly one of the four patterns below, and no `interfacename` matches any of them. The algorithms in this document dispatch on these patterns and read their named captures. `` stands for the [`label`](Explainer.md#import-and-export-definitions) production.
+
+| Pattern | Regex | Example |
+|---|---|---|
+| *Plain* | `^(?)$` | `query-selector` |
+| *Property* | `^\[(?get\|set)\](?)$` | `[get]inner-HTML` |
+| *Constructor* | `^\[constructor\](?)$` | `[constructor]element` |
+| *Member* | `^\[(?method\|static)\](?:\[(?get\|set)\])?(?)\.(?)$` | `[method][set]element.inner-HTML` |
+
+`plainname`'s are restricted by component [strong uniqueness](./Explainer.md#name-uniqueness). This helps us statically avoid collisions when building high-level export types (such as [guest resource classes](#guest-resource-classes)) and using the name transformations below.
+
+`LabelOf`(|name|), where |name| is a `plainname`, returns the label that names the definition in JS:
+1. If |name| matches *Constructor*:
+ 1. Return the `resource` capture.
+1. Return the `name` capture.
+
+`Fragments`(|label|):
+1. Return the List of Strings produced by splitting |label| on occurrences of U+002D (-). The hyphens themselves are discarded.
+
+`Capitalize`(|fragment|):
+1. If |fragment| is an [`acronym`](Explainer.md#import-and-export-definitions):
+ 1. Return |fragment|.
+1. Return |fragment| with its first character uppercased.
+
+`PascalCase`(|label|):
+1. Let |fragments| be `Fragments`(|label|).
+1. Let |result| be the empty String.
+1. For each |fragment| of |fragments|:
+ 1. Set |result| to the string-concatenation of |result| and `Capitalize`(|fragment|).
+1. Return |result|.
+
+`CamelCase`(|label|):
+1. Let |fragments| be `Fragments`(|label|).
+1. Let |result| be |fragments|[0] with every character lowercased.
+1. For each |fragment| of |fragments| after the first:
+ 1. Set |result| to the string-concatenation of |result| and `Capitalize`(|fragment|).
+1. Return |result|.
+
+The JS name of an import or export declaration is then:
+
+`JSName`(|decl|):
+1. If |decl|.Name is an `interfacename`:
+ 1. Return |decl|.Name.
+1. If |decl| is a type declaration:
+ 1. Return `PascalCase`(`LabelOf`(|decl|.Name)).
+1. Return `CamelCase`(`LabelOf`(|decl|.Name)).
+
+An import's specifier is its [`external-id`](Explainer.md#import-and-export-definitions) attribute if it has one, and its JS name otherwise:
+
+`JSSpecifier`(|decl|):
+1. If |decl| has an `external-id` attribute that is the Unicode string |id|:
+ 1. Return |id|.
+1. Return `JSName`(|decl|).
+
+## Types and values
+
+Components and JS maintain separate type/value systems, so any value crossing the boundary needs a defined translation in both directions.
+
+This section specifies that translation as two abstract operations:
+1. `ToJSValue` - convert a component value to a JS value.
+1. `ToComponentValue` - convert a JS value to a component value of a given type.
+
+Roundtripping from `ToJSValue` back through `ToComponentValue` is designed to be strictly the identity function with the following exceptions:
+ 1. A `map` with duplicate keys keeps only the last pair per key (see [`ToJSValueMap`](#tojsvalue))
+ 1. Float NaNs are [canonicalized](CanonicalABI.md#loading)
+
+Every object a conversion creates, including any error it throws, belongs to the *component realm*: the realm of the `WebAssembly` namespace the component was instantiated through.
+
+### ToJSValue
+
+`ToJSValue(componentValue, componentValType)` converts a component value to a JS value. It is infallible.
+
+Dispatch on `componentValType`:
+
+- `bool` โ Boolean.
+- Integer types other than `s64`/`u64` โ Number, an exact integer.
+- `s64` / `u64` โ BigInt.
+- `f32` / `f64` โ Number, including NaN and infinities.
+- `char` โ String containing exactly the one Unicode scalar value.
+- `string` โ String [(well formed)](https://tc39.es/ecma262/#sec-isstringwellformedunicode).
+- `list` โ A `scalar typed array class` over a fresh ArrayBuffer holding the scalars.
+- `list` โ `ToJSValueList`(the elements, T).
+- `list` โ as `list`; `length` is `N`.
+- `tuple` โ as `list`, with element `i` converted as `T_i`.
+- `record { f: T, ... }` โ `ToJSValueRecord`(|componentValue|, the fields).
+- `flags "L"+` โ `ToJSValueFlags`(|componentValue|, the labels).
+- `enum "L"+` โ String, the label verbatim.
+- Top-level `option` โ **undefined** for `none`, else `ToJSValue`(the payload, T).
+- `variant`, and nested `option`, and `result` outside return position โ `ToJSValueVariant`(|componentValue|, the cases). In return position a `result` is unwrapped instead, into a return value or a thrown `ComponentError` (see [Read the imports](#read-the-imports-object) and [Create the exports object](#create-the-exports-object)).
+- `map` โ `ToJSValueMap`(|componentValue|, K, V).
+- `own` / `borrow` โ See [Resource types](#resource-types).
+- `future` โ a Promise (TODO).
+- `stream` โ an `AsyncIterator` (TODO).
+- `error-context` โ TODO.
+
+The `scalar typed array class` is given by:
+
+| Component type | JS class |
+|----------------|----------|
+| `s8` | Int8Array |
+| `u8` | Uint8Array |
+| `s16` | Int16Array |
+| `u16` | Uint16Array |
+| `s32` | Int32Array |
+| `u32` | Uint32Array |
+| `f32` | Float32Array |
+| `f64` | Float64Array |
+| `s64` | BigInt64Array |
+| `u64` | BigUint64Array |
+
+`ToJSValueList(values, T)`:
+1. Let |n| be the number of |values|.
+1. Let |array| be `ArrayCreate`(|n|).
+1. For each i in [0, |n|):
+ 1. Perform `CreateDataPropertyOrThrow`(|array|, `ToString`(๐ฝ(i)), `ToJSValue`(|values|[i], T)).
+1. Return |array|.
+
+`ToJSValueRecord(value, fields)`:
+1. Let |object| be `OrdinaryObjectCreate`(**null**).
+1. For each field `f: T` of |fields|, in declaration order:
+ 1. Perform `CreateDataPropertyOrThrow`(|object|, `CamelCase`(f), `ToJSValue`(|value|'s `f`, T)).
+1. Return |object|.
+
+`ToJSValueFlags(value, labels)`:
+1. Let |object| be `OrdinaryObjectCreate`(**null**).
+1. For each label `L` of |labels|:
+ 1. Perform `CreateDataPropertyOrThrow`(|object|, `CamelCase`(L), |value|'s `L` bit as a Boolean).
+1. Return |object|.
+
+`ToJSValueVariant(value, cases)`:
+1. Let |object| be `OrdinaryObjectCreate`(**null**).
+1. Perform `CreateDataPropertyOrThrow`(|object|, "kind", `PascalCase`(`CaseLabelOf`(|value|, |cases|))).
+1. If that case has a payload of type T:
+ 1. Perform `CreateDataPropertyOrThrow`(|object|, "value", `ToJSValue`(`PayloadOf`(|value|), T)).
+1. Return |object|.
+
+This operation is used for variant, and also cases in the above table where we can't specialize the behavior of `option` and `result`.
+
+`ToJSValueMap(value, K, V)`:
+1. Let |map| be a new ordinary `Map` object with an empty [[MapData]] and the component realm's `%Map.prototype%`.
+1. For each pair (k, v) of |value|, in order:
+ 1. Let |key| be `ToJSValue`(k, K).
+ 1. Let |mapValue| be `ToJSValue`(v, V).
+ 1. If [[MapData]] has an entry whose key is `SameValueZero` to |key|:
+ 1. Set that entry's value to |mapValue|.
+ 1. Else:
+ 1. Append an entry (|key|, |mapValue|) to [[MapData]].
+1. Return |map|.
+
+A `map` is a [specialization](Explainer.md#type-definitions) of `list>` where the last pair for a key defines its value. So `[(a,1),(a,2)]` round-trips from a component value to JS and back as `[(a,2)]`.
+
+### ToComponentValue
+
+`ToComponentValue(jsValue, targetComponentType)` converts a JS value to a component value. It may throw if the JS value doesn't match the component value type.
+
+A component value is a specification device. An implementation lowers the JS value straight into the component's memory and handle tables, so the steps below are interleaved with the canonical ABI's lowering. A final specification would need to be more precise on the ordering of observable actions.
+
+Dispatch on `targetComponentType`:
+
+- `bool` โ `ToBoolean`(|jsValue|).
+- Integer types โ `ToComponentValueInteger`(|jsValue|, the type).
+- Float types โ `ToComponentValueFloat`(|jsValue|, the type).
+- `char` โ ? `ToString`(|jsValue|); it must consist of exactly one Unicode scalar value, else throw a `TypeError`. A lone surrogate is not a scalar value and is therefore a `TypeError`.
+- `string` โ ? `ToString`(|jsValue|), then replace each unpaired surrogate with U+FFFD (matching WebIDL `USVString`).
+- `list` โ `ToComponentValueScalarList`(|scalar|, |jsValue|).
+- `list` โ `ToComponentValueList`(|jsValue|, T).
+- `list` โ as `list`, then the length must be exactly `N`, else throw a `TypeError`.
+- `tuple` โ as `list`, then the length must be exactly the arity, and element `i` converts to `T_i`.
+- `record { f: T, ... }` โ `ToComponentValueRecord`(|jsValue|, the fields).
+- `flags "L"+` โ `ToComponentValueFlags`(|jsValue|, the labels).
+- `enum` โ ? `ToString`(|jsValue|) must be one of the labels, else throw a `TypeError`.
+- Top-level `option` โ **null** and **undefined** both give `none`; anything else gives `some(ToComponentValue(jsValue, T))`.
+- `variant`, and nested `option`, and `result` outside return position โ `ToComponentValueVariant`(|jsValue|, the cases). In return position a `result` is unwrapped instead: a JS return value becomes `result.ok`, and a thrown exception becomes `result.error` (see [Read the imports](#read-the-imports-object) and [Create the exports object](#create-the-exports-object)).
+- `map` โ `ToComponentValueMap`(|jsValue|, K, V).
+- `own` / `borrow` โ See [Resource types](#resource-types).
+- `future` โ TODO.
+- `stream` โ TODO.
+- `error-context` โ TODO.
+
+`ToComponentValueInteger(jsValue, t)`:
+1. If |t| is `s64` or `u64` and `Type`(|jsValue|) is BigInt:
+ 1. Let |n| be |jsValue|'s value.
+ 1. If |n| is outside |t|'s range:
+ 1. Throw a `TypeError`.
+ 1. Return |n|.
+1. Let |number| be ? `ToNumber`(|jsValue|).
+1. If |number| is `NaN` or an infinity:
+ 1. Throw a `TypeError`.
+1. Let |n| be |number| truncated toward zero.
+1. If |n| is outside |t|'s range:
+ 1. Throw a `TypeError`.
+1. Return |n|.
+
+`ToComponentValueFloat(jsValue, t)`:
+1. Let |num| be ? `ToNumber`(|jsValue|).
+1. If |t| is `f32`:
+ 1. Set |num| to |num| rounded to the nearest f32 value (ties to even).
+1. Return |num|.
+
+`NaN` and infinities are accepted (matching WebIDL `unrestricted float`/`unrestricted double`).
+
+`ToComponentValueScalarList(scalar, jsValue)`:
+1. If |jsValue| has a [[TypedArrayName]] internal slot whose value is the `scalar typed array class` for |scalar|:
+ 1. If |jsValue|'s underlying buffer is detached or |jsValue| is out of bounds:
+ 1. Throw a `TypeError`.
+ 1. Return one |scalar| per element of |jsValue|, in order.
+1. Return `ToComponentValueList`(|jsValue|, |scalar|).
+
+A typed array is copied directly, since that is what `ToJSValue` produces. Anything else (including other typed arrays) goes through the iterable path.
+
+`ToComponentValueList(jsValue, T)`:
+1. If |jsValue| is not an Object:
+ 1. Throw a `TypeError`.
+1. Let |method| be ? `GetMethod`(|jsValue|, `%Symbol.iterator%`).
+1. If |method| is **undefined**:
+ 1. Throw a `TypeError`.
+1. Let |values| be ? `IteratorToList`(? `GetIteratorFromMethod`(|jsValue|, |method|)).
+1. Let |valuesLength| be the length of |values|.
+1. Let |list| be an empty component list with length |valuesLength| of type `T`.
+1. For |i| in 0..|valuesLength|:
+ 1. Let |value| be |values|[|i|].
+ 1. Set |list|[|i|] to ? `ToComponentValue`(|value|, `T`).
+1. Return |list|.
+
+The iterable is consumed before any element is converted, so that the canonical ABI has the list's length before calling realloc and converting elements.
+
+`ToComponentValueRecord(jsValue, fields)`:
+1. If |jsValue| is not an Object:
+ 1. Throw a `TypeError`.
+1. Let |record| be a new component record value with one field per |fields|.
+1. For each field `f: T` of |fields|, in declaration order:
+ 1. Let |m| be ? `Get`(|jsValue|, `CamelCase`(f)).
+ 1. If |m| is **undefined** and `T` is not `option<_>`:
+ 1. Throw a `TypeError`.
+ 1. Set |record|'s `f` field to ? `ToComponentValue`(|m|, T).
+1. Return |record|.
+
+`ToComponentValueFlags(jsValue, labels)`:
+1. If |jsValue| is not an Object:
+ 1. Throw a `TypeError`.
+1. Let |flags| be a new component flags value with every bit initially **false**.
+1. For each label `L` of |labels|:
+ 1. Set |flags|'s `L` bit to `ToBoolean`(? `Get`(|jsValue|, `CamelCase`(L))).
+1. Return |flags|.
+
+An absent property is therefore **false**, matching a `boolean` dictionary member defaulted to **false**.
+
+`ToComponentValueVariant(jsValue, cases)`:
+1. If |jsValue| is not an Object:
+ 1. Throw a `TypeError`.
+1. Let |kind| be ? `ToString`(? `Get`(|jsValue|, "kind")).
+1. If there is no case of |cases| whose label `L` has `PascalCase`(`L`) equal to |kind|:
+ 1. Throw a `TypeError`.
+1. Let |case| be that case.
+1. If |case| has a payload type T:
+ 1. Let |payload| be ? `ToComponentValue`(? `Get`(|jsValue|, "value"), T).
+ 1. Return a variant value of |case| whose payload is |payload|.
+1. Return a variant value of |case| with no payload.
+
+This operation is used for variant, and also cases in the above table where we can't specialize the behavior of `option` and `result`.
+
+`ToComponentValueMap(jsValue, K, V)`:
+1. If |jsValue| is not an Object:
+ 1. Throw a `TypeError`.
+1. If ? `GetMethod`(|jsValue|, `%Symbol.iterator%`) is not **undefined**:
+ 1. Return `ToComponentValueList`(|jsValue|, `tuple`).
+1. If K is not `string`:
+ 1. Throw a `TypeError`.
+1. Return one pair per own enumerable string-keyed property of |jsValue|, in property order, reading each value with ? `Get` and converting it with `ToComponentValue`(_, V).
+
+If the value is not iterable, we fall back to converting the object the way WebIDL's `record` would, for compatibility.
+
+## Resource types
+
+A component resource type can be defined in a component (i.e. a guest resource), or else as an imported abstract type (i.e. a host resource).
+
+The component JS-API defines:
+
+1. How a JS value satisfies a resource type import.
+1. A spec representation of host resource types and values.
+1. A JS representation of guest resource types and values.
+
+### Embedder extensions
+
+We sketch two operations here that will be formalized more fully in the [embedding interface](CanonicalABI.md#embedding).
+
+To `create a resource type for host` given a host function |destructor|:
+1. Return a fresh component resource type whose representation is host-defined and whose destructor is |destructor|.
+
+To `drop a guest resource` given a resource type |resourceType| and a guest rep |rep| owned by the host:
+1. Let |instance| be the surrounding component instance.
+1. If |instance|.[[Store]].is_locked_down()
+ 1. Perform ? `trap` given |instance|.
+1. Perform the effect of [`canon resource.drop`](CanonicalABI.md#canon-resourcedrop) on an owning handle holding |resourceType| and |rep|, invoking |resourceType|'s destructor. There is no handle table entry to remove, because the host was holding the rep.
+1. If that traps:
+ 1. Perform ? `trap` given |instance|.
+
+### Abstract and transparent types
+
+Imported and exported resource types are either abstract or transparently equivalent to a previous abstract import or export.
+
+```
+(component
+ (import "r1" (type $r1 (sub resource)))
+ (import "r2" (type (eq $r1)))
+ (import "r3" (type (sub resource)))
+
+ (export "r4" (type $r4 (sub resource)))
+ (export "r5" (type (eq $r4)))
+ (export "r6" (type (sub resource)))
+
+ (export "r7" (type (eq $r3)))
+)
+```
+
+`r1`, `r3`, `r4`, `r6` are the abstract types of this component type, while `r2`, `r5`, and `r7` are transparently equal to one of the abstract types.
+
+Host/guest resource types below are created only for abstract types, and stored in maps on the component instance. The map is keyed by an *abstract type key*, which is an import/export declaration for an abstract type.
+
+A type import or export *declares a resource type* if following `(eq R)` reaches a `(sub resource)`. An *abstract type key* can be found for any such declaration by following `(eq R)` until you reach that `(sub resource)`.
+
+Type declarations that do not declare a resource type, such as an exported `record`, exist only to satisfy [external visibility](Explainer.md#external-visibility-of-types) and have no JS representation. The JS-API skips them: a type import is not read from the imports object and a type export is left off the exports object.
+
+### Host resource types (i.e. imported)
+
+#### Brand checks
+
+A resource type import is satisfied by a constructor. Each time a JS value needs to be converted to a value of that resource type, it is *brand checked* against the constructor.
+
+To `brand check` given a JS value |jsValue| and an Object |constructor|:
+1. If |constructor| is a WebIDL [interface object](https://webidl.spec.whatwg.org/#dfn-interface-object):
+ 1. Return **true** if and only if |jsValue| is a platform object that [implements](https://webidl.spec.whatwg.org/#implements) the interface |constructor| is the interface object of.
+1. If |constructor| has a [[ConstructorFunc]] internal slot:
+ 1. Assert: |constructor| is a [guest resource class](#guest-resource-classes).
+ 1. Return **true** if and only if |jsValue| has a [[ResourceClass]] internal slot whose value is |constructor|.
+1. Return ? `InstanceofOperator`(|jsValue|, |constructor|).
+
+Which case applies is fixed for the lifetime of |constructor|.
+
+The first two cases are real brand checks. The `instanceof` fallback only inspects the prototype chain, so a value that was never created by |constructor| can pass it. In the future we may add a way for JS to supply a custom brand check.
+
+The case of a guest resource class may either be from an export of the current component instance, or else an export from a different component instance.
+
+#### Host resource types and values
+
+A *host resource type* is what the JS-API creates to satisfy a resource type import. It is a Record with the following fields:
+
+| Field | Value |
+|---|---|
+| [[ComponentResourceType]] | the component resource type produced by `create a resource type for host` |
+| [[ConstructorObject]] | the JS constructor that satisfied the import |
+
+A *host resource value* is the `rep` of a host resource type. It too is a Record:
+
+| Field | Value |
+|---|---|
+| [[Type]] | the host resource type this is a rep of |
+| [[JSValue]] | the JS value, held strongly |
+
+A host resource value just holds a strong reference to the underlying value. `%Symbol.dispose` is captured upon instantiation and is invoked when the resource is dropped. Dropping a resource is infallible, so if the destructor fails this results in a trap and lockdown.
+
+One host resource type is created per imported [abstract type](#abstract-and-transparent-types). Two abstract type imports satisfied by the same JS constructor become distinct component resource types, and a handle for one cannot be passed where the other is expected.
+
+A map from imported abstract type to host resource type is built by [`read the imports`](#read-the-imports-object) and stored on a [component instance](#entry-points).
+
+#### Conversions for host resources
+
+For a resource type `R` whose abstract type is one of the component's type imports:
+
+- `ToJSValue(rep, own | borrow)`:
+ 1. Let |instance| be the surrounding component instance.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |R|.
+ 1. Let |hostType| be |instance|.[[HostResourceTypes]][|abstractTypeKey|].
+ 1. Assert: |rep| is a host resource value whose [[Type]] is |hostType|.
+ 1. Return |rep|.[[JSValue]].
+- `ToComponentValue(jsValue, own | borrow)`:
+ 1. Let |instance| be the surrounding component instance.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |R|.
+ 1. Let |hostType| be |instance|.[[HostResourceTypes]][|abstractTypeKey|].
+ 1. Let |matches| be ? `brand check` given |jsValue| and |hostType|.[[ConstructorObject]].
+ 1. If |matches| is **false**:
+ 1. Throw a `TypeError`.
+ 1. Return a host resource value whose [[Type]] is |hostType| and whose [[JSValue]] is |jsValue|.
+
+Converting the same JS value to a host resource type yields fresh handle indices. There is no canonicalization of indices.
+
+### Guest resource types (i.e. exported)
+
+#### Re-exported host resource types
+
+A component's type may export a resource type that is transparently equal to one of its imported resource types (see [abstract types](#abstract-and-transparent-types)). This currently [throws](#create-the-exports-object), but may be relaxed in the future.
+
+An exported resource type that is only privately a re-export of an imported type, i.e. the component's type declares it as a fresh abstract export, will wrap the original host resource type in a new [guest resource class](#guest-resource-classes). This keeps callers from observing whether an exported resource type is a re-export or defined in the component.
+
+### Re-imported guest resource types
+
+An exported guest resource type may be imported by a separate component instance. In this case, the guest resource type is treated as if it was a host resource type and the previous section rules apply. As explained in [component store](#component-store), there is no direct component model linking between top-level instances through the JS-API.
+
+#### Guest resource classes
+
+A unique JS *guest resource class* is created for each exported [abstract type](#abstract-and-transparent-types). A map from [abstract type key](#abstract-and-transparent-types) to guest resource class is stored on the component instance.
+
+A guest resource class is a built-in function object with the following slots:
+1. [[ResourceType]] - the guest resource type.
+1. [[ConstructorFunc]] - the component function that implements `new`, or **empty**.
+1. [[ComponentInstance]] - the component instance the class belongs to.
+
+To `create a guest resource class` given a component instance |componentInstance|, resource type |resourceType|, String |name| and an integer |arity|:
+1. Let |prototype| be `OrdinaryObjectCreate`(`%Object.prototype%`).
+1. Let |constructor| be a built-in function object with name |name| and length |arity|.
+1. Set |constructor|.[[ResourceType]] to |resourceType|.
+1. Set |constructor|.[[ConstructorFunc]] to **empty**.
+1. Set |constructor|.[[ComponentInstance]] to |componentInstance|.
+1. Set |constructor|'s [[Call]] behaviour to throw a `TypeError`.
+1. Set |constructor|'s [[Construct]] behaviour, given JS arguments |args| and |newTarget|, to perform:
+ 1. If |constructor|.[[ConstructorFunc]] is **empty**:
+ 1. Throw a `TypeError`.
+ 1. Let |rep| be ? `invoke a component function` given |constructor|.[[ConstructorFunc]], **false**, **undefined** and |args|.
+ 1. Return ? `create a guest resource instance` given |constructor|, |rep|, **true** and |newTarget|.
+1. Perform `DefinePropertyOrThrow`(|prototype|, `%Symbol.dispose%`, PropertyDescriptor { [[Value]]: a built-in function object with name "[Symbol.dispose]" and length 0 that performs `drop a guest resource instance` given its **this** value, [[Writable]]: **true**, [[Enumerable]]: **false**, [[Configurable]]: **true** }).
+1. Perform `DefinePropertyOrThrow`(|prototype|, `%Symbol.toStringTag%`, PropertyDescriptor { [[Value]]: |name|, [[Writable]]: **false**, [[Enumerable]]: **false**, [[Configurable]]: **true** }).
+1. Perform `DefinePropertyOrThrow`(|prototype|, "constructor", PropertyDescriptor { [[Value]]: |constructor|, [[Writable]]: **true**, [[Enumerable]]: **false**, [[Configurable]]: **true** }).
+1. Perform `DefinePropertyOrThrow`(|constructor|, "prototype", PropertyDescriptor { [[Value]]: |prototype|, [[Writable]]: **false**, [[Enumerable]]: **false**, [[Configurable]]: **false** }).
+1. Let |members| be the function exports in |componentInstance|'s scope whose names match *Constructor* or *Member* with a `resource` capture naming |resourceType|.
+1. If some |c| of |members| matches *Constructor*:
+ 1. Assert: there is only one by validation rules.
+ 1. Set |constructor|.[[ConstructorFunc]] to |c|.Func.
+1. For each |e| of |members| matching *Member*, in declaration order:
+ 1. If `JSName`(|e|) is in `reserved class members`:
+ 1. Continue.
+ 1. If |e|.Name's `scope` capture is "method":
+ 1. Let |target| be |prototype|.
+ 1. Let |takesSelf| be **true**.
+ 1. Else:
+ 1. Assert: |e|.Name's `scope` capture is "constructor".
+ 1. Let |target| be |constructor|
+ 1. Let |takesSelf| be **false**.
+ 1. If |e|.Name has an `accessor` capture:
+ 1. Perform `define an accessor for a component function` given |target|, |e| and **false**.
+ 1. Else:
+ 1. Let |func| be `create a JS function for a component function` given |e|.Func, `JSName`(|e|) and |takesSelf|.
+ 1. Perform `DefinePropertyOrThrow`(|target|, `JSName`(|e|), PropertyDescriptor { [[Value]]: |func|, [[Writable]]: **true**, [[Enumerable]]: **false**, [[Configurable]]: **true** }).
+1. Return |constructor|.
+
+The following names are `reserved class members`:
+ * "__proto__"
+ * "constructor"
+ * "prototype"
+ * "arguments"
+ * "caller"
+ * "name"
+ * "length"
+
+Defining these on the constructor or prototype may unexpectedly change JS class semantics. They are exported through `create the exports object` instead.
+
+*Member* exports with an `accessor` capture become the two halves of one accessor property, on `prototype` when `scope` is "method" and on the class itself when it is "static". Validation requires a `[set]` to be preceded in the same scope by the `[get]` it pairs with, so the getter is always defined first and the setter only fills in the accessor's [[Set]] field.
+
+#### Guest resource instances
+
+An instance of a guest resource class has the following slots:
+1. [[ResourceClass]] - the resource class this is an instance of.
+1. [[Rep]] - the rep, or **empty** once the handle has been dropped.
+1. [[Own]] - whether this instance owns the resource.
+1. [[LendCount]] - how many outstanding `borrow`s were lent from this instance.
+
+It holds the same state a handle table entry does, plus the class it belongs to.
+
+To `create a guest resource instance` given a resource class |class|, |rep|, |own| and an optional |newTarget|:
+1. Let |defaultProto| be the value of |class|'s `"prototype"` property.
+1. If |newTarget| is present:
+ 1. Let |proto| be ? `Get`(|newTarget|, "prototype").
+ 1. If `Type`(|proto|) is not Object:
+ 1. Set |proto| to |defaultProto|.
+1. Else:
+ 1. Let |proto| be |defaultProto|.
+1. Let |instance| be `OrdinaryObjectCreate`(|proto|, ยซ [[ResourceClass]], [[Rep]], [[Own]], [[LendCount]] ยป).
+1. Set |instance|.[[ResourceClass]] to |class|.
+1. Set |instance|.[[Rep]] to |rep|.
+1. Set |instance|.[[Own]] to |own|.
+1. Set |instance|.[[LendCount]] to 0.
+1. If |own| is **true**:
+ 1. Register |instance| in the [guest resource `FinalizationRegistry`](#guest-resource-finalizationregistry) with held value a record { [[ResourceClass]]: |class|, [[Rep]]: |rep| } and unregister token |instance|.
+1. Return |instance|.
+
+#### Conversions for guest resources
+
+The *current lender list* is a per-call spec state. `invoke a component function` establishes it for a JS-to-component call. Each guest resource instance lowered as a `borrow` during that call has its [[LendCount]] incremented and is appended to the list, which protects it from being dropped while lent. When the call returns, every [[LendCount]] in the list is decremented.
+
+For a resource type `R` whose [abstract type](#abstract-and-transparent-types) is one of the component's type exports:
+
+- `ToJSValue(rep, own)`:
+ 1. Let |instance| be the surrounding component instance.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |R|.
+ 1. Let |class| be |instance|.[[GuestResourceClasses]][|abstractTypeKey|].
+ 1. Return `create a guest resource instance` given |class|, |rep| and **true**.
+- `ToJSValue(rep, borrow)`:
+ 1. Assert: unreachable.
+ 1. This can only happen if an exported function returns a borrow, which is not allowed.
+- `ToComponentValue(jsValue, own)`:
+ 1. Let |instance| be the surrounding component instance.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |R|.
+ 1. Let |class| be |instance|.[[GuestResourceClasses]][|abstractTypeKey|].
+ 1. If |jsValue| does not have a [[ResourceClass]] internal slot, or |jsValue|.[[ResourceClass]] is not |class|:
+ 1. Throw a `TypeError`.
+ 1. If |jsValue|.[[Rep]] is **empty**, or |jsValue|.[[Own]] is **false**, or |jsValue|.[[LendCount]] is not 0:
+ 1. Throw a `TypeError`.
+ 1. Let |rep| be |jsValue|.[[Rep]].
+ 1. Set |jsValue|.[[Rep]] to **empty**.
+ 1. Unregister |jsValue| from the [guest resource `FinalizationRegistry`](#guest-resource-finalizationregistry).
+ 1. Return |rep|.
+- `ToComponentValue(jsValue, borrow)`:
+ 1. Let |instance| be the surrounding component instance.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |R|.
+ 1. Let |class| be |instance|.[[GuestResourceClasses]][|abstractTypeKey|].
+ 1. If |jsValue| does not have a [[ResourceClass]] internal slot, or |jsValue|.[[ResourceClass]] is not |class|:
+ 1. Throw a `TypeError`.
+ 1. If |jsValue|.[[Rep]] is **empty**:
+ 1. Throw a `TypeError`.
+ 1. Assert: a lender list is currently established.
+ 1. Increment |jsValue|.[[LendCount]].
+ 1. Append |jsValue| to the current lender list.
+ 1. Return |jsValue|.[[Rep]].
+
+#### Guest resource FinalizationRegistry
+
+There is an unexposed "guest resource `FinalizationRegistry`" created per-Realm of the WebAssembly namespace object. The callback for it, given a held value |record|, performs `drop a guest resource` given |record|.[[ResourceClass]].[[ResourceType]] and |record|.[[Rep]].
+
+The held value is a record of the instance's class and rep rather than the instance itself, because registering an object with itself as the held value would keep it alive forever. The record never goes stale, because the instance is unregistered whenever its [[Rep]] is taken.
+
+To `drop a guest resource instance` given |resourceInstance|:
+1. If |resourceInstance|.[[Rep]] is **empty** or |resourceInstance|.[[Own]] is **false**:
+ 1. Return **undefined**.
+1. Let |class| be |resourceInstance|.[[ResourceClass]].
+1. If |resourceInstance|.[[LendCount]] is not 0:
+ 1. Throw a `TypeError`.
+1. Let |rep| be |resourceInstance|.[[Rep]].
+1. Set |resourceInstance|.[[Rep]] to **empty**.
+1. Unregister |resourceInstance| from the guest resource `FinalizationRegistry`.
+1. Perform `drop a guest resource` given |class|.[[ResourceType]] and |rep|.
+1. Return **undefined**.
+
+The [[LendCount]] check can only fail on the `%Symbol.dispose%` path, because a lent instance is kept alive by the current lender list.
+
+## Instantiation
+
+To `instantiate a component` given |component|, a list of component definitions |imports|, and |hostResourceTypes|:
+1. Let |store| be a new component store.
+1. Let |instance| be the result of instantiating |component| with |imports| in |store|.
+1. If instantiation traps:
+ 1. Throw a `WebAssembly.RuntimeError`.
+1. Perform ? `create guest resource classes` given |instance|.
+1. Let |exportsObject| be ? `create the exports object` given |instance|.
+1. Return a Record with:
+ * [[Store]]: |store|
+ * [[ComponentInstance]]: |instance|
+ * [[Exports]]: |exportsObject|
+ * [[HostResourceTypes]]: |hostResourceTypes|
+ * [[GuestResourceClasses]]: |instance|.[[GuestResourceClasses]].
+
+To `instantiate a component from an imports object` given |component|, |importsObject|, and |enabledBuiltins|:
+1. Let |imports| and |hostResourceTypes| be ? `read the imports` given |component|, |importsObject|, and |enabledBuiltins|.
+1. Return ? `instantiate a component` given |component|, |imports|, and |hostResourceTypes|.
+
+### Read the imports object
+
+The top-level `read the imports` algorithm walks the component's imports and resolves each to a JS value via property lookups on the |importsObject|, mirroring the core JS-API's algorithm of the same name.
+
+The resolved JS values are then handed to the per-sort algorithms (`read the function import`, `read the type import`, and the rest) to produce the component definitions used during instantiation.
+
+While walking, the algorithm recognizes the pattern of a resource type import accompanied by *Constructor* and *Member* function imports naming it. A resource type import is read first and looks for a constructor (see [resource types](#resource-types)). Those function imports then read from the constructor and its prototype directly. This allows the common case of importing a class to be satisfied by just passing the constructor.
+
+Passing an exported component definition to a component import via the JS-API/ESM-integration is treated as if the import were a JS value. There is no "direct linking" that bypasses going through JS semantics. See [component store](#component-store) for more details.
+
+To `read the imports` given |component|, |importsObject|, and |enabledBuiltins|:
+1. Let |hostResourceTypes| be an empty map from [abstract type key](#abstract-and-transparent-types) to [host resource type record](#host-resource-types-and-values).
+1. If |component| has no imports:
+ 1. Return an empty list and |hostResourceTypes|.
+1. Let |imports| be ? `read a scope of imports` given |component|.Imports, |importsObject|, |enabledBuiltins|, and |hostResourceTypes|.
+1. Return |imports| and |hostResourceTypes|.
+
+To `read a scope of imports` given a list of import declarations |importDecls|, |importsObject|, |enabledBuiltins|, and |hostResourceTypes|:
+1. Let |definitions| be a new empty list.
+1. For each |importDecl| of |importDecls|, in declaration order:
+ 1. If |importDecl|.Sort is **type**:
+ 1. If |importDecl| does not declare a resource type:
+ 1. Append the type |importDecl| declares to |definitions|.
+ 1. Continue.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |importDecl|.
+ 1. If |hostResourceTypes|[|abstractTypeKey|] exists:
+ 1. Append |hostResourceTypes|[|abstractTypeKey|].[[ComponentResourceType]] to |definitions|.
+ 1. Continue.
+ 1. Let |name| be `JSSpecifier`(|importDecl|).
+ 1. Let |staticReceiver| be **undefined**.
+ 1. Let |builtin| be `resolve a builtin specifier` given |name| and |enabledBuiltins|.
+ 1. If |builtin| is not **empty**:
+ 1. Let |importValue| be |builtin|.
+ 1. Else:
+ 1. If |importDecl|.Sort is **func** and |importDecl|.Name matches *Constructor* or *Member*:
+ 1. Let |abstractTypeKey| be the *abstract type key* of the type import named by the `resource` capture.
+ 1. Assert: |hostResourceTypes|[|abstractTypeKey|] exists. (Validation requires that declaration to precede this one in the same scope)
+ 1. Let |constructorFunction| be |hostResourceTypes|[|abstractTypeKey|].[[ConstructorObject]].
+ 1. If |importDecl|.Name matches *Constructor*:
+ 1. Let |importValue| be |constructorFunction|.
+ 1. Else:
+ 1. If the `scope` capture is "static":
+ 1. Let |lookupTarget| be |constructorFunction|.
+ 1. Set |staticReceiver| to |lookupTarget|.
+ 1. Else:
+ 1. Let |lookupTarget| be ? `Get`(|constructorFunction|, "prototype").
+ 1. If `Type`(|lookupTarget|) is not Object:
+ 1. Throw a `WebAssembly.LinkError`.
+
+ 1. If |importDecl|.Name has an `accessor` capture:
+ 1. Let |importValue| be ? `find an accessor` given |lookupTarget|, |name| and that capture.
+ 1. Else:
+ 1. Let |importValue| be ? `Get`(|lookupTarget|, |name|).
+ 1. Else:
+ 1. If `Type`(|importsObject|) is not Object:
+ 1. Throw a `TypeError`.
+
+ 1. If |importDecl|.Sort is **func** and |importDecl|.Name matches *Property*:
+ 1. Set |staticReceiver| to |importsObject|.
+ 1. Let |importValue| be ? `find an accessor` given |importsObject|, |name| and the `accessor` capture.
+ 1. Else:
+ 1. Let |importValue| be ? `Get`(|importsObject|, |name|).
+ 1. Let |resolved| be ? `read an import` given |importDecl|, |importValue|, |staticReceiver| and |hostResourceTypes|.
+ 1. Append |resolved| to |definitions|.
+1. Return |definitions|.
+
+To `read an import` given |importDecl|, |importValue|, |staticReceiver| and |hostResourceTypes|:
+1. Match |importDecl|.Sort:
+ 1. **core module**: return ? `read the core module import` given |importDecl|.ModuleType and |importValue|.
+ 1. **func**: return ? `read the function import` given |importDecl|.FuncType, |importValue|, |importDecl|.Name and |staticReceiver|.
+ 1. **type**: return ? `read the type import` given |importDecl|, |importValue|, and |hostResourceTypes|.
+ 1. **value**: return ? `read the value import` given |importDecl|.ValType and |importValue|.
+ 1. **instance**: return ? `read the instance import` given |importDecl|.InstanceType, |importValue| and |hostResourceTypes|.
+ 1. **component**: return ? `read the component import` given |importDecl|.ComponentType and |importValue|.
+
+To `read the core module import` given |coreModuleType| and |importValue|:
+1. If |importValue| does not have a [[Module]] internal slot:
+ 1. Throw a `WebAssembly.LinkError`.
+1. If the type of |importValue|.[[Module]] is not equal to |coreModuleType|:
+ 1. Throw a `WebAssembly.LinkError`.
+1. Return |importValue|.[[Module]].
+
+To `read the component import` given |componentType| and |importValue|:
+1. If |importValue| does not have a [[Component]] internal slot:
+ 1. Throw a `WebAssembly.LinkError`.
+1. If the type of |importValue|.[[Component]] is not a subtype of |componentType|:
+ 1. Throw a `WebAssembly.LinkError`.
+1. Return |importValue|.[[Component]].
+
+To `read the instance import` given |instanceType|, |importValue| and |hostResourceTypes|:
+1. If `Type`(|importValue|) is not Object:
+ 1. Throw a `WebAssembly.LinkError`.
+1. Let |definitions| be ? `read a scope of imports` given |instanceType|.Exports, |importValue|, an empty set of enabled builtins, and |hostResourceTypes|.
+1. Return a component instance whose exports are |definitions|.
+
+To `read the type import` given |importDecl|, |importValue|, and |hostResourceTypes|:
+1. Let |abstractTypeKey| be the *abstract type key* of |importDecl|.
+1. Assert: |hostResourceTypes|[|abstractTypeKey|] does not exist. (`read a scope of imports` handles transparent imports)
+1. If `IsCallable`(|importValue|) is **false**:
+ 1. Throw a `WebAssembly.LinkError`.
+1. Let |dispose| be ? `Get`(|importValue|, %Symbol.dispose%).
+1. Let |hasDispose| be `IsCallable`(|dispose|).
+1. Let |destructor| be a host function that given a host resource value |self|:
+ 1. Let |selfValue| be |self|.[[JSValue]].
+ 1. Set |self|.[[JSValue]] to `undefined`.
+ 1. If |hasDispose|:
+ 1. Let |result| be `Call`(|dispose|, |selfValue|, the empty list).
+ 1. If |result| is an abrupt completion:
+ 1. Trap.
+1. Let |destructor| be a host function that, given a host resource value, releases its reference to [[JSValue]] and returns.
+1. Let |resourceType| be `create a resource type for host` given |destructor|.
+1. Let |hostResourceType| be a new host resource type record whose [[ComponentResourceType]] is |resourceType| and [[ConstructorObject]] is |importValue|.
+1. Set |hostResourceTypes|[|abstractTypeKey|] to |hostResourceType|.
+1. Return |resourceType|.
+
+`%Symbol.dispose` is captured and called when the resource is dropped. Dropping a resource is infallible, so if it throws an exception, this becomes a trap which results in lockdown.
+
+To `find an accessor` given an object |target|, a property key |key| and |kind|, which is either "get" or "set":
+1. Let |object| be |target|.
+1. Repeat, while |object| is not **null**:
+ 1. Let |desc| be ? |object|.[[GetOwnProperty]](|key|).
+ 1. If |desc| is not **undefined**:
+ 1. If `IsAccessorDescriptor`(|desc|) is **false**:
+ 1. Return **undefined**.
+ 1. If |kind| is "get", return |desc|.[[Get]].
+ 1. Return |desc|.[[Set]].
+ 1. Set |object| to ? |object|.[[GetPrototypeOf]]().
+1. Return **undefined**.
+
+The walk stops at the first own property it finds, as an ordinary property access does. A data property that shadows an accessor further up the chain therefore resolves to **undefined** and becomes a `LinkError`.
+
+To `read the function import` given |componentFuncType|, |importValue|, |importName| and |staticReceiver|:
+1. If `IsCallable`(|importValue|) is **false**:
+ 1. Throw a `WebAssembly.LinkError`.
+1. If |importName| matches *Constructor* and `IsConstructor`(|importValue|) is **false**:
+ 1. Throw a `WebAssembly.LinkError`.
+1. Let |callable| be |importValue|.
+
+1. Let |callKind|, |receiverRule| and |paramOffset| be determined by |importName|:
+ 1. *Constructor*: `Construct`, no receiver, offset 0.
+ 1. *Member* with `scope` "method": `Call`, receiver is component argument 0 (the `borrow` self parameter), offset 1.
+ 1. Otherwise: `Call`, receiver is |staticReceiver|, offset 0.
+1. Let |paramTypes| be |componentFuncType|.Params.
+1. Let |resultType| be |componentFuncType|.Result.
+1. If |resultType| is a `result`:
+ 1. Let |okType| be its `ok` payload type, or **empty** if it has none.
+ 1. Let |errorType| be its `error` payload type, or **empty** if it has none.
+ 1. Let |throwing| be **true**.
+1. Else:
+ 1. Let |okType| be |resultType|, or **empty** if |componentFuncType| has no result.
+ 1. Let |throwing| be **false**.
+1. Return a component host function of type |componentFuncType| whose body, given component arguments ยซ |v_0|, ..., |v_{n-1}| ยป where |n| is |paramTypes|.length, performs:
+ 1. Let |args| be a new empty List.
+ 1. For each i in [|paramOffset|, |n|):
+ 1. Append `ToJSValue`(|v_i|, |paramTypes|[i]) to |args|.
+ 1. If |callKind| is `Construct`:
+ 1. Let |completion| be `Construct`(|callable|, |args|).
+ 1. Else:
+ 1. If |receiverRule| is "component argument 0":
+ 1. Let |thisArg| be `ToJSValue`(|v_0|, |paramTypes|[0]).
+ 1. Else:
+ 1. Let |thisArg| be |receiverRule|.
+ 1. Let |completion| be `Call`(|callable|, |thisArg|, |args|).
+ 1. If |completion| is an abrupt completion:
+ 1. If |throwing| is **false**:
+ 1. Trap.
+ 1. If |errorType| is **empty**:
+ 1. Return `result.error`.
+ 1. Let |errorValue| be `ToComponentValue`(|completion|.[[Value]], |errorType|).
+ 1. If that throws:
+ 1. Trap.
+ 1. Return `result.error(|errorValue|)`.
+ 1. If |okType| is **empty**:
+ 1. If |throwing| is **true**:
+ 1. Return `result.ok`.
+ 1. Return with no result.
+ 1. Let |componentResult| be `ToComponentValue`(|completion|.[[Value]], |okType|).
+ 1. If that throws:
+ 1. Trap.
+ 1. If |throwing| is **true**:
+ 1. Return `result.ok(|componentResult|)`.
+ 1. Else:
+ 1. Return |componentResult|.
+
+To `read the value import` given |componentValType| and |importValue|:
+1. Return ? `ToComponentValue`(|importValue|, |componentValType|).
+
+### Builtin imports
+
+The component JS-API can provide builtins to imports just as the core JS-API does.
+
+Builtin imports are opt-in via the `builtins` field of `WebAssemblyCompileOptions` when used in the JS-API. [ESM-integration](#webassembly-esm-integration) enables all builtins by default.
+
+This spec defines one builtin specifier:
+
+| Specifier | Resolves to |
+|---|---|
+| `wasm:js/global/*` | [the global object](#the-global-object) |
+
+To `resolve a builtin specifier` given a String |specifier| and a set of Strings |enabledBuiltins|:
+1. If |specifier| does not start with "wasm:":
+ 1. Return **empty**.
+1. Let |name| be the portion of |specifier| after "wasm:".
+1. If |name| does not match something in |enabledBuiltins|:
+ 1. Return **empty**.
+1. If |name| starts with "js/global":
+ 1. Return `resolve a js global builtin` with |name|.
+1. Return **empty**.
+
+#### The global object
+
+The normal [`read the imports`](#read-the-imports-object) rules are designed so that JS classes can be imported by just providing the constructor object. `wasm:js/global/*` provides a fine-grained way to get access to globally exposed constructors and other functions. This reduces the amount of glue code needed in the common case.
+
+`wasm:js/global` resolves to the `globalThis` of the [component realm](#types-and-values), and nested paths resolve to a chain of property accessors off of the global (e.g. `wasm:js/global/console` is `globalThis.console`).
+
+To `resolve a js global builtin` with String |name|:
+1. Assert: |name| starts with "js/global".
+1. Let |result| be the component realm's `globalThis`.
+1. Let |remaining| be |name| with the regex "js\/global\/?" trimmed from the prefix.
+1. Let |projections| be the result of splitting |remaining| on "/".
+1. For |projection| in |projections|:
+ 1. Set |result| to ? `Get`(|result|, |projection|).
+1. Return |result|.
+
+TODO: Handle whitespace?
+TODO: Within the wasm scheme we're parsing this similar to a general URL, but no using the [canonical algorithm](https://url.spec.whatwg.org/). We don't need the general algorithm and it's a nice dependency to avoid. But are there future compatibility or extensibility reasons we should use it?
+
+### Create the exports object
+
+The `create the exports object` algorithm walks the component's exports and builds a fresh JS object whose properties are the exports.
+
+Exported resource types become [guest resource classes](#guest-resource-classes) named `JSName`(|export|), and function exports matching *Constructor* or *Member* are mapped onto the class `R` named by their `resource` capture, just as in `read the imports`:
+- *Constructor*: the function becomes `R`'s constructor behaviour. Names are strongly-unique, so there can only be one.
+- *Member* with `scope` "method": the function becomes a method named `JSName`(|export|) on `R.prototype`.
+- *Member* with `scope` "static": the function becomes a static method named `JSName`(|export|) on `R`.
+- *Member* with an `accessor` capture: the "get" and "set" functions become the getter and setter of one accessor property named `JSName`(|export|), again on `R.prototype` or on `R`.
+
+A *Property* export becomes an accessor property on the exports object itself. All other exported component definitions are given JS definitions named `JSName`(|export|) on the exports object.
+
+To `create guest resource classes` given a component instance |componentInstance|:
+1. Let |guestResourceClasses| be an empty map from [abstract type key](#abstract-and-transparent-types) to [guest resource class](#guest-resource-classes).
+1. Let |component| be |componentInstance|.[[Component]].
+1. For each type export |export| of |component|'s type, in declaration order, recursing into exported instances:
+ 1. If |export| does not declare a resource type:
+ 1. Continue.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |export|.
+ 1. If |abstractTypeKey| is one of |component|'s type imports:
+ 1. Throw a `TypeError`.
+ 1. If |guestResourceClasses|[|abstractTypeKey|] exists:
+ 1. Continue.
+ 1. Let |resourceType| be the component resource type |export| refers to in |componentInstance|.
+ 1. Let |arity| be the parameter count of the export whose name matches *Constructor* with a `resource` capture naming |export|, or 0 if there is none.
+ 1. Let |class| be `create a guest resource class` given |componentInstance|, |resourceType|, `JSName`(|export|) and |arity|.
+ 1. Set |guestResourceClasses|[|abstractTypeKey|] to |class|.
+1. Set |componentInstance|.[[GuestResourceClasses]] to |guestResourceClasses|.
+
+To `create the exports object` given a |componentInstance|:
+1. Let |exportsObject| be `OrdinaryObjectCreate`(**null**).
+1. For each |export| of |componentInstance|.Exports, in declaration order:
+ 1. If |export|.Name matches *Constructor*:
+ 1. Continue.
+ 1. If |export|.Name matches *Member* and `JSName`(|export|) is not in `reserved class members`:
+ 1. Continue.
+ 1. If |export|.Name matches *Property*:
+ 1. Perform `define an accessor for a component function` given |exportsObject|, |export| and **true**.
+ 1. Continue.
+ 1. Let |key| be `JSName`(|export|).
+ 1. Match |export|.Sort:
+ 1. **core module**:
+ 1. Let |value| be a new `Module` whose [[Module]] is |export|.Module.
+ 1. **type**:
+ 1. If |export| does not declare a resource type:
+ 1. Continue.
+ 1. Let |abstractTypeKey| be the *abstract type key* of |export|.
+ 1. Let |value| be |componentInstance|.[[GuestResourceClasses]][|abstractTypeKey|].
+ 1. **func**:
+ 1. Let |value| be `create a JS function for a component function` given |export|.Func, |key| and **false**.
+ 1. **value**:
+ 1. Let |value| be `ToJSValue`(|export|.Value, |export|.Type).
+ 1. **instance**:
+ 1. Let |value| be ? `create the exports object` given the exported instance.
+ 1. **component**:
+ 1. Let |value| be a new `Component` whose [[Component]] is |export|.Component.
+ 1. Perform `CreateDataPropertyOrThrow`(|exportsObject|, |key|, |value|).
+1. Perform `SetIntegrityLevel`(|exportsObject|, "frozen").
+1. Return |exportsObject|.
+
+TODO: We need a JSName for members that hit the `reserved class members` list. It needs to concatenate the resource name with the method name somehow.
+
+To `create a JS function for a component function` given |componentFunc|, |name| and |takesSelf|:
+1. Let |paramOffset| be 1 if |takesSelf| is **true**, else 0.
+1. If |componentFunc|.Result is a `result`:
+ 1. Let |okType| be its `ok` payload type, or **empty** if it has none.
+1. Else:
+ 1. Let |okType| be |componentFunc|.Result, or **empty** if |componentFunc| has no result.
+1. Return a built-in function object with name |name| and length |componentFunc|.Params.length - |paramOffset|, whose behaviour, given a **this** value |thisValue| and JS arguments |args|, performs:
+ 1. Let |componentResult| be ? `invoke a component function` given |componentFunc|, |takesSelf|, |thisValue| and |args|.
+ 1. If |okType| is **empty**:
+ 1. Return **undefined**.
+ 1. Return `ToJSValue`(|componentResult|, |okType|).
+
+To `define an accessor for a component function` given an object |target|, a function export |export| and a Boolean |enumerable|:
+1. Let |key| be `JSName`(|export|).
+1. Let |accessor| be the `accessor` capture of |export|.Name.
+1. Let |name| be the string-concatenation of |accessor|, " " and |key|.
+1. Let |takesSelf| be **true** if |export|.Name matches *Member* with `scope` "method", and **false** otherwise.
+1. Let |func| be `create a JS function for a component function` given |export|.Func, |name| and |takesSelf|.
+1. If |accessor| is "get":
+ 1. Perform `DefinePropertyOrThrow`(|target|, |key|, PropertyDescriptor { [[Get]]: |func|, [[Set]]: **undefined**, [[Enumerable]]: |enumerable|, [[Configurable]]: **true** }).
+1. Else:
+ 1. Perform `DefinePropertyOrThrow`(|target|, |key|, PropertyDescriptor { [[Set]]: |func| }).
+
+The "set" case defines a partial descriptor, so it only replaces the [[Set]] field of the accessor property the matching `[get]` export already defined. The `"get "`/`"set "` prefix on the function name follows how JS names accessor functions.
+
+To `invoke a component function` given |componentFunc|, a Boolean |takesSelf|, |thisValue| and a List of JS values |args|:
+1. Let |paramTypes| be |componentFunc|.Params.
+1. Let |resultType| be |componentFunc|.Result.
+1. Let |formalParamsOffset| be 1 if |takesSelf| is **true**, else 0.
+1. Let |formalParamsCount| be |paramTypes|.length - |formalParamsOffset|.
+1. If |resultType| is a `result`:
+ 1. Let |okType| be its `ok` payload type, or **empty** if it has none.
+ 1. Let |errorType| be its `error` payload type, or **empty** if it has none.
+ 1. Let |throwing| be **true**.
+1. Else:
+ 1. Let |okType| be |resultType|, or **empty** if |componentFunc| has no result.
+ 1. Let |throwing| be **false**.
+1. If `Length`(|args|) is less than |formalParamsCount|:
+ 1. Let |missingFormalArgCount| be |formalParamsCount| - `Length`(|args|).
+ 1. Let |missingFormalArgs| be a List of `undefined` repeated |missingFormalArgCount| times.
+ 1. Set |args| to |args| concatenated with |missingFormalArgs|.
+1. Let |instance| be the instance of |componentFunc|.
+1. If |instance|.[[Store]].is_locked_down():
+ 1. Perform ? `trap` given |instance|.
+1. Let |lenders| be a new empty List.
+1. Let |previousLenders| be the current lender list.
+1. Set the current lender list to |lenders|.
+1. Once the remaining steps complete, either normally or abruptly, perform:
+ 1. Decrement the [[LendCount]] of every instance in |lenders|.
+ 1. Set the current lender list to |previousLenders|.
+ 1. If the completion is abrupt and the call has entered the guest:
+ 1. Invoke |instance|.[[Store]].lock_down().
+1. Let |values| be a new empty List.
+1. If |formalParamsOffset| is 1:
+ 1. Append ? `ToComponentValue`(|thisValue|, |paramTypes|[0]) to |values|.
+1. For each i in [0, |formalParamsCount|): append ? `ToComponentValue`(|args|[i], |paramTypes|[i + |formalParamsOffset|]) to |values|.
+1. Let |componentResult| be the result of invoking |componentFunc| with |values|.
+1. If the call traps:
+ 1. Perform ? `trap` given |instance|.
+1. If |throwing| is **true** and |componentResult| is `result.error(|e|)`:
+ 1. Throw `create a component error` for |e| and |errorType|.
+1. If |okType| is **empty**:
+ 1. Return **empty**.
+1. If |throwing| is **true**:
+ 1. Return the `result.ok` payload of |componentResult|.
+1. Else:
+ 1. Return |componentResult|.
+
+To `create a component error` for an optional component value |e| and component type |errorType|:
+1. If |errorType| is **empty**:
+ 1. Let |payload| be **undefined**.
+1. Else:
+ 1. Let |payload| be `ToJSValue`(|e|, |errorType|).
+1. Return a new `ComponentError` whose `data` is |payload| and whose `message` is implementation-defined.
+
+## WebAssembly ESM-integration
+
+[ESM-integration](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration) extends to components. The module loader branches on the `layer` field of the binary to decide whether the bytes decode as a module or a component, so a component can be loaded anywhere a module can be today.
+
+Each component import has a [module specifier](https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#prod-ModuleSpecifier) given by `JSSpecifier`(|decl|).
+
+Which binding of the resolved module the component receives depends on the import's type:
+
+| Import type | JS equivalent | Value |
+|---|---|---|
+| bare type, function, value | `import v from "JSSpecifier(decl)"` | the [default export](https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#prod-ImportedDefaultBinding) |
+| instance | `import { a, b } from "JSSpecifier(decl)"` | one [named import](https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#prod-NamedImports) per export of the instance type whose name is an `interfacename` or matches *Plain*, named `JSName` of that export |
+| core module, component | `import source M from "JSSpecifier(decl)"` | the [module source](https://github.com/tc39/proposal-source-phase-imports), as a `Module` or `Component` |
+
+Reading the imports snapshots the resolved values, and so components cannot participate in cycles: a binding that is still uninitialized when the component is evaluated throws a `ReferenceError`. This matches how core modules work today with ESM-integration.
+
+Each resolved value is handed to [`read an import`](#read-the-imports-object) and the resulting definitions are passed to [`instantiate a component`](#instantiation).
+
+A component's exports become the bindings of its module namespace object. There is one binding per `JSName`(|export|), holding what [`create the exports object`](#create-the-exports-object) puts under that name, and no `default` binding. Exports matching *Property* have no binding, since a binding cannot be an accessor.
+
+## Follow ups
+
+1. How to dynamically pass a union value? Statically passing a single case of the union works, but not dynamic choice.
+1. How to import multiple overloads of a function? Can we just use `external-id`?
+1. How to support class inheritance and casting?
+1. Do we support a reference equality protocol? `ToJSValue` creates a fresh resource instance per lift, so two `borrow`s of one component-defined resource are two JS objects that do not compare equal. Reps are opaque and reusable after a drop, so an identity map would need careful invalidation.
+1. Do we let a JS constructor supply its own brand check?
+1. Should a `[get]`/`[set]` import fall back to a `Get`/`Set` on the target when the property is not an accessor? That would let data properties, `Proxy` traps and module namespace bindings satisfy a property import.
+1. How does a component feature test an import?
+1. How does a component pass one of its own functions to a JS callback, e.g. `add-event-listener`?
+1. Top-level await, and async start functions.