diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index c02bd9b1..ce5baacf 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -262,7 +262,8 @@ pub struct Dictionary { #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[derive(Clone)] pub struct DictionaryField { - pub name: Ident, + pub rust_name: Ident, + pub js_name: String, pub required: bool, pub ty: syn::Type, } diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index b941c0d4..55259d06 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1152,7 +1152,7 @@ impl ToTokens for ast::Dictionary { .fields .iter() .filter(|f| f.required) - .map(|f| &f.name) + .map(|f| &f.rust_name) .collect::>(); let required_types = &self .fields @@ -1282,14 +1282,15 @@ impl ToTokens for ast::Dictionary { impl ToTokens for ast::DictionaryField { fn to_tokens(&self, tokens: &mut TokenStream) { - let name = &self.name; + let rust_name = &self.rust_name; + let js_name = &self.js_name; let ty = &self.ty; (quote! { - pub fn #name(&mut self, val: #ty) -> &mut Self { + pub fn #rust_name(&mut self, val: #ty) -> &mut Self { use wasm_bindgen::JsValue; let r = ::js_sys::Reflect::set( self.obj.as_ref(), - &JsValue::from(stringify!(#name)), + &JsValue::from(#js_name), &JsValue::from(val), ); debug_assert!(r.is_ok(), "setting properties should never fail on our dictionary objects"); diff --git a/crates/webidl-tests/dictionary.js b/crates/webidl-tests/dictionary.js index 46b2127a..7eadc871 100644 --- a/crates/webidl-tests/dictionary.js +++ b/crates/webidl-tests/dictionary.js @@ -20,3 +20,7 @@ global.assert_dict_required = function(c) { assert.strictEqual(c.b, "a"); assert.strictEqual(c.c, 4); }; + +global.assert_camel_case = function(dict) { + assert.strictEqual(dict.wierd_fieldName, 1); +} diff --git a/crates/webidl-tests/dictionary.rs b/crates/webidl-tests/dictionary.rs index d769b9e9..94029cd9 100644 --- a/crates/webidl-tests/dictionary.rs +++ b/crates/webidl-tests/dictionary.rs @@ -16,6 +16,7 @@ extern "C" { #[wasm_bindgen(js_name = mk_dict_a)] fn mk_dict_a2() -> Option; fn assert_dict_required(r: &Required); + fn assert_camel_case(dict: &PreserveNames); } #[wasm_bindgen_test] @@ -51,3 +52,8 @@ fn many_types() { fn required() { assert_dict_required(Required::new(3, "a").c(4)); } + +#[wasm_bindgen_test] +fn correct_casing_in_js() { + assert_camel_case(PreserveNames::new().wierd_field_name(1)); +} diff --git a/crates/webidl-tests/dictionary.webidl b/crates/webidl-tests/dictionary.webidl index 75944104..f513323a 100644 --- a/crates/webidl-tests/dictionary.webidl +++ b/crates/webidl-tests/dictionary.webidl @@ -45,3 +45,7 @@ dictionary Required { required long a; long c; }; + +dictionary PreserveNames { + long wierd_fieldName; +}; diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 1b8ef399..2e11b128 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -337,11 +337,7 @@ impl<'src> FirstPassRecord<'src> { } } } - // Note that this sort isn't *quite* right in that it is sorting - // based on snake case instead of the original casing which could - // produce inconsistent results, but should work well enough for - // now! - dst[start..].sort_by_key(|f| f.name.clone()); + dst[start..].sort_by_key(|f| f.js_name.clone()); return true; } @@ -394,7 +390,8 @@ impl<'src> FirstPassRecord<'src> { Some(ast::DictionaryField { required: field.required.is_some(), - name: rust_ident(&snake_case_ident(field.identifier.0)), + rust_name: rust_ident(&snake_case_ident(field.identifier.0)), + js_name: field.identifier.0.to_string(), ty, }) } @@ -742,7 +739,8 @@ impl<'src> FirstPassRecord<'src> { let pos = TypePosition::Argument; fields.push(ast::DictionaryField { required: false, - name: rust_ident(&snake_case_ident(identifier)), + rust_name: rust_ident(&snake_case_ident(identifier)), + js_name: identifier.to_string(), ty: idl_type::IdlType::Callback.to_syn_type(pos).unwrap(), }); }