-
Notifications
You must be signed in to change notification settings - Fork 27k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: wasm text format and import support (vercel/turborepo#5636)
- Loading branch information
1 parent
7953188
commit 5543765
Showing
20 changed files
with
749 additions
and
239 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
crates/turbopack-tests/tests/execution/turbopack/wasm/complex/input/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Adapted from webpack | ||
https://github.com/webpack/webpack/blob/6be4065ade1e252c1d8dcba4af0f43e32af1bdc1/examples/wasm-complex/README.md |
20 changes: 20 additions & 0 deletions
20
crates/turbopack-tests/tests/execution/turbopack/wasm/complex/input/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
describe("complex wasm", () => { | ||
it("should be possible to use imported memory", async () => { | ||
// magic.js is an async module, so we import it inside this function to make sure the entrypoint isn't async. | ||
const { get, set } = await import("./magic.js"); | ||
|
||
set(42); | ||
expect(get()).toEqual(42); | ||
set(123); | ||
expect(get()).toEqual(123); | ||
}); | ||
|
||
it("should be possible to use imported functions", async () => { | ||
// magic.js is an async module, so we import it inside this function to make sure the entrypoint isn't async. | ||
const { getNumber } = await import("./magic.js"); | ||
|
||
// random numbers | ||
expect(getNumber()).toBeGreaterThanOrEqual(0); | ||
expect(getNumber()).toBeGreaterThanOrEqual(0); | ||
}); | ||
}) |
7 changes: 7 additions & 0 deletions
7
crates/turbopack-tests/tests/execution/turbopack/wasm/complex/input/magic-number.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export function getNumber() { | ||
return 42; | ||
} | ||
|
||
export function getRandomNumber() { | ||
return Math.floor(Math.random() * 256); | ||
} |
2 changes: 2 additions & 0 deletions
2
crates/turbopack-tests/tests/execution/turbopack/wasm/complex/input/magic.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// reexporting | ||
export * from "./magic.wat"; |
15 changes: 15 additions & 0 deletions
15
crates/turbopack-tests/tests/execution/turbopack/wasm/complex/input/magic.wat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
(module | ||
(type $t0 (func (result i32))) | ||
(type $t1 (func (param i32))) | ||
(import "./memory.js" "memory" (memory 1)) | ||
(import "./magic-number.js" "getRandomNumber" (func $getRandomNumber (type $t0))) | ||
(func $get (export "get") (type $t0) (result i32) | ||
(i32.load | ||
(i32.const 0))) | ||
(func $set (export "set") (type $t1) (param $p i32) | ||
(i32.store | ||
(i32.const 0) | ||
(get_local $p))) | ||
(func $getNumber (export "getNumber") (type $t0) (result i32) | ||
(call $getRandomNumber)) | ||
) |
7 changes: 7 additions & 0 deletions
7
crates/turbopack-tests/tests/execution/turbopack/wasm/complex/input/memory.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
async function getMemoryFromParentInWorker() { | ||
await new Promise(r => setTimeout(r, 200)); | ||
// fake | ||
return new WebAssembly.Memory({ initial: 1 }); | ||
} | ||
|
||
export const memory = await getMemoryFromParentInWorker(); |
2 changes: 1 addition & 1 deletion
2
crates/turbopack-tests/tests/execution/turbopack/wasm/simple/input/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use std::collections::BTreeMap; | ||
|
||
use anyhow::Result; | ||
use turbo_tasks::Vc; | ||
use turbo_tasks_fs::FileContent; | ||
use turbopack_core::asset::Asset; | ||
use wasmparser::{Chunk, Parser, Payload}; | ||
|
||
use crate::source::WebAssemblySource; | ||
|
||
/// Imports and exports of a WebAssembly file. | ||
#[turbo_tasks::value] | ||
#[derive(Default)] | ||
pub(crate) struct WebAssemblyAnalysis { | ||
pub imports: BTreeMap<String, Vec<String>>, | ||
pub exports: Vec<String>, | ||
} | ||
|
||
/// Analyse a WebAssembly file. | ||
/// | ||
/// Extracts imports and exports. | ||
#[turbo_tasks::function] | ||
pub(crate) async fn analyze(source: Vc<WebAssemblySource>) -> Result<Vc<WebAssemblyAnalysis>> { | ||
let content = source.content().file_content().await?; | ||
|
||
let mut analysis = WebAssemblyAnalysis::default(); | ||
|
||
let FileContent::Content(file) = &*content else { | ||
return Ok(analysis.cell()); | ||
}; | ||
|
||
let mut bytes = &*file.content().to_bytes()?; | ||
|
||
let mut parser = Parser::new(0); | ||
loop { | ||
let payload = match parser.parse(bytes, true)? { | ||
Chunk::Parsed { consumed, payload } => { | ||
bytes = &bytes[consumed..]; | ||
payload | ||
} | ||
// this state isn't possible with `eof = true` | ||
Chunk::NeedMoreData(_) => unreachable!(), | ||
}; | ||
|
||
match payload { | ||
Payload::ImportSection(s) => { | ||
for import in s { | ||
let import = import?; | ||
|
||
analysis | ||
.imports | ||
.entry(import.module.to_string()) | ||
.or_default() | ||
.push(import.name.to_string()); | ||
} | ||
} | ||
Payload::ExportSection(s) => { | ||
for export in s { | ||
let export = export?; | ||
|
||
analysis.exports.push(export.name.to_string()); | ||
} | ||
} | ||
|
||
// skip over code sections | ||
Payload::CodeSectionStart { size, .. } => { | ||
parser.skip_section(); | ||
bytes = &bytes[size as usize..]; | ||
} | ||
|
||
Payload::End(_) => break, | ||
_ => {} | ||
} | ||
} | ||
|
||
Ok(analysis.cell()) | ||
} |
Oops, something went wrong.