Skip to content

Commit d8d2a58

Browse files
authored
Merge pull request #12 from commontoolsinc/feat/runtime-library-registration
rfc: Runtime Library Registration
2 parents 1e93a94 + ac2f6c5 commit d8d2a58

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+2573
-1854
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
target
22
.wireit
33
node_modules
4-
dist
4+
dist
5+
lib
6+
*.tsbuildinfo

Cargo.lock

Lines changed: 21 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
[workspace]
22
members = [
3-
"rust/example-crate",
43
"rust/usuba",
54
"rust/usuba-compat"
65
]
@@ -9,10 +8,12 @@ members = [
98
resolver = "2"
109

1110
[workspace.dependencies]
11+
anyhow = { version = "1" }
1212
async-trait = { version = "0.1" }
1313
axum = { version = "0.7" }
1414
blake3 = { version = "1.5" }
1515
bytes = { version = "1" }
16+
hyper-util = { version = "0.1", features = ["client", "client-legacy"] }
1617
js-component-bindgen = { version = "1", features = ["transpile-bindgen"] }
1718
js-sys = { version = "0.3" }
1819
mime_guess = { version = "2" }
@@ -23,6 +24,7 @@ serde_json = { version = "1" }
2324
tempfile = { version = "3" }
2425
thiserror = { version = "1" }
2526
tokio = { version = "1" }
27+
tower-http = { version = "0.5" }
2628
tracing = { version = "0.1" }
2729
tracing-subscriber = { version = "0.3", features = ["env-filter", "tracing-log", "json"] }
2830
tracing-web = { version = "0.1" }
@@ -32,7 +34,8 @@ wasm-bindgen = { version = "0.2" }
3234
wasmtime-environ = { version = "20" }
3335
web-sys = { version = "0.3" }
3436
wit-bindgen = { version = "0.25" }
37+
wit-parser = { version = "0.208" }
3538

3639
[profile.release]
3740
opt-level = 'z'
38-
lto = true
41+
lto = true

rfcs/2024-05-19-on-demand-isolated-component.md renamed to rfcs/2024-05-19-on-demand-isolated-modules.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# On-demand Isolated Components
1+
# On-demand Isolated Modules
22

3-
This document proposes a basic assembly of tools and processes that aims to significantly reduce the time and effort required to experiment with multi-language isolated components within a host web browser Wasm runtime.
3+
This document proposes a basic assembly of tools and processes that aims to significantly reduce the time and effort required to experiment with multi-language isolated modules within a host web browser Wasm runtime.
44

55
In most cases, the workflow may be reduced to importing a JavaScript module (available with associated TypeScript definitions) using the base64-encoded source file as a module specifier. For example:
66

@@ -32,11 +32,11 @@ const javascriptBase64 = atob(javascriptSourceCode);
3232

3333
// Import the modules:
3434
const { pythonComponent } = await import(
35-
`/__/wasm/on-demand/py/${witComponentDefinition}/${pythonSourceCode}`
35+
`/module/on-demand/py/${witComponentDefinition}/${pythonSourceCode}`
3636
);
3737

3838
const { javascriptComponent } = await import(
39-
`/__/wasm/on-demand/js/${witComponentDefinition}/${javascriptSourceCode}`
39+
`/module/on-demand/js/${witComponentDefinition}/${javascriptSourceCode}`
4040
);
4141

4242
// Prints "Hello, Python!" to the console
@@ -46,7 +46,7 @@ console.log(pythonComponent.hello());
4646
console.log(javascriptComponent.hello());
4747
```
4848

49-
In the example above, the action of importing each module invokes Wasm Component compilation / transpilation and Wasm instantiation behind the scenes, producing "on-demand" isolated components with high-level, comprehensively-typed JavaScript interfaces. The interface exported by the on-demand module can be invoked, re-exported and/or incorporated idiomatically into other JavaScript modules.
49+
In the example above, the action of importing each JavaScript module invokes Wasm Component compilation / transpilation and Wasm instantiation behind the scenes, producing "on-demand" isolated Modules with high-level, comprehensively-typed JavaScript interfaces. The interface exported by the on-demand module can be invoked, re-exported and/or incorporated idiomatically into other standard JavaScript modules.
5050

5151
Although the example uses [dynamic import][dynamic-import], the import specifiers should work equally well when used with static imports.
5252

@@ -81,21 +81,21 @@ Wasm runtimes in web browsers all implement [Core Wasm], which may be thought of
8181

8282
[Wasm Components][wasm-components] constitute an ABI defined on top of [Core Wasm], as part of ongoing [WASI] development efforts. Native support for Wasm Components is available in some Wasm runtimes, but it is not as ubiquitous as [Core Wasm].
8383

84-
### Components
84+
### Modules
8585

86-
Although the term "component" commonly refers to discrete, composable units of a user interface, this document uses the term in the sense of a [Wasm Component][wasm-components]. In this sense, a component may be thought of as any re-usable chunk of software.
86+
Modules are our domain jargon for a self-contained unit of code suitable for variable runtime environments. In our jargon, a [Wasm Component][wasm-components] may be thought of as a special case of a Module.
8787

88-
For the purposes of reasoning about what may or may not be part of a component's interface: anything that can be expressed in a [WIT][wit] definition is considered a candidate (this means you can express anything you want, probably).
88+
For the purposes of reasoning about what may or may not be part of a Module's interface: anything that can be expressed in a [WIT][wit] definition is considered a candidate (this means you can express anything you want, probably).
8989

9090
### Isolation
9191

92-
The techniques in this document are centered on making components out of [Wasm][wasm]. Therefor, when the term isolation is used, it mainly refers to the properties enabled by the Wasm runtime insofar as we may access it in a web browser. In a typical case, a Wasm module:
92+
The techniques in this document are centered on making Modules out of [Wasm][wasm]. Therefor, when the term isolation is used, it mainly refers to the properties enabled by the Wasm runtime insofar as we may access it in a web browser. In a typical case, a Wasm module:
9393

9494
- Will have its own, unshared buffer of memory
9595
- May only import objects, capabilities and metadata from "outside" the runtime when they are explicitly provided by its host
9696
- Must be invoked explicitly by its host
9797

98-
Wasm provides a reasonable, basic substrate for component isolation. But, it's important to note that this isolation does not constitute a security boundary. It is easy to accidentally grant more capabilities than intended to a Wasm module when providing it access to host APIs (especially within a web browser host). And, vulnerabilities such as [Specter][specter] and [Rowhammer][rowhammer] are theoretically possible to exploit from a Wasm module.
98+
Wasm provides a reasonable, basic substrate for Module isolation. But, it's important to note that this isolation does not constitute a security boundary. It is easy to accidentally grant more capabilities than intended to a Wasm module when providing it access to host APIs (especially within a web browser host). And, vulnerabilities such as [Specter][specter] and [Rowhammer][rowhammer] are theoretically possible to exploit from a Wasm module.
9999

100100
## Tools
101101

@@ -114,14 +114,14 @@ We will create a Build Server. The Build Server is responsible transforming rece
114114

115115
The Build Server provides a REST API domain in service of this responsibility.
116116

117-
#### POST /api/v0/component
117+
#### POST /api/v0/module
118118

119119
Accepts `multipart/form-data` requests.
120120

121121
For the first version, the body is expected to contain two files:
122122

123123
- A WIT component definition
124-
- A single source code file that implements the component interface
124+
- A single source code file that implements the suggested component interface
125125

126126
To handle a valid request, the Build Server must:
127127

@@ -141,7 +141,7 @@ The Build Server then responds with:
141141

142142
In the future, we may expand on this API to support many WIT definitions and source files in a single request (including support for many languages in one collection of files).
143143

144-
#### GET /api/v0/component/:id
144+
#### GET /api/v0/module/:id
145145

146146
This API serves [Wasm Components][wasm-components] that were successfully built by earlier requests to [POST /api/v0/component](#post-apiv0component).
147147

@@ -161,15 +161,15 @@ The [js-component-bindgen] Rust crate provides an API for transforming any valid
161161

162162
We will create a [Service Worker] that wraps up the capabilities of [js-component-bindgen] in order to polyfill transparent, on-demand support for [Wasm Components][wasm-components] in a web browser.
163163

164-
The Service Worker intercepts `GET` requests to a well-known local path that is unlikely to conflict with a REST-y path in use by the local application domain. For the purposes of this document, we'll say that the matching path looks like `/__/v0/wasm/on-demand/:ext/:wit/:source_code`. When a request is made to that path, the Service Worker performs the following steps:
164+
The Service Worker intercepts `GET` requests to a well-known local path. For the purposes of this document, we'll say that the matching path looks like `/module/on-demand/:ext/:wit/:source_code`. When a request is made to that path, the Service Worker performs the following steps:
165165

166166
1. Resolve the [WIT][wit] component definition by base64-decoding the `wit` part of the path
167167
2. Resolve the component source code by base64-decoding the `source_code` part of the path
168168
3. Prepare a `multipart/form-data` request body that includes two files:
169169
1. `component.wit`: The resolved WIT component definition
170170
2. `component.$EXT`: The resolved source file, where `$EXT` is replaced with the `ext` part of the path
171-
4. Make a request to [`POST /api/v0/component`](#post-apiv0component) on a running [Build Server](#build-server) using the prepared request body
172-
5. Make a request for the prepared [Wasm Component][wasm-components] using [`GET /api/v0/component/:id`](#get-apiv0componentid) on a running Build Server
171+
4. Make a request to [`POST /api/v0/module`](#post-apiv0component) on a running [Build Server](#build-server) using the prepared request body
172+
5. Make a request for the prepared [Wasm Component][wasm-components] using [`GET /api/v0/module/:id`](#get-apiv0componentid) on a running Build Server
173173
6. Invoke the [`transpile`][js-component-bindgen-transpile] API provided by [js-component-bindgen] and cache the returned files at the appropriate paths
174174
7. Create a wrapper ESM that imports the cached artifacts and re-exports the component API
175175
8. Respond to the intercepted request with the generated wrapper module

0 commit comments

Comments
 (0)