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, };