11import { stat , readFile , writeFile } from "node:fs/promises" ;
22import { resolve , basename } from "node:path" ;
3+
4+ import * as wasmToolsComponent from "../../obj/wasm-tools.js" ;
5+
36import { styleText } from "../common.js" ;
47
58/** All features that can be enabled/disabled */
@@ -8,19 +11,61 @@ const ALL_FEATURES = ["clocks", "http", "random", "stdio", "fetch-event"];
811/** Features that should be used for --debug mode */
912const DEBUG_FEATURES = [ "stdio" ] ;
1013
11- export async function componentize ( jsSource , opts ) {
12- const { componentize : componentizeFn } = await eval ( 'import("@bytecodealliance/componentize-js")' ) ;
14+ /**
15+ * Detect whether the WIT of a given component contains an older version of
16+ * `wasi:http` which necessitates an older version of `componentize-js`
17+ *
18+ * @param {string } witPath
19+ * @returns bool
20+ */
21+ async function usesOlderWasiHTTP ( witPath , worldName ) {
22+ await wasmToolsComponent . $init ;
23+
24+ const worldMetadata = wasmToolsComponent . tools . componentWitMetadataForWorld (
25+ { tag : "path" , val : witPath } ,
26+ worldName ?? null ,
27+ ) ;
28+
29+ // Check if the an old `wasi:http/incoming-handler` version is exported
30+ const exportsOldIncomingHandler = worldMetadata . exports . some ( ( iface ) => {
31+ return (
32+ iface . namespace === "wasi" &&
33+ iface . package === "http" &&
34+ iface . interface === "incoming-handler" &&
35+ iface . version !== null &&
36+ iface . version . major === 0n &&
37+ iface . version . minor < 3n &&
38+ iface . version . patch < 10n
39+ ) ;
40+ } ) ;
1341
42+ return exportsOldIncomingHandler ;
43+
44+ }
45+ export async function componentize ( jsSource , opts ) {
1446 const { disableFeatures, enableFeatures } = calculateFeatureSet ( opts ) ;
1547
1648 const source = await readFile ( jsSource , "utf8" ) ;
17-
1849 const witPath = resolve ( opts . wit ) ;
1950 const sourceName = basename ( jsSource ) ;
2051
52+ // Load an older version of componentize-js if we detect an older version of WASI HTTP in use
53+ // as the version that is usable is baked into the StarlingMonkey version provided by a given version
54+ // of componentize-js
55+ let componentizeJSModule ;
56+ const useOldComponentizeJS = await usesOlderWasiHTTP ( witPath , opts . worldName ) ;
57+ if ( useOldComponentizeJS ) {
58+ // NOTE: if we were to use a version of componentize-js 0.20.0 or newer here,
59+ // the build would fail, as newer versions do not support wasi:http < 0.2.10
60+ // for fetch.
61+ componentizeJSModule = await eval ( 'import("@bytecodealliance/componentize-js-0-19-3")' ) ;
62+ } else {
63+ componentizeJSModule = await eval ( 'import("@bytecodealliance/componentize-js")' ) ;
64+ }
65+
2166 let component ;
2267 try {
23- const result = await componentizeFn ( source , {
68+ const result = await componentizeJSModule . componentize ( source , {
2469 enableAot : opts . aot ,
2570 aotMinStackSizeBytes : opts . aotMinStackSizeBytes ,
2671 wevalBin : opts . wevalBin ,
@@ -41,7 +86,7 @@ export async function componentize(jsSource, opts) {
4186 } ,
4287 } ) ;
4388 if ( result . debug ) {
44- console . error ( `${ styleText ( "cyan" , "DEBUG" ) } Debug output\n${ JSON . stringify ( debug , null , 2 ) } \n` ) ;
89+ console . error ( `${ styleText ( "cyan" , "DEBUG" ) } Debug output\n${ JSON . stringify ( result . debug , null , 2 ) } \n` ) ;
4590 }
4691
4792 component = result . component ;
0 commit comments