Merge pull request #914 from alexcrichton/rename-polyfill

Rename `polyfill` to `vendor_prefix`
This commit is contained in:
Alex Crichton 2018-10-01 14:47:07 -07:00 committed by GitHub
commit 9c085dc0f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 112 additions and 100 deletions

View File

@ -144,7 +144,7 @@ pub struct ImportType {
pub doc_comment: Option<String>, pub doc_comment: Option<String>,
pub instanceof_shim: String, pub instanceof_shim: String,
pub extends: Vec<Ident>, pub extends: Vec<Ident>,
pub polyfills: Vec<Ident>, pub vendor_prefixes: Vec<Ident>,
} }
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
@ -479,7 +479,7 @@ impl ImportType {
shared::ImportType { shared::ImportType {
name: self.js_name.clone(), name: self.js_name.clone(),
instanceof_shim: self.instanceof_shim.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(),
} }
} }
} }

View File

@ -69,7 +69,7 @@ struct ClassField {
pub struct SubContext<'a, 'b: 'a> { pub struct SubContext<'a, 'b: 'a> {
pub program: &'a shared::Program, pub program: &'a shared::Program,
pub cx: &'a mut Context<'b>, pub cx: &'a mut Context<'b>,
pub polyfills: HashMap<String, Vec<String>>, pub vendor_prefixes: HashMap<String, Vec<String>>,
} }
const INITIAL_SLAB_VALUES: &[&str] = &["undefined", "null", "true", "false"]; 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() { for f in self.program.imports.iter() {
if let shared::ImportKind::Type(ty) = &f.kind { if let shared::ImportKind::Type(ty) = &f.kind {
self.register_polyfills(ty); self.register_vendor_prefix(ty);
} }
} }
for f in self.program.imports.iter() { for f in self.program.imports.iter() {
@ -2147,17 +2147,17 @@ impl<'a, 'b> SubContext<'a, 'b> {
self.cx.typescript.push_str("}\n"); self.cx.typescript.push_str("}\n");
} }
fn register_polyfills( fn register_vendor_prefix(
&mut self, &mut self,
info: &shared::ImportType, info: &shared::ImportType,
) { ) {
if info.polyfills.len() == 0 { if info.vendor_prefixes.len() == 0 {
return return
} }
self.polyfills self.vendor_prefixes
.entry(info.name.to_string()) .entry(info.name.to_string())
.or_insert(Vec::new()) .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<String, Error> { fn import_name(&mut self, import: &shared::Import, item: &str) -> Result<String, Error> {
@ -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 // apis, shouldn't be necessary for things like npm packages or other
// imported items. // imported items.
let polyfills = self.polyfills.get(item); let vendor_prefixes = self.vendor_prefixes.get(item);
if let Some(polyfills) = polyfills { if let Some(vendor_prefixes) = vendor_prefixes {
assert!(polyfills.len() > 0); assert!(vendor_prefixes.len() > 0);
if let Some(module) = &import.module { if let Some(module) = &import.module {
bail!( bail!(
"import of `{}` from `{}` has a polyfill of `{}` listed, but "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, item,
module, module,
&polyfills[0], &vendor_prefixes[0],
); );
} }
if let Some(ns) = &import.js_namespace { if let Some(ns) = &import.js_namespace {
@ -2239,25 +2239,31 @@ impl<'a, 'b> SubContext<'a, 'b> {
)); ));
} }
name 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("const l");
imports_post.push_str(&name); imports_post.push_str(&name);
imports_post.push_str(" = "); imports_post.push_str(" = ");
switch(imports_post, &name, polyfills); switch(imports_post, &name, "", vendor_prefixes);
imports_post.push_str(";\n"); 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 { if left.len() == 0 {
dst.push_str(prefix);
return dst.push_str(name); return dst.push_str(name);
} }
dst.push_str("(typeof "); dst.push_str("(typeof ");
dst.push_str(prefix);
dst.push_str(name); dst.push_str(name);
dst.push_str(" == 'undefined' ? "); dst.push_str(" == 'undefined' ? ");
match left.len() { match left.len() {
1 => dst.push_str(&left[0]), 1 => {
_ => switch(dst, &left[0], &left[1..]), dst.push_str(&left[0]);
dst.push_str(name);
}
_ => switch(dst, name, &left[0], &left[1..]),
} }
dst.push_str(" : "); dst.push_str(" : ");
dst.push_str(prefix);
dst.push_str(name); dst.push_str(name);
dst.push_str(")"); dst.push_str(")");
} }

View File

@ -209,7 +209,7 @@ impl Bindgen {
js::SubContext { js::SubContext {
program, program,
cx: &mut cx, cx: &mut cx,
polyfills: Default::default(), vendor_prefixes: Default::default(),
}.generate()?; }.generate()?;
} }
cx.finalize(stem)? cx.finalize(stem)?

View File

@ -185,9 +185,9 @@ impl BindgenAttrs {
}) })
} }
fn polyfills(&self) -> impl Iterator<Item = &Ident> { fn vendor_prefixes(&self) -> impl Iterator<Item = &Ident> {
self.attrs.iter().filter_map(|a| match a { self.attrs.iter().filter_map(|a| match a {
BindgenAttr::Polyfill(s) => Some(s), BindgenAttr::VendorPrefix(s) => Some(s),
_ => None, _ => None,
}) })
} }
@ -233,7 +233,7 @@ pub enum BindgenAttr {
JsName(String, Span), JsName(String, Span),
JsClass(String), JsClass(String),
Extends(Ident), Extends(Ident),
Polyfill(Ident), VendorPrefix(Ident),
Variadic, Variadic,
} }
@ -294,9 +294,9 @@ impl Parse for BindgenAttr {
input.parse::<Token![=]>()?; input.parse::<Token![=]>()?;
return Ok(BindgenAttr::Extends(input.parse::<AnyIdent>()?.0)); return Ok(BindgenAttr::Extends(input.parse::<AnyIdent>()?.0));
} }
if attr == "polyfill" { if attr == "vendor_prefix" {
input.parse::<Token![=]>()?; input.parse::<Token![=]>()?;
return Ok(BindgenAttr::Polyfill(input.parse::<AnyIdent>()?.0)); return Ok(BindgenAttr::VendorPrefix(input.parse::<AnyIdent>()?.0));
} }
if attr == "module" { if attr == "module" {
input.parse::<Token![=]>()?; input.parse::<Token![=]>()?;
@ -568,7 +568,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
rust_name: self.ident, rust_name: self.ident,
js_name, js_name,
extends: attrs.extends().cloned().collect(), extends: attrs.extends().cloned().collect(),
polyfills: attrs.polyfills().cloned().collect(), vendor_prefixes: attrs.vendor_prefixes().cloned().collect(),
})) }))
} }
} }

View File

@ -87,7 +87,7 @@ pub struct ImportStatic {
pub struct ImportType { pub struct ImportType {
pub name: String, pub name: String,
pub instanceof_shim: String, pub instanceof_shim: String,
pub polyfills: Vec<String>, pub vendor_prefixes: Vec<String>,
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]

View File

@ -500,13 +500,13 @@ impl<'src> FirstPassRecord<'src> {
doc_comment: None, doc_comment: None,
instanceof_shim: format!("__widl_instanceof_{}", name), instanceof_shim: format!("__widl_instanceof_{}", name),
extends: Vec::new(), extends: Vec::new(),
polyfills: Vec::new(), vendor_prefixes: Vec::new(),
}; };
// whitelist a few names that have known polyfills // whitelist a few names that have known polyfills
match name { match name {
"AudioContext" => { "AudioContext" => {
import_type.polyfills.push(Ident::new("webkitAudioContext", Span::call_site())); import_type.vendor_prefixes.push(Ident::new("webkit", Span::call_site()));
} }
_ => {} _ => {}
} }

View File

@ -67,7 +67,7 @@
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md) - [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
- [`structural`](./reference/attributes/on-js-imports/structural.md) - [`structural`](./reference/attributes/on-js-imports/structural.md)
- [`variadic`](./reference/attributes/on-js-imports/variadic.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) - [On Rust Exports](./reference/attributes/on-rust-exports/index.md)
- [`constructor`](./reference/attributes/on-rust-exports/constructor.md) - [`constructor`](./reference/attributes/on-rust-exports/constructor.md)
- [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md) - [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md)

View File

@ -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.

View File

@ -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.

View File

@ -26,7 +26,6 @@ pub mod math;
pub mod node; pub mod node;
pub mod option; pub mod option;
pub mod optional_primitives; pub mod optional_primitives;
pub mod polyfill;
pub mod rethrow; pub mod rethrow;
pub mod simple; pub mod simple;
pub mod slice; pub mod slice;
@ -34,3 +33,4 @@ pub mod structural;
pub mod u64; pub mod u64;
pub mod validate_prt; pub mod validate_prt;
pub mod variadic; pub mod variadic;
pub mod vendor_prefix;

View File

@ -1,5 +0,0 @@
exports.import_me = function() {};
global.PolyfillBar = class {
foo() { return 123; }
};

View File

@ -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);
}

View File

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

View File

@ -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);
}