mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-12 20:41:24 +00:00
Leverage new rustc wasm features
This commit leverages two new attributes in the Rust compiler, `#[wasm_custom_section]` and `#[wasm_import_module]`. These two attributes allow removing a lot of hacks found in wasm-bindgen and also allows removing the requirement of `wasm-opt` to remove the unused data sections. This does require two new nightly features but we already required the `proc_macro` nightly feature and these will hopefully be stabilized before that feature!
This commit is contained in:
@ -16,7 +16,6 @@ pub struct Context<'a> {
|
||||
pub required_internal_exports: HashSet<&'static str>,
|
||||
pub config: &'a Bindgen,
|
||||
pub module: &'a mut Module,
|
||||
pub imports_to_rewrite: HashSet<String>,
|
||||
pub custom_type_names: HashMap<char, String>,
|
||||
pub imported_names: HashSet<String>,
|
||||
pub exported_classes: HashMap<String, ExportedClass>,
|
||||
@ -288,18 +287,7 @@ impl<'a> Context<'a> {
|
||||
.flat_map(|s| s.entries_mut());
|
||||
|
||||
for import in imports {
|
||||
if import.field().starts_with("__wbindgen") {
|
||||
import.module_mut().truncate(0);
|
||||
import.module_mut().push_str("./");
|
||||
import.module_mut().push_str(module_name);
|
||||
continue
|
||||
}
|
||||
|
||||
// rustc doesn't have support for importing from anything other
|
||||
// than the module `env` so let's use the metadata here to
|
||||
// rewrite the imports if they import from `env` until it's
|
||||
// fixed upstream.
|
||||
if self.imports_to_rewrite.contains(import.field()) {
|
||||
if import.module() == "__wbindgen_placeholder__" {
|
||||
import.module_mut().truncate(0);
|
||||
import.module_mut().push_str("./");
|
||||
import.module_mut().push_str(module_name);
|
||||
@ -954,7 +942,7 @@ impl<'a> Context<'a> {
|
||||
};
|
||||
|
||||
imports.entries().iter().any(|i| {
|
||||
i.module() == "env" && i.field() == name
|
||||
i.module() == "__wbindgen_placeholder__" && i.field() == name
|
||||
})
|
||||
}
|
||||
|
||||
@ -1336,7 +1324,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
info: &shared::Import,
|
||||
import: &shared::ImportStatic) {
|
||||
// TODO: should support more types to import here
|
||||
self.cx.imports_to_rewrite.insert(import.shim.clone());
|
||||
let obj = self.import_name(info, &import.name);
|
||||
self.cx.expose_add_heap_object();
|
||||
self.cx.globals.push_str(&format!("
|
||||
@ -1349,8 +1336,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
pub fn generate_import_function(&mut self,
|
||||
info: &shared::Import,
|
||||
import: &shared::ImportFunction) {
|
||||
self.cx.imports_to_rewrite.insert(import.shim.clone());
|
||||
|
||||
let mut dst = String::new();
|
||||
|
||||
dst.push_str(&format!("function {}(", import.shim));
|
||||
|
@ -6,7 +6,6 @@ extern crate wasm_gc;
|
||||
use std::char;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::slice;
|
||||
|
||||
@ -90,7 +89,6 @@ impl Bindgen {
|
||||
typescript: format!("/* tslint:disable */\n"),
|
||||
exposed_globals: Default::default(),
|
||||
required_internal_exports: Default::default(),
|
||||
imports_to_rewrite: Default::default(),
|
||||
custom_type_names: Default::default(),
|
||||
imported_names: Default::default(),
|
||||
exported_classes: Default::default(),
|
||||
@ -133,40 +131,33 @@ impl Bindgen {
|
||||
|
||||
fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
|
||||
let version = shared::version();
|
||||
let data = module.sections_mut()
|
||||
.iter_mut()
|
||||
.filter_map(|s| {
|
||||
match *s {
|
||||
Section::Data(ref mut s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.next();
|
||||
|
||||
let mut ret = Vec::new();
|
||||
let data = match data {
|
||||
Some(data) => data,
|
||||
None => return ret,
|
||||
};
|
||||
|
||||
for entry in data.entries_mut() {
|
||||
let mut value = bytes_to_u32(entry.value_mut());
|
||||
let mut tmp = &mut *value;
|
||||
loop {
|
||||
let value = tmp;
|
||||
let start = match value.iter().position(|i| i.0 == 0x30d97887) {
|
||||
Some(i) => i,
|
||||
None => break,
|
||||
};
|
||||
if value.get(start + 1).map(|c| c.0) != Some(0xd4182f61) {
|
||||
tmp = &mut value[1..];
|
||||
continue
|
||||
}
|
||||
let cnt = value[start + 2].0 as usize;
|
||||
let (a, b) = value[start..].split_at_mut(cnt + 3);
|
||||
tmp = b;
|
||||
let json = a[3..].iter()
|
||||
.map(|i| char::from_u32(i.0).unwrap())
|
||||
#[repr(packed)]
|
||||
struct Unaligned(u32);
|
||||
|
||||
module.sections_mut().retain(|s| {
|
||||
let custom = match *s {
|
||||
Section::Custom(ref s) => s,
|
||||
_ => return true,
|
||||
};
|
||||
if custom.name() != "__wasm_bindgen_unstable" {
|
||||
return true
|
||||
}
|
||||
|
||||
assert!(custom.payload().len() % 4 == 0);
|
||||
let mut payload = unsafe {
|
||||
slice::from_raw_parts(custom.payload().as_ptr() as *const Unaligned,
|
||||
custom.payload().len() / 4)
|
||||
};
|
||||
|
||||
while payload.len() > 0 {
|
||||
let len = payload[0].0.to_le();
|
||||
assert!(len % 4 == 0);
|
||||
let (a, b) = payload[1..].split_at((len / 4) as usize);
|
||||
payload = b;
|
||||
let json = a.iter()
|
||||
.map(|i| char::from_u32(i.0.to_le()).unwrap())
|
||||
.collect::<String>();
|
||||
let p: shared::Program = match serde_json::from_str(&json) {
|
||||
Ok(f) => f,
|
||||
@ -200,57 +191,9 @@ to open an issue at https://github.com/alexcrichton/wasm-bindgen/issues!
|
||||
p.version, version);
|
||||
}
|
||||
ret.push(p);
|
||||
|
||||
for slot in a {
|
||||
slot.0 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
});
|
||||
return ret
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
struct Unaligned(u32);
|
||||
|
||||
struct FutzWithAlign<'a> {
|
||||
data: &'a mut Vec<u8>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
fn bytes_to_u32(a: &mut Vec<u8>) -> FutzWithAlign {
|
||||
let prev_len = a.len();
|
||||
// Data implicitly contains zeros after it and it looks like LLD exploits
|
||||
// this. Pad our view into the vector with zeros to make sure that we read
|
||||
// off everything when we iterate. After we're done iterating though we put
|
||||
// this back as we found it, hence the newtype wrapper w/ a dtor.
|
||||
while a.len() % 4 != 0 {
|
||||
a.push(0);
|
||||
}
|
||||
FutzWithAlign { data: a, len: prev_len }
|
||||
}
|
||||
|
||||
impl<'a> Deref for FutzWithAlign<'a> {
|
||||
type Target = [Unaligned];
|
||||
|
||||
fn deref(&self) -> &[Unaligned] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.data.as_ptr() as *const Unaligned,
|
||||
self.data.len() / 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DerefMut for FutzWithAlign<'a> {
|
||||
fn deref_mut(&mut self) -> &mut [Unaligned] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.data.as_mut_ptr() as *mut Unaligned,
|
||||
self.data.len() / 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for FutzWithAlign<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.data.truncate(self.len);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user