Merge remote-tracking branch 'upstream/master'

# Conflicts:
#	crates/webidl/src/first_pass.rs
#	crates/webidl/src/lib.rs
#	crates/webidl/src/util.rs
This commit is contained in:
Anton Danilkin 2018-08-06 22:07:36 +03:00
commit ef3f086102
73 changed files with 2203 additions and 2619 deletions

View File

@ -52,6 +52,9 @@ matrix:
script: script:
- cargo test --release - cargo test --release
- cargo test --target wasm32-unknown-unknown - cargo test --target wasm32-unknown-unknown
- WASM_BINDGEN_NO_DEBUG=1 cargo test --target wasm32-unknown-unknown
- cargo test --target wasm32-unknown-unknown --features serde-serialize
- cargo test --target wasm32-unknown-unknown -p no-std
# Check JS output from all tests against eslint # Check JS output from all tests against eslint
- npm run run-lint-generated-tests - npm run run-lint-generated-tests
# Check Examples against eslint # Check Examples against eslint

View File

@ -33,6 +33,9 @@ serde_json = { version = "1.0", optional = true }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies] [target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = { path = 'crates/test', version = '=0.2.15' } wasm-bindgen-test = { path = 'crates/test', version = '=0.2.15' }
serde_derive = "1.0"
wasm-bindgen-test-crate-a = { path = 'tests/crates/a' }
wasm-bindgen-test-crate-b = { path = 'tests/crates/b' }
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
wasm-bindgen-test-project-builder = { path = "crates/test-project-builder", version = '=0.2.15' } wasm-bindgen-test-project-builder = { path = "crates/test-project-builder", version = '=0.2.15' }
@ -63,6 +66,7 @@ members = [
"examples/performance", "examples/performance",
"examples/smorgasboard", "examples/smorgasboard",
"examples/wasm-in-wasm", "examples/wasm-in-wasm",
"tests/no-std",
] ]
[patch.crates-io] [patch.crates-io]

View File

@ -56,7 +56,6 @@ pub enum MethodSelf {
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
pub struct Import { pub struct Import {
pub module: Option<String>, pub module: Option<String>,
pub version: Option<String>,
pub js_namespace: Option<Ident>, pub js_namespace: Option<Ident>,
pub kind: ImportKind, pub kind: ImportKind,
} }
@ -119,7 +118,7 @@ pub struct ImportStatic {
pub ty: syn::Type, pub ty: syn::Type,
pub shim: Ident, pub shim: Ident,
pub rust_name: Ident, pub rust_name: Ident,
pub js_name: Ident, pub js_name: String,
} }
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
@ -146,7 +145,7 @@ pub struct ImportEnum {
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
pub struct Function { pub struct Function {
pub name: Ident, pub name: String,
pub arguments: Vec<syn::ArgCaptured>, pub arguments: Vec<syn::ArgCaptured>,
pub ret: Option<syn::Type>, pub ret: Option<syn::Type>,
pub rust_attrs: Vec<syn::Attribute>, pub rust_attrs: Vec<syn::Attribute>,
@ -304,33 +303,8 @@ impl Variant {
impl Import { impl Import {
fn shared(&self) -> Result<shared::Import, Diagnostic> { fn shared(&self) -> Result<shared::Import, Diagnostic> {
match (&self.module, &self.version) {
(&Some(ref m), None) if m.starts_with("./") => {}
(&Some(ref m), &Some(_)) if m.starts_with("./") => {
panic!(
"when a module path starts with `./` that indicates \
that a local file is being imported so the `version` \
key cannot also be specified"
);
}
(&Some(_), &Some(_)) => {}
(&Some(_), &None) => panic!(
"when the `module` directive doesn't start with `./` \
then it's interpreted as an NPM package which requires \
a `version` to be specified as well, try using \
#[wasm_bindgen(module = \"...\", version = \"...\")]"
),
(&None, &Some(_)) => {
panic!(
"the #[wasm_bindgen(version = \"...\")] attribute can only \
be used when `module = \"...\"` is also specified"
);
}
(&None, &None) => {}
}
Ok(shared::Import { Ok(shared::Import {
module: self.module.clone(), module: self.module.clone(),
version: self.version.clone(),
js_namespace: self.js_namespace.as_ref().map(|s| s.to_string()), js_namespace: self.js_namespace.as_ref().map(|s| s.to_string()),
kind: self.kind.shared(), kind: self.kind.shared(),
}) })

View File

@ -94,7 +94,6 @@ pub fn ident_ty(ident: Ident) -> syn::Type {
pub fn wrap_import_function(function: ast::ImportFunction) -> ast::Import { pub fn wrap_import_function(function: ast::ImportFunction) -> ast::Import {
ast::Import { ast::Import {
module: None, module: None,
version: None,
js_namespace: None, js_namespace: None,
kind: ast::ImportKind::Function(function), kind: ast::ImportKind::Function(function),
} }

View File

@ -15,7 +15,6 @@ base64 = "0.9"
failure = "0.1.2" failure = "0.1.2"
parity-wasm = "0.31" parity-wasm = "0.31"
serde = "1.0" serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
tempfile = "3.0" tempfile = "3.0"
wasm-bindgen-shared = { path = "../shared", version = '=0.2.15' } wasm-bindgen-shared = { path = "../shared", version = '=0.2.15' }

View File

@ -5,7 +5,6 @@ use std::mem;
use failure::{Error, ResultExt}; use failure::{Error, ResultExt};
use parity_wasm; use parity_wasm;
use parity_wasm::elements::*; use parity_wasm::elements::*;
use serde_json;
use shared; use shared;
use wasm_gc; use wasm_gc;
@ -43,7 +42,6 @@ pub struct Context<'a> {
pub exported_classes: HashMap<String, ExportedClass>, pub exported_classes: HashMap<String, ExportedClass>,
pub function_table_needed: bool, pub function_table_needed: bool,
pub run_descriptor: &'a Fn(&str) -> Option<Vec<u32>>, pub run_descriptor: &'a Fn(&str) -> Option<Vec<u32>>,
pub module_versions: Vec<(String, String)>,
} }
#[derive(Default)] #[derive(Default)]
@ -458,7 +456,6 @@ impl<'a> Context<'a> {
self.export_table(); self.export_table();
self.gc()?; self.gc()?;
self.add_wasm_pack_section();
while js.contains("\n\n\n") { while js.contains("\n\n\n") {
js = js.replace("\n\n\n", "\n\n"); js = js.replace("\n\n\n", "\n\n");
@ -1629,28 +1626,6 @@ impl<'a> Context<'a> {
self.globals.push_str("\n"); self.globals.push_str("\n");
} }
fn add_wasm_pack_section(&mut self) {
if self.module_versions.len() == 0 {
return;
}
#[derive(Serialize)]
struct WasmPackSchema<'a> {
version: &'a str,
modules: &'a [(String, String)],
}
let contents = serde_json::to_string(&WasmPackSchema {
version: "0.0.1",
modules: &self.module_versions,
}).unwrap();
let mut section = CustomSection::default();
*section.name_mut() = "__wasm_pack_unstable".to_string();
*section.payload_mut() = contents.into_bytes();
self.module.sections_mut().push(Section::Custom(section));
}
fn use_node_require(&self) -> bool { fn use_node_require(&self) -> bool {
self.config.nodejs && !self.config.nodejs_experimental_modules self.config.nodejs && !self.config.nodejs_experimental_modules
} }
@ -1766,7 +1741,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
} }
fn generate_import(&mut self, import: &shared::Import) -> Result<(), Error> { fn generate_import(&mut self, import: &shared::Import) -> Result<(), Error> {
self.validate_import_module(import)?;
match import.kind { match import.kind {
shared::ImportKind::Function(ref f) => { shared::ImportKind::Function(ref f) => {
self.generate_import_function(import, f).with_context(|_| { self.generate_import_function(import, f).with_context(|_| {
@ -1787,41 +1761,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
Ok(()) Ok(())
} }
fn validate_import_module(&mut self, import: &shared::Import) -> Result<(), Error> {
let version = match import.version {
Some(ref s) => s,
None => return Ok(()),
};
let module = match import.module {
Some(ref s) => s,
None => return Ok(()),
};
if module.starts_with("./") {
return Ok(());
}
let pkg = if module.starts_with("@") {
// Translate `@foo/bar/baz` to `@foo/bar` and `@foo/bar` to itself
let first_slash = match module.find('/') {
Some(i) => i,
None => bail!(
"packages starting with `@` must be of the form \
`@foo/bar`, but found: `{}`",
module
),
};
match module[first_slash + 1..].find('/') {
Some(i) => &module[..i],
None => module,
}
} else {
module.split('/').next().unwrap()
};
self.cx
.module_versions
.push((pkg.to_string(), version.clone()));
Ok(())
}
fn generate_import_static( fn generate_import_static(
&mut self, &mut self,
info: &shared::Import, info: &shared::Import,

View File

@ -2,8 +2,6 @@
extern crate parity_wasm; extern crate parity_wasm;
extern crate wasm_bindgen_shared as shared; extern crate wasm_bindgen_shared as shared;
#[macro_use]
extern crate serde_derive;
extern crate serde_json; extern crate serde_json;
extern crate wasm_gc; extern crate wasm_gc;
extern crate wasmi; extern crate wasmi;
@ -203,7 +201,6 @@ impl Bindgen {
config: &self, config: &self,
module: &mut module, module: &mut module,
function_table_needed: false, function_table_needed: false,
module_versions: Default::default(),
run_descriptor: &|name| { run_descriptor: &|name| {
let mut v = MyExternals(Vec::new()); let mut v = MyExternals(Vec::new());
match instance.invoke_export(name, &[], &mut v) { match instance.invoke_export(name, &[], &mut v) {

View File

@ -123,11 +123,12 @@ fn rmain() -> Result<(), Error> {
node = !custom.payload().contains(&0x01); node = !custom.payload().contains(&0x01);
} }
let headless = env::var("NO_HEADLESS").is_err(); let headless = env::var("NO_HEADLESS").is_err();
let debug = env::var("WASM_BINDGEN_NO_DEBUG").is_err();
// Make the generated bindings available for the tests to execute against. // Make the generated bindings available for the tests to execute against.
shell.status("Executing bindgen..."); shell.status("Executing bindgen...");
let mut b = Bindgen::new(); let mut b = Bindgen::new();
b.debug(true) b.debug(debug)
.nodejs(node) .nodejs(node)
.input_module(module, wasm, |w| parity_wasm::serialize(w).unwrap()) .input_module(module, wasm, |w| parity_wasm::serialize(w).unwrap())
.keep_debug(false) .keep_debug(false)

View File

@ -361,6 +361,16 @@ extern "C" {
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
pub fn new(length: u32) -> ArrayBuffer; pub fn new(length: u32) -> ArrayBuffer;
/// The byteLength property of an object which is an instance of type ArrayBuffer
/// it's an accessor property whose set accessor function is undefined,
/// meaning that you can only read this property.
/// The value is established when the array is constructed and cannot be changed.
/// This property returns 0 if this ArrayBuffer has been detached.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/byteLength
#[wasm_bindgen(method, getter, js_name = byteLength)]
pub fn byte_length(this: &ArrayBuffer) -> u32;
/// The `isView()` method returns true if arg is one of the `ArrayBuffer` /// The `isView()` method returns true if arg is one of the `ArrayBuffer`
/// views, such as typed array objects or a DataView; false otherwise. /// views, such as typed array objects or a DataView; false otherwise.
/// ///
@ -2168,6 +2178,30 @@ extern {
#[wasm_bindgen(method, getter)] #[wasm_bindgen(method, getter)]
pub fn multiline(this: &RegExp) -> bool; pub fn multiline(this: &RegExp) -> bool;
/// The non-standard $1, $2, $3, $4, $5, $6, $7, $8, $9 properties
/// are static and read-only properties of regular expressions
/// that contain parenthesized substring matches.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/n
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$1")]
pub fn n1() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$2")]
pub fn n2() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$3")]
pub fn n3() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$4")]
pub fn n4() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$5")]
pub fn n5() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$6")]
pub fn n6() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$7")]
pub fn n7() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$8")]
pub fn n8() -> JsString;
#[wasm_bindgen(static_method_of = RegExp, getter, js_name = "$9")]
pub fn n9() -> JsString;
/// The RegExp constructor creates a regular expression object for matching text with a pattern. /// The RegExp constructor creates a regular expression object for matching text with a pattern.
/// ///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

View File

@ -9,6 +9,12 @@ fn new() {
assert!(y.is_object()); assert!(y.is_object());
} }
#[wasm_bindgen_test]
fn byte_length() {
let buf = ArrayBuffer::new(42);
assert_eq!(buf.byte_length(), 42);
}
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn is_view() { fn is_view() {
let x = Uint8Array::new(&JsValue::from(42)); let x = Uint8Array::new(&JsValue::from(42));

View File

@ -29,7 +29,7 @@ fn apply() {
assert_eq!(Array::from(&arr).length(), 1); assert_eq!(Array::from(&arr).length(), 1);
} }
#[wasm_bindgen(module = "tests/wasm/Function.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/Function.js")]
extern { extern {
fn get_function_to_bind() -> Function; fn get_function_to_bind() -> Function;
fn get_value_to_bind_to() -> JsValue; fn get_value_to_bind_to() -> JsValue;

View File

@ -2,7 +2,7 @@ use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use js_sys::*; use js_sys::*;
#[wasm_bindgen(module = "tests/wasm/Generator.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/Generator.js")]
extern { extern {
fn one_two_generator() -> Generator; fn one_two_generator() -> Generator;
fn dummy_generator() -> Generator; fn dummy_generator() -> Generator;

View File

@ -10,7 +10,7 @@ extern {
fn set_foo(this: &Foo42, val: JsValue); fn set_foo(this: &Foo42, val: JsValue);
} }
#[wasm_bindgen(module = "tests/wasm/Object.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/Object.js")]
extern { extern {
fn map_with_symbol_key() -> Object; fn map_with_symbol_key() -> Object;
fn symbol_key() -> JsValue; fn symbol_key() -> JsValue;

View File

@ -2,7 +2,7 @@ use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use js_sys::*; use js_sys::*;
#[wasm_bindgen(module = "tests/wasm/Proxy.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/Proxy.js")]
extern { extern {
fn proxy_target() -> JsValue; fn proxy_target() -> JsValue;
fn proxy_handler() -> Object; fn proxy_handler() -> Object;

View File

@ -2,7 +2,7 @@ use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use js_sys::*; use js_sys::*;
#[wasm_bindgen(module = "tests/wasm/Reflect.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/Reflect.js")]
extern { extern {
fn get_char_at() -> Function; fn get_char_at() -> Function;

View File

@ -3,7 +3,6 @@ use js_sys::*;
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn exec() { fn exec() {
let re = RegExp::new("quick\\s(brown).+?(jumps)", "ig"); let re = RegExp::new("quick\\s(brown).+?(jumps)", "ig");
let result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog"); let result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog");
@ -76,6 +75,21 @@ fn multiline() {
assert!(re.multiline()); assert!(re.multiline());
} }
#[wasm_bindgen_test]
fn n1_to_n9() {
let re = RegExp::new(r"(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)", "");
re.test("The Quick Brown Fox Jumps Over The Lazy Dog");
assert_eq!(RegExp::n1(), "The");
assert_eq!(RegExp::n2(), "Quick");
assert_eq!(RegExp::n3(), "Brown");
assert_eq!(RegExp::n4(), "Fox");
assert_eq!(RegExp::n5(), "Jumps");
assert_eq!(RegExp::n6(), "Over");
assert_eq!(RegExp::n7(), "The");
assert_eq!(RegExp::n8(), "Lazy");
assert_eq!(RegExp::n9(), "Dog");
}
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn new() { fn new() {
let re = RegExp::new("foo", ""); let re = RegExp::new("foo", "");

View File

@ -2,7 +2,7 @@ use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use js_sys::*; use js_sys::*;
#[wasm_bindgen(module = "tests/wasm/Symbol.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/Symbol.js")]
extern { extern {
fn test_has_instance(sym: &Symbol); fn test_has_instance(sym: &Symbol);
fn test_is_concat_spreadable(sym: &Symbol); fn test_is_concat_spreadable(sym: &Symbol);

View File

@ -53,17 +53,6 @@ impl BindgenAttrs {
.next() .next()
} }
/// Get the first version attribute
fn version(&self) -> Option<&str> {
self.attrs
.iter()
.filter_map(|a| match a {
BindgenAttr::Version(s) => Some(&s[..]),
_ => None,
})
.next()
}
/// Whether the catch attribute is present /// Whether the catch attribute is present
fn catch(&self) -> bool { fn catch(&self) -> bool {
self.attrs.iter().any(|a| match a { self.attrs.iter().any(|a| match a {
@ -173,11 +162,11 @@ impl BindgenAttrs {
} }
/// Get the first js_name attribute /// Get the first js_name attribute
fn js_name(&self) -> Option<&Ident> { fn js_name(&self) -> Option<&str> {
self.attrs self.attrs
.iter() .iter()
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::JsName(s) => Some(s), BindgenAttr::JsName(s) => Some(&s[..]),
_ => None, _ => None,
}) })
.next() .next()
@ -219,7 +208,6 @@ pub enum BindgenAttr {
StaticMethodOf(Ident), StaticMethodOf(Ident),
JsNamespace(Ident), JsNamespace(Ident),
Module(String), Module(String),
Version(String),
Getter(Option<Ident>), Getter(Option<Ident>),
Setter(Option<Ident>), Setter(Option<Ident>),
SpecialGetter, SpecialGetter,
@ -227,7 +215,7 @@ pub enum BindgenAttr {
SpecialDeleter, SpecialDeleter,
Structural, Structural,
Readonly, Readonly,
JsName(Ident), JsName(String),
JsClass(String), JsClass(String),
} }
@ -290,18 +278,15 @@ impl syn::synom::Synom for BindgenAttr {
(s.value()) (s.value())
)=> { BindgenAttr::Module } )=> { BindgenAttr::Module }
| |
do_parse!(
call!(term, "version") >>
punct!(=) >>
s: syn!(syn::LitStr) >>
(s.value())
)=> { BindgenAttr::Version }
|
do_parse!( do_parse!(
call!(term, "js_name") >> call!(term, "js_name") >>
punct!(=) >> punct!(=) >>
ns: call!(term2ident) >> name: alt!(
(ns) syn!(syn::LitStr) => { |s| s.value() }
|
call!(term2ident) => { |s| s.to_string() }
) >>
(name)
)=> { BindgenAttr::JsName } )=> { BindgenAttr::JsName }
| |
do_parse!( do_parse!(
@ -398,9 +383,10 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
fn convert(self, (opts, module): (BindgenAttrs, &'a Option<String>)) fn convert(self, (opts, module): (BindgenAttrs, &'a Option<String>))
-> Result<Self::Target, Diagnostic> -> Result<Self::Target, Diagnostic>
{ {
let js_name = opts.js_name().unwrap_or(&self.ident).clone(); let default_name = self.ident.to_string();
let js_name = opts.js_name().unwrap_or(&default_name);
let wasm = function_from_decl( let wasm = function_from_decl(
&js_name, js_name,
self.decl.clone(), self.decl.clone(),
self.attrs.clone(), self.attrs.clone(),
self.vis.clone(), self.vis.clone(),
@ -517,7 +503,9 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
ast::ImportFunctionKind::Method { ref class, .. } => (1, &class[..]), ast::ImportFunctionKind::Method { ref class, .. } => (1, &class[..]),
}; };
let data = (ns, &self.ident, module); let data = (ns, &self.ident, module);
format!("__wbg_{}_{}", js_name, ShortHash(data)) format!("__wbg_{}_{}",
js_name.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>(),
ShortHash(data))
}; };
Ok(ast::ImportKind::Function(ast::ImportFunction { Ok(ast::ImportKind::Function(ast::ImportFunction {
function: wasm, function: wasm,
@ -552,13 +540,16 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemStatic {
if self.mutability.is_some() { if self.mutability.is_some() {
bail_span!(self.mutability, "cannot import mutable globals yet") bail_span!(self.mutability, "cannot import mutable globals yet")
} }
let js_name = opts.js_name().unwrap_or(&self.ident); let default_name = self.ident.to_string();
let shim = format!("__wbg_static_accessor_{}_{}", js_name, self.ident); let js_name = opts.js_name().unwrap_or(&default_name);
let shim = format!("__wbg_static_accessor_{}_{}",
js_name.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>(),
self.ident);
Ok(ast::ImportKind::Static(ast::ImportStatic { Ok(ast::ImportKind::Static(ast::ImportStatic {
ty: *self.ty, ty: *self.ty,
vis: self.vis, vis: self.vis,
rust_name: self.ident.clone(), rust_name: self.ident.clone(),
js_name: js_name.clone(), js_name: js_name.to_string(),
shim: Ident::new(&shim, Span::call_site()), shim: Ident::new(&shim, Span::call_site()),
})) }))
} }
@ -579,14 +570,15 @@ impl ConvertToAst<BindgenAttrs> for syn::ItemFn {
bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions"); bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions");
} }
let name = attrs.js_name().unwrap_or(&self.ident); let default_name = self.ident.to_string();
let name = attrs.js_name().unwrap_or(&default_name);
Ok(function_from_decl(name, self.decl, self.attrs, self.vis, false, None)?.0) Ok(function_from_decl(name, self.decl, self.attrs, self.vis, false, None)?.0)
} }
} }
/// Construct a function (and gets the self type if appropriate) for our AST from a syn function. /// Construct a function (and gets the self type if appropriate) for our AST from a syn function.
fn function_from_decl( fn function_from_decl(
name: &Ident, name: &str,
decl: Box<syn::FnDecl>, decl: Box<syn::FnDecl>,
attrs: Vec<syn::Attribute>, attrs: Vec<syn::Attribute>,
vis: syn::Visibility, vis: syn::Visibility,
@ -661,7 +653,7 @@ fn function_from_decl(
Ok(( Ok((
ast::Function { ast::Function {
name: name.clone(), name: name.to_string(),
arguments, arguments,
ret, ret,
rust_vis: vis, rust_vis: vis,
@ -824,7 +816,7 @@ impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
}; };
let (function, method_self) = function_from_decl( let (function, method_self) = function_from_decl(
opts.js_name().unwrap_or(&method.sig.ident), opts.js_name().unwrap_or(&method.sig.ident.to_string()),
Box::new(method.sig.decl.clone()), Box::new(method.sig.decl.clone()),
method.attrs.clone(), method.attrs.clone(),
method.vis.clone(), method.vis.clone(),
@ -940,10 +932,6 @@ impl<'a> MacroParse<&'a BindgenAttrs> for syn::ForeignItem {
BindgenAttrs::find(attrs)? BindgenAttrs::find(attrs)?
}; };
let module = item_opts.module().or(opts.module()).map(|s| s.to_string()); let module = item_opts.module().or(opts.module()).map(|s| s.to_string());
let version = item_opts
.version()
.or(opts.version())
.map(|s| s.to_string());
let js_namespace = item_opts.js_namespace().or(opts.js_namespace()).cloned(); let js_namespace = item_opts.js_namespace().or(opts.js_namespace()).cloned();
let kind = match self { let kind = match self {
syn::ForeignItem::Fn(f) => f.convert((item_opts, &module))?, syn::ForeignItem::Fn(f) => f.convert((item_opts, &module))?,
@ -954,7 +942,6 @@ impl<'a> MacroParse<&'a BindgenAttrs> for syn::ForeignItem {
program.imports.push(ast::Import { program.imports.push(ast::Import {
module, module,
version,
js_namespace, js_namespace,
kind, kind,
}); });

View File

@ -24,7 +24,6 @@ pub struct Program {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct Import { pub struct Import {
pub module: Option<String>, pub module: Option<String>,
pub version: Option<String>,
pub js_namespace: Option<String>, pub js_namespace: Option<String>,
pub kind: ImportKind, pub kind: ImportKind,
} }

View File

@ -32,9 +32,16 @@ pub fn wasm_bindgen_test(
let mut body = TokenStream::from(body).into_iter(); let mut body = TokenStream::from(body).into_iter();
// Assume the input item is of the form `fn #ident ...`, and extract // Skip over other attributes to `fn #ident ...`, and extract `#ident`
// `#ident` let mut leading_tokens = Vec::new();
let fn_tok = body.next(); while let Some(token) = body.next() {
leading_tokens.push(token.clone());
if let TokenTree::Ident(token) = token {
if token == "fn" {
break
}
}
}
let ident = match body.next() { let ident = match body.next() {
Some(TokenTree::Ident(token)) => token, Some(TokenTree::Ident(token)) => token,
_ => panic!("expected a function name"), _ => panic!("expected a function name"),
@ -64,7 +71,7 @@ pub fn wasm_bindgen_test(
} }
}).into_iter()); }).into_iter());
tokens.extend(fn_tok); tokens.extend(leading_tokens);
tokens.push(ident.into()); tokens.push(ident.into());
tokens.extend(body); tokens.extend(body);

View File

@ -1,4 +1,5 @@
extern crate env_logger; extern crate env_logger;
#[macro_use]
extern crate failure; extern crate failure;
extern crate wasm_bindgen_webidl; extern crate wasm_bindgen_webidl;
extern crate sourcefile; extern crate sourcefile;
@ -8,9 +9,8 @@ use sourcefile::SourceFile;
use std::env; use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::io::Write;
use std::path; use std::path;
use std::process; use std::process::{self, Command};
fn main() { fn main() {
if let Err(e) = try_main() { if let Err(e) = try_main() {
@ -32,12 +32,14 @@ fn try_main() -> Result<(), failure::Error> {
let mut source = SourceFile::default(); let mut source = SourceFile::default();
for entry in entries { for entry in entries {
let entry = entry.context("getting webidls/enabled/*.webidl entry")?; let entry = entry.context("getting webidls/enabled/*.webidl entry")?;
if entry.path().extension() == Some(OsStr::new("webidl")) { let path = entry.path();
println!("cargo:rerun-if-changed={}", entry.path().display()); if path.extension() != Some(OsStr::new("webidl")) {
source = source.add_file(entry.path()) continue
.with_context(|_| format!("reading contents of file \"{}\"",
entry.path().display()))?;
} }
println!("cargo:rerun-if-changed={}", path.display());
source = source.add_file(&path)
.with_context(|_| format!("reading contents of file \"{}\"",
path.display()))?;
} }
let bindings = match wasm_bindgen_webidl::compile(&source.contents) { let bindings = match wasm_bindgen_webidl::compile(&source.contents) {
@ -60,17 +62,19 @@ fn try_main() -> Result<(), failure::Error> {
let out_dir = env::var("OUT_DIR").context("reading OUT_DIR environment variable")?; let out_dir = env::var("OUT_DIR").context("reading OUT_DIR environment variable")?;
let out_file_path = path::Path::new(&out_dir).join("bindings.rs"); let out_file_path = path::Path::new(&out_dir).join("bindings.rs");
let mut out_file = fs::File::create(&out_file_path) fs::write(&out_file_path, bindings)
.context("creating output bindings file")?;
out_file
.write_all(bindings.as_bytes())
.context("writing bindings to output file")?; .context("writing bindings to output file")?;
// run rustfmt on the generated file - really handy for debugging // run rustfmt on the generated file - really handy for debugging
//if ! process::Command::new("rustfmt").arg(&out_file_path).status() if env::var("WEBIDL_RUSTFMT_BINDINGS").is_ok() {
// .context("running rustfmt")?.success() { let status = Command::new("rustfmt")
// return Err(format_err!("rustfmt failed to format {}", out_file_path.display())); .arg(&out_file_path)
//} .status()
.context("running rustfmt")?;
if !status.success() {
bail!("rustfmt failed: {}", status)
}
}
Ok(()) Ok(())
} }

View File

@ -28,7 +28,7 @@ fn main() {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
#[wasm_bindgen(module = "{}", version = "*")] #[wasm_bindgen(module = "{}")]
extern {{ extern {{
fn not_actually_a_function{1}(); fn not_actually_a_function{1}();
}} }}

View File

@ -20,4 +20,4 @@ proc-macro2 = "0.4.8"
quote = '0.6' quote = '0.6'
syn = { version = '0.14', features = ['full'] } syn = { version = '0.14', features = ['full'] }
wasm-bindgen-backend = { version = "=0.2.15", path = "../backend" } wasm-bindgen-backend = { version = "=0.2.15", path = "../backend" }
webidl = "0.7.0" weedle = "0.6"

View File

@ -7,69 +7,61 @@
//! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can //! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can
//! be partial. //! be partial.
use std::{ use std::collections::{BTreeMap, BTreeSet};
collections::{BTreeMap, BTreeSet}, mem,
};
use webidl; use weedle::argument::Argument;
use weedle::attribute::ExtendedAttribute;
use weedle::interface::StringifierOrStatic;
use weedle::mixin::MixinMembers;
use weedle;
use super::Result; use super::Result;
use util;
/// Collection of constructs that may use partial. /// Collection of constructs that may use partial.
#[derive(Default)] #[derive(Default)]
pub(crate) struct FirstPassRecord<'a> { pub(crate) struct FirstPassRecord<'src> {
pub(crate) interfaces: BTreeMap<String, InterfaceData>, pub(crate) interfaces: BTreeMap<&'src str, InterfaceData<'src>>,
pub(crate) dictionaries: BTreeSet<String>, pub(crate) dictionaries: BTreeSet<&'src str>,
pub(crate) enums: BTreeSet<String>, pub(crate) enums: BTreeSet<&'src str>,
/// The mixins, mapping their name to the webidl ast node for the mixin. /// The mixins, mapping their name to the webidl ast node for the mixin.
pub(crate) mixins: BTreeMap<String, MixinData<'a>>, pub(crate) mixins: BTreeMap<&'src str, Vec<&'src MixinMembers<'src>>>,
pub(crate) typedefs: BTreeMap<String, webidl::ast::Type>, pub(crate) typedefs: BTreeMap<&'src str, &'src weedle::types::Type<'src>>,
} }
/// We need to collect interface data during the first pass, to be used later. /// We need to collect interface data during the first pass, to be used later.
#[derive(Default)] #[derive(Default)]
pub(crate) struct InterfaceData { pub(crate) struct InterfaceData<'src> {
/// Whether only partial interfaces were encountered /// Whether only partial interfaces were encountered
pub(crate) partial: bool, pub(crate) partial: bool,
pub(crate) operations: BTreeMap<OperationId, OperationData>,
pub(crate) global: bool, pub(crate) global: bool,
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
} }
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum OperationId { pub(crate) enum OperationId<'src> {
Constructor, Constructor,
Operation(Option<String>), Operation(Option<&'src str>),
SpecialGetter, SpecialGetter,
SpecialSetter, SpecialSetter,
SpecialDeleter, SpecialDeleter,
} }
#[derive(Default)] #[derive(Default)]
pub(crate) struct OperationData { pub(crate) struct OperationData<'src> {
pub(crate) overloaded: bool, pub(crate) overloaded: bool,
/// Map from argument names to whether they are the same for multiple overloads /// Map from argument names to whether they are the same for multiple overloads
pub(crate) argument_names_same: BTreeMap<Vec<String>, bool>, pub(crate) argument_names_same: BTreeMap<Vec<&'src str>, bool>,
}
/// We need to collect mixin data during the first pass, to be used later.
#[derive(Default)]
pub(crate) struct MixinData<'a> {
/// The non partial mixin, if present. If there is more than one, we are
/// parsing is a malformed WebIDL file, but the parser will recover by
/// using the last parsed mixin.
pub(crate) non_partial: Option<&'a webidl::ast::NonPartialMixin>,
/// 0 or more partial mixins.
pub(crate) partials: Vec<&'a webidl::ast::PartialMixin>,
} }
/// Implemented on an AST node to populate the `FirstPassRecord` struct. /// Implemented on an AST node to populate the `FirstPassRecord` struct.
pub(crate) trait FirstPass<Ctx> { pub(crate) trait FirstPass<'src, Ctx> {
/// Populate `record` with any constructs in `self`. /// Populate `record` with any constructs in `self`.
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, ctx: Ctx) -> Result<()>; fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, ctx: Ctx) -> Result<()>;
} }
impl FirstPass<()> for [webidl::ast::Definition] { impl<'src> FirstPass<'src, ()> for [weedle::Definition<'src>] {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
for def in self { for def in self {
def.first_pass(record, ())?; def.first_pass(record, ())?;
} }
@ -78,15 +70,17 @@ impl FirstPass<()> for [webidl::ast::Definition] {
} }
} }
impl FirstPass<()> for webidl::ast::Definition { impl<'src> FirstPass<'src, ()> for weedle::Definition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
use webidl::ast::Definition::*; use weedle::Definition::*;
match self { match self {
Dictionary(dictionary) => dictionary.first_pass(record, ()), Dictionary(dictionary) => dictionary.first_pass(record, ()),
Enum(enum_) => enum_.first_pass(record, ()), Enum(enum_) => enum_.first_pass(record, ()),
Interface(interface) => interface.first_pass(record, ()), Interface(interface) => interface.first_pass(record, ()),
Mixin(mixin) => mixin.first_pass(record, ()), PartialInterface(interface) => interface.first_pass(record, ()),
InterfaceMixin(mixin) => mixin.first_pass(record, ()),
PartialInterfaceMixin(mixin) => mixin.first_pass(record, ()),
Typedef(typedef) => typedef.first_pass(record, ()), Typedef(typedef) => typedef.first_pass(record, ()),
_ => { _ => {
// Other definitions aren't currently used in the first pass // Other definitions aren't currently used in the first pass
@ -96,46 +90,38 @@ impl FirstPass<()> for webidl::ast::Definition {
} }
} }
impl FirstPass<()> for webidl::ast::Dictionary { impl<'src> FirstPass<'src, ()> for weedle::DictionaryDefinition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
use webidl::ast::Dictionary::*; if !record.dictionaries.insert(self.identifier.0) {
warn!("encountered multiple dictionary declarations of {}", self.identifier.0);
match self {
NonPartial(dictionary) => dictionary.first_pass(record, ()),
_ => {
// Other dictionaries aren't currently used in the first pass
Ok(())
}
} }
Ok(())
} }
} }
impl FirstPass<()> for webidl::ast::NonPartialDictionary { impl<'src> FirstPass<'src, ()> for weedle::EnumDefinition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
if record.dictionaries.insert(self.name.clone()) { if !record.enums.insert(self.identifier.0) {
warn!("Encountered multiple declarations of {}", self.name); warn!("Encountered multiple enum declarations of {}", self.identifier.0);
} }
Ok(()) Ok(())
} }
} }
impl FirstPass<()> for webidl::ast::Enum { fn first_pass_operation<'src>(
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { record: &mut FirstPassRecord<'src>,
if record.enums.insert(self.name.clone()) { self_name: &'src str,
warn!("Encountered multiple declarations of {}", self.name); id: OperationId<'src>,
} arguments: &[Argument<'src>],
Ok(())
}
}
fn first_pass_operation<'a>(
record: &mut FirstPassRecord<'a>,
self_name: &str,
id: OperationId,
arguments: &[webidl::ast::Argument],
) -> Result<()> { ) -> Result<()> {
let mut names = Vec::with_capacity(arguments.len());
for argument in arguments {
match argument {
Argument::Single(arg) => names.push(arg.identifier.0),
Argument::Variadic(_) => return Ok(()),
}
}
record record
.interfaces .interfaces
.get_mut(self_name) .get_mut(self_name)
@ -143,77 +129,48 @@ fn first_pass_operation<'a>(
.operations .operations
.entry(id) .entry(id)
.and_modify(|operation_data| operation_data.overloaded = true) .and_modify(|operation_data| operation_data.overloaded = true)
.or_insert_with(|| .or_insert_with(Default::default)
OperationData {
overloaded: false,
argument_names_same: Default::default(),
}
)
.argument_names_same .argument_names_same
.entry(arguments.iter().map(|argument| argument.name.clone()).collect()) .entry(names)
.and_modify(|same_argument_names| *same_argument_names = true) .and_modify(|same_argument_names| *same_argument_names = true)
.or_insert(false); .or_insert(false);
Ok(()) Ok(())
} }
impl FirstPass<()> for webidl::ast::Interface { impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
use webidl::ast::Interface::*; {
let interface = record
match self { .interfaces
Partial(interface) => interface.first_pass(record, ()), .entry(self.identifier.0)
NonPartial(interface) => interface.first_pass(record, ()), .or_insert_with(Default::default);
// TODO interface.partial = false;
Callback(..) => {
warn!("Unsupported WebIDL interface: {:?}", self);
Ok(())
}
} }
}
}
impl FirstPass<()> for webidl::ast::NonPartialInterface { if util::is_chrome_only(&self.attributes) {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
record
.interfaces
.entry(self.name.clone())
.and_modify(|interface_data| {
if interface_data.partial {
interface_data.partial = false;
} else {
warn!("Encountered multiple declarations of {}", self.name);
}
})
.or_insert_with(||
InterfaceData {
partial: false,
operations: Default::default(),
global: false,
},
);
if ::util::is_chrome_only(&self.extended_attributes) {
return Ok(()) return Ok(())
} }
for extended_attribute in &self.extended_attributes { if let Some(attrs) = &self.attributes {
extended_attribute.first_pass(record, &self.name)?; for attr in &attrs.body.list {
attr.first_pass(record, self.identifier.0)?;
}
} }
for member in &self.members { for member in &self.members.body {
member.first_pass(record, &self.name)?; member.first_pass(record, self.identifier.0)?;
} }
Ok(()) Ok(())
} }
} }
impl FirstPass<()> for webidl::ast::PartialInterface { impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
record record
.interfaces .interfaces
.entry(self.name.clone()) .entry(self.identifier.0)
.or_insert_with(|| .or_insert_with(||
InterfaceData { InterfaceData {
partial: true, partial: true,
@ -222,191 +179,129 @@ impl FirstPass<()> for webidl::ast::PartialInterface {
}, },
); );
if ::util::is_chrome_only(&self.extended_attributes) { if util::is_chrome_only(&self.attributes) {
return Ok(()) return Ok(())
} }
for member in &self.members { for member in &self.members.body {
member.first_pass(record, &self.name)?; member.first_pass(record, self.identifier.0)?;
} }
Ok(()) Ok(())
} }
} }
impl<'b> FirstPass<&'b str> for webidl::ast::ExtendedAttribute { impl<'src> FirstPass<'src, &'src str> for ExtendedAttribute<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
match self { match self {
webidl::ast::ExtendedAttribute::ArgumentList( ExtendedAttribute::ArgList(list) if list.identifier.0 == "Constructor" => {
webidl::ast::ArgumentListExtendedAttribute { arguments, name }, first_pass_operation(
) record,
if name == "Constructor" => self_name,
{ OperationId::Constructor,
first_pass_operation( &list.args.body.list,
record, )
self_name, }
OperationId::Constructor, ExtendedAttribute::NoArgs(name) if (name.0).0 == "Constructor" => {
&arguments, first_pass_operation(
) record,
} self_name,
webidl::ast::ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name)) OperationId::Constructor,
if name == "Constructor" => &[],
{ )
first_pass_operation( }
record, ExtendedAttribute::NamedArgList(list)
self_name, if list.lhs_identifier.0 == "NamedConstructor" =>
OperationId::Constructor, {
&[], first_pass_operation(
) record,
} self_name,
webidl::ast::ExtendedAttribute::NamedArgumentList( OperationId::Constructor,
webidl::ast::NamedArgumentListExtendedAttribute { &list.args.body.list,
lhs_name, )
rhs_arguments, }
.. ExtendedAttribute::Ident(id) if id.lhs_identifier.0 == "Global" => {
}, record.interfaces.get_mut(self_name).unwrap().global = true;
) Ok(())
if lhs_name == "NamedConstructor" => }
{ ExtendedAttribute::IdentList(id) if id.identifier.0 == "Global" => {
first_pass_operation( record.interfaces.get_mut(self_name).unwrap().global = true;
record, Ok(())
self_name, }
OperationId::Constructor,
&rhs_arguments,
)
},
webidl::ast::ExtendedAttribute::Identifier(
webidl::ast::IdentifierExtendedAttribute { lhs, .. }
)
| webidl::ast::ExtendedAttribute::IdentifierList(
webidl::ast::IdentifierListExtendedAttribute { lhs, .. }
)
if lhs == "Global" =>
{
record.interfaces.get_mut(self_name).unwrap().global = true;
Ok(())
}
_ => Ok(()) _ => Ok(())
} }
} }
} }
impl<'b> FirstPass<&'b str> for webidl::ast::InterfaceMember { impl<'src> FirstPass<'src, &'src str> for weedle::interface::InterfaceMember<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
match self { match self {
webidl::ast::InterfaceMember::Operation(op) => op.first_pass(record, self_name), weedle::interface::InterfaceMember::Operation(op) => {
op.first_pass(record, self_name)
}
_ => Ok(()), _ => Ok(()),
} }
} }
} }
impl<'b> FirstPass<&'b str> for webidl::ast::Operation { impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceMember<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
match self { if !self.specials.is_empty() && self.specials.len() != 1 {
webidl::ast::Operation::Regular(op) => op.first_pass(record, self_name), warn!("Unsupported webidl operation {:?}", self);
webidl::ast::Operation::Static(op) => op.first_pass(record, self_name), return Ok(())
webidl::ast::Operation::Special(op) => op.first_pass(record, self_name), }
// TODO if let Some(StringifierOrStatic::Stringifier(_)) = self.modifier {
webidl::ast::Operation::Stringifier(_) => { warn!("Unsupported webidl operation {:?}", self);
warn!("Unsupported WebIDL operation: {:?}", self); return Ok(())
Ok(())
}
} }
}
}
impl<'b> FirstPass<&'b str> for webidl::ast::RegularOperation {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
first_pass_operation( first_pass_operation(
record, record,
self_name, self_name,
OperationId::Operation(self.name.clone()), match self.identifier.map(|s| s.0) {
&self.arguments, None => match self.specials.get(0) {
) None => OperationId::Operation(None),
} Some(weedle::interface::Special::Getter(weedle::term::Getter)) => OperationId::SpecialGetter,
} Some(weedle::interface::Special::Setter(weedle::term::Setter)) => OperationId::SpecialSetter,
Some(weedle::interface::Special::Deleter(weedle::term::Deleter)) => OperationId::SpecialDeleter,
impl<'b> FirstPass<&'b str> for webidl::ast::StaticOperation { Some(weedle::interface::Special::LegacyCaller(weedle::term::LegacyCaller)) => return Ok(()),
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
first_pass_operation(
record,
self_name,
OperationId::Operation(self.name.clone()),
&self.arguments,
)
}
}
impl<'b> FirstPass<&'b str> for webidl::ast::SpecialOperation {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
first_pass_operation(
record,
self_name,
match self.name {
None => match self.special_keywords.iter().next() {
Some(webidl::ast::Special::Getter) => OperationId::SpecialGetter,
Some(webidl::ast::Special::Setter) => OperationId::SpecialSetter,
Some(webidl::ast::Special::Deleter) => OperationId::SpecialDeleter,
Some(webidl::ast::Special::LegacyCaller) => return Ok(()),
None => {
panic!("unsupported special operation: {:?} of {}", self, self_name);
}
}, },
Some(ref name) => OperationId::Operation(Some(name.clone())), Some(ref name) => OperationId::Operation(Some(name.clone())),
}, },
&self.arguments, &self.args.body.list,
) )
} }
} }
impl FirstPass<()> for webidl::ast::Mixin { impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src>{
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
use webidl::ast::Mixin::*; record
match self {
NonPartial(mixin) => mixin.first_pass(record, ()),
Partial(mixin) => mixin.first_pass(record, ()),
}
}
}
impl FirstPass<()> for webidl::ast::NonPartialMixin {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
let entry = record
.mixins .mixins
.entry(self.name.clone()) .entry(self.identifier.0)
.or_insert_with(Default::default); .or_insert_with(Default::default)
if mem::replace(&mut entry.non_partial, Some(self)).is_some() { .push(&self.members.body);
warn!(
"Encounterd multiple declarations of {}, using last encountered",
self.name
);
}
Ok(()) Ok(())
} }
} }
impl FirstPass<()> for webidl::ast::PartialMixin { impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceMixinDefinition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
let entry = record record
.mixins .mixins
.entry(self.name.clone()) .entry(self.identifier.0)
.or_insert_with(Default::default); .or_insert_with(Default::default)
entry.partials.push(self); .push(&self.members.body);
Ok(()) Ok(())
} }
} }
impl FirstPass<()> for webidl::ast::Typedef { impl<'src> FirstPass<'src, ()> for weedle::TypedefDefinition<'src> {
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
if ::util::is_chrome_only(&self.extended_attributes) { if util::is_chrome_only(&self.attributes) {
return Ok(()); return Ok(());
} }
if record.typedefs.insert(self.name.clone(), *self.type_.clone()).is_some() { if record.typedefs.insert(self.identifier.0, &self.type_.type_).is_some() {
warn!("Encountered multiple declarations of {}", self.name); warn!("Encountered multiple declarations of {}", self.identifier.0);
} }
Ok(()) Ok(())

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,37 +5,6 @@ controlling precisely how imports are imported and what they map to in JS. This
section is intended to hopefully be an exhaustive reference of the section is intended to hopefully be an exhaustive reference of the
possibilities! possibilities!
* `module` and `version` - we've seen `module` so far indicating where we can
import items from but `version` is also allowed:
```rust
#[wasm_bindgen(module = "moment", version = "^2.0.0")]
extern {
type Moment;
fn moment() -> Moment;
#[wasm_bindgen(method)]
fn format(this: &Moment) -> String;
}
```
The `module` key is used to configure the module that each item is imported
from. The `version` key does not affect the generated wasm itself but rather
it's an informative directive for tools like [wasm-pack]. Tools like wasm-pack
will generate a `package.json` for you and the `version` listed here, when
`module` is also an NPM package, will correspond to what to write down in
`package.json`.
In other words the usage of `module` as the name of an NPM package and
`version` as the version requirement allows you to, inline in Rust, depend on
the NPM ecosystem and import functionality from those packages. When bundled
with a tool like [wasm-pack] everything will automatically get wired up with
bundlers and you should be good to go!
Note that the `version` is *required* if `module` doesn't start with `./`. If
`module` starts with `./` then it is an error to provide a version.
[wasm-pack]: https://github.com/rustwasm/wasm-pack
* `catch` - this attribute allows catching a JS exception. This can be attached * `catch` - this attribute allows catching a JS exception. This can be attached
to any imported function and the function must return a `Result` where the to any imported function and the function must return a `Result` where the
`Err` payload is a `JsValue`, like so: `Err` payload is a `JsValue`, like so:

73
package-lock.json generated
View File

@ -106,9 +106,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "10.5.5", "version": "10.5.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.6.tgz",
"integrity": "sha512-6Qnb1gXbp3g1JX9QVJj3A6ORzc9XCyhokxUKaoonHgNXcQhmk8adhotxfkeK8El9TnFeUuH72yI6jQ5nDJKS6w==", "integrity": "sha512-c5Z1j1ysgo4878ptz6gxLcgMfJ6Wf908R3l5KAGabr0XJ72ZFmOCgsaodPpNYTfp4iOrSwgTDvR/BxbFfB4zPQ==",
"dev": true "dev": true
}, },
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
@ -1759,9 +1759,9 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "5.2.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.2.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz",
"integrity": "sha512-zlggW1qp7/TBjwLfouRoY7eWXrXwJZFqCdIxxh0/LVB/QuuKuIMkzyUZEcDo6LBadsry5JcEMxIqd3H/66CXVg==", "integrity": "sha512-N/tCqlMKkyNvAvLu+zI9AqDasnSLt00K+Hu8kdsERliC9jYEc8ck12XtjvOXrBKu8fK6RrBcN9bat6Xk++9jAg==",
"dev": true, "dev": true,
"requires": { "requires": {
"ajv": "^6.5.0", "ajv": "^6.5.0",
@ -1795,7 +1795,7 @@
"path-is-inside": "^1.0.2", "path-is-inside": "^1.0.2",
"pluralize": "^7.0.0", "pluralize": "^7.0.0",
"progress": "^2.0.0", "progress": "^2.0.0",
"regexpp": "^1.1.0", "regexpp": "^2.0.0",
"require-uncached": "^1.0.3", "require-uncached": "^1.0.3",
"semver": "^5.5.0", "semver": "^5.5.0",
"string.prototype.matchall": "^2.0.0", "string.prototype.matchall": "^2.0.0",
@ -2379,7 +2379,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -2400,12 +2401,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -2420,17 +2423,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -2547,7 +2553,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -2559,6 +2566,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -2573,6 +2581,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -2580,12 +2589,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -2604,6 +2615,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -2684,7 +2696,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -2696,6 +2709,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -2781,7 +2795,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -2817,6 +2832,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -2836,6 +2852,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -2879,12 +2896,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@ -3225,9 +3244,9 @@
"dev": true "dev": true
}, },
"ignore": { "ignore": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.2.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.3.tgz",
"integrity": "sha512-uoxnT7PYpyEnsja+yX+7v49B7LXxmzDJ2JALqHH3oEGzpM2U1IGcbfnOr8Dt57z3B/UWs7/iAgPFbmye8m4I0g==", "integrity": "sha512-Z/vAH2GGIEATQnBVXMclE2IGV6i0GyVngKThcGZ5kHgHMxLo9Ow2+XHRq1aEKEej5vOF1TPJNbvX6J/anT0M7A==",
"dev": true "dev": true
}, },
"immediate": { "immediate": {
@ -5020,9 +5039,9 @@
} }
}, },
"regexpp": { "regexpp": {
"version": "1.1.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz",
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==",
"dev": true "dev": true
}, },
"remove-trailing-separator": { "remove-trailing-separator": {
@ -6379,9 +6398,9 @@
} }
}, },
"webpack": { "webpack": {
"version": "4.16.4", "version": "4.16.5",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.4.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.5.tgz",
"integrity": "sha512-RqUfwp4qMqv3oFwBQQOoK69C2tdu2FHJEqPABPqgjGDvOIOLqkTOhmmdJjpiRabzNAAH1ahmkA3z4xowlHN+VA==", "integrity": "sha512-i5cHYHonzSc1zBuwB5MSzW4v9cScZFbprkHK8ZgzPDCRkQXGGpYzPmJhbus5bOrZ0tXTcQp+xyImRSvKb0b+Kw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.5.13", "@webassemblyjs/ast": "1.5.13",

View File

@ -8,14 +8,14 @@
"run-lint-generated-tests": "eslint ./target/generated-tests/*/out*js" "run-lint-generated-tests": "eslint ./target/generated-tests/*/out*js"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^10.5.5", "@types/node": "^10.5.6",
"babel-eslint": "^8.2.6", "babel-eslint": "^8.2.6",
"eslint": "^5.2.0", "eslint": "^5.3.0",
"geckodriver": "^1.12.1", "geckodriver": "^1.12.1",
"selenium-webdriver": "^4.0.0-alpha.1", "selenium-webdriver": "^4.0.0-alpha.1",
"ts-loader": "^4.4.2", "ts-loader": "^4.4.2",
"typescript": "^3.0.1", "typescript": "^3.0.1",
"webpack": "^4.16.4", "webpack": "^4.16.5",
"webpack-cli": "^3.1.0", "webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5" "webpack-dev-server": "^3.1.5"
} }

View File

@ -1,209 +0,0 @@
use super::project;
#[test]
fn dependencies_work() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
extern crate dependency;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn return_dep_ty(x: f64) -> dependency::Foo {
dependency::Foo(x)
}
#[wasm_bindgen]
pub fn takes_own_dep_ty(foo: dependency::Foo) -> f64 {
foo.0
}
#[wasm_bindgen]
pub fn takes_ref_dep_ty(foo: &dependency::Foo) -> f64 {
foo.0
}
#[wasm_bindgen]
pub fn takes_mut_dep_ty(foo: &mut dependency::Foo, x: f64) {
foo.0 = x;
}
"#,
)
.add_local_dependency("dependency", "vendor/dependency")
.file(
"vendor/dependency/Cargo.toml",
&format!(
r#"
[package]
name = "dependency"
version = "0.0.1"
authors = []
[dependencies]
wasm-bindgen = {{ path = '{}' }}
"#,
env!("CARGO_MANIFEST_DIR")
),
)
.file(
"vendor/dependency/src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo(pub f64);
#[wasm_bindgen]
impl Foo {
pub fn new(x: f64) -> Foo { Foo(x) }
pub fn get(&self) -> f64 { self.0 }
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
const foo = wasm.return_dep_ty(42);
assert.strictEqual(foo.get(), 42);
const x = wasm.takes_ref_dep_ty(foo);
assert.strictEqual(x, 42);
const y = 1337;
wasm.takes_mut_dep_ty(foo, y);
assert.strictEqual(foo.get(), y);
const z = wasm.takes_own_dep_ty(foo);
assert.strictEqual(z, y);
assert.strictEqual(foo.ptr, 0);
}
"#,
)
.test();
}
#[test]
fn same_api_two_crates() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
extern crate a;
extern crate b;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./foo")]
extern {
fn assert_next_undefined();
fn assert_next_ten();
}
#[wasm_bindgen]
pub fn test() {
assert_next_undefined();
a::test();
assert_next_ten();
b::test();
}
"#,
)
.file(
"foo.js",
r#"
import { strictEqual } from "assert";
let next = null;
export function assert_next_undefined() {
next = undefined;
}
export function assert_next_ten() {
next = 10;
}
export function foo(a) {
console.log(a, next);
strictEqual(a, next);
next = null;
}
"#,
)
.add_local_dependency("a", "a")
.file(
"a/Cargo.toml",
&format!(r#"
[package]
name = 'a'
version = '0.0.0'
[dependencies]
wasm-bindgen = {{ path = '{}' }}
"#,
env!("CARGO_MANIFEST_DIR")
),
)
.file(
"a/src/lib.rs",
"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = \"./foo\")]
extern {
fn foo();
}
pub fn test() {
foo();
}
",
)
.add_local_dependency("b", "b")
.file(
"b/Cargo.toml",
&format!(r#"
[package]
name = 'b'
version = '0.0.0'
[dependencies]
wasm-bindgen = {{ path = '{}' }}
"#,
env!("CARGO_MANIFEST_DIR")
),
)
.file(
"b/src/lib.rs",
"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = \"./foo\")]
extern {
fn foo(x: u32);
}
pub fn test() {
foo(10);
}
",
)
.test();
}

View File

@ -1,88 +0,0 @@
use super::project;
#[test]
fn unused_imports_not_generated() {
let mut project = project();
project
.debug(false)
.file("src/lib.rs", r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
pub fn foo();
}
#[wasm_bindgen]
pub fn run() {
}
"#)
.file("test.js", r#"
import { run } from "./out";
export function test() {
run();
}
"#)
.test();
let contents = project.read_js();
assert!(contents.contains("run"), "didn't find `run` in {}", contents);
assert!(!contents.contains("foo"), "found `foo` in {}", contents);
}
#[test]
fn versions() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "webpack", version = "^0.2.0")]
extern {
fn foo();
}
#[wasm_bindgen]
pub fn run() {
foo();
}
"#,
)
.file(
"test.js",
r#"
import * as fs from 'fs';
import * as assert from 'assert';
export function test() {
const bytes = fs.readFileSync('out_bg.wasm');
const m = new WebAssembly.Module(bytes);
const name = '__wasm_pack_unstable';
const sections = WebAssembly.Module.customSections(m, name);
assert.strictEqual(sections.length, 1);
const b = new Uint8Array(sections[0]);
const buf = new Buffer(b);
const map = JSON.parse(buf.toString());
assert.deepStrictEqual(map, {
version: '0.0.1',
modules: [
['webpack', '^0.2.0']
]
});
};
"#,
)
.test();
}

View File

@ -1,94 +0,0 @@
use super::project;
#[test]
fn serde() {
project()
.serde(true)
.depend("serde = '1.0'")
.depend("serde_derive = '1.0'")
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
#[macro_use]
extern crate serde_derive;
use wasm_bindgen::prelude::*;
#[derive(Deserialize, Serialize)]
pub struct Foo {
a: u32,
b: String,
c: Option<Bar>,
d: Bar,
}
#[derive(Deserialize, Serialize)]
pub struct Bar {
a: u32,
}
#[wasm_bindgen(module = "./test")]
extern {
fn verify(a: JsValue) -> JsValue;
}
#[wasm_bindgen]
pub fn run() {
let js = JsValue::from_serde("foo").unwrap();
assert_eq!(js.as_string(), Some("foo".to_string()));
let ret = verify(JsValue::from_serde(&Foo {
a: 0,
b: "foo".to_string(),
c: None,
d: Bar { a: 1 },
}).unwrap());
let foo = ret.into_serde::<Foo>().unwrap();
assert_eq!(foo.a, 2);
assert_eq!(foo.b, "bar");
assert!(foo.c.is_some());
assert_eq!(foo.c.as_ref().unwrap().a, 3);
assert_eq!(foo.d.a, 4);
}
#[wasm_bindgen]
pub fn parse(j: &JsValue) {
let s = j.into_serde::<String>().unwrap();
assert_eq!(s, "bar");
}
"#,
)
.file(
"test.js",
r#"
import { run, parse } from "./out";
import * as assert from "assert";
export function verify(a) {
assert.deepStrictEqual(a, {
a: 0,
b: 'foo',
c: null,
d: { a: 1 }
});
return {
a: 2,
b: 'bar',
c: { a: 3 },
d: { a: 4 },
}
}
export function test() {
run();
parse('bar');
}
"#,
)
.test();
}

View File

@ -2,14 +2,7 @@
extern crate wasm_bindgen_test_project_builder as project_builder; extern crate wasm_bindgen_test_project_builder as project_builder;
use project_builder::{project, run}; use project_builder::project;
mod comments; mod comments;
mod dependencies;
mod js_objects;
mod imports;
mod node;
mod non_debug;
mod non_wasm;
mod simple;
mod typescript; mod typescript;

View File

@ -1,161 +0,0 @@
use super::project;
#[test]
fn works() {
project()
.debug(false)
.nodejs_experimental_modules(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")]
extern {
static FOO: JsValue;
fn hit();
}
#[wasm_bindgen]
pub fn run() {
hit();
assert_eq!(FOO.as_f64(), Some(1.0));
}
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Foo {
Foo::with_contents(0)
}
pub fn with_contents(a: u32) -> Foo {
Foo { contents: a }
}
pub fn add(&mut self, amt: u32) -> u32 {
self.contents += amt;
self.contents
}
}
#[wasm_bindgen]
pub enum Color {
Green,
Yellow,
Red,
}
#[wasm_bindgen]
pub fn cycle(color: Color) -> Color {
match color {
Color::Green => Color::Yellow,
Color::Yellow => Color::Red,
Color::Red => Color::Green,
}
}
#[wasm_bindgen]
pub fn math(a: f32, b: f64) -> f64 {
b.acos() +
b.asin() +
b.atan() +
b.atan2(b) +
b.cbrt() +
b.cosh() +
b.exp_m1() +
b.ln_1p() +
b.sinh() +
b.tan() +
b.tanh() +
b.hypot(b) +
b.cos() +
b.exp() +
b.exp2() +
b.mul_add(b, b) +
b.ln() +
b.log(b) +
b.log10() +
b.log2() +
b.powi(8) +
b.powf(b) +
b.round() +
b.sin() +
b.abs() +
b.signum() +
b.floor() +
b.ceil() +
b.trunc() +
b.sqrt() +
(b % (a as f64)) +
((a.cos() +
a.exp() +
a.exp2() +
a.mul_add(a, a) +
a.ln() +
a.log(a) +
a.log10() +
a.log2() +
a.powi(8) +
a.powf(a) +
a.round() +
a.sin() +
a.abs() +
a.signum() +
a.floor() +
a.ceil() +
a.trunc() +
a.sqrt() +
(a % (b as f32))) as f64) +
(b + 2.0f64.powf(a as f64))
}
"#,
)
.file(
"test.js",
r#"
const assert = require('assert');
var called = false;
module.exports.hit = function() {
called = true;
};
module.exports.FOO = 1.0;
const { math, run, Foo, Color, cycle } = require('./out');
module.exports.test = function() {
run();
assert.strictEqual(called, true);
var r = Foo.new();
assert.strictEqual(r.add(0), 0);
assert.strictEqual(r.add(1), 1);
assert.strictEqual(r.add(2), 3);
r.free();
var r2 = Foo.with_contents(10);
assert.strictEqual(r2.add(0), 10);
assert.strictEqual(r2.add(1), 11);
assert.strictEqual(r2.add(2), 13);
r2.free();
assert.strictEqual(Color.Green, 0);
assert.strictEqual(Color.Yellow, 1);
assert.strictEqual(Color.Red, 2);
assert.strictEqual(Object.keys(Color).length, 3);
assert.strictEqual(cycle(Color.Green), Color.Yellow);
math(1.0, 2.0);
};
"#,
)
.test();
}

View File

@ -1,48 +0,0 @@
use super::project;
#[test]
fn works() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct A {}
#[wasm_bindgen]
impl A {
pub fn new() -> A {
A {}
}
}
#[wasm_bindgen]
pub fn clone(a: &JsValue) -> JsValue {
drop(a.clone());
a.clone()
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
let sym = Symbol('a');
assert.strictEqual(wasm.clone(sym), sym);
let a = wasm.A.new();
a.free();
}
"#,
)
.test();
}

View File

@ -1,101 +0,0 @@
use super::{project, run};
use std::process::Command;
#[test]
fn works() {
let mut p = project();
let name = p.crate_name();
p.rlib(true)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct A {
x: u32,
}
#[wasm_bindgen]
impl A {
pub fn new() -> A {
A { x: 3 }
}
pub fn foo(&self) {
}
}
#[wasm_bindgen]
pub fn foo(x: bool) {
A::new().foo();
if x {
bar("test");
baz(JsValue::from(3));
}
}
#[wasm_bindgen]
extern {
fn some_import();
static A: JsValue;
}
#[wasm_bindgen]
pub fn bar(_: &str) -> JsValue {
some_import();
A.clone()
}
#[wasm_bindgen]
pub fn baz(_: JsValue) {
}
"#,
)
.file(
"tests/foo.rs",
&format!(
"
extern crate {} as mytest;
#[test]
fn foo() {{
mytest::foo(false);
mytest::A::new().foo();
}}
",
name
),
)
.file(
"benches/foo.rs",
&format!(
"
#![feature(test)]
extern crate test;
extern crate {} as mytest;
#[bench]
fn foo(b: &mut test::Bencher) {{
b.iter(|| mytest::foo(false));
}}
",
name
),
);
let (root, target_dir) = p.build();
let mut cmd = Command::new("cargo");
cmd.arg("test")
.arg("--test")
.arg("foo")
.arg("--bench")
.arg("foo")
.current_dir(&root)
.env("CARGO_TARGET_DIR", &target_dir);
run(&mut cmd, "cargo");
}

View File

@ -1,564 +0,0 @@
use super::project;
#[test]
fn add() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: u32, b: u32) -> u32 {
a + b
}
#[wasm_bindgen]
pub fn add3(a: u32) -> u32 {
a + 3
}
#[wasm_bindgen]
pub fn get2(_b: bool) -> u32 {
2
}
#[wasm_bindgen]
pub fn return_and_take_bool(a: bool, b: bool) -> bool {
a && b
}
#[wasm_bindgen]
pub fn raw_pointers_work(a: *mut u32, b: *const u8) -> *const u32 {
unsafe {
(*a) = (*b) as u32;
return a
}
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
assert.strictEqual(wasm.add(1, 2), 3);
assert.strictEqual(wasm.add(2, 3), 5);
assert.strictEqual(wasm.add3(2), 5);
assert.strictEqual(wasm.get2(true), 2);
assert.strictEqual(wasm.return_and_take_bool(true, false), false);
}
"#,
)
.test();
}
#[test]
fn add_headless() {
project()
.headless(true)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: u32, b: u32) -> u32 {
a + b
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
console.log("start `add_headless` test");
assert.strictEqual(wasm.add(1, 2), 3);
console.log("end `add_headless` test");
}
"#,
)
.test();
}
#[test]
fn string_arguments() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn assert_foo_and_bar(a: &str, b: &str) {
assert_eq!(a, "foo2");
assert_eq!(b, "bar");
}
#[wasm_bindgen]
pub fn assert_foo(a: &str) {
assert_eq!(a, "foo");
}
"#,
)
.file(
"test.js",
r#"
import * as wasm from "./out";
export function test() {
wasm.assert_foo("foo");
wasm.assert_foo_and_bar("foo2", "bar");
}
"#,
)
.test();
}
#[test]
fn return_a_string() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn clone(a: &str) -> String {
a.to_string()
}
#[wasm_bindgen]
pub fn concat(a: &str, b: &str, c: i8) -> String {
format!("{} {} {}", a, b, c)
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
assert.strictEqual(wasm.clone("foo"), "foo");
assert.strictEqual(wasm.clone("another"), "another");
assert.strictEqual(wasm.concat("a", "b", 3), "a b 3");
assert.strictEqual(wasm.concat("c", "d", -2), "c d -2");
}
"#,
)
.test();
}
#[test]
fn exceptions() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn foo(_a: u32) {}
#[wasm_bindgen]
pub fn bar(_a: &str) {}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
assert.throws(() => wasm.foo('a'), /expected a number argument/);
assert.throws(() => wasm.bar(3), /expected a string argument/);
}
"#,
)
.test();
}
// #[test]
// fn other_imports() {
// project()
// .file("src/lib.rs", r#"
// #![feature(use_extern_macros)]
//
// extern crate wasm_bindgen;
//
// use wasm_bindgen::prelude::*;
//
// extern {
// fn another_import(a: u32);
// }
//
// wasm_bindgen! {
// pub fn foo(a: u32) {
// unsafe { another_import(a); }
// }
// }
// "#)
// .file("test.js", r#"
// import * as assert from "assert";
// import * as wasm from "./out";
//
// let ARG: number | null = null;
//
// export function test() {
// wasm.foo(2);
// assert.strictEqual(ARG, 2);
// }
// "#)
// .test();
// }
#[test]
fn other_exports() {
project()
.file(
"src/lib.rs",
r#"
#[no_mangle]
pub extern fn foo(_a: u32) {
}
"#,
)
.file(
"test.js",
r#"
import * as wasm from "./out_bg";
export function test() {
wasm.foo(2);
}
"#,
)
.test();
}
#[test]
fn no_std() {
project()
.no_std(true)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
#![no_std]
#![allow(dead_code)]
extern crate wasm_bindgen;
extern crate std as _some_other_name;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./foo")]
extern {
fn test(a: &str);
type Js;
#[wasm_bindgen(constructor)]
fn new() -> Js;
#[wasm_bindgen(method)]
fn init(this: &Js);
}
#[wasm_bindgen]
pub fn foo(_a: u32) {}
"#,
)
.file(
"test.js",
r#"
import * as wasm from "./out_bg";
export function test() {
// mostly just testing the project compiles here
wasm.foo(1);
}
"#,
)
.file(
"foo.js",
r#"
export class Js {
init() {
}
}
"#,
)
.test();
}
#[test]
fn no_std_class() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
#![no_std]
#![allow(dead_code)]
extern crate wasm_bindgen;
extern crate std as _some_other_name;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
fn test(a: &str);
type Js;
#[wasm_bindgen(constructor)]
fn new() -> Js;
#[wasm_bindgen(method, structural)]
fn init(this: &Js);
}
#[wasm_bindgen]
pub fn foo(_a: u32) {}
#[wasm_bindgen]
pub struct A {}
#[wasm_bindgen]
impl A {
pub fn foo(&self) {}
pub fn bar(&mut self) {}
}
"#,
)
.file(
"test.js",
r#"
import * as wasm from "./out_bg";
export function test() {
// mostly just testing the project compiles here
wasm.foo(1);
}
"#,
)
.test();
}
#[test]
fn jsvalue_typeof() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn is_object(val: &JsValue) -> bool {
val.is_object()
}
#[wasm_bindgen]
pub fn is_function(val: &JsValue) -> bool {
val.is_function()
}
#[wasm_bindgen]
pub fn is_string(val: &JsValue) -> bool {
val.is_string()
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
assert.ok(wasm.is_object({}));
assert.ok(!wasm.is_object(42));
assert.ok(wasm.is_function(function() {}));
assert.ok(!wasm.is_function(42));
assert.ok(wasm.is_string("2b or !2b"));
assert.ok(!wasm.is_string(42));
}
"#,
)
.test();
}
#[test]
fn binding_to_unimplemented_apis_doesnt_break_everything() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
#[derive(Clone)]
type Array;
#[wasm_bindgen(constructor)]
fn new() -> Array;
#[wasm_bindgen(method, catch)]
fn standardized_method_this_js_runtime_doesnt_implement_yet(this: &Array)
-> Result<(), JsValue>;
}
#[wasm_bindgen]
pub fn test() {
let array = Array::new();
let res = array.standardized_method_this_js_runtime_doesnt_implement_yet();
assert!(res.is_err());
}
"#,
)
.test();
}
#[test]
fn optional_slices() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros, wasm_custom_section)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./foo")]
extern {
fn optional_str_none(a: Option<&str>);
fn optional_str_some(a: Option<&str>);
fn optional_slice_none(a: Option<&[u8]>);
fn optional_slice_some(a: Option<&[u8]>);
fn optional_string_none(a: Option<String>);
fn optional_string_some(a: Option<String>);
fn optional_string_some_empty(a: Option<String>);
fn return_string_none() -> Option<String>;
fn return_string_some() -> Option<String>;
fn run_rust_tests();
}
#[wasm_bindgen]
pub fn test() {
optional_str_none(None);
optional_str_some(Some("x"));
optional_slice_none(None);
optional_slice_some(Some(&[1, 2, 3]));
optional_string_none(None);
optional_string_some_empty(Some(String::new()));
optional_string_some(Some("abcd".to_string()));
assert_eq!(return_string_none(), None);
assert_eq!(return_string_some(), Some("foo".to_string()));
run_rust_tests();
}
#[wasm_bindgen]
pub fn take_optional_str_none(x: Option<String>) {
assert!(x.is_none())
}
#[wasm_bindgen]
pub fn take_optional_str_some(x: Option<String>) {
assert_eq!(x, Some(String::from("hello")));
}
#[wasm_bindgen]
pub fn return_optional_str_none() -> Option<String> {
None
}
#[wasm_bindgen]
pub fn return_optional_str_some() -> Option<String> {
Some("world".to_string())
}
"#,
)
.file(
"foo.js",
r#"
import { strictEqual } from "assert";
import * as wasm from "./out";
export function optional_str_none(x) {
strictEqual(x, undefined);
}
export function optional_str_some(x) {
strictEqual(x, 'x');
}
export function optional_slice_none(x) {
strictEqual(x, undefined);
}
export function optional_slice_some(x) {
strictEqual(x.length, 3);
strictEqual(x[0], 1);
strictEqual(x[1], 2);
strictEqual(x[2], 3);
}
export function optional_string_none(x) {
strictEqual(x, undefined);
}
export function optional_string_some(x) {
strictEqual(x, 'abcd');
}
export function optional_string_some_empty(x) {
strictEqual(x, '');
}
export function return_string_none() {}
export function return_string_some() {
return 'foo';
}
export function run_rust_tests() {
wasm.take_optional_str_none();
wasm.take_optional_str_none(null);
wasm.take_optional_str_none(undefined);
wasm.take_optional_str_some('hello');
strictEqual(wasm.return_optional_str_none(), undefined);
strictEqual(wasm.return_optional_str_some(), 'world');
}
"#
)
.test();
}

View File

@ -0,0 +1,9 @@
[package]
name = "wasm-bindgen-test-crate-a"
version = "0.1.0"
authors = ["The wasm-bindgen Authors"]
license = "MIT/Apache-2.0"
description = "internal test crate for wasm-bindgen"
[dependencies]
wasm-bindgen = { path = '../../..', version = '0.2' }

14
tests/crates/a/src/lib.rs Normal file
View File

@ -0,0 +1,14 @@
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicate_deps.js")]
extern {
fn foo();
}
pub fn test() {
foo();
}

View File

@ -0,0 +1,9 @@
[package]
name = "wasm-bindgen-test-crate-b"
version = "0.1.0"
authors = ["The wasm-bindgen Authors"]
license = "MIT/Apache-2.0"
description = "internal test crate for wasm-bindgen"
[dependencies]
wasm-bindgen = { path = '../../..', version = '0.2' }

14
tests/crates/b/src/lib.rs Normal file
View File

@ -0,0 +1,14 @@
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicate_deps.js")]
extern {
fn foo(x: u32);
}
pub fn test() {
foo(10);
}

10
tests/no-std/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "no-std"
version = "0.1.0"
authors = ["The wasm-bindgen Developers"]
[lib]
path = "test.rs"
[dependencies]
wasm-bindgen = { path = '../..', default-features = false }

0
tests/no-std/lib.rs Normal file
View File

28
tests/no-std/test.rs Normal file
View File

@ -0,0 +1,28 @@
//! This is a test that we compile `wasm-bindgen` itself in `no_std` mode and we
//! can export/import various items.
//!
//! This doesn't actually run any tests, it's mostly a compile-time verification
//! that things work.
#![feature(use_extern_macros)]
#![no_std]
#![allow(dead_code)]
extern crate wasm_bindgen;
extern crate std as _some_other_name;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn foo(_a: u32) {}
#[wasm_bindgen]
extern {
fn test(a: &str);
type Js;
#[wasm_bindgen(constructor)]
fn new() -> Js;
#[wasm_bindgen(method, structural)]
fn init(this: &Js);
}

53
tests/non_wasm.rs Normal file
View File

@ -0,0 +1,53 @@
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct A {
x: u32,
}
#[wasm_bindgen]
impl A {
pub fn new() -> A {
A { x: 3 }
}
pub fn foo(&self) {
drop(self.x);
}
}
#[wasm_bindgen]
pub fn foo(x: bool) {
A::new().foo();
if x {
bar("test");
baz(JsValue::from(3));
}
}
#[wasm_bindgen]
extern {
fn some_import();
static A: JsValue;
}
#[wasm_bindgen]
pub fn bar(_: &str) -> JsValue {
some_import();
A.clone()
}
#[wasm_bindgen]
pub fn baz(_: JsValue) {
}
#[test]
fn test_foo() {
foo(false);
A::new().foo();
}

View File

@ -0,0 +1,30 @@
//! This is a test that we can define items in a `#![no_std]` crate when
//! `wasm-bindgen` is compiled itself with the `std` feature and everything
//! works out just fine.
#![feature(use_extern_macros)]
#![no_std]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
fn test(a: &str);
type Js;
#[wasm_bindgen(constructor)]
fn new() -> Js;
#[wasm_bindgen(method, structural)]
fn init(this: &Js);
}
#[wasm_bindgen]
pub struct A {}
#[wasm_bindgen]
impl A {
pub fn foo(&self) {}
pub fn bar(&mut self) {}
}

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/api.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/api.js")]
extern { extern {
fn js_works(); fn js_works();
fn js_eq_works(); fn js_eq_works();

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/char.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/char.js")]
extern { extern {
fn js_identity(c: char) -> char; fn js_identity(c: char) -> char;
fn js_works(); fn js_works();

View File

@ -31,6 +31,10 @@ exports.js_strings = () => {
}; };
exports.js_exceptions = () => { exports.js_exceptions = () => {
// this test only works when `--debug` is passed to `wasm-bindgen` (or the
// equivalent thereof)
if (require('process').env.WASM_BINDGEN_NO_DEBUG)
return;
assert.throws(() => new wasm.ClassesExceptions1(), /cannot invoke `new` directly/); assert.throws(() => new wasm.ClassesExceptions1(), /cannot invoke `new` directly/);
let a = wasm.ClassesExceptions1.new(); let a = wasm.ClassesExceptions1.new();
a.free(); a.free();

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/classes.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/classes.js")]
extern { extern {
fn js_simple(); fn js_simple();
fn js_strings(); fn js_strings();

View File

@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*;
use std::cell::Cell; use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
#[wasm_bindgen(module = "tests/wasm/closures.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/closures.js")]
extern { extern {
fn works_call(a: &Fn()); fn works_call(a: &Fn());
fn works_thread(a: &Fn(u32) -> u32) -> u32; fn works_thread(a: &Fn(u32) -> u32) -> u32;

View File

@ -0,0 +1,17 @@
const assert = require('assert');
let next = null;
exports.assert_next_undefined = function() {
next = undefined;
};
exports.assert_next_ten = function() {
next = 10;
};
exports.foo = function(a) {
console.log(a, next);
assert.strictEqual(a, next);
next = null;
};

View File

@ -0,0 +1,18 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
use wasm_bindgen_test_crate_a as a;
use wasm_bindgen_test_crate_b as b;
#[wasm_bindgen(module = "tests/wasm/duplicate_deps.js")]
extern {
fn assert_next_undefined();
fn assert_next_ten();
}
#[wasm_bindgen_test]
fn works() {
assert_next_undefined();
a::test();
assert_next_ten();
b::test();
}

View File

@ -3,7 +3,7 @@ use wasm_bindgen_test::*;
pub mod same_function_different_locations_a { pub mod same_function_different_locations_a {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_a.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/duplicates_a.js")]
extern { extern {
pub fn foo(); pub fn foo();
} }
@ -12,7 +12,7 @@ pub mod same_function_different_locations_a {
pub mod same_function_different_locations_b { pub mod same_function_different_locations_b {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_a.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/duplicates_a.js")]
extern { extern {
pub fn foo(); pub fn foo();
} }
@ -27,7 +27,7 @@ fn same_function_different_locations() {
pub mod same_function_different_modules_a { pub mod same_function_different_modules_a {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_b.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/duplicates_b.js")]
extern { extern {
pub fn foo() -> bool; pub fn foo() -> bool;
} }
@ -36,7 +36,7 @@ pub mod same_function_different_modules_a {
pub mod same_function_different_modules_b { pub mod same_function_different_modules_b {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_c.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/duplicates_c.js")]
extern { extern {
pub fn foo() -> bool; pub fn foo() -> bool;
} }

View File

@ -2,7 +2,7 @@ use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use self::inner::ColorWithCustomValues; use self::inner::ColorWithCustomValues;
#[wasm_bindgen(module = "tests/wasm/enums.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/enums.js")]
extern { extern {
fn js_c_style_enum(); fn js_c_style_enum();
fn js_c_style_enum_with_custom_values(); fn js_c_style_enum_with_custom_values();

View File

@ -5,7 +5,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/import_class.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/import_class.js")]
extern { extern {
fn math_log(f: f64) -> f64; fn math_log(f: f64) -> f64;

View File

@ -1,5 +1,6 @@
const assert = require('assert'); const assert = require('assert');
const wasm = require('wasm-bindgen-test'); const wasm = require('wasm-bindgen-test');
const fs = require('fs');
let ARG = null; let ARG = null;
let ANOTHER_ARG = null; let ANOTHER_ARG = null;
@ -90,3 +91,12 @@ exports.touch_custom_type = function() {
exports.interpret_2_as_custom_type = function() { exports.interpret_2_as_custom_type = function() {
assert.throws(wasm.interpret_2_as_custom_type, /expected value of type CustomType/); assert.throws(wasm.interpret_2_as_custom_type, /expected value of type CustomType/);
}; };
exports.baz$ = function() {};
exports.$foo = 1.0;
exports.assert_dead_import_not_generated = function() {
const filename = require.resolve("wasm-bindgen-test");
const bindings = fs.readFileSync(filename);
assert.ok(!bindings.includes("unused_import"));
};

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/imports.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/imports.js")]
extern { extern {
fn test_simple(); fn test_simple();
@ -42,6 +42,14 @@ extern {
fn custom_type_return_2() -> CustomType; fn custom_type_return_2() -> CustomType;
#[wasm_bindgen(js_name = interpret_2_as_custom_type)] #[wasm_bindgen(js_name = interpret_2_as_custom_type)]
fn js_interpret_2_as_custom_type(); fn js_interpret_2_as_custom_type();
#[wasm_bindgen(js_name = "baz$")]
fn renamed_with_dollar_sign();
#[wasm_bindgen(js_name = "$foo")]
static RENAMED: JsValue;
fn unused_import();
fn assert_dead_import_not_generated();
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -153,3 +161,18 @@ impl CustomType {
} }
} }
#[wasm_bindgen_test]
fn rename_with_string() {
renamed_with_dollar_sign();
}
#[wasm_bindgen_test]
fn rename_static_with_string() {
assert_eq!(RENAMED.as_f64(), Some(1.0));
}
#[wasm_bindgen_test]
fn dead_imports_not_generated() {
assert_dead_import_not_generated();
}

View File

@ -82,3 +82,19 @@ exports.js_returning_vector = () => {
exports.js_another_vector_return = () => { exports.js_another_vector_return = () => {
assert.deepStrictEqual(wasm.another_vector_return_get_array(), [1, 2, 3, 4, 5, 6]); assert.deepStrictEqual(wasm.another_vector_return_get_array(), [1, 2, 3, 4, 5, 6]);
}; };
exports.verify_serde = function(a) {
assert.deepStrictEqual(a, {
a: 0,
b: 'foo',
c: null,
d: { a: 1 }
});
return {
a: 2,
b: 'bar',
c: { a: 3 },
d: { a: 4 },
}
};

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/js_objects.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/js_objects.js")]
extern { extern {
fn simple_foo(s: &JsValue); fn simple_foo(s: &JsValue);
fn js_simple(); fn js_simple();
@ -26,6 +26,7 @@ extern {
fn js_returning_vector(); fn js_returning_vector();
fn js_another_vector_return(); fn js_another_vector_return();
fn verify_serde(val: JsValue) -> JsValue;
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -105,3 +106,40 @@ pub fn another_vector_return_get_array() -> Vec<JsValue> {
fn another_vector_return() { fn another_vector_return() {
js_another_vector_return(); js_another_vector_return();
} }
#[cfg(feature = "serde-serialize")]
#[wasm_bindgen_test]
fn serde() {
#[derive(Deserialize, Serialize)]
pub struct Foo {
a: u32,
b: String,
c: Option<Bar>,
d: Bar,
}
#[derive(Deserialize, Serialize)]
pub struct Bar {
a: u32,
}
let js = JsValue::from_serde("foo").unwrap();
assert_eq!(js.as_string(), Some("foo".to_string()));
let ret = verify_serde(JsValue::from_serde(&Foo {
a: 0,
b: "foo".to_string(),
c: None,
d: Bar { a: 1 },
}).unwrap());
let foo = ret.into_serde::<Foo>().unwrap();
assert_eq!(foo.a, 2);
assert_eq!(foo.b, "bar");
assert!(foo.c.is_some());
assert_eq!(foo.c.as_ref().unwrap().a, 3);
assert_eq!(foo.d.a, 4);
assert_eq!(JsValue::from("bar").into_serde::<String>().unwrap(), "bar");
}

View File

@ -3,19 +3,28 @@
extern crate wasm_bindgen_test; extern crate wasm_bindgen_test;
extern crate wasm_bindgen; extern crate wasm_bindgen;
extern crate wasm_bindgen_test_crate_a;
extern crate wasm_bindgen_test_crate_b;
#[cfg(feature = "serde-serialize")]
#[macro_use]
extern crate serde_derive;
pub mod api; pub mod api;
pub mod char; pub mod char;
pub mod classes; pub mod classes;
pub mod closures; pub mod closures;
pub mod duplicate_deps;
pub mod duplicates; pub mod duplicates;
pub mod enums; pub mod enums;
pub mod imports;
pub mod import_class; pub mod import_class;
pub mod imports;
pub mod js_objects; pub mod js_objects;
pub mod math; pub mod math;
pub mod node;
pub mod option; pub mod option;
pub mod optional_primitives; pub mod optional_primitives;
pub mod simple;
pub mod slice; pub mod slice;
pub mod structural; pub mod structural;
pub mod u64; pub mod u64;

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/math.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/math.js")]
extern { extern {
fn js_auto_bind_math(); fn js_auto_bind_math();
} }
@ -64,4 +64,4 @@ pub fn math(a: f32, b: f64) -> f64 {
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn auto_bind_math() { fn auto_bind_math() {
js_auto_bind_math(); js_auto_bind_math();
} }

34
tests/wasm/node.js Normal file
View File

@ -0,0 +1,34 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
var called = false;
exports.hit = function() {
called = true;
};
exports.FOO = 1.0;
exports.test_works = function() {
assert.strictEqual(called, true);
var r = wasm.Foo.new();
assert.strictEqual(r.add(0), 0);
assert.strictEqual(r.add(1), 1);
assert.strictEqual(r.add(2), 3);
r.free();
var r2 = wasm.Foo.with_contents(10);
assert.strictEqual(r2.add(0), 10);
assert.strictEqual(r2.add(1), 11);
assert.strictEqual(r2.add(2), 13);
r2.free();
assert.strictEqual(wasm.Color.Green, 0);
assert.strictEqual(wasm.Color.Yellow, 1);
assert.strictEqual(wasm.Color.Red, 2);
assert.strictEqual(Object.keys(wasm.Color).length, 3);
assert.strictEqual(wasm.cycle(wasm.Color.Green), wasm.Color.Yellow);
wasm.node_math(1.0, 2.0);
};

105
tests/wasm/node.rs Normal file
View File

@ -0,0 +1,105 @@
use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/node.js")]
extern {
fn test_works();
static FOO: JsValue;
fn hit();
}
#[wasm_bindgen_test]
fn works() {
hit();
assert_eq!(FOO.as_f64(), Some(1.0));
test_works();
}
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Foo {
Foo::with_contents(0)
}
pub fn with_contents(a: u32) -> Foo {
Foo { contents: a }
}
pub fn add(&mut self, amt: u32) -> u32 {
self.contents += amt;
self.contents
}
}
#[wasm_bindgen]
pub enum Color {
Green,
Yellow,
Red,
}
#[wasm_bindgen]
pub fn cycle(color: Color) -> Color {
match color {
Color::Green => Color::Yellow,
Color::Yellow => Color::Red,
Color::Red => Color::Green,
}
}
#[wasm_bindgen]
pub fn node_math(a: f32, b: f64) -> f64 {
b.acos() +
b.asin() +
b.atan() +
b.atan2(b) +
b.cbrt() +
b.cosh() +
b.exp_m1() +
b.ln_1p() +
b.sinh() +
b.tan() +
b.tanh() +
b.hypot(b) +
b.cos() +
b.exp() +
b.exp2() +
b.mul_add(b, b) +
b.ln() +
b.log(b) +
b.log10() +
b.log2() +
b.powi(8) +
b.powf(b) +
b.round() +
b.sin() +
b.abs() +
b.signum() +
b.floor() +
b.ceil() +
b.trunc() +
b.sqrt() +
(b % (a as f64)) +
((a.cos() +
a.exp() +
a.exp2() +
a.mul_add(a, a) +
a.ln() +
a.log(a) +
a.log10() +
a.log2() +
a.powi(8) +
a.powf(a) +
a.round() +
a.sin() +
a.abs() +
a.signum() +
a.floor() +
a.ceil() +
a.trunc() +
a.sqrt() +
(a % (b as f32))) as f64) +
(b + 2.0f64.powf(a as f64))
}

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/option.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/option.js")]
extern { extern {
pub type MyType; pub type MyType;
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/optional_primitives.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/optional_primitives.js")]
extern { extern {
fn optional_i32_js_identity(a: Option<i32>) -> Option<i32>; fn optional_i32_js_identity(a: Option<i32>) -> Option<i32>;
fn optional_u32_js_identity(a: Option<u32>) -> Option<u32>; fn optional_u32_js_identity(a: Option<u32>) -> Option<u32>;

89
tests/wasm/simple.js Normal file
View File

@ -0,0 +1,89 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
exports.test_add = function() {
assert.strictEqual(wasm.simple_add(1, 2), 3);
assert.strictEqual(wasm.simple_add(2, 3), 5);
assert.strictEqual(wasm.simple_add3(2), 5);
assert.strictEqual(wasm.simple_get2(true), 2);
assert.strictEqual(wasm.simple_return_and_take_bool(true, false), false);
};
exports.test_string_arguments = function() {
wasm.simple_assert_foo("foo");
wasm.simple_assert_foo_and_bar("foo2", "bar");
};
exports.test_return_a_string = function() {
assert.strictEqual(wasm.simple_clone("foo"), "foo");
assert.strictEqual(wasm.simple_clone("another"), "another");
assert.strictEqual(wasm.simple_concat("a", "b", 3), "a b 3");
assert.strictEqual(wasm.simple_concat("c", "d", -2), "c d -2");
};
exports.test_wrong_types = function() {
// this test only works when `--debug` is passed to `wasm-bindgen` (or the
// equivalent thereof)
if (require('process').env.WASM_BINDGEN_NO_DEBUG)
return;
assert.throws(() => wasm.simple_int('a'), /expected a number argument/);
assert.throws(() => wasm.simple_str(3), /expected a string argument/);
};
exports.test_other_exports_still_available = function() {
require('wasm-bindgen-test_bg').foo(3);
};
exports.test_jsvalue_typeof = function() {
assert.ok(wasm.is_object({}));
assert.ok(!wasm.is_object(42));
assert.ok(wasm.is_function(function() {}));
assert.ok(!wasm.is_function(42));
assert.ok(wasm.is_string("2b or !2b"));
assert.ok(!wasm.is_string(42));
};
exports.optional_str_none = function(x) {
assert.strictEqual(x, undefined);
};
exports.optional_str_some = function(x) {
assert.strictEqual(x, 'x');
};
exports.optional_slice_none = function(x) {
assert.strictEqual(x, undefined);
};
exports.optional_slice_some = function(x) {
assert.strictEqual(x.length, 3);
assert.strictEqual(x[0], 1);
assert.strictEqual(x[1], 2);
assert.strictEqual(x[2], 3);
}
exports.optional_string_none = function(x) {
assert.strictEqual(x, undefined);
};
exports.optional_string_some = function(x) {
assert.strictEqual(x, 'abcd');
};
exports.optional_string_some_empty = function(x) {
assert.strictEqual(x, '');
};
exports.return_string_none = function() {};
exports.return_string_some = function() {
return 'foo';
};
exports.test_rust_optional = function() {
wasm.take_optional_str_none();
wasm.take_optional_str_none(null);
wasm.take_optional_str_none(undefined);
wasm.take_optional_str_some('hello');
assert.strictEqual(wasm.return_optional_str_none(), undefined);
assert.strictEqual(wasm.return_optional_str_some(), 'world');
};

180
tests/wasm/simple.rs Normal file
View File

@ -0,0 +1,180 @@
use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/simple.js")]
extern {
fn test_add();
fn test_string_arguments();
fn test_return_a_string();
fn test_wrong_types();
fn test_other_exports_still_available();
fn test_jsvalue_typeof();
fn optional_str_none(a: Option<&str>);
fn optional_str_some(a: Option<&str>);
fn optional_slice_none(a: Option<&[u8]>);
fn optional_slice_some(a: Option<&[u8]>);
fn optional_string_none(a: Option<String>);
fn optional_string_some(a: Option<String>);
fn optional_string_some_empty(a: Option<String>);
fn return_string_none() -> Option<String>;
fn return_string_some() -> Option<String>;
fn test_rust_optional();
}
#[wasm_bindgen_test]
fn add() {
test_add();
}
#[wasm_bindgen]
pub fn simple_add(a: u32, b: u32) -> u32 {
a + b
}
#[wasm_bindgen]
pub fn simple_add3(a: u32) -> u32 {
a + 3
}
#[wasm_bindgen]
pub fn simple_get2(_b: bool) -> u32 {
2
}
#[wasm_bindgen]
pub fn simple_return_and_take_bool(a: bool, b: bool) -> bool {
a && b
}
#[wasm_bindgen]
pub fn simple_raw_pointers_work(a: *mut u32, b: *const u8) -> *const u32 {
unsafe {
(*a) = (*b) as u32;
return a
}
}
#[wasm_bindgen_test]
fn string_arguments() {
test_string_arguments();
}
#[wasm_bindgen]
pub fn simple_assert_foo_and_bar(a: &str, b: &str) {
assert_eq!(a, "foo2");
assert_eq!(b, "bar");
}
#[wasm_bindgen]
pub fn simple_assert_foo(a: &str) {
assert_eq!(a, "foo");
}
#[wasm_bindgen_test]
fn return_a_string() {
test_return_a_string();
}
#[wasm_bindgen]
pub fn simple_clone(a: &str) -> String {
a.to_string()
}
#[wasm_bindgen]
pub fn simple_concat(a: &str, b: &str, c: i8) -> String {
format!("{} {} {}", a, b, c)
}
#[wasm_bindgen_test]
fn wrong_types() {
test_wrong_types();
}
#[wasm_bindgen]
pub fn simple_int(_a: u32) {}
#[wasm_bindgen]
pub fn simple_str(_a: &str) {}
#[wasm_bindgen_test]
fn other_exports() {
test_other_exports_still_available();
}
#[no_mangle]
pub extern fn foo(_a: u32) {
}
#[wasm_bindgen_test]
fn jsvalue_typeof() {
test_jsvalue_typeof();
}
#[wasm_bindgen]
pub fn is_object(val: &JsValue) -> bool {
val.is_object()
}
#[wasm_bindgen]
pub fn is_function(val: &JsValue) -> bool {
val.is_function()
}
#[wasm_bindgen]
pub fn is_string(val: &JsValue) -> bool {
val.is_string()
}
#[wasm_bindgen]
extern {
#[derive(Clone)]
type Array;
#[wasm_bindgen(constructor)]
fn new() -> Array;
#[wasm_bindgen(method, catch)]
fn standardized_method_this_js_runtime_doesnt_implement_yet(this: &Array)
-> Result<(), JsValue>;
}
#[wasm_bindgen_test]
fn binding_to_unimplemented_apis_doesnt_break_everything() {
let array = Array::new();
let res = array.standardized_method_this_js_runtime_doesnt_implement_yet();
assert!(res.is_err());
}
#[wasm_bindgen_test]
fn optional_slices() {
optional_str_none(None);
optional_str_some(Some("x"));
optional_slice_none(None);
optional_slice_some(Some(&[1, 2, 3]));
optional_string_none(None);
optional_string_some_empty(Some(String::new()));
optional_string_some(Some("abcd".to_string()));
assert_eq!(return_string_none(), None);
assert_eq!(return_string_some(), Some("foo".to_string()));
test_rust_optional();
}
#[wasm_bindgen]
pub fn take_optional_str_none(x: Option<String>) {
assert!(x.is_none())
}
#[wasm_bindgen]
pub fn take_optional_str_some(x: Option<String>) {
assert_eq!(x, Some(String::from("hello")));
}
#[wasm_bindgen]
pub fn return_optional_str_none() -> Option<String> {
None
}
#[wasm_bindgen]
pub fn return_optional_str_some() -> Option<String> {
Some("world".to_string())
}

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/slice.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/slice.js")]
extern { extern {
fn js_export(); fn js_export();
@ -44,7 +44,7 @@ fn export() {
macro_rules! import_macro { macro_rules! import_macro {
($(($rust:ident, $js:ident, $i:ident))*) => ($( ($(($rust:ident, $js:ident, $i:ident))*) => ($(
#[wasm_bindgen(module = "tests/wasm/slice.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/slice.js")]
extern { extern {
fn $js(a: &[$i]) -> Vec<$i>; fn $js(a: &[$i]) -> Vec<$i>;
} }
@ -105,7 +105,7 @@ fn pass_array() {
macro_rules! import_mut_macro { macro_rules! import_mut_macro {
($(($rust:ident, $js:ident, $i:ident))*) => ( ($(($rust:ident, $js:ident, $i:ident))*) => (
$( $(
#[wasm_bindgen(module = "tests/wasm/slice.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/slice.js")]
extern { extern {
fn $js(a: &mut [$i]); fn $js(a: &mut [$i]);
} }

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/structural.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/structural.js")]
extern { extern {
fn js_works(); fn js_works();
} }

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/u64.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/u64.js")]
extern { extern {
fn i64_js_identity(a: i64) -> i64; fn i64_js_identity(a: i64) -> i64;
fn u64_js_identity(a: u64) -> u64; fn u64_js_identity(a: u64) -> u64;

View File

@ -1,7 +1,7 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/validate_prt.js", version = "*")] #[wasm_bindgen(module = "tests/wasm/validate_prt.js")]
extern { extern {
fn js_works(); fn js_works();
} }

View File

@ -78,9 +78,9 @@
lodash "^4.2.0" lodash "^4.2.0"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@types/node@^10.5.5": "@types/node@^10.5.6":
version "10.5.5" version "10.5.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.5.tgz#8e84d24e896cd77b0d4f73df274027e3149ec2ba" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.6.tgz#1640f021dd0eaf12e731e54198c12ad2e020dc8e"
"@webassemblyjs/ast@1.5.13": "@webassemblyjs/ast@1.5.13":
version "1.5.13" version "1.5.13"
@ -245,9 +245,9 @@ acorn@^5.0.0, acorn@^5.0.3, acorn@^5.6.0, acorn@^5.6.2:
version "5.7.1" version "5.7.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
adm-zip@0.4.7: adm-zip@0.4.11:
version "0.4.7" version "0.4.11"
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a"
ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: ajv-keywords@^3.0.0, ajv-keywords@^3.1.0:
version "3.2.0" version "3.2.0"
@ -1267,9 +1267,9 @@ eslint-visitor-keys@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
eslint@^5.2.0: eslint@^5.3.0:
version "5.2.0" version "5.3.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.2.0.tgz#3901ae249195d473e633c4acbc370068b1c964dc" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.3.0.tgz#53695aca5213968aacdf970ccb231e42a2b285f8"
dependencies: dependencies:
ajv "^6.5.0" ajv "^6.5.0"
babel-code-frame "^6.26.0" babel-code-frame "^6.26.0"
@ -1302,7 +1302,7 @@ eslint@^5.2.0:
path-is-inside "^1.0.2" path-is-inside "^1.0.2"
pluralize "^7.0.0" pluralize "^7.0.0"
progress "^2.0.0" progress "^2.0.0"
regexpp "^1.1.0" regexpp "^2.0.0"
require-uncached "^1.0.3" require-uncached "^1.0.3"
semver "^5.5.0" semver "^5.5.0"
string.prototype.matchall "^2.0.0" string.prototype.matchall "^2.0.0"
@ -1651,11 +1651,11 @@ gauge@~2.7.3:
strip-ansi "^3.0.1" strip-ansi "^3.0.1"
wide-align "^1.1.0" wide-align "^1.1.0"
geckodriver@^1.12.0: geckodriver@^1.12.1:
version "1.12.0" version "1.12.1"
resolved "https://registry.yarnpkg.com/geckodriver/-/geckodriver-1.12.0.tgz#997a1efeca90543192fbcf1eae70d7cb2196330e" resolved "https://registry.yarnpkg.com/geckodriver/-/geckodriver-1.12.1.tgz#f3b2ecd5224f383462f07841f4fdcf5007d1b42d"
dependencies: dependencies:
adm-zip "0.4.7" adm-zip "0.4.11"
bluebird "3.4.6" bluebird "3.4.6"
got "5.6.0" got "5.6.0"
tar "4.0.2" tar "4.0.2"
@ -3271,9 +3271,9 @@ regexp.prototype.flags@^1.2.0:
dependencies: dependencies:
define-properties "^1.1.2" define-properties "^1.1.2"
regexpp@^1.1.0: regexpp@^2.0.0:
version "1.1.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.0.tgz#b2a7534a85ca1b033bcf5ce9ff8e56d4e0755365"
remove-trailing-separator@^1.0.1: remove-trailing-separator@^1.0.1:
version "1.1.0" version "1.1.0"
@ -4185,9 +4185,9 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0:
source-list-map "^2.0.0" source-list-map "^2.0.0"
source-map "~0.6.1" source-map "~0.6.1"
webpack@^4.16.4: webpack@^4.16.5:
version "4.16.4" version "4.16.5"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.16.4.tgz#6b020f76483bc66339164c296d89978aa100d37a" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.16.5.tgz#29fb39462823d7eb8aefcab8b45f7f241db0d092"
dependencies: dependencies:
"@webassemblyjs/ast" "1.5.13" "@webassemblyjs/ast" "1.5.13"
"@webassemblyjs/helper-module-context" "1.5.13" "@webassemblyjs/helper-module-context" "1.5.13"