diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 05d8a62d..2b4a2d39 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -144,7 +144,7 @@ pub struct ImportType { pub doc_comment: Option, pub instanceof_shim: String, pub extends: Vec, - pub polyfills: Vec, + pub vendor_prefixes: Vec, } #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] @@ -479,7 +479,7 @@ impl ImportType { shared::ImportType { name: self.js_name.clone(), instanceof_shim: self.instanceof_shim.clone(), - polyfills: self.polyfills.iter().map(|s| s.to_string()).collect(), + vendor_prefixes: self.vendor_prefixes.iter().map(|s| s.to_string()).collect(), } } } diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 57490dd2..6ad9f76d 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -69,7 +69,7 @@ struct ClassField { pub struct SubContext<'a, 'b: 'a> { pub program: &'a shared::Program, pub cx: &'a mut Context<'b>, - pub polyfills: HashMap>, + pub vendor_prefixes: HashMap>, } const INITIAL_SLAB_VALUES: &[&str] = &["undefined", "null", "true", "false"]; @@ -1769,7 +1769,7 @@ impl<'a, 'b> SubContext<'a, 'b> { } for f in self.program.imports.iter() { if let shared::ImportKind::Type(ty) = &f.kind { - self.register_polyfills(ty); + self.register_vendor_prefix(ty); } } for f in self.program.imports.iter() { @@ -2147,17 +2147,17 @@ impl<'a, 'b> SubContext<'a, 'b> { self.cx.typescript.push_str("}\n"); } - fn register_polyfills( + fn register_vendor_prefix( &mut self, info: &shared::ImportType, ) { - if info.polyfills.len() == 0 { + if info.vendor_prefixes.len() == 0 { return } - self.polyfills + self.vendor_prefixes .entry(info.name.to_string()) .or_insert(Vec::new()) - .extend(info.polyfills.iter().cloned()); + .extend(info.vendor_prefixes.iter().cloned()); } fn import_name(&mut self, import: &shared::Import, item: &str) -> Result { @@ -2173,20 +2173,20 @@ impl<'a, 'b> SubContext<'a, 'b> { } } - // Similar to `--no-modules`, only allow polyfills basically for web + // Similar to `--no-modules`, only allow vendor prefixes basically for web // apis, shouldn't be necessary for things like npm packages or other // imported items. - let polyfills = self.polyfills.get(item); - if let Some(polyfills) = polyfills { - assert!(polyfills.len() > 0); + let vendor_prefixes = self.vendor_prefixes.get(item); + if let Some(vendor_prefixes) = vendor_prefixes { + assert!(vendor_prefixes.len() > 0); if let Some(module) = &import.module { bail!( "import of `{}` from `{}` has a polyfill of `{}` listed, but - polyfills aren't supported when importing from modules", + vendor prefixes aren't supported when importing from modules", item, module, - &polyfills[0], + &vendor_prefixes[0], ); } if let Some(ns) = &import.js_namespace { @@ -2239,25 +2239,31 @@ impl<'a, 'b> SubContext<'a, 'b> { )); } name - } else if let Some(polyfills) = polyfills { + } else if let Some(vendor_prefixes) = vendor_prefixes { imports_post.push_str("const l"); imports_post.push_str(&name); imports_post.push_str(" = "); - switch(imports_post, &name, polyfills); + switch(imports_post, &name, "", vendor_prefixes); imports_post.push_str(";\n"); - fn switch(dst: &mut String, name: &str, left: &[String]) { + fn switch(dst: &mut String, name: &str, prefix: &str, left: &[String]) { if left.len() == 0 { + dst.push_str(prefix); return dst.push_str(name); } dst.push_str("(typeof "); + dst.push_str(prefix); dst.push_str(name); dst.push_str(" == 'undefined' ? "); match left.len() { - 1 => dst.push_str(&left[0]), - _ => switch(dst, &left[0], &left[1..]), + 1 => { + dst.push_str(&left[0]); + dst.push_str(name); + } + _ => switch(dst, name, &left[0], &left[1..]), } dst.push_str(" : "); + dst.push_str(prefix); dst.push_str(name); dst.push_str(")"); } diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index 59fb56f8..d44f8347 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -209,7 +209,7 @@ impl Bindgen { js::SubContext { program, cx: &mut cx, - polyfills: Default::default(), + vendor_prefixes: Default::default(), }.generate()?; } cx.finalize(stem)? diff --git a/crates/macro-support/src/parser.rs b/crates/macro-support/src/parser.rs index aef0aa16..3947b005 100644 --- a/crates/macro-support/src/parser.rs +++ b/crates/macro-support/src/parser.rs @@ -185,9 +185,9 @@ impl BindgenAttrs { }) } - fn polyfills(&self) -> impl Iterator { + fn vendor_prefixes(&self) -> impl Iterator { self.attrs.iter().filter_map(|a| match a { - BindgenAttr::Polyfill(s) => Some(s), + BindgenAttr::VendorPrefix(s) => Some(s), _ => None, }) } @@ -233,7 +233,7 @@ pub enum BindgenAttr { JsName(String, Span), JsClass(String), Extends(Ident), - Polyfill(Ident), + VendorPrefix(Ident), Variadic, } @@ -294,9 +294,9 @@ impl Parse for BindgenAttr { input.parse::()?; return Ok(BindgenAttr::Extends(input.parse::()?.0)); } - if attr == "polyfill" { + if attr == "vendor_prefix" { input.parse::()?; - return Ok(BindgenAttr::Polyfill(input.parse::()?.0)); + return Ok(BindgenAttr::VendorPrefix(input.parse::()?.0)); } if attr == "module" { input.parse::()?; @@ -568,7 +568,7 @@ impl ConvertToAst for syn::ForeignItemType { rust_name: self.ident, js_name, extends: attrs.extends().cloned().collect(), - polyfills: attrs.polyfills().cloned().collect(), + vendor_prefixes: attrs.vendor_prefixes().cloned().collect(), })) } } diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index b5d58ea7..05140dd9 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -87,7 +87,7 @@ pub struct ImportStatic { pub struct ImportType { pub name: String, pub instanceof_shim: String, - pub polyfills: Vec, + pub vendor_prefixes: Vec, } #[derive(Deserialize, Serialize)] diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index f4f64835..48b8270d 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -500,13 +500,13 @@ impl<'src> FirstPassRecord<'src> { doc_comment: None, instanceof_shim: format!("__widl_instanceof_{}", name), extends: Vec::new(), - polyfills: Vec::new(), + vendor_prefixes: Vec::new(), }; // whitelist a few names that have known polyfills match name { "AudioContext" => { - import_type.polyfills.push(Ident::new("webkitAudioContext", Span::call_site())); + import_type.vendor_prefixes.push(Ident::new("webkit", Span::call_site())); } _ => {} } diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index 9abb834b..c87039e0 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -67,7 +67,7 @@ - [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md) - [`structural`](./reference/attributes/on-js-imports/structural.md) - [`variadic`](./reference/attributes/on-js-imports/variadic.md) - - [`polyfill`](./reference/attributes/on-js-imports/polyfill.md) + - [`vendor_prefix`](./reference/attributes/on-js-imports/vendor_prefix.md) - [On Rust Exports](./reference/attributes/on-rust-exports/index.md) - [`constructor`](./reference/attributes/on-rust-exports/constructor.md) - [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md) diff --git a/guide/src/reference/attributes/on-js-imports/polyfill.md b/guide/src/reference/attributes/on-js-imports/polyfill.md deleted file mode 100644 index aa089df0..00000000 --- a/guide/src/reference/attributes/on-js-imports/polyfill.md +++ /dev/null @@ -1,24 +0,0 @@ -# Polyfilling APIs - -In JS new APIs often have polyfills via different names in various contexts. For -example the `AudioContext` API is known as `webkitAudioContext` in Safari at the -time of this writing. The `polyfill` attribute indicates these alternative -names. - -For example to use `AudioContext` you might do: - -```rust -#[wasm_bindgen] -extern { - #[wasm_bindgen(polyfill = webkitAudioContext)] - type AudioContext; - - // methods on `AudioContext` ... -} -``` - -Whenever `AudioContext` is used it'll use `AudioContext` if the global namespace -defines it or alternatively it'll fall back to `webkitAudioContext`. - -Note that `polyfill` cannot be used with `module = "..."` or `js_namespace = -...`, so it's basically limited to web-platform APIs today. diff --git a/guide/src/reference/attributes/on-js-imports/vendor_prefix.md b/guide/src/reference/attributes/on-js-imports/vendor_prefix.md new file mode 100644 index 00000000..803e1929 --- /dev/null +++ b/guide/src/reference/attributes/on-js-imports/vendor_prefix.md @@ -0,0 +1,24 @@ +# Vendor-prefixed APIs + +On the web new APIs often have vendor prefixes while they're in an experimental +state. For example the `AudioContext` API is known as `webkitAudioContext` in +Safari at the time of this writing. The `vendor_prefix` attribute indicates +these alternative names, which are used if the normal name isn't defined. + +For example to use `AudioContext` you might do: + +```rust +#[wasm_bindgen] +extern { + #[wasm_bindgen(vendor_prefix = webkit)] + type AudioContext; + + // methods on `AudioContext` ... +} +``` + +Whenever `AudioContext` is used it'll use `AudioContext` if the global namespace +defines it or alternatively it'll fall back to `webkitAudioContext`. + +Note that `vendor_prefix` cannot be used with `module = "..."` or +`js_namespace = ...`, so it's basically limited to web-platform APIs today. diff --git a/tests/wasm/main.rs b/tests/wasm/main.rs index d79216ad..4ea2604d 100644 --- a/tests/wasm/main.rs +++ b/tests/wasm/main.rs @@ -26,7 +26,6 @@ pub mod math; pub mod node; pub mod option; pub mod optional_primitives; -pub mod polyfill; pub mod rethrow; pub mod simple; pub mod slice; @@ -34,3 +33,4 @@ pub mod structural; pub mod u64; pub mod validate_prt; pub mod variadic; +pub mod vendor_prefix; diff --git a/tests/wasm/polyfill.js b/tests/wasm/polyfill.js deleted file mode 100644 index 9fc3325c..00000000 --- a/tests/wasm/polyfill.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.import_me = function() {}; - -global.PolyfillBar = class { - foo() { return 123; } -}; diff --git a/tests/wasm/polyfill.rs b/tests/wasm/polyfill.rs deleted file mode 100644 index 2c1c9fc2..00000000 --- a/tests/wasm/polyfill.rs +++ /dev/null @@ -1,40 +0,0 @@ -use wasm_bindgen::prelude::*; -use wasm_bindgen_test::*; - -#[wasm_bindgen(module = "tests/wasm/polyfill.js")] -extern "C" { - fn import_me(); -} - -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(polyfill = PolyfillBar)] - type PolyfillFoo; - #[wasm_bindgen(constructor)] - fn new() -> PolyfillFoo; - #[wasm_bindgen(method)] - fn foo(this: &PolyfillFoo) -> u32; - - #[wasm_bindgen(polyfill = PolyfillBaz1, polyfill = PolyfillBar)] - type PolyfillFoo2; - #[wasm_bindgen(constructor)] - fn new() -> PolyfillFoo2; - #[wasm_bindgen(method)] - fn foo(this: &PolyfillFoo2) -> u32; - - #[wasm_bindgen(polyfill = PolyfillBaz1, polyfill = PolyfillBar, polyfill = PolyfillBaz2)] - type PolyfillFoo3; - #[wasm_bindgen(constructor)] - fn new() -> PolyfillFoo3; - #[wasm_bindgen(method)] - fn foo(this: &PolyfillFoo3) -> u32; -} - -#[wasm_bindgen_test] -pub fn polyfill_works() { - import_me(); - - assert_eq!(PolyfillFoo::new().foo(), 123); - assert_eq!(PolyfillFoo2::new().foo(), 123); - assert_eq!(PolyfillFoo3::new().foo(), 123); -} diff --git a/tests/wasm/vendor_prefix.js b/tests/wasm/vendor_prefix.js new file mode 100644 index 00000000..a8cd4db1 --- /dev/null +++ b/tests/wasm/vendor_prefix.js @@ -0,0 +1,11 @@ +exports.import_me = function() {}; + +global.webkitMySpecialApi = class { + foo() { return 123; } +}; +global.MySpecialApi2 = class { + foo() { return 124; } +}; +global.bMySpecialApi3 = class { + foo() { return 125; } +}; diff --git a/tests/wasm/vendor_prefix.rs b/tests/wasm/vendor_prefix.rs new file mode 100644 index 00000000..5d0c98f0 --- /dev/null +++ b/tests/wasm/vendor_prefix.rs @@ -0,0 +1,40 @@ +use wasm_bindgen::prelude::*; +use wasm_bindgen_test::*; + +#[wasm_bindgen(module = "tests/wasm/vendor_prefix.js")] +extern "C" { + fn import_me(); +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(vendor_prefix = webkit)] + type MySpecialApi; + #[wasm_bindgen(constructor)] + fn new() -> MySpecialApi; + #[wasm_bindgen(method)] + fn foo(this: &MySpecialApi) -> u32; + + #[wasm_bindgen(vendor_prefix = webkit)] + type MySpecialApi2; + #[wasm_bindgen(constructor)] + fn new() -> MySpecialApi2; + #[wasm_bindgen(method)] + fn foo(this: &MySpecialApi2) -> u32; + + #[wasm_bindgen(vendor_prefix = a, vendor_prefix = b)] + type MySpecialApi3; + #[wasm_bindgen(constructor)] + fn new() -> MySpecialApi3; + #[wasm_bindgen(method)] + fn foo(this: &MySpecialApi3) -> u32; +} + +#[wasm_bindgen_test] +pub fn polyfill_works() { + import_me(); + + assert_eq!(MySpecialApi::new().foo(), 123); + assert_eq!(MySpecialApi2::new().foo(), 124); + assert_eq!(MySpecialApi3::new().foo(), 125); +}