diff --git a/Cargo.lock b/Cargo.lock index 0abd766..5cc4684 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,9 +254,9 @@ dependencies = [ [[package]] name = "deno_ast" -version = "0.37.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67f9b18b22c707b59cf1ee9cb6f0afbfcf0d03a59b9244ddadacf6a4dc7cfeba" +checksum = "b2be70f80fee64edfbbc4a61c50f18b4a0fbff0b2657d26f6f0443e1db279af9" dependencies = [ "anyhow", "base64", @@ -333,9 +333,9 @@ dependencies = [ [[package]] name = "deno_graph" -version = "0.72.0" +version = "0.73.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508791f6140a8b5b1ac40bac1842db04281b61db4b64c5fd5bf9f1f7259f328a" +checksum = "046123e4f8de81c7db363d0869d783a5dcd6ceb007b07c6ba4fdf3cc0a82314e" dependencies = [ "anyhow", "async-trait", @@ -360,9 +360,9 @@ dependencies = [ [[package]] name = "deno_media_type" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a798670c20308e5770cc0775de821424ff9e85665b602928509c8c70430b3ee0" +checksum = "a8978229b82552bf8457a0125aa20863f023619cfc21ebb007b1e571d68fd85b" dependencies = [ "data-url", "serde", @@ -692,9 +692,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1928,9 +1928,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1938,9 +1938,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -1953,9 +1953,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1965,9 +1965,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1975,9 +1975,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -1988,9 +1988,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" diff --git a/Cargo.toml b/Cargo.toml index 23de5ea..abb8784 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ [workspace.dependencies] anyhow = "1.0.44" base64 = "0.21.5" -deno_graph = { version = "0.72.0", default-features = false } +deno_graph = { version = "0.73.1", default-features = false } url = { version = "2.3.1" } [profile.release] diff --git a/deno.jsonc b/deno.jsonc index e75f4bd..7b2949c 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -3,7 +3,7 @@ "tasks": { "test": "deno test -A", "update-snapshots": "deno test -A -- --update", - "build": "cp LICENSE js/LICENSE && deno run -A https://deno.land/x/wasmbuild@0.15.1/main.ts --out js" + "build": "cp LICENSE js/LICENSE && deno run -A jsr:@deno/wasmbuild@0.17.1 --out js" }, "exclude": [ "lib", diff --git a/js/emit.generated.d.ts b/js/emit.generated.d.ts new file mode 100644 index 0000000..320ff30 --- /dev/null +++ b/js/emit.generated.d.ts @@ -0,0 +1,50 @@ +// deno-lint-ignore-file +// deno-fmt-ignore-file + +export interface InstantiateResult { + instance: WebAssembly.Instance; + exports: { + bundle: typeof bundle; + transpile: typeof transpile + }; +} + +/** Gets if the Wasm module has been instantiated. */ +export function isInstantiated(): boolean; + +/** Options for instantiating a Wasm instance. */ +export interface InstantiateOptions { + /** Optional url to the Wasm file to instantiate. */ + url?: URL; + /** Callback to decompress the raw Wasm file bytes before instantiating. */ + decompress?: (bytes: Uint8Array) => Uint8Array; +} + +/** Instantiates an instance of the Wasm module returning its functions. +* @remarks It is safe to call this multiple times and once successfully +* loaded it will always return a reference to the same object. */ +export function instantiate(opts?: InstantiateOptions): Promise; + +/** Instantiates an instance of the Wasm module along with its exports. + * @remarks It is safe to call this multiple times and once successfully + * loaded it will always return a reference to the same object. */ +export function instantiateWithInstance(opts?: InstantiateOptions): Promise; + +/** +* @param {string} root +* @param {Function} load +* @param {string | undefined} maybe_bundle_type +* @param {any} maybe_import_map +* @param {any} maybe_compiler_options +* @param {boolean} minify +* @returns {Promise} +*/ +export function bundle(root: string, load: Function, maybe_bundle_type: string | undefined, maybe_import_map: any, maybe_compiler_options: any, minify: boolean): Promise; +/** +* @param {string} root +* @param {Function} load +* @param {any} maybe_import_map +* @param {any} maybe_compiler_options +* @returns {Promise} +*/ +export function transpile(root: string, load: Function, maybe_import_map: any, maybe_compiler_options: any): Promise; diff --git a/js/mod.ts b/js/mod.ts index 4e6e25d..9cc1aba 100644 --- a/js/mod.ts +++ b/js/mod.ts @@ -41,7 +41,7 @@ import { type CacheSetting, createCache, type FetchCacher, -} from "https://deno.land/x/deno_cache@0.7.1/mod.ts"; +} from "jsr:@deno/cache-dir@0.8"; /** The output of the {@linkcode bundle} function. */ export interface BundleEmit { @@ -218,7 +218,7 @@ export async function bundle( }); }, type, - processImportMapInput(importMap), + await processImportMapInput(importMap, bundleLoad), compilerOptions, minify ?? false, ); @@ -275,7 +275,7 @@ export async function transpile( }, ); }, - processImportMapInput(importMap), + await processImportMapInput(importMap, transpileLoad), compilerOptions, ); } @@ -308,13 +308,33 @@ function checkCompilerOptions( * @param importMap The import map as provided to the JS API. * @returns The import map that must be provided to the Rust API. */ -function processImportMapInput( +async function processImportMapInput( importMap: ImportMapJsLibInput, -): ImportMapRustLibInput { + load: FetchCacher["load"], +): Promise { if (typeof importMap === "string" || importMap instanceof URL) { - return locationToUrl(importMap).toString(); - } - if (typeof importMap === "object") { + importMap = locationToUrl(importMap); + const data = await load(importMap.toString(), false, "use"); + if (data == null) { + return undefined; + } + switch (data.kind) { + case "module": { + return { + baseUrl: importMap.toString(), + jsonString: data.content instanceof Uint8Array + ? new TextDecoder().decode(data.content) + : data.content, + }; + } + case "external": + throw new Error("External import maps are not supported."); + default: { + const _assertNever: never = data; + throw new Error("Unexpected kind."); + } + } + } else if (typeof importMap === "object") { const { baseUrl, imports, scopes } = importMap; const url = locationToUrl(baseUrl ?? Deno.cwd()); // Rust lib expects url to be the file URL to the import map file, but the @@ -327,8 +347,9 @@ function processImportMapInput( baseUrl: url.toString(), jsonString: JSON.stringify({ imports, scopes }), }; + } else { + return undefined; } - return undefined; } type ImportMapJsLibInput = @@ -340,5 +361,4 @@ type ImportMapRustLibInput = baseUrl: string; jsonString: string; } - | string | undefined; diff --git a/rs-lib/src/emit.rs b/rs-lib/src/emit.rs index c63f05b..4defd5a 100644 --- a/rs-lib/src/emit.rs +++ b/rs-lib/src/emit.rs @@ -356,14 +356,14 @@ mod test { root: S, sources: Vec<(S, Source)>, ) -> (ModuleGraph, CapturingModuleAnalyzer, ModuleSpecifier) { - let mut memory_loader = MemoryLoader::new(sources, vec![]); + let memory_loader = MemoryLoader::new(sources, vec![]); let root = ModuleSpecifier::parse(root.as_ref()).unwrap(); let analyzer = CapturingModuleAnalyzer::default(); let mut graph = ModuleGraph::new(GraphKind::CodeOnly); graph .build( vec![root.clone()], - &mut memory_loader, + &memory_loader, BuildOptions { module_analyzer: &analyzer, ..Default::default() diff --git a/rs-lib/src/lib.rs b/rs-lib/src/lib.rs index 235366b..3618929 100644 --- a/rs-lib/src/lib.rs +++ b/rs-lib/src/lib.rs @@ -8,7 +8,6 @@ mod emit; mod text; use anyhow::Result; -use deno_graph::source::LoadResponse; use deno_graph::source::ResolveError; use deno_graph::BuildOptions; use deno_graph::CapturingModuleAnalyzer; @@ -43,8 +42,7 @@ pub async fn bundle( maybe_import_map: Option, options: BundleOptions, ) -> Result { - let maybe_import_map = - get_import_map_from_input(&maybe_import_map, loader).await?; + let maybe_import_map = get_import_map_from_input(&maybe_import_map)?; let import_map_resolver = ImportMapResolver(maybe_import_map); let mut graph = ModuleGraph::new(GraphKind::CodeOnly); graph @@ -69,8 +67,7 @@ pub async fn transpile( emit_options: &EmitOptions, ) -> Result> { let analyzer = CapturingModuleAnalyzer::default(); - let maybe_import_map = - get_import_map_from_input(&maybe_import_map, loader).await?; + let maybe_import_map = get_import_map_from_input(&maybe_import_map)?; let import_map_resolver = ImportMapResolver(maybe_import_map); let mut graph = ModuleGraph::new(GraphKind::CodeOnly); graph @@ -112,72 +109,26 @@ pub async fn transpile( } #[derive(Debug)] -pub enum ImportMapInput { - ModuleSpecifier(ModuleSpecifier), - Json { base_url: Url, json_string: String }, +pub struct ImportMapInput { + pub base_url: Url, + pub json_string: String, } -async fn get_import_map_from_input( +fn get_import_map_from_input( maybe_input: &Option, - loader: &mut dyn Loader, ) -> Result> { if let Some(input) = maybe_input { - match input { - ImportMapInput::ModuleSpecifier(url) => { - let response = loader - .load( - url, - LoadOptions { - is_dynamic: false, - cache_setting: CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await? - .ok_or_else(|| { - anyhow::anyhow!("Could not find import map {}", url) - })?; - match response { - LoadResponse::External { specifier } => Err(anyhow::anyhow!( - "Did not expect external import map {}", - specifier - )), - LoadResponse::Module { - content, - specifier, - maybe_headers: _, - } => { - let import_map = import_map::parse_from_json_with_options( - &specifier, - &String::from_utf8(content.to_vec())?, - ImportMapOptions { - address_hook: None, - // always do this for simplicity - expand_imports: true, - }, - )? - .import_map; - Ok(Some(import_map)) - } - } - } - ImportMapInput::Json { - base_url, - json_string, - } => { - let import_map = import_map::parse_from_json_with_options( - base_url, - json_string, - ImportMapOptions { - address_hook: None, - // always do this for simplicity - expand_imports: true, - }, - )? - .import_map; - Ok(Some(import_map)) - } - } + let import_map = import_map::parse_from_json_with_options( + &input.base_url, + &input.json_string, + ImportMapOptions { + address_hook: None, + // always do this for simplicity + expand_imports: true, + }, + )? + .import_map; + Ok(Some(import_map)) } else { Ok(None) } diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 277216f..bd0a50f 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -19,9 +19,9 @@ console_error_panic_hook = "0.1.7" deno_emit = { path = "../rs-lib" } deno_graph = { workspace = true, features = ["wasm_executor"] } getrandom = { version = "*", features = ["js"] } -js-sys = { version = "=0.3.64" } +js-sys = { version = "=0.3.69" } serde = { version = "1.0.130", features = ["derive", "rc"] } url = { workspace = true } -wasm-bindgen = { version = "=0.2.87" } -wasm-bindgen-futures = { version = "=0.4.37" } +wasm-bindgen = { version = "=0.2.92" } +wasm-bindgen-futures = { version = "=0.4.42" } serde-wasm-bindgen = "0.5.0" diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 0a0b93f..ff02b7b 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -76,6 +76,7 @@ impl CompilerOptions { jsx_development, jsx_import_source: self.jsx_import_source, precompile_jsx, + precompile_jsx_skip_elements: None, }, EmitOptions { inline_sources: self.inline_sources, @@ -105,36 +106,20 @@ impl Default for CompilerOptions { } #[derive(serde::Deserialize, Debug)] -#[serde(untagged)] -enum ImportMapJsInput { - ModuleSpecifier(String), - #[serde(rename_all = "camelCase")] - Json { - base_url: String, - json_string: String, - }, +#[serde(rename_all = "camelCase")] +struct ImportMapJsInput { + base_url: String, + json_string: String, } impl TryFrom for ImportMapInput { type Error = anyhow::Error; fn try_from(js_input: ImportMapJsInput) -> anyhow::Result { - match js_input { - ImportMapJsInput::ModuleSpecifier(specifier) => { - let specifier = ModuleSpecifier::parse(&specifier)?; - Ok(ImportMapInput::ModuleSpecifier(specifier)) - } - ImportMapJsInput::Json { - base_url, - json_string, - } => { - let base_url = Url::parse(&base_url)?; - Ok(ImportMapInput::Json { - base_url, - json_string, - }) - } - } + Ok(ImportMapInput { + base_url: Url::parse(&js_input.base_url)?, + json_string: js_input.json_string, + }) } } @@ -160,7 +145,7 @@ impl JsLoader { impl Loader for JsLoader { fn load( - &mut self, + &self, specifier: &ModuleSpecifier, options: LoadOptions, ) -> LoadFuture {