Skip to content

Commit

Permalink
Transcoding support (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford authored Aug 28, 2023
1 parent c7af4ba commit 7b81d14
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ js-component-bindgen = { path = "./crates/js-component-bindgen" }
wit-component = { workspace = true }

[build-dependencies]
anyhow = "1.0.71"
anyhow = { workspace = true }
js-component-bindgen = { path = "./crates/js-component-bindgen" }
wit-component = { workspace = true }

Expand Down
Binary file added adapter.wasm
Binary file not shown.
4 changes: 4 additions & 0 deletions bin/self_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ fn main() -> Result<()> {
encoder = encoder.adapter("wasi_snapshot_preview1", &adapter)?;

let adapted_component = encoder.encode()?;
fs::create_dir_all(PathBuf::from("./obj"))?;
let mut component_path = PathBuf::from("./obj").join(&name);
component_path.set_extension("component.wasm");
fs::write(component_path, &adapted_component)?;

let import_map = HashMap::from([
(
Expand Down
8 changes: 4 additions & 4 deletions crates/js-component-bindgen/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ pub fn render_intrinsics(
}
"),

Intrinsic::DataView => output.push_str("
let dv = new DataView(new ArrayBuffer());
const dataView = mem => dv.buffer === mem.buffer ? dv : dv = new DataView(mem.buffer);
"),
Intrinsic::DataView => output.push_str("
let dv = new DataView(new ArrayBuffer());
const dataView = mem => dv.buffer === mem.buffer ? dv : dv = new DataView(mem.buffer);
"),

Intrinsic::FetchCompile => if !no_nodejs_compat {
output.push_str("
Expand Down
54 changes: 44 additions & 10 deletions crates/js-component-bindgen/src/transpile_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ use wasmtime_environ::{
GlobalInitializer, InstantiateModule, LoweredIndex, RuntimeImportIndex,
RuntimeInstanceIndex, StaticModuleIndex, Trampoline, TrampolineIndex,
},
fact::{FixedEncoding, Transcode},
EntityIndex, PrimaryMap,
};
use wasmtime_environ::{EntityIndex, PrimaryMap};
use wit_bindgen_core::abi::{self, LiftLower};
use wit_component::StringEncoding;
use wit_parser::abi::AbiVariant;
Expand Down Expand Up @@ -431,6 +432,7 @@ impl<'a> Instantiator<'a, '_> {
}

fn trampoline(&mut self, i: TrampolineIndex, trampoline: &'a Trampoline) {
let i = i.as_u32();
match trampoline {
// these are hoisted before initialization
Trampoline::LowerImport { .. } => {}
Expand All @@ -446,15 +448,48 @@ impl<'a> Instantiator<'a, '_> {
// for now since it can't be tested and additionally JS doesn't
// support multi-memory which transcoders rely on anyway.
Trampoline::Transcoder {
op: _,
from: _,
from64: _,
to: _,
to64: _,
} => unimplemented!(),
op,
from,
from64,
to,
to64,
} => {
if *from64 || *to64 {
unimplemented!("memory 64 transcoder");
}
let from = from.as_u32();
let to = to.as_u32();
match op {
Transcode::Copy(FixedEncoding::Utf8) => {
uwriteln!(
self.src.js,
"function trampoline{i} (from_ptr, len, to_ptr) {{
new Uint8Array(memory{to}.buffer, to_ptr, len).set(new Uint8Array(memory{from}.buffer, from_ptr, len));
}}
"
);
}
Transcode::Copy(FixedEncoding::Utf16) => unimplemented!("utf16 copier"),
Transcode::Copy(FixedEncoding::Latin1) => unimplemented!("latin1 copier"),
Transcode::Latin1ToUtf16 => unimplemented!("latin to utf16 transcoder"),
Transcode::Latin1ToUtf8 => unimplemented!("latin to utf8 transcoder"),
Transcode::Utf16ToCompactProbablyUtf16 => {
unimplemented!("utf16 to compact wtf16 transcoder")
}
Transcode::Utf16ToCompactUtf16 => {
unimplemented!("utf16 to compact utf16 transcoder")
}
Transcode::Utf16ToLatin1 => unimplemented!("utf16 to latin1 transcoder"),
Transcode::Utf16ToUtf8 => unimplemented!("utf16 to utf8 transcoder"),
Transcode::Utf8ToCompactUtf16 => {
unimplemented!("utf8 to compact utf16 transcoder")
}
Transcode::Utf8ToLatin1 => unimplemented!("utf8 to latin1 transcoder"),
Transcode::Utf8ToUtf16 => unimplemented!("utf8 to utf16 transcoder"),
};
}

Trampoline::ResourceNew(resource) => {
let i = i.as_u32();
self.ensure_resource_table(*resource);
let rid = resource.as_u32();
uwrite!(
Expand All @@ -468,7 +503,6 @@ impl<'a> Instantiator<'a, '_> {
);
}
Trampoline::ResourceRep(resource) => {
let i = i.as_u32();
self.ensure_resource_table(*resource);
let rid = resource.as_u32();
uwrite!(
Expand All @@ -484,7 +518,6 @@ impl<'a> Instantiator<'a, '_> {
);
}
Trampoline::ResourceDrop(resource) => {
let i = i.as_u32();
self.ensure_resource_table(*resource);
let rid = resource.as_u32();
let resource = &self.types[*resource];
Expand Down Expand Up @@ -585,6 +618,7 @@ impl<'a> Instantiator<'a, '_> {
prev.is_none(),
"unsupported duplicate import of `{module}::{name}`"
);
assert!(prev.is_none());
}
let mut imports = String::new();
if !import_obj.is_empty() {
Expand Down
12 changes: 11 additions & 1 deletion test/cli.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { deepStrictEqual, ok, strictEqual } from 'node:assert';
import { readFile, rm } from 'node:fs/promises';
import { readFile, rm, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'url';
import { exec, jcoPath } from './helpers.js';
import { tmpdir } from 'node:os';
Expand All @@ -18,6 +18,16 @@ export async function cliTest (fixtures) {
catch {}
}

test('Transcoding', async () => {
const outDir = fileURLToPath(new URL(`./output/env-allow`, import.meta.url));
const { stderr } = await exec(jcoPath, 'transpile', `test/fixtures/env-allow.composed.wasm`, '-o', outDir);
strictEqual(stderr, '');
await writeFile(`${outDir}/package.json`, JSON.stringify({ type: 'module' }));
const source = await readFile(`${outDir}/env-allow.composed.js`);
const m = await import(`${outDir}/env-allow.composed.js`);
deepStrictEqual(m.testGetEnv(), [['CUSTOM', 'VAL']]);
});

test('Transpile', async () => {
try {
const name = 'flavorful';
Expand Down
Binary file added test/fixtures/env-allow.composed.wasm
Binary file not shown.
Binary file added test/fixtures/virt.wasm
Binary file not shown.
6 changes: 6 additions & 0 deletions update-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ cd ..
./src/jco.js componentize test/fixtures/component-gen/import-fn.js --wit test/fixtures/component-gen/import-fn.wit -o test/fixtures/components/import-fn.component.wasm

rm -rf wit-bindgen

## wasi virt to generate composition case
git clone https://github.com/bytecodealliance/wasi-virt
cd wasi-virt
cargo test
cp tests/generated/env-allow.composed.wasm ../test/fixtures/

0 comments on commit 7b81d14

Please sign in to comment.