Skip to content

Commit e588476

Browse files
authored
feat: support importing WebAssembly modules (#519)
* chore: update dependency * chore: update `Cargo.lock` * feat: support wasm modules * chore: add an integration test for wasm module import
1 parent fdf922e commit e588476

File tree

9 files changed

+69
-19
lines changed

9 files changed

+69
-19
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ windows-sys = { version = "0.59.0", features = ["Win32_Foundation", "Win32_Media
202202
[patch.crates-io]
203203
# If the PR is merged upstream, remove the line below.
204204
deno_core = { git = "https://github.com/supabase/deno_core", branch = "324-supabase" }
205-
eszip = { git = "https://github.com/supabase/eszip", branch = "fix-pub-vis-0-80-0" }
205+
eszip = { git = "https://github.com/supabase/eszip", branch = "fix-pub-vis-0-80-1" }
206206

207207
[profile.dind]
208208
inherits = "dev"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"workspace": []
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { add } from "./math.wasm";
2+
3+
const three = add(1, 2) === 3;
4+
5+
export default {
6+
fetch() {
7+
return new Response(three ? "meow" : "woem");
8+
},
9+
};
318 Bytes
Binary file not shown.

crates/base/tests/integration_tests.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3794,6 +3794,25 @@ async fn test_should_be_able_to_trigger_early_drop_with_mem() {
37943794
unreachable!("test failed");
37953795
}
37963796

3797+
#[tokio::test]
3798+
#[serial]
3799+
async fn test_eszip_wasm_import() {
3800+
integration_test!(
3801+
"./test_cases/main",
3802+
NON_SECURE_PORT,
3803+
"eszip-wasm",
3804+
None,
3805+
None,
3806+
None,
3807+
(|resp| async {
3808+
let resp = resp.unwrap();
3809+
assert_eq!(resp.status().as_u16(), 200);
3810+
assert_eq!(resp.text().await.unwrap().as_str(), "meow");
3811+
}),
3812+
TerminationToken::new()
3813+
);
3814+
}
3815+
37973816
#[derive(Deserialize)]
37983817
struct ErrorResponsePayload {
37993818
msg: String,

crates/deno_facade/eszip/parse.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Below is roughly originated from eszip@0.72.2/src/v2.rs
1+
// Below is roughly originated from eszip@fix-pub-vis-0-80-1/src/v2.rs
22

33
use std::collections::HashMap;
44
use std::sync::Arc;
@@ -10,6 +10,7 @@ use eszip::v2::EszipNpmPackageIndex;
1010
use eszip::v2::EszipV2Module;
1111
use eszip::v2::EszipV2Modules;
1212
use eszip::v2::EszipV2SourceSlot;
13+
use eszip::v2::EszipVersion;
1314
use eszip::v2::Options;
1415
use eszip::v2::Section;
1516
use eszip::EszipV2;
@@ -20,22 +21,28 @@ use futures::AsyncRead;
2021
use futures::AsyncReadExt;
2122
use hashlink::LinkedHashMap;
2223

23-
const ESZIP_V2_MAGIC: &[u8; 8] = b"ESZIP_V2";
24-
const ESZIP_V2_2_MAGIC: &[u8; 8] = b"ESZIP2.2";
25-
2624
pub async fn parse_v2_header<R: AsyncRead + Unpin>(
27-
mut reader: &mut BufReader<R>,
25+
reader: &mut BufReader<R>,
2826
) -> Result<EszipV2, ParseError> {
2927
let mut magic = [0u8; 8];
3028
reader.read_exact(&mut magic).await?;
3129

32-
if !EszipV2::has_magic(&magic) {
30+
let Some(version) = EszipVersion::from_magic(&magic) else {
3331
return Err(ParseError::InvalidV2);
34-
}
32+
};
33+
34+
parse_v2_header_inner(version, reader).await
35+
}
36+
37+
// parse_with_version
38+
async fn parse_v2_header_inner<R: AsyncRead + Unpin>(
39+
version: EszipVersion,
40+
mut reader: &mut BufReader<R>,
41+
) -> Result<EszipV2, ParseError> {
42+
let supports_npm = version != EszipVersion::V2;
43+
let supports_options = version >= EszipVersion::V2_2;
3544

36-
let supports_npm = magic != *ESZIP_V2_MAGIC;
37-
let supports_options = magic == *ESZIP_V2_2_MAGIC;
38-
let mut options = Options::default_for_version(&magic);
45+
let mut options = Options::default_for_version(version);
3946

4047
if supports_options {
4148
let mut pre_options = options;
@@ -82,8 +89,8 @@ pub async fn parse_v2_header<R: AsyncRead + Unpin>(
8289
}
8390
}
8491

85-
let header = Section::read(&mut reader, options).await?;
86-
if !header.is_checksum_valid() {
92+
let modules_header = Section::read(&mut reader, options).await?;
93+
if !modules_header.is_checksum_valid() {
8794
return Err(ParseError::InvalidV2HeaderHash);
8895
}
8996

@@ -97,16 +104,16 @@ pub async fn parse_v2_header<R: AsyncRead + Unpin>(
97104
// error.
98105
macro_rules! read {
99106
($n:expr, $err:expr) => {{
100-
if read + $n > header.content_len() {
107+
if read + $n > modules_header.content_len() {
101108
return Err(ParseError::InvalidV2Header($err));
102109
}
103110
let start = read;
104111
read += $n;
105-
&header.content()[start..read]
112+
&modules_header.content()[start..read]
106113
}};
107114
}
108115

109-
while read < header.content_len() {
116+
while read < modules_header.content_len() {
110117
let specifier_len =
111118
u32::from_be_bytes(read!(4, "specifier len").try_into().unwrap())
112119
as usize;
@@ -130,6 +137,7 @@ pub async fn parse_v2_header<R: AsyncRead + Unpin>(
130137
1 => ModuleKind::Json,
131138
2 => ModuleKind::Jsonc,
132139
3 => ModuleKind::OpaqueData,
140+
4 => ModuleKind::Wasm,
133141
n => return Err(ParseError::InvalidV2ModuleKind(n, read)),
134142
};
135143
let source = if source_offset == 0 && source_len == 0 {

crates/deno_facade/graph.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub async fn create_eszip_from_graph_raw(
3838
eszip::EszipV2::from_graph(eszip::FromGraphOptions {
3939
graph,
4040
parser,
41+
module_kind_resolver: Default::default(),
4142
transpile_options,
4243
emit_options,
4344
relative_file_base,

crates/deno_facade/module_loader/standalone.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,16 @@ impl ModuleLoader for EmbeddedModuleLoader {
404404
type_error(format!("Module not found: {}", original_specifier))
405405
})?;
406406

407+
if module.inner.kind == ModuleKind::Wasm {
408+
return Ok(deno_core::ModuleSource::new_with_redirect(
409+
ModuleType::Wasm,
410+
ModuleSourceCode::Bytes(code.into()),
411+
&original_specifier,
412+
&module.specifier,
413+
None,
414+
));
415+
}
416+
407417
let code = arc_u8_to_arc_str(code)
408418
.map_err(|_| type_error("Module source is not utf-8"))?;
409419

@@ -467,7 +477,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
467477
ModuleKind::Jsonc => {
468478
return Err(type_error("jsonc modules not supported"))
469479
}
470-
ModuleKind::OpaqueData => {
480+
ModuleKind::OpaqueData | ModuleKind::Wasm => {
471481
unreachable!();
472482
}
473483
},

0 commit comments

Comments
 (0)