Skip to content

Commit

Permalink
feat: add import map support to TS build (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucacasonato authored Sep 8, 2022
1 parent 7871ce3 commit f5a371c
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 28 deletions.
16 changes: 15 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ path = "lib.rs"
crate-type = ["cdylib"]

[dependencies]
js-sys = { version = "0.3.58" }
web-sys = { version = "0.3.58", features = ["ReadableStreamByobReader"] }
anyhow = "1"
console_error_panic_hook = "0.1.7"
deno_graph = "0.34.0"
eszip = { path = "../" }
import_map = "0.12.1"
js-sys = { version = "0.3.58" }
tokio = { version = "1.16", features = ["io-std", "io-util"] }
wasm-bindgen = { version = "0.2.81", features = ["serde-serialize"] }
wasm-bindgen-futures = { version = "0.4.31" }
tokio = { version = "1.16", features = ["io-std", "io-util"] }
console_error_panic_hook = "0.1.7"
anyhow = "1"
web-sys = { version = "0.3.58", features = ["ReadableStreamByobReader"] }
5 changes: 5 additions & 0 deletions lib/eszip_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ Deno.test("build default loader", async () => {
assert(eszip instanceof Uint8Array);
});

Deno.test("build with import map", async () => {
const eszip = await build(["data:application/javascript,import 'std/fs/mod.ts'"], undefined, "data:application/json,{\"imports\":{\"std/\":\"https://deno.land/std/\"}}");
assert(eszip instanceof Uint8Array);
});

Deno.test("loader errors", async () => {
await assertRejects(
() =>
Expand Down
43 changes: 24 additions & 19 deletions lib/eszip_wasm.generated.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @generated file from wasmbuild -- do not edit
// deno-lint-ignore-file
// deno-fmt-ignore-file
// source-hash: 98a0140f8d0e2627618501d48d383881dd895f6e
// source-hash: 0e24dd809865bd2b3c39b005f133376180af8ad2
let wasm;

const heap = new Array(32).fill(undefined);
Expand Down Expand Up @@ -141,7 +141,7 @@ function makeMutClosure(arg0, arg1, dtor, f) {
}
function __wbg_adapter_18(arg0, arg1, arg2) {
wasm
._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb729232beb9b5d9b(
._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hd4f05ebc54a3a357(
arg0,
arg1,
addHeapObject(arg2),
Expand All @@ -158,10 +158,15 @@ function passArray8ToWasm0(arg, malloc) {
* Serialize a module graph into eszip.
* @param {any} roots
* @param {Function} loader
* @param {any} import_map_url
* @returns {Promise<Uint8Array>}
*/
export function build(roots, loader) {
const ret = wasm.build(addHeapObject(roots), addHeapObject(loader));
export function build(roots, loader, import_map_url) {
const ret = wasm.build(
addHeapObject(roots),
addHeapObject(loader),
addHeapObject(import_map_url),
);
return takeObject(ret);
}

Expand All @@ -173,7 +178,7 @@ function handleError(f, args) {
}
}
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
wasm.wasm_bindgen__convert__closures__invoke2_mut__hdebb88ee150b08b4(
wasm.wasm_bindgen__convert__closures__invoke2_mut__hccb8632b1071bfde(
arg0,
arg1,
addHeapObject(arg2),
Expand Down Expand Up @@ -292,10 +297,6 @@ const imports = {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
},
__wbg_resolve_f269ce174f88b294: function (arg0) {
const ret = Promise.resolve(getObject(arg0));
return addHeapObject(ret);
},
__wbindgen_json_serialize: function (arg0, arg1) {
const obj = getObject(arg1);
const ret = JSON.stringify(obj === undefined ? null : obj);
Expand All @@ -308,14 +309,6 @@ const imports = {
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
},
__wbg_new_2ab697f1555e0dbc: function () {
const ret = new Array();
return addHeapObject(ret);
},
__wbg_push_811c8b08bf4ff9d5: function (arg0, arg1) {
const ret = getObject(arg0).push(getObject(arg1));
return ret;
},
__wbg_new_651776e932b7e9c7: function (arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
Expand All @@ -340,6 +333,18 @@ const imports = {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
},
__wbg_resolve_f269ce174f88b294: function (arg0) {
const ret = Promise.resolve(getObject(arg0));
return addHeapObject(ret);
},
__wbg_new_2ab697f1555e0dbc: function () {
const ret = new Array();
return addHeapObject(ret);
},
__wbg_push_811c8b08bf4ff9d5: function (arg0, arg1) {
const ret = getObject(arg0).push(getObject(arg1));
return ret;
},
__wbg_newwithlength_e833b89f9db02732: function (arg0) {
const ret = new Uint8Array(arg0 >>> 0);
return addHeapObject(ret);
Expand Down Expand Up @@ -452,8 +457,8 @@ const imports = {
const ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
},
__wbindgen_closure_wrapper9210: function (arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 134, __wbg_adapter_18);
__wbindgen_closure_wrapper9485: function (arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 143, __wbg_adapter_18);
return addHeapObject(ret);
},
},
Expand Down
Binary file modified lib/eszip_wasm_bg.wasm
Binary file not shown.
75 changes: 72 additions & 3 deletions lib/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use deno_graph::source::load_data_url;
use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::Loader;
use deno_graph::source::ResolveResponse;
use deno_graph::source::Resolver;
use deno_graph::ModuleSpecifier;
use eszip::v2::Url;
use import_map::ImportMap;
use js_sys::Promise;
use js_sys::Uint8Array;
use std::cell::RefCell;
Expand All @@ -11,6 +15,7 @@ use std::io::Error;
use std::io::ErrorKind;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
use tokio::io::AsyncRead;
Expand Down Expand Up @@ -243,12 +248,41 @@ impl Parser {
pub async fn build_eszip(
roots: JsValue,
loader: js_sys::Function,
import_map_url: JsValue,
) -> Result<Uint8Array, JsValue> {
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
let roots: Vec<deno_graph::ModuleSpecifier> = roots
.into_serde()
.map_err(|e| js_sys::Error::new(&e.to_string()))?;
let mut loader = GraphLoader(loader);
let import_map_url: Option<Url> = import_map_url
.into_serde()
.map_err(|e| js_sys::Error::new(&e.to_string()))?;
let (maybe_import_map, maybe_import_map_data) =
if let Some(import_map_url) = import_map_url {
let resp =
deno_graph::source::Loader::load(&mut loader, &import_map_url, false)
.await
.map_err(|e| js_sys::Error::new(&e.to_string()))?
.ok_or_else(|| {
js_sys::Error::new(&format!(
"import map not found at '{import_map_url}'"
))
})?;
match resp {
deno_graph::source::LoadResponse::Module {
specifier, content, ..
} => {
let import_map =
import_map::parse_from_json(&specifier, &content).unwrap();
(Some(import_map.import_map), Some((specifier, content)))
}
_ => unimplemented!(),
}
} else {
(None, None)
};
let resolver = GraphResolver(maybe_import_map);
let analyzer = deno_graph::CapturingModuleAnalyzer::default();
let graph = deno_graph::create_graph(
roots
Expand All @@ -258,7 +292,7 @@ pub async fn build_eszip(
false,
None,
&mut loader,
None,
Some(&resolver),
None,
Some(&analyzer),
None,
Expand All @@ -267,8 +301,20 @@ pub async fn build_eszip(
graph
.valid()
.map_err(|e| js_sys::Error::new(&e.to_string()))?;
let eszip = eszip::EszipV2::from_graph(graph, &analyzer.as_capturing_parser(), Default::default())
.map_err(|e| js_sys::Error::new(&e.to_string()))?;
let mut eszip = eszip::EszipV2::from_graph(
graph,
&analyzer.as_capturing_parser(),
Default::default(),
)
.map_err(|e| js_sys::Error::new(&e.to_string()))?;
if let Some((import_map_specifier, import_map_content)) =
maybe_import_map_data
{
eszip.add_import_map(
import_map_specifier.to_string(),
Arc::new(import_map_content.as_bytes().to_vec()),
)
}
Ok(Uint8Array::from(eszip.into_bytes().as_slice()))
}

Expand Down Expand Up @@ -316,3 +362,26 @@ impl Loader for GraphLoader {
}
}
}

#[derive(Debug)]
pub struct GraphResolver(Option<ImportMap>);

impl Resolver for GraphResolver {
fn resolve(
&self,
specifier: &str,
referrer: &deno_graph::ModuleSpecifier,
) -> ResolveResponse {
if let Some(import_map) = &self.0 {
match import_map.resolve(specifier, referrer) {
Ok(specifier) => ResolveResponse::Specifier(specifier),
Err(err) => ResolveResponse::Err(err.into()),
}
} else {
match deno_graph::resolve_import(specifier, referrer) {
Ok(specifier) => ResolveResponse::Specifier(specifier),
Err(err) => ResolveResponse::Err(err.into()),
}
}
}
}
2 changes: 2 additions & 0 deletions lib/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ export class Parser extends InternalParser {
export async function build(
roots: string[],
loader: (url: string) => Promise<LoadResponse | undefined> = load,
importMapUrl?: string,
): Promise<Uint8Array> {
const { build } = await instantiate();
return build(
roots,
(specifier: string) =>
loader(specifier).catch((err) => Promise.reject(String(err))),
importMapUrl,
);
}

0 comments on commit f5a371c

Please sign in to comment.