Skip to content

Commit 2a628d2

Browse files
authored
feat: allow using fetchEvent for wasi:http/[email protected] optionally (#122)
1 parent 498be91 commit 2a628d2

File tree

6 files changed

+48
-18
lines changed

6 files changed

+48
-18
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ Note that pure components **will not report errors and will instead trap**, so t
133133
Note that features explicitly imported by the target world cannot be disabled - if you target a component to a world
134134
that imports `wasi:clocks`, then `disableFeatures: ['clocks']` will not be supported.
135135

136+
## Using StarlingMonkey's `fetch-event`
137+
138+
The StarlingMonkey engine provides the ability to use `fetchEvent` to handle calls to `wasi:http/[email protected]#handle`. When targeting worlds that export `wasi:http/[email protected]` the fetch event will automatically be attached. Alternatively, to override the fetch event with a custom handler, export an explict `incomingHandler` or `'wasi:http/[email protected]'` object. Using the `fetchEvent` requires enabling the `http` feature.
139+
136140
## API
137141

138142
```ts

crates/spidermonkey-embedding-splicer/src/bindgen.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{uwrite, uwriteln};
1+
use crate::{uwrite, uwriteln, Features};
22
use anyhow::{bail, Result};
33
use heck::*;
44
use js_component_bindgen::function_bindgen::{
@@ -131,6 +131,7 @@ pub fn componentize_bindgen(
131131
name: &str,
132132
guest_imports: &Vec<String>,
133133
guest_exports: &Vec<String>,
134+
features: Vec<Features>,
134135
) -> Result<Componentization> {
135136
let mut bindgen = JsBindgen {
136137
src: Source::default(),
@@ -156,7 +157,7 @@ pub fn componentize_bindgen(
156157

157158
bindgen.imports_bindgen(&guest_imports);
158159

159-
bindgen.exports_bindgen(&guest_exports)?;
160+
bindgen.exports_bindgen(&guest_exports, features)?;
160161
bindgen.esm_bindgen.populate_export_aliases();
161162

162163
// consolidate import specifiers and generate wrappers
@@ -370,7 +371,11 @@ impl JsBindgen<'_> {
370371
return intrinsic.name().to_string();
371372
}
372373

373-
fn exports_bindgen(&mut self, guest_exports: &Vec<String>) -> Result<()> {
374+
fn exports_bindgen(
375+
&mut self,
376+
guest_exports: &Vec<String>,
377+
features: Vec<Features>,
378+
) -> Result<()> {
374379
for (key, export) in &self.resolve.worlds[self.world].exports {
375380
let name = self.resolve.name_world_key(key);
376381

@@ -382,9 +387,25 @@ impl JsBindgen<'_> {
382387
WorldKey::Interface(iface) => {
383388
if !guest_exports.contains(&name) {
384389
let iface = &self.resolve.interfaces[*iface];
385-
if let Some(name) = iface.name.as_ref() {
386-
let camel_case_name = name.to_lower_camel_case();
390+
if let Some(iface_name) = iface.name.as_ref() {
391+
let camel_case_name = iface_name.to_lower_camel_case();
387392
if !guest_exports.contains(&camel_case_name) {
393+
// For wasi:http/incoming-handler, we treat it
394+
// as a special case as the engine already
395+
// provides the export using fetchEvent and that
396+
// can be used when an explicit export is not
397+
// defined by the guest content.
398+
if iface_name == "incoming-handler"
399+
|| name == "wasi:http/[email protected]"
400+
{
401+
if !features.contains(&Features::Http) {
402+
bail!(
403+
"JS export definition for '{}' not found. Cannot use fetchEvent because the http feature is not enabled.",
404+
camel_case_name
405+
)
406+
}
407+
continue;
408+
}
388409
bail!("Expected a JS export definition for '{}'", camel_case_name);
389410
}
390411
// TODO: move populate_export_aliases to a preprocessing

crates/spidermonkey-embedding-splicer/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl Guest for SpidermonkeyEmbeddingSplicerComponent {
115115
world_name: Option<String>,
116116
mut guest_imports: Vec<String>,
117117
guest_exports: Vec<String>,
118+
features: Vec<Features>,
118119
debug: bool,
119120
) -> Result<SpliceResult, String> {
120121
let source_name = source_name.unwrap_or("source.js".to_string());
@@ -194,6 +195,7 @@ impl Guest for SpidermonkeyEmbeddingSplicerComponent {
194195
&source_name,
195196
&guest_imports,
196197
&guest_exports,
198+
features,
197199
)
198200
.map_err(|err| err.to_string())?;
199201

crates/spidermonkey-embedding-splicer/wit/spidermonkey-embedding-splicer.wit

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ world spidermonkey-embedding-splicer {
3333

3434
export stub-wasi: func(engine: list<u8>, features: list<features>, wit-world: option<string>, wit-path: option<string>, world-name: option<string>) -> result<list<u8>, string>;
3535

36-
export splice-bindings: func(source-name: option<string>, spidermonkey-engine: list<u8>, wit-world: option<string>, wit-path: option<string>, world-name: option<string>, guest-imports: list<string>, guest-exports: list<string>, debug: bool) -> result<splice-result, string>;
36+
export splice-bindings: func(source-name: option<string>, spidermonkey-engine: list<u8>, wit-world: option<string>, wit-path: option<string>, world-name: option<string>, guest-imports: list<string>, guest-exports: list<string>, features: list<features>, debug: bool) -> result<splice-result, string>;
3737
}

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/componentize.js

+13-10
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,6 @@ export async function componentize(jsSource, witWorld, opts) {
6666
guestExports.push(k.n);
6767
});
6868

69-
let { wasm, jsBindings, importWrappers, exports, imports } = spliceBindings(
70-
sourceName,
71-
await readFile(engine),
72-
witWorld,
73-
maybeWindowsPath(witPath),
74-
worldName,
75-
guestImports,
76-
guestExports,
77-
false
78-
);
7969

8070
// we never disable a feature that is already in the target world usage
8171
const features = [];
@@ -92,6 +82,19 @@ export async function componentize(jsSource, witWorld, opts) {
9282
features.push('http');
9383
}
9484

85+
let { wasm, jsBindings, importWrappers, exports, imports } = spliceBindings(
86+
sourceName,
87+
await readFile(engine),
88+
witWorld,
89+
maybeWindowsPath(witPath),
90+
worldName,
91+
guestImports,
92+
guestExports,
93+
features,
94+
false
95+
);
96+
97+
9598
if (DEBUG_BINDINGS) {
9699
console.log('--- JS Source ---');
97100
console.log(jsSource);

0 commit comments

Comments
 (0)