From afbd7d3ff88a8fbdcff9f381893a2f36b68315b5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 11 Jun 2019 11:58:06 -0700 Subject: [PATCH] Include self-pointer in `Function` descriptions Previously a `Function` didn't actually take into account the self pointer and instead left it as an implicit argument. This instead ensures that there's a `Descriptor::I32` type inside of a `Function` description that we have to later skip, and this should not only make the anyref pass correct for Rust exports but it should also make it more accurate for future webidl transformations. --- crates/cli-support/src/js/js2rust.rs | 18 ++++++++++-- crates/cli-support/src/webidl.rs | 41 +++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index 4fe8c303..771055fd 100644 --- a/crates/cli-support/src/js/js2rust.rs +++ b/crates/cli-support/src/js/js2rust.rs @@ -68,6 +68,9 @@ pub struct Js2Rust<'a, 'b: 'a> { /// The string value here is the class that this should be a constructor /// for. constructor: Option, + + /// whether or not we're generating a method + method: bool, } impl<'a, 'b> Js2Rust<'a, 'b> { @@ -83,6 +86,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { ret_ty: String::new(), ret_expr: String::new(), constructor: None, + method: false, } } @@ -93,12 +97,19 @@ impl<'a, 'b> Js2Rust<'a, 'b> { function: &Function, opt_arg_names: &Option>, ) -> Result<&mut Self, Error> { + // Chop off the implicit i32 first argument if we're a method since it + // was already handled by `method` below. + let arguments = if self.method { + &function.arguments[1..] + } else { + &function.arguments[..] + }; 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()], + None => vec![None; arguments.len()], }; - assert_eq!(arg_names.len(), function.arguments.len()); - for (arg, arg_name) in function.arguments.iter().zip(arg_names) { + assert_eq!(arg_names.len(), arguments.len()); + for (arg, arg_name) in 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(); @@ -124,6 +135,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { /// Flag this shim as a method call into Rust, so the first Rust argument /// passed should be `this.ptr`. pub fn method(&mut self, consumed: bool) -> &mut Self { + self.method = true; if self.cx.config.debug { self.prelude( "if (this.ptr === 0) { diff --git a/crates/cli-support/src/webidl.rs b/crates/cli-support/src/webidl.rs index 0409e39a..c8913cda 100644 --- a/crates/cli-support/src/webidl.rs +++ b/crates/cli-support/src/webidl.rs @@ -580,7 +580,7 @@ impl<'a> Context<'a> { Some(class) => struct_function_export_name(class, export.function.name), None => export.function.name.to_string(), }; - let descriptor = match self.descriptors.remove(&wasm_name) { + let mut descriptor = match self.descriptors.remove(&wasm_name) { None => return Ok(()), Some(d) => d.unwrap_function(), }; @@ -595,23 +595,32 @@ impl<'a> Context<'a> { match export.method_kind { decode::MethodKind::Constructor => AuxExportKind::Constructor(class), decode::MethodKind::Operation(op) => match op.kind { - decode::OperationKind::Getter(f) => AuxExportKind::Getter { - class, - field: f.to_string(), - }, - decode::OperationKind::Setter(f) => AuxExportKind::Setter { - class, - field: f.to_string(), - }, + decode::OperationKind::Getter(f) => { + descriptor.arguments.insert(0, Descriptor::I32); + AuxExportKind::Getter { + class, + field: f.to_string(), + } + } + decode::OperationKind::Setter(f) => { + descriptor.arguments.insert(0, Descriptor::I32); + AuxExportKind::Setter { + class, + field: f.to_string(), + } + } _ if op.is_static => AuxExportKind::StaticFunction { class, name: export.function.name.to_string(), }, - _ => AuxExportKind::Method { - class, - name: export.function.name.to_string(), - consumed: export.consumed, - }, + _ => { + descriptor.arguments.insert(0, Descriptor::I32); + AuxExportKind::Method { + class, + name: export.function.name.to_string(), + consumed: export.consumed, + } + } }, } } @@ -931,7 +940,7 @@ impl<'a> Context<'a> { // Register a webidl transformation for the getter let (getter_id, _) = self.function_exports[&getter]; let getter_descriptor = Function { - arguments: Vec::new(), + arguments: vec![Descriptor::I32], shim_idx: 0, ret: descriptor.clone(), }; @@ -956,7 +965,7 @@ impl<'a> Context<'a> { let (setter_id, _) = self.function_exports[&setter]; let setter_descriptor = Function { - arguments: vec![descriptor], + arguments: vec![Descriptor::I32, descriptor], shim_idx: 0, ret: Descriptor::Unit, };