From b51df39bc961c64c3ad20a8afe53d63f0be80e0b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 31 May 2019 10:54:03 -0700 Subject: [PATCH] Reimplement `anyref` processing and passes This commit reimplements the `anyref` transformation pass tasked with taking raw rustc output and enhancing the module to use `anyref`. This was disabled in the previous commits during refactoring, and now the pass is re-enabled in the manner originally intended. Instead of being tangled up in the `js/mod.rs` pass, the anyref transformation now happens locally within one module, `cli-support/src/anyref.rs`, which exclusively uses the output of the `webidl` module which produces a WebIDL bindings section as well as an auxiliary wasm-bindgen specific section. This makes the anyref transform much more straightforward and local, ensuring that it doesn't propagate elsewhere and can be a largely local concern during the transformation. The main addition needed to support this pass was detailed knowledge of the ABI of a `Descriptor`. This knowledge is already implicitly hardcoded in `js2rust.rs` and `rust2js.rs` through the ABI shims generated. This was previously used for the anyref transformation to piggy-back what was already there, but as a separate pass we are unable to reuse the knowledge in the binding generator. Instead `Descriptor` now has two dedicated methods describing the various ABI properties of a type. This is then asserted to be correct (all the time) when processing bindings, ensuring that the two are kept in sync. --- crates/anyref-xform/src/lib.rs | 104 ++++++++++----------------- crates/cli-support/src/anyref.rs | 87 ++++++++++++++++++++++ crates/cli-support/src/descriptor.rs | 77 ++++++++++++++++++++ crates/cli-support/src/js/js2rust.rs | 74 ++++++------------- crates/cli-support/src/js/mod.rs | 46 +++++------- crates/cli-support/src/js/rust2js.rs | 62 ++++++---------- crates/cli-support/src/lib.rs | 7 +- 7 files changed, 264 insertions(+), 193 deletions(-) create mode 100644 crates/cli-support/src/anyref.rs diff --git a/crates/anyref-xform/src/lib.rs b/crates/anyref-xform/src/lib.rs index 94c2d1fd..1862eb99 100644 --- a/crates/anyref-xform/src/lib.rs +++ b/crates/anyref-xform/src/lib.rs @@ -20,6 +20,7 @@ use std::cmp; use std::collections::{BTreeMap, HashMap, HashSet}; use std::mem; use walrus::ir::*; +use walrus::{ExportId, ImportId}; use walrus::{FunctionId, GlobalId, InitExpr, Module, TableId, ValType}; // must be kept in sync with src/lib.rs and ANYREF_HEAP_START @@ -32,8 +33,8 @@ pub struct Context { // Functions within the module that we're gonna be wrapping, organized by // type. The `Function` contains information about what arguments/return // values in the function signature should turn into anyref. - imports: HashMap>, - exports: HashMap, + imports: HashMap, + exports: HashMap, elements: BTreeMap, // When wrapping closures with new shims, this is the index of the next @@ -42,9 +43,6 @@ pub struct Context { // The anyref table we'll be using, injected after construction table: Option, - - // Whether or not the transformation will actually be run at the end - pub enabled: bool, } struct Transform<'a> { @@ -68,7 +66,6 @@ struct Transform<'a> { } struct Function { - name: String, // A map of argument index to whether it's an owned or borrowed anyref // (owned = true) args: HashMap, @@ -87,10 +84,6 @@ impl Context { /// large the function table is so we know what indexes to hand out when /// we're appending entries. pub fn prepare(&mut self, module: &mut Module) -> Result<(), Error> { - if !self.enabled { - return Ok(()); - } - // Figure out what the maximum index of functions pointers are. We'll // be adding new entries to the function table later (maybe) so // precalculate this ahead of time. @@ -118,19 +111,13 @@ impl Context { /// transformed. The actual transformation happens later during `run`. pub fn import_xform( &mut self, - module: &str, - name: &str, + id: ImportId, anyref: &[(usize, bool)], ret_anyref: bool, ) -> &mut Self { - if !self.enabled { - return self; + if let Some(f) = self.function(anyref, ret_anyref) { + self.imports.insert(id, f); } - let f = self.function(name, anyref, ret_anyref); - self.imports - .entry(module.to_string()) - .or_insert_with(Default::default) - .insert(name.to_string(), f); self } @@ -138,15 +125,13 @@ impl Context { /// transformed. The actual transformation happens later during `run`. pub fn export_xform( &mut self, - name: &str, + id: ExportId, anyref: &[(usize, bool)], ret_anyref: bool, ) -> &mut Self { - if !self.enabled { - return self; + if let Some(f) = self.function(anyref, ret_anyref) { + self.exports.insert(id, f); } - let f = self.function(name, anyref, ret_anyref); - self.exports.insert(name.to_string(), f); self } @@ -158,34 +143,26 @@ impl Context { idx: u32, anyref: &[(usize, bool)], ret_anyref: bool, - ) -> u32 { - if !self.enabled { - return idx; - } - let name = format!("closure{}", idx); - let f = self.function(&name, anyref, ret_anyref); - let ret = self.next_element; - self.next_element += 1; - self.elements.insert(ret, (idx, f)); - ret + ) -> Option { + self.function(anyref, ret_anyref).map(|f| { + let ret = self.next_element; + self.next_element += 1; + self.elements.insert(ret, (idx, f)); + ret + }) } - fn function(&self, name: &str, anyref: &[(usize, bool)], ret_anyref: bool) -> Function { - Function { - name: name.to_string(), + fn function(&self, anyref: &[(usize, bool)], ret_anyref: bool) -> Option { + if !ret_anyref && anyref.len() == 0 { + return None; + } + Some(Function { args: anyref.iter().cloned().collect(), ret_anyref, - } - } - - pub fn anyref_table_id(&self) -> TableId { - self.table.unwrap() + }) } pub fn run(&mut self, module: &mut Module) -> Result<(), Error> { - if !self.enabled { - return Ok(()); - } let table = self.table.unwrap(); // Inject a stack pointer global which will be used for managing the @@ -261,9 +238,7 @@ impl Transform<'_> { // Perform transformations of imports, exports, and function pointers. self.process_imports(module); - for m in self.cx.imports.values() { - assert!(m.is_empty()); - } + assert!(self.cx.imports.is_empty()); self.process_exports(module); assert!(self.cx.exports.is_empty()); self.process_elements(module)?; @@ -333,20 +308,15 @@ impl Transform<'_> { walrus::ImportKind::Function(f) => f, _ => continue, }; - let import = { - let entries = match self.cx.imports.get_mut(&import.module) { - Some(s) => s, - None => continue, - }; - match entries.remove(&import.name) { - Some(s) => s, - None => continue, - } + let func = match self.cx.imports.remove(&import.id()) { + Some(s) => s, + None => continue, }; let shim = self.append_shim( f, - import, + &import.name, + func, &mut module.types, &mut module.funcs, &mut module.locals, @@ -356,29 +326,25 @@ impl Transform<'_> { } fn process_exports(&mut self, module: &mut Module) { - let mut new_exports = Vec::new(); - for export in module.exports.iter() { + // let mut new_exports = Vec::new(); + for export in module.exports.iter_mut() { let f = match export.item { walrus::ExportItem::Function(f) => f, _ => continue, }; - let function = match self.cx.exports.remove(&export.name) { + let function = match self.cx.exports.remove(&export.id()) { Some(s) => s, None => continue, }; let shim = self.append_shim( f, + &export.name, function, &mut module.types, &mut module.funcs, &mut module.locals, ); - new_exports.push((export.name.to_string(), shim, export.id())); - } - - for (name, shim, old_id) in new_exports { - module.exports.add(&name, shim); - module.exports.delete(old_id); + export.item = shim.into(); } } @@ -402,6 +368,7 @@ impl Transform<'_> { let target = kind.elements[idx as usize].unwrap(); let shim = self.append_shim( target, + &format!("closure{}", idx), function, &mut module.types, &mut module.funcs, @@ -422,6 +389,7 @@ impl Transform<'_> { fn append_shim( &mut self, shim_target: FunctionId, + name: &str, mut func: Function, types: &mut walrus::ModuleTypes, funcs: &mut walrus::ModuleFunctions, @@ -625,7 +593,7 @@ impl Transform<'_> { // nice name for debugging and then we're good to go! let expr = builder.with_side_effects(before, result, after); let id = builder.finish_parts(shim_ty, params, vec![expr], types, funcs); - let name = format!("{}_anyref_shim", func.name); + let name = format!("{}_anyref_shim", name); funcs.get_mut(id).name = Some(name); self.shims.insert(id); return id; diff --git a/crates/cli-support/src/anyref.rs b/crates/cli-support/src/anyref.rs new file mode 100644 index 00000000..44b17b3a --- /dev/null +++ b/crates/cli-support/src/anyref.rs @@ -0,0 +1,87 @@ +use crate::descriptor::Function; +use crate::webidl::{ImportBinding, WasmBindgenAux, WebidlCustomSection, AuxImport}; +use failure::Error; +use std::collections::HashSet; +use walrus::Module; + +pub fn process(module: &mut Module) -> Result<(), Error> { + let mut cfg = wasm_bindgen_anyref_xform::Context::default(); + cfg.prepare(module)?; + let bindings = module + .customs + .get_typed::() + .expect("webidl custom section should exist"); + + for (export, binding) in bindings.exports.iter() { + let (args, ret) = extract_anyrefs(binding); + cfg.export_xform(*export, &args, ret); + } + + for (import, kind) in bindings.imports.iter() { + let binding = match kind { + ImportBinding::Function(f) => f, + ImportBinding::Constructor(f) => f, + ImportBinding::Method(f) => f, + }; + let (args, ret) = extract_anyrefs(binding); + cfg.import_xform(*import, &args, ret); + } + + let aux = module + .customs + .get_typed_mut::() + .expect("webidl custom section should exist"); + for import in aux.import_map.values_mut() { + let closure = match import { + AuxImport::Closure(f) => f, + _ => continue, + }; + let (args, ret) = extract_anyrefs(&closure.function); + if let Some(new) = cfg.table_element_xform(closure.shim_idx, &args, ret) { + closure.shim_idx = new; + } + } + + cfg.run(module)?; + walrus::passes::gc::run(module); + + // The GC pass above may end up removing some imported intrinsics. For + // example `__wbindgen_object_clone_ref` is no longer needed after the + // anyref pass. Make sure to delete the associated metadata for those + // intrinsics so we don't try to access stale intrinsics later on. + let remaining_imports = module + .imports + .iter() + .map(|i| i.id()) + .collect::>(); + module + .customs + .get_typed_mut::() + .expect("webidl custom section should exist") + .imports + .retain(|id, _| remaining_imports.contains(id)); + module + .customs + .get_typed_mut::() + .expect("wasm-bindgen aux section should exist") + .import_map + .retain(|id, _| remaining_imports.contains(id)); + Ok(()) +} + +fn extract_anyrefs(f: &Function) -> (Vec<(usize, bool)>, bool) { + let mut args = Vec::new(); + let mut cur = 0; + if f.ret.abi_returned_through_pointer() { + cur += 1; + } + for arg in f.arguments.iter() { + if arg.is_anyref() { + args.push((cur, true)); + } else if arg.is_ref_anyref() { + args.push((cur, false)); + } + cur += arg.abi_arg_count(); + } + (args, f.ret.is_anyref()) +} diff --git a/crates/cli-support/src/descriptor.rs b/crates/cli-support/src/descriptor.rs index 6efeb370..ebaf794f 100644 --- a/crates/cli-support/src/descriptor.rs +++ b/crates/cli-support/src/descriptor.rs @@ -292,6 +292,83 @@ impl Descriptor { _ => false, } } + + pub fn abi_returned_through_pointer(&self) -> bool { + if self.vector_kind().is_some() { + return true; + } + if self.get_64().is_some() { + return true; + } + match self { + Descriptor::Option(inner) => match &**inner { + Descriptor::Anyref + | Descriptor::RustStruct(_) + | Descriptor::Enum { .. } + | Descriptor::Char + | Descriptor::Boolean + | Descriptor::I8 + | Descriptor::U8 + | Descriptor::I16 + | Descriptor::U16 => false, + _ => true, + }, + _ => false, + } + } + + pub fn abi_arg_count(&self) -> usize { + if let Descriptor::Option(inner) = self { + if inner.get_64().is_some() { + return 4; + } + if let Descriptor::Ref(inner) = &**inner { + match &**inner { + Descriptor::Anyref => return 1, + _ => {} + } + } + } + if self.stack_closure().is_some() { + return 2; + } + if self.abi_returned_through_pointer() { + 2 + } else { + 1 + } + } + + pub fn assert_abi_return_correct(&self, before: usize, after: usize) { + if before != after { + assert_eq!( + before + 1, + after, + "abi_returned_through_pointer wrong for {:?}", + self, + ); + assert!( + self.abi_returned_through_pointer(), + "abi_returned_through_pointer wrong for {:?}", + self, + ); + } else { + assert!( + !self.abi_returned_through_pointer(), + "abi_returned_through_pointer wrong for {:?}", + self, + ); + } + } + + pub fn assert_abi_arg_correct(&self, before: usize, after: usize) { + assert_eq!( + before + self.abi_arg_count(), + after, + "abi_arg_count wrong for {:?}", + self, + ); + } } fn get(a: &mut &[u32]) -> u32 { diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index 0bc199d7..4fe8c303 100644 --- a/crates/cli-support/src/js/js2rust.rs +++ b/crates/cli-support/src/js/js2rust.rs @@ -68,15 +68,6 @@ pub struct Js2Rust<'a, 'b: 'a> { /// The string value here is the class that this should be a constructor /// for. constructor: Option, - - /// metadata for anyref transformations - anyref_args: Vec<(usize, bool)>, - ret_anyref: bool, -} - -pub enum ExportedShim<'a> { - Named(&'a str), - TableElement(&'a mut u32), } impl<'a, 'b> Js2Rust<'a, 'b> { @@ -92,8 +83,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> { ret_ty: String::new(), ret_expr: String::new(), constructor: None, - anyref_args: Vec::new(), - ret_anyref: false, } } @@ -104,17 +93,26 @@ impl<'a, 'b> Js2Rust<'a, 'b> { function: &Function, opt_arg_names: &Option>, ) -> Result<&mut Self, Error> { - if let Some(arg_names) = opt_arg_names { - assert_eq!(arg_names.len(), function.arguments.len()); - for (arg, arg_name) in function.arguments.iter().zip(arg_names) { - self.argument(arg, arg_name.as_str())?; - } - } else { - for arg in function.arguments.iter() { - self.argument(arg, None)?; - } + let arg_names = match opt_arg_names { + Some(arg_names) => arg_names.iter().map(|s| Some(s.as_str())).collect(), + None => vec![None; function.arguments.len()], + }; + assert_eq!(arg_names.len(), function.arguments.len()); + for (arg, arg_name) in function.arguments.iter().zip(arg_names) { + // Process the function argument and assert that the metadata about + // the number of arguments on the Rust side required is correct. + let before = self.rust_arguments.len(); + self.argument(arg, arg_name)?; + arg.assert_abi_arg_correct(before, self.rust_arguments.len()); } + + // Process the return argument, and assert that the metadata returned + // about the descriptor is indeed correct. + let before = self.rust_arguments.len(); self.ret(&function.ret)?; + function + .ret + .assert_abi_return_correct(before, self.rust_arguments.len()); Ok(self) } @@ -181,12 +179,9 @@ impl<'a, 'b> Js2Rust<'a, 'b> { ret } - pub fn argument<'c, I>(&mut self, arg: &Descriptor, opt_arg_name: I) -> Result<&mut Self, Error> - where - I: Into>, - { + fn argument(&mut self, arg: &Descriptor, arg_name: Option<&str>) -> Result<&mut Self, Error> { let i = self.arg_idx; - let name = self.abi_arg(opt_arg_name.into()); + let name = self.abi_arg(arg_name); let (arg, optional) = match arg { Descriptor::Option(t) => (&**t, true), @@ -252,7 +247,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> { self.rust_arguments .push(format!("isLikeNone({0}) ? 0 : addToAnyrefTable({0})", name)); } else { - self.anyref_args.push((self.rust_arguments.len(), true)); self.rust_arguments.push(name); } } else { @@ -449,7 +443,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> { self.js_arguments .push(JsArgument::required(name.clone(), "any".to_string())); if self.cx.config.anyref { - self.anyref_args.push((self.rust_arguments.len(), false)); self.rust_arguments.push(name); } else { // the "stack-ful" nature means that we're always popping from the @@ -492,7 +485,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { Ok(self) } - pub fn ret(&mut self, ty: &Descriptor) -> Result<&mut Self, Error> { + fn ret(&mut self, ty: &Descriptor) -> Result<&mut Self, Error> { if let Some(name) = ty.rust_struct() { match &self.constructor { Some(class) if class == name => { @@ -566,7 +559,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> { if ty.is_anyref() { self.ret_ty = "any".to_string(); self.ret_expr = format!("return {};", self.cx.take_object("RET")); - self.ret_anyref = true; return Ok(self); } @@ -784,12 +776,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { /// Returns two strings, the first of which is the JS expression for the /// generated function shim and the second is a TypeScript signature of the /// JS expression. - pub fn finish( - &mut self, - prefix: &str, - invoc: &str, - exported_shim: ExportedShim, - ) -> (String, String, String) { + pub fn finish(&mut self, prefix: &str, invoc: &str) -> (String, String, String) { let js_args = self .js_arguments .iter() @@ -854,23 +841,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> { } ts.push(';'); - if self.ret_anyref || self.anyref_args.len() > 0 { - match exported_shim { - ExportedShim::Named(name) => { - self.cx - .anyref - .export_xform(name, &self.anyref_args, self.ret_anyref); - } - ExportedShim::TableElement(idx) => { - *idx = self.cx.anyref.table_element_xform( - *idx, - &self.anyref_args, - self.ret_anyref, - ); - } - } - } - (js, ts, self.js_doc_comments()) } diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 485683e9..08b09318 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -2,7 +2,7 @@ mod js2rust; mod rust2js; use crate::descriptor::VectorKind; -use crate::js::js2rust::{ExportedShim, Js2Rust}; +use crate::js::js2rust::Js2Rust; use crate::js::rust2js::Rust2Js; use crate::webidl::{AuxEnum, AuxExport, AuxExportKind, AuxImport, AuxStruct}; use crate::webidl::{JsImport, JsImportName, WasmBindgenAux, WebidlCustomSection}; @@ -47,8 +47,6 @@ pub struct Context<'a> { /// A map of the name of npm dependencies we've loaded so far to the path /// they're defined in as well as their version specification. pub npm_dependencies: HashMap, - - pub anyref: wasm_bindgen_anyref_xform::Context, } #[derive(Default)] @@ -99,7 +97,6 @@ impl<'a> Context<'a> { module, function_table_needed: false, memory, - anyref: Default::default(), npm_dependencies: Default::default(), }) } @@ -192,13 +189,6 @@ impl<'a> Context<'a> { // `__wrap` and such. self.write_classes()?; - // And now that we're almost ready, run the final "anyref" pass. This is - // where we transform a wasm module which doesn't actually use `anyref` - // anywhere to using the type internally. The transformation here is - // based off all the previous data we've collected so far for each - // import/export listed. - // self.anyref.run(self.module)?; - // We're almost done here, so we can delete any internal exports (like // `__wbindgen_malloc`) if none of our JS glue actually needed it. self.unexport_unused_internal_exports(); @@ -1794,9 +1784,17 @@ impl<'a> Context<'a> { if !self.should_write_global("anyref_table") { return; } - self.module - .exports - .add("__wbg_anyref_table", self.anyref.anyref_table_id()); + let table = self + .module + .tables + .iter() + .find(|t| match t.kind { + walrus::TableKind::Anyref(_) => true, + _ => false, + }) + .expect("failed to find anyref table in module") + .id(); + self.module.exports.add("__wbg_anyref_table", table); } fn expose_add_to_anyref_table(&mut self) -> Result<(), Error> { @@ -1878,11 +1876,7 @@ impl<'a> Context<'a> { AuxExportKind::Function(name) => { let (js, ts, js_doc) = Js2Rust::new(&name, self) .process(&descriptor, &export.arg_names)? - .finish( - "function", - &format!("wasm.{}", wasm_name), - ExportedShim::Named(&wasm_name), - ); + .finish("function", &format!("wasm.{}", wasm_name)); self.export( &name, &js, @@ -1897,11 +1891,7 @@ impl<'a> Context<'a> { let (js, ts, raw_docs) = Js2Rust::new("constructor", self) .constructor(Some(&class)) .process(&descriptor, &export.arg_names)? - .finish( - "", - &format!("wasm.{}", wasm_name), - ExportedShim::Named(&wasm_name), - ); + .finish("", &format!("wasm.{}", wasm_name)); let exported = require_class(&mut self.exported_classes, class); if exported.has_constructor { bail!("found duplicate constructor for class `{}`", class); @@ -1924,11 +1914,9 @@ impl<'a> Context<'a> { j2r.method(false); } } - let (js, ts, raw_docs) = j2r.process(&descriptor, &export.arg_names)?.finish( - "", - &format!("wasm.{}", wasm_name), - ExportedShim::Named(&wasm_name), - ); + let (js, ts, raw_docs) = j2r + .process(&descriptor, &export.arg_names)? + .finish("", &format!("wasm.{}", wasm_name)); let ret_ty = j2r.ret_ty.clone(); let exported = require_class(&mut self.exported_classes, class); let docs = format_doc_comments(&export.comments, Some(raw_docs)); diff --git a/crates/cli-support/src/js/rust2js.rs b/crates/cli-support/src/js/rust2js.rs index d9520632..36acf1fd 100644 --- a/crates/cli-support/src/js/rust2js.rs +++ b/crates/cli-support/src/js/rust2js.rs @@ -1,6 +1,5 @@ use crate::descriptor::Descriptor; use crate::intrinsic::Intrinsic; -use crate::js::js2rust::ExportedShim; use crate::js::{Context, Js2Rust}; use crate::webidl::{AuxImport, AuxValue, ImportBinding}; use failure::{bail, Error}; @@ -119,9 +118,19 @@ impl<'a, 'b> Rust2Js<'a, 'b> { } }; for arg in function.arguments.iter() { + // Process the function argument and assert that the metadata about + // the number of arguments on the Rust side required is correct. + let before = self.shim_arguments.len(); self.argument(arg)?; + arg.assert_abi_arg_correct(before, self.shim_arguments.len()); } + // Process the return argument, and assert that the metadata returned + // about the descriptor is indeed correct. + let before = self.shim_arguments.len(); self.ret(&function.ret)?; + function + .ret + .assert_abi_return_correct(before, self.shim_arguments.len()); Ok(self) } @@ -308,7 +317,6 @@ impl<'a, 'b> Rust2Js<'a, 'b> { if let Some((f, mutable)) = arg.stack_closure() { let arg2 = self.shim_argument(); - let mut shim = f.shim_idx; let (js, _ts, _js_doc) = { let mut builder = Js2Rust::new("", self.cx); if mutable { @@ -320,11 +328,10 @@ impl<'a, 'b> Rust2Js<'a, 'b> { } else { builder.rust_argument("this.a"); } - builder.rust_argument("this.b").process(f, &None)?.finish( - "function", - "this.f", - ExportedShim::TableElement(&mut shim), - ) + builder + .rust_argument("this.b") + .process(f, &None)? + .finish("function", "this.f") }; self.cx.function_table_needed = true; self.global_idx(); @@ -338,7 +345,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { abi, arg2, js = js, - idx = shim, + idx = f.shim_idx, )); self.finally(&format!("cb{0}.a = cb{0}.b = 0;", abi)); self.js_arguments.push(format!("cb{0}.bind(cb{0})", abi)); @@ -676,7 +683,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { format!("new {}({})", js, variadic_args(&self.js_arguments)?) } Style::Method => { - let descriptor = |anchor: &str, extra: &str, field: &str, which:&str| { + let descriptor = |anchor: &str, extra: &str, field: &str, which: &str| { format!( "GetOwnOrInheritedPropertyDescriptor({}{}, '{}').{}", anchor, extra, field, which @@ -741,7 +748,6 @@ impl<'a, 'b> Rust2Js<'a, 'b> { assert!(self.style == Style::Function); assert!(!variadic); assert_eq!(self.js_arguments.len(), 3); - let mut shim = closure.shim_idx; let (js, _ts, _js_doc) = { let mut builder = Js2Rust::new("", self.cx); @@ -777,11 +783,9 @@ impl<'a, 'b> Rust2Js<'a, 'b> { .finally("this.a = 0;") .finally("}"); } - builder.process(&closure.function, &None)?.finish( - "function", - "f", - ExportedShim::TableElement(&mut shim), - ) + builder + .process(&closure.function, &None)? + .finish("function", "f") }; self.cx.function_table_needed = true; let body = format!( @@ -795,7 +799,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { let real = cb.bind(cb); real.original = cb; ", - shim, + closure.shim_idx, closure.dtor_idx, &self.js_arguments[1], js, @@ -978,32 +982,6 @@ impl<'a, 'b> Rust2Js<'a, 'b> { ret.push_str(&invoc); ret.push_str("\n}\n"); - // if self.ret_anyref || self.anyref_args.len() > 0 { - // // Some return values go at the the beginning of the argument list - // // (they force a return pointer). Handle that here by offsetting all - // // our arg indices by one, but throw in some sanity checks for if - // // this ever changes. - // if let Some(start) = self.shim_arguments.get(0) { - // if start == "ret" { - // assert!(!self.ret_anyref); - // if let Some(next) = self.shim_arguments.get(1) { - // assert_eq!(next, "arg0"); - // } - // for (idx, _) in self.anyref_args.iter_mut() { - // *idx += 1; - // } - // } else { - // assert_eq!(start, "arg0"); - // } - // } - // self.cx.anyref.import_xform( - // "__wbindgen_placeholder__", - // shim, - // &self.anyref_args, - // self.ret_anyref, - // ); - // } - Ok(ret) } diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index b43a251c..1c65c484 100755 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -9,6 +9,7 @@ use std::path::{Path, PathBuf}; use std::str; use walrus::Module; +mod anyref; mod decode; mod intrinsic; mod descriptor; @@ -316,6 +317,10 @@ impl Bindgen { // supports that aren't covered by WebIDL bindings. webidl::process(&mut module)?; + if self.anyref { + anyref::process(&mut module)?; + } + // If we're in a testing mode then remove the start function since we // shouldn't execute it. if !self.emit_start { @@ -326,8 +331,6 @@ impl Bindgen { // shim generation which will actually generate JS for all this. let (js, ts) = { let mut cx = js::Context::new(&mut module, self)?; - cx.anyref.enabled = self.anyref; - cx.anyref.prepare(cx.module)?; let aux = cx.module.customs.delete_typed::() .expect("aux section should be present");