From e4dcb8f85e226161f466c50b003c875dee5263ca Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 8 Jun 2018 14:22:18 -0700 Subject: [PATCH 1/6] Add associated constants for common JS values --- src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 055e7e3b..5905adc9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,18 @@ const JSIDX_FALSE: u32 = 6; const JSIDX_RESERVED: u32 = 8; impl JsValue { + /// The `null` JS value constant. + pub const NULL: JsValue = JsValue { idx: JSIDX_NULL }; + + /// The `undefined` JS value constant. + pub const UNDEFINED: JsValue = JsValue { idx: JSIDX_UNDEFINED }; + + /// The `true` JS value constant. + pub const TRUE: JsValue = JsValue { idx: JSIDX_TRUE }; + + /// The `false` JS value constant. + pub const FALSE: JsValue = JsValue { idx: JSIDX_FALSE }; + /// Creates a new JS value which is a string. /// /// The utf-8 string provided is copied to the JS heap and the string will From 132103eb065919ce71c8578d592e83e30a77d5d3 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 18 Jun 2018 13:48:57 -0700 Subject: [PATCH 2/6] cli-support: Ignore missing descriptor functions This can happen when a nested dependency crate exports things but the root crate doesn't use them. In these cases, it is fine to ignore the missing descriptor, because the thing it describes was removed as dead code. --- crates/cli-support/src/js/mod.rs | 31 +++++++++++++++++++++++-------- crates/cli-support/src/lib.rs | 19 ++++++++++++++----- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 9b8f1f60..d5e7a782 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -29,7 +29,7 @@ pub struct Context<'a> { pub imported_names: HashSet, pub exported_classes: HashMap, pub function_table_needed: bool, - pub run_descriptor: &'a Fn(&str) -> Vec, + pub run_descriptor: &'a Fn(&str) -> Option>, pub module_versions: Vec<(String, String)>, } @@ -474,7 +474,10 @@ impl<'a> Context<'a> { for field in class.fields.iter() { let wasm_getter = shared::struct_field_get(name, &field.name); let wasm_setter = shared::struct_field_set(name, &field.name); - let descriptor = self.describe(&wasm_getter); + let descriptor = match self.describe(&wasm_getter) { + None => continue, + Some(d) => d, + }; let set = { let mut cx = Js2Rust::new(&field.name, self); @@ -1393,10 +1396,9 @@ impl<'a> Context<'a> { Ok(()) } - fn describe(&self, name: &str) -> Descriptor { + fn describe(&self, name: &str) -> Option { let name = format!("__wbindgen_describe_{}", name); - let ret = (self.run_descriptor)(&name); - Descriptor::decode(&ret) + (self.run_descriptor)(&name).map(|d| Descriptor::decode(&d)) } fn global(&mut self, s: &str) { @@ -1474,7 +1476,12 @@ impl<'a, 'b> SubContext<'a, 'b> { if let Some(ref class) = export.class { return self.generate_export_for_class(class, export); } - let descriptor = self.cx.describe(&export.function.name); + + let descriptor = match self.cx.describe(&export.function.name) { + None => return Ok(()), + Some(d) => d, + }; + let (js, ts) = Js2Rust::new(&export.function.name, self.cx) .process(descriptor.unwrap_function())? .finish("function", &format!("wasm.{}", export.function.name)); @@ -1492,7 +1499,12 @@ impl<'a, 'b> SubContext<'a, 'b> { export: &shared::Export, ) -> Result<(), Error> { let wasm_name = shared::struct_function_export_name(class_name, &export.function.name); - let descriptor = self.cx.describe(&wasm_name); + + let descriptor = match self.cx.describe(&wasm_name) { + None => return Ok(()), + Some(d) => d, + }; + let (js, ts) = Js2Rust::new(&export.function.name, self.cx) .method(export.method) .process(descriptor.unwrap_function())? @@ -1603,7 +1615,10 @@ impl<'a, 'b> SubContext<'a, 'b> { import: &shared::ImportFunction) -> Result<(), Error> { - let descriptor = self.cx.describe(&import.shim); + let descriptor = match self.cx.describe(&import.shim) { + None => return Ok(()), + Some(d) => d, + }; let target = match import.class { Some(ref class) if import.js_new => { diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index 8f80a087..092f8f2c 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -140,11 +140,19 @@ impl Bindgen { module_versions: Default::default(), run_descriptor: &|name| { let mut v = MyExternals(Vec::new()); - let ret = instance - .invoke_export(name, &[], &mut v) - .expect("failed to run export"); - assert!(ret.is_none()); - v.0 + match instance.invoke_export(name, &[], &mut v) { + Ok(None) => Some(v.0), + Ok(Some(_)) => { + unreachable!( + "there is only one export, and we only return None from it" + ) + }, + // Allow missing exported describe functions. This can + // happen when a nested dependency crate exports things + // but the root crate doesn't use them. + Err(wasmi::Error::Function(_)) => None, + Err(e) => panic!("unexpected error running descriptor: {}", e), + } }, }; for program in programs.iter() { @@ -342,6 +350,7 @@ impl wasmi::ImportResolver for MyResolver { } struct MyExternals(Vec); + #[derive(Debug)] struct MyError(String); From 161fce9d509f6bc66781c68957af74ee98cf275f Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 8 Jun 2018 16:46:51 -0700 Subject: [PATCH 3/6] Expose objects and functions from the JavaScript global scope These are bindings to JavaScript's standard, built-in objects and their methods and properties. This does *not* include any Web, Node, or any other JS environment APIs. Only the things that are guaranteed to exist in the global scope by the ECMAScript standard. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects --- Cargo.toml | 3 +- src/js.rs | 88 +++++++++++++++++++++++ src/lib.rs | 8 +++ tests/all/js_globals.rs | 150 ++++++++++++++++++++++++++++++++++++++++ tests/all/main.rs | 1 + 5 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/js.rs create mode 100644 tests/all/js_globals.rs diff --git a/Cargo.toml b/Cargo.toml index 7cd2b5e8..40ff56ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,8 @@ test = false doctest = false [features] -default = ["spans", "std"] +default = ["spans", "std", "js_globals"] +js_globals = [] spans = ["wasm-bindgen-macro/spans"] std = [] serde-serialize = ["serde", "serde_json", "std"] diff --git a/src/js.rs b/src/js.rs new file mode 100644 index 00000000..98e57928 --- /dev/null +++ b/src/js.rs @@ -0,0 +1,88 @@ +//! Bindings to JavaScript's standard, built-in objects, including their methods +//! and properties. +//! +//! This does *not* include any Web, Node, or any other JS environment +//! APIs. Only the things that are guaranteed to exist in the global scope by +//! the ECMAScript standard. +//! +//! https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects +//! +//! ## A Note About `camelCase`, `snake_case`, and Naming Conventions +//! +//! JavaScript's global objects use `camelCase` naming conventions for functions +//! and methods, but Rust style is to use `snake_case`. These bindings expose +//! the Rust style `snake_case` name. Additionally, acronyms within a method +//! name are all lower case, where as in JavaScript they are all upper case. For +//! example, `decodeURI` in JavaScript is exposed as `decode_uri` in these +//! bindings. + +use wasm_bindgen_macro::*; +use JsValue; +if_std! { + use std::prelude::v1::*; +} + +// When adding new imports: +// +// * Keep imports in alphabetical order. +// +// * Rename imports with `js_name = ...` according to the note about `camelCase` +// and `snake_case` in the module's documentation above. +// +// * Include the one sentence summary of the import from the MDN link in the +// module's documentation above, and the MDN link itself. +// +// * If a function or method can throw an exception, make it catchable by adding +// `#[wasm_bindgen(catch)]`. +// +// * Add a new `#[test]` to the `tests/all/js_globals.rs` file. If the imported +// function or method can throw an exception, make sure to also add test +// coverage for that case. + +#[wasm_bindgen] +extern { + /// The `decodeURI()` function decodes a Uniform Resource Identifier (URI) + /// previously created by `encodeURI` or by a similar routine. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI + #[cfg(feature = "std")] + #[wasm_bindgen(catch, js_name = decodeURI)] + pub fn decode_uri(encoded: &str) -> Result; + + /// The `encodeURI()` function encodes a Uniform Resource Identifier (URI) + /// by replacing each instance of certain characters by one, two, three, or + /// four escape sequences representing the UTF-8 encoding of the character + /// (will only be four escape sequences for characters composed of two + /// "surrogate" characters). + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI + #[cfg(feature = "std")] + #[wasm_bindgen(js_name = encodeURI)] + pub fn encode_uri(decoded: &str) -> String; + + /// The `eval()` function evaluates JavaScript code represented as a string. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval + #[wasm_bindgen(catch)] + pub fn eval(js_source_text: &str) -> Result; +} + +// Object. +#[wasm_bindgen] +extern { + pub type Object; + + /// The Object constructor creates an object wrapper. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object + #[wasm_bindgen(constructor)] + pub fn new() -> Object; + + /// The `hasOwnProperty()` method returns a boolean indicating whether the + /// object has the specified property as its own property (as opposed to + /// inheriting it). + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty + #[wasm_bindgen(method, js_name = hasOwnProperty)] + pub fn has_own_property(this: &Object, property: &str) -> bool; +} diff --git a/src/lib.rs b/src/lib.rs index 5905adc9..c1f3b266 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ //! interface. #![feature(use_extern_macros, wasm_import_module, try_reserve, unsize)] +#![cfg_attr(feature = "js_globals", feature(proc_macro, wasm_custom_section))] #![no_std] #[cfg(feature = "serde-serialize")] @@ -43,6 +44,13 @@ pub mod prelude { pub mod convert; pub mod describe; +#[cfg(feature = "js_globals")] +pub mod js; + +#[cfg(feature = "js_globals")] +mod wasm_bindgen { + pub use super::*; +} if_std! { extern crate std; diff --git a/tests/all/js_globals.rs b/tests/all/js_globals.rs new file mode 100644 index 00000000..1fc65992 --- /dev/null +++ b/tests/all/js_globals.rs @@ -0,0 +1,150 @@ +// Keep these tests in alphabetical order, just like the imports in `src/js.rs`. + +use super::project; + +#[test] +#[cfg(feature = "std")] +fn decode_uri() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn test() { + let x = js::decode_uri("https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B") + .ok() + .expect("should decode URI OK"); + assert_eq!(x, "https://mozilla.org/?x=шеллы"); + + assert!(js::decode_uri("%E0%A4%A").is_err()); + } + "#) + .file("test.ts", r#" + import * as wasm from "./out"; + + export function test() { + wasm.test(); + } + "#) + .test(); +} + +#[test] +#[cfg(feature = "std")] +fn encode_uri() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn test() { + let x = js::encode_uri("ABC abc 123"); + assert_eq!(x, "ABC%20abc%20123"); + } + "#) + .file("test.ts", r#" + import * as wasm from "./out"; + + export function test() { + wasm.test(); + } + "#) + .test(); +} + +#[test] +fn eval() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn test() { + let x = js::eval("42").ok().expect("should eval OK"); + assert_eq!(x.as_f64().unwrap(), 42.0); + + let err = js::eval("(function () { throw 42; }())") + .err() + .expect("eval should throw"); + assert_eq!(err.as_f64().unwrap(), 42.0); + } + "#) + .file("test.ts", r#" + import * as wasm from "./out"; + + export function test() { + wasm.test(); + } + "#) + .test(); +} + +#[allow(non_snake_case)] +mod Object { + use project; + + #[test] + fn new() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn new_object() -> js::Object { + js::Object::new() + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + assert.equal(typeof wasm.new_object(), "object"); + } + "#) + .test() + } + + #[test] + fn has_own_property() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn has_own_foo_property(obj: &js::Object) -> bool { + obj.has_own_property("foo") + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + assert.ok(wasm.has_own_foo_property({ foo: 42 })); + assert.ok(!wasm.has_own_foo_property({})); + } + "#) + .test() + } +} diff --git a/tests/all/main.rs b/tests/all/main.rs index b909788a..4f88bad8 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -528,6 +528,7 @@ mod enums; mod import_class; mod imports; mod jsobjects; +#[cfg(feature = "js_globals")] mod js_globals; mod math; mod node; mod non_debug; From d9cac3bd906dbd8db9276318ac1c6ad96cbe671d Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 18 Jun 2018 15:30:29 -0700 Subject: [PATCH 4/6] Don't document descriptor functions They aren't part of any public API, and are just an implementation detail of wasm-bindgen. --- crates/backend/src/codegen.rs | 3 +++ crates/webidl/tests/expected/Event.rs | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 96275b82..f95a33b6 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -266,6 +266,7 @@ impl ToTokens for ast::StructField { } #[no_mangle] + #[doc(hidden)] pub extern fn #desc() { use wasm_bindgen::describe::*; <#ty as WasmDescribe>::describe(); @@ -445,6 +446,7 @@ impl ToTokens for ast::Export { // binary along with anything it references. #[no_mangle] #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] + #[doc(hidden)] pub extern fn #descriptor_name() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -726,6 +728,7 @@ impl<'a> ToTokens for DescribeImport<'a> { (quote! { #[no_mangle] #[allow(non_snake_case)] + #[doc(hidden)] pub extern fn #describe_name() { use wasm_bindgen::describe::*; inform(FUNCTION); diff --git a/crates/webidl/tests/expected/Event.rs b/crates/webidl/tests/expected/Event.rs index 51807c4d..2bcf0b3f 100644 --- a/crates/webidl/tests/expected/Event.rs +++ b/crates/webidl/tests/expected/Event.rs @@ -55,6 +55,7 @@ impl From for ::wasm_bindgen::JsValue { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_new_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -104,6 +105,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_event_phase_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -147,6 +149,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_stop_propagation_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -186,6 +189,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_stop_immediate_propagation_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -225,6 +229,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_bubbles_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -268,6 +273,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_cancelable_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -311,6 +317,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_prevent_default_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -350,6 +357,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_default_prevented_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -393,6 +401,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_default_prevented_by_chrome_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -436,6 +445,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_default_prevented_by_content_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -479,6 +489,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_composed_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -522,6 +533,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_is_trusted_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -565,6 +577,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_time_stamp_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -608,6 +621,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_init_event_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -661,6 +675,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_cancel_bubble_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -704,6 +719,7 @@ impl Event { } #[no_mangle] #[allow(non_snake_case)] +#[doc(hidden)] pub extern "C" fn __wbindgen_describe___widl_f_set_cancel_bubble_Event() { use wasm_bindgen::describe::*; inform(FUNCTION); @@ -753,4 +769,4 @@ pub type DOMHighResTimeStamp = f64; pub type EventInit = bool; #[allow(non_upper_case_globals)] #[wasm_custom_section = "__wasm_bindgen_unstable"] -const __WASM_BINDGEN_GENERATED_wasm_bindgen_webidl_0_2_11_0 : [ u8 ; 4451usize ] = * b"_\x11\0\0{\"exports\":[],\"enums\":[],\"imports\":[{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"type\"}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_new_Event\",\"catch\":false,\"method\":false,\"js_new\":true,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"new\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_event_phase_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"eventPhase\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"eventPhase\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_stop_propagation_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"stopPropagation\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_stop_immediate_propagation_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"stopImmediatePropagation\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_bubbles_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"bubbles\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"bubbles\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_cancelable_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"cancelable\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"cancelable\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_prevent_default_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"preventDefault\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_default_prevented_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"defaultPrevented\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"defaultPrevented\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_default_prevented_by_chrome_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"defaultPreventedByChrome\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"defaultPreventedByChrome\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_default_prevented_by_content_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"defaultPreventedByContent\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"defaultPreventedByContent\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_composed_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"composed\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"composed\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_is_trusted_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"isTrusted\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"isTrusted\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_time_stamp_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"timeStamp\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"timeStamp\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_init_event_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"initEvent\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_cancel_bubble_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"cancelBubble\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"cancelBubble\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_set_cancel_bubble_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":\"cancelBubble\",\"class\":\"Event\",\"function\":{\"name\":\"set_CancelBubble\"}}}],\"structs\":[],\"version\":\"0.2.11 (0cd767c9d)\",\"schema_version\":\"4\"}" ; +const __WASM_BINDGEN_GENERATED_wasm_bindgen_webidl_0_2_11_0 : [ u8 ; 4451usize ] = * b"_\x11\0\0{\"exports\":[],\"enums\":[],\"imports\":[{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"type\"}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_new_Event\",\"catch\":false,\"method\":false,\"js_new\":true,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"new\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_event_phase_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"eventPhase\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"eventPhase\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_stop_propagation_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"stopPropagation\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_stop_immediate_propagation_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"stopImmediatePropagation\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_bubbles_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"bubbles\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"bubbles\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_cancelable_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"cancelable\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"cancelable\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_prevent_default_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"preventDefault\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_default_prevented_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"defaultPrevented\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"defaultPrevented\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_default_prevented_by_chrome_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"defaultPreventedByChrome\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"defaultPreventedByChrome\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_default_prevented_by_content_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"defaultPreventedByContent\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"defaultPreventedByContent\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_composed_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"composed\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"composed\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_is_trusted_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"isTrusted\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"isTrusted\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_time_stamp_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"timeStamp\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"timeStamp\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_init_event_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"initEvent\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_cancel_bubble_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":\"cancelBubble\",\"setter\":null,\"class\":\"Event\",\"function\":{\"name\":\"cancelBubble\"}}},{\"module\":null,\"version\":null,\"js_namespace\":null,\"kind\":{\"kind\":\"function\",\"shim\":\"__widl_f_set_cancel_bubble_Event\",\"catch\":false,\"method\":true,\"js_new\":false,\"structural\":false,\"getter\":null,\"setter\":\"cancelBubble\",\"class\":\"Event\",\"function\":{\"name\":\"set_CancelBubble\"}}}],\"structs\":[],\"version\":\"0.2.11 (161fce9d5)\",\"schema_version\":\"4\"}" ; From a201cafdeaafe03cdb732cf07e6edbb4a6e38c7b Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 19 Jun 2018 10:15:09 -0700 Subject: [PATCH 5/6] test: Move `Object`-related js_globals tests to submodule file --- tests/all/js_globals/Object.rs | 56 +++++++++++++++++ .../all/{js_globals.rs => js_globals/mod.rs} | 60 +------------------ 2 files changed, 58 insertions(+), 58 deletions(-) create mode 100755 tests/all/js_globals/Object.rs rename tests/all/{js_globals.rs => js_globals/mod.rs} (62%) diff --git a/tests/all/js_globals/Object.rs b/tests/all/js_globals/Object.rs new file mode 100755 index 00000000..0c2f8311 --- /dev/null +++ b/tests/all/js_globals/Object.rs @@ -0,0 +1,56 @@ +#![allow(non_snake_case)] + +use project; + +#[test] +fn new() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn new_object() -> js::Object { + js::Object::new() + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + assert.equal(typeof wasm.new_object(), "object"); + } + "#) + .test() +} + +#[test] +fn has_own_property() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn has_own_foo_property(obj: &js::Object) -> bool { + obj.has_own_property("foo") + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + assert.ok(wasm.has_own_foo_property({ foo: 42 })); + assert.ok(!wasm.has_own_foo_property({})); + } + "#) + .test() +} diff --git a/tests/all/js_globals.rs b/tests/all/js_globals/mod.rs similarity index 62% rename from tests/all/js_globals.rs rename to tests/all/js_globals/mod.rs index 1fc65992..5c41ea6c 100644 --- a/tests/all/js_globals.rs +++ b/tests/all/js_globals/mod.rs @@ -2,6 +2,8 @@ use super::project; +mod Object; + #[test] #[cfg(feature = "std")] fn decode_uri() { @@ -90,61 +92,3 @@ fn eval() { "#) .test(); } - -#[allow(non_snake_case)] -mod Object { - use project; - - #[test] - fn new() { - project() - .file("src/lib.rs", r#" - #![feature(proc_macro, wasm_custom_section)] - - extern crate wasm_bindgen; - use wasm_bindgen::prelude::*; - use wasm_bindgen::js; - - #[wasm_bindgen] - pub fn new_object() -> js::Object { - js::Object::new() - } - "#) - .file("test.ts", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - assert.equal(typeof wasm.new_object(), "object"); - } - "#) - .test() - } - - #[test] - fn has_own_property() { - project() - .file("src/lib.rs", r#" - #![feature(proc_macro, wasm_custom_section)] - - extern crate wasm_bindgen; - use wasm_bindgen::prelude::*; - use wasm_bindgen::js; - - #[wasm_bindgen] - pub fn has_own_foo_property(obj: &js::Object) -> bool { - obj.has_own_property("foo") - } - "#) - .file("test.ts", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - assert.ok(wasm.has_own_foo_property({ foo: 42 })); - assert.ok(!wasm.has_own_foo_property({})); - } - "#) - .test() - } -} From 7b0e779ffde04046ec5b69b00baee242b47fd25b Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 19 Jun 2018 10:17:42 -0700 Subject: [PATCH 6/6] test: remove unnecessary `test.ts` files The testing infrastructure will add exactly this default `test.ts` when it isn't explicitly specified. --- tests/all/js_globals/mod.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/tests/all/js_globals/mod.rs b/tests/all/js_globals/mod.rs index 5c41ea6c..a7eaaeeb 100644 --- a/tests/all/js_globals/mod.rs +++ b/tests/all/js_globals/mod.rs @@ -25,13 +25,6 @@ fn decode_uri() { assert!(js::decode_uri("%E0%A4%A").is_err()); } "#) - .file("test.ts", r#" - import * as wasm from "./out"; - - export function test() { - wasm.test(); - } - "#) .test(); } @@ -52,13 +45,6 @@ fn encode_uri() { assert_eq!(x, "ABC%20abc%20123"); } "#) - .file("test.ts", r#" - import * as wasm from "./out"; - - export function test() { - wasm.test(); - } - "#) .test(); } @@ -83,12 +69,5 @@ fn eval() { assert_eq!(err.as_f64().unwrap(), 42.0); } "#) - .file("test.ts", r#" - import * as wasm from "./out"; - - export function test() { - wasm.test(); - } - "#) .test(); }