From 01ff04d85cdd0024629019394ff202d332dc85ba Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 20 Jul 2018 15:23:56 -0700 Subject: [PATCH] Port `Object` tests to `wasm` --- crates/js-sys/src/lib.rs | 12 +- crates/js-sys/tests/all/Object.rs | 522 ----------------------------- crates/js-sys/tests/all/main.rs | 1 - crates/js-sys/tests/wasm/Object.js | 11 + crates/js-sys/tests/wasm/Object.rs | 129 +++++++ crates/js-sys/tests/wasm/main.rs | 1 + 6 files changed, 152 insertions(+), 524 deletions(-) delete mode 100644 crates/js-sys/tests/all/Object.rs create mode 100644 crates/js-sys/tests/wasm/Object.js create mode 100644 crates/js-sys/tests/wasm/Object.rs diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index 1a28826f..14d7215a 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -1603,6 +1603,16 @@ extern "C" { extern "C" { pub type Object; + /// The `Object.freeze()` method freezes an object: that is, prevents new + /// properties from being added to it; prevents existing properties from + /// being removed; and prevents existing properties, or their enumerability, + /// configurability, or writability, from being changed, it also prevents + /// the prototype from being changed. The method returns the passed object. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze + #[wasm_bindgen(static_method_of = Object)] + pub fn freeze(value: &Object) -> Object; + /// The `hasOwnProperty()` method returns a boolean indicating whether the /// object has the specified property as its own property (as opposed to /// inheriting it). @@ -1672,7 +1682,7 @@ extern "C" { /// /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal #[wasm_bindgen(static_method_of = Object)] - pub fn seal(value: &JsValue) -> JsValue; + pub fn seal(value: &Object) -> Object; /// The `Object.setPrototypeOf()` method sets the prototype (i.e., the /// internal `[[Prototype]]` property) of a specified object to another diff --git a/crates/js-sys/tests/all/Object.rs b/crates/js-sys/tests/all/Object.rs deleted file mode 100644 index 970d31fd..00000000 --- a/crates/js-sys/tests/all/Object.rs +++ /dev/null @@ -1,522 +0,0 @@ -#![allow(non_snake_case)] - -use project; - -#[test] -fn new() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn new_object() -> js_sys::Object { - js_sys::Object::new() - } - "#, - ) - .file( - "test.js", - 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(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn has_own_foo_property(obj: &js_sys::Object, property: &JsValue) -> bool { - obj.has_own_property(&property) - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - assert.ok(wasm.has_own_foo_property({ foo: 42 }, "foo")); - assert.ok(wasm.has_own_foo_property({ 42: "foo" }, 42)); - assert.ok(!wasm.has_own_foo_property({ foo: 42 }, "bar")); - - const s = Symbol(); - assert.ok(wasm.has_own_foo_property({ [s]: "foo" }, s)); - } - "#, - ) - .test() -} - -#[test] -fn to_string() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn to_string(obj: &js_sys::Object) -> js_sys::JsString { - obj.to_string() - } - - #[wasm_bindgen] - pub fn test() { - let object = js_sys::Object::new(); - assert_eq!(String::from(object.to_string()), "[object Object]"); - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - assert.equal(wasm.to_string({ foo: 42 }), "[object Object]"); - wasm.test(); - } - "#, - ) - .test() -} - -#[test] -fn is_extensible() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn is_extensible(obj: &js_sys::Object) -> bool { - js_sys::Object::is_extensible(&obj) - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = {}; - assert.ok(wasm.is_extensible(object)); - - Object.preventExtensions(object); - assert.ok(!wasm.is_extensible(object)); - } - "#) - .test() -} - -#[test] -fn is_frozen() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn is_frozen(obj: &js_sys::Object) -> bool { - js_sys::Object::is_frozen(&obj) - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = {}; - assert.ok(!wasm.is_frozen(object)); - - Object.freeze(object); - assert.ok(wasm.is_frozen(object)); - } - "#) - .test() -} - -#[test] -fn is_sealed() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn is_sealed(obj: &js_sys::Object) -> bool { - js_sys::Object::is_sealed(&obj) - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = {}; - assert.ok(!wasm.is_sealed(object)); - - Object.seal(object); - assert.ok(wasm.is_sealed(object)); - } - "#) - .test() -} - -#[test] -fn is_prototype_of() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn obj_is_prototype_of_value(obj: &js_sys::Object, value: &JsValue) -> bool { - obj.is_prototype_of(&value) - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - class Foo {} - class Bar {} - - export function test() { - const foo = new Foo(); - assert.ok(wasm.obj_is_prototype_of_value(Foo.prototype, foo)); - assert.ok(!wasm.obj_is_prototype_of_value(Bar.prototype, foo)); - } - "#, - ) - .test() -} - -#[test] -fn keys() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn keys(obj: &js_sys::Object) -> js_sys::Array { - js_sys::Object::keys(obj) - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const obj = { a: 1, b: 2, c: 3 }; - assert.deepStrictEqual(wasm.keys(obj), ["a", "b", "c"]); - } - "#, - ) - .test() -} - -#[test] -fn prevent_extensions() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn prevent_extensions(obj: &js_sys::Object) { - js_sys::Object::prevent_extensions(obj); - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = {}; - wasm.prevent_extensions(object); - - assert.ok(!Object.isExtensible(object)); - assert.throws(() => { - 'use strict'; - Object.defineProperty(object, 'foo', { value: 42 }); - }, TypeError); - } - "#) - .test() -} - -#[test] -fn property_is_enumerable() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn property_is_enumerable(obj: &js_sys::Object, property: &JsValue) -> bool { - obj.property_is_enumerable(&property) - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - assert.ok(wasm.property_is_enumerable({ foo: 42 }, "foo")); - assert.ok(wasm.property_is_enumerable({ 42: "foo" }, 42)); - assert.ok(!wasm.property_is_enumerable({}, 42)); - - const obj = {}; - Object.defineProperty(obj, "foo", { enumerable: false }); - assert.ok(!wasm.property_is_enumerable(obj, "foo")); - - const s = Symbol(); - assert.ok(wasm.property_is_enumerable({ [s]: true }, s)); - } - "#, - ) - .test() -} - -#[test] -fn seal() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn seal(value: &JsValue) -> JsValue { - js_sys::Object::seal(&value) - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = { foo: 'bar' }; - const sealedObject = wasm.seal(object); - assert.strictEqual(object, sealedObject); - assert.throws(() => { - 'use strict'; - sealedObject.bar = 'foo'; - }, TypeError); - assert.throws(() => { - 'use strict'; - delete sealedObject.foo; - }, TypeError); - - const primitive = 42; - assert.doesNotThrow(() => { - 'use strict'; - // according to ES2015, this should not throw anymore - // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal#Notes - wasm.seal(primitive); - }); - - const array = [1, 2, 3]; - const sealedArray = wasm.seal(array); - assert.throws(() => { - 'use strict'; - sealedArray.push(42); - }, TypeError); - } - "#) - .test() -} - -#[test] -fn set_prototype_of() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn set_prototype_of(object: &js_sys::Object, prototype: &js_sys::Object) -> js_sys::Object { - js_sys::Object::set_prototype_of(&object, &prototype) - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = { foo: 42 }; - const newPrototype = { bar: 'baz' }; - - const modifiedObject = wasm.set_prototype_of(object, newPrototype); - assert.ok(newPrototype.isPrototypeOf(modifiedObject)); - } - "#) - .test() -} - -#[test] -fn to_locale_string() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn to_locale_string() -> js_sys::JsString { - let object = js_sys::Object::new(); - object.to_locale_string() - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - assert.equal(wasm.to_locale_string(), "[object Object]"); - } - "#, - ) - .test() -} - -#[test] -fn value_of() { - project() - .file( - "src/lib.rs", - r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn value_of(obj: &js_sys::Object) -> js_sys::Object { - obj.value_of() - } - "#, - ) - .file( - "test.js", - r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const obj = { foo: 42 }; - assert.strictEqual(wasm.value_of(obj), obj); - assert.notStrictEqual(wasm.value_of(obj), { foo: 42 }); - } - "#, - ) - .test() -} - -#[test] -fn values() { - project() - .file("src/lib.rs", r#" - #![feature(use_extern_macros)] - - extern crate wasm_bindgen; - extern crate js_sys; - use wasm_bindgen::prelude::*; - - #[wasm_bindgen] - pub fn values(obj: &js_sys::Object) -> js_sys::Array { - js_sys::Object::values(&obj) - } - "#) - .file("test.js", r#" - import * as assert from "assert"; - import * as wasm from "./out"; - - export function test() { - const object = { foo: 'bar', baz: 'qux' }; - const values = wasm.values(object); - assert.equal(values.length, 2); - assert.deepEqual(values.sort(), ['bar', 'qux']); - } - "#) - .test() -} diff --git a/crates/js-sys/tests/all/main.rs b/crates/js-sys/tests/all/main.rs index a6c78ed2..1c55acfe 100644 --- a/crates/js-sys/tests/all/main.rs +++ b/crates/js-sys/tests/all/main.rs @@ -11,7 +11,6 @@ fn project() -> project_builder::Project { // Keep these tests in alphabetical order, just like the imports in `src/js.rs`. mod ArrayIterator; -mod Object; mod Proxy; mod Reflect; mod Set; diff --git a/crates/js-sys/tests/wasm/Object.js b/crates/js-sys/tests/wasm/Object.js new file mode 100644 index 00000000..3f82fc9b --- /dev/null +++ b/crates/js-sys/tests/wasm/Object.js @@ -0,0 +1,11 @@ +const symbol_key = Symbol(); + +exports.map_with_symbol_key = function() { + return { [symbol_key]: 42 }; +}; +exports.symbol_key = function() { + return symbol_key; +}; + +exports.Foo = class {}; +exports.Bar = class {}; diff --git a/crates/js-sys/tests/wasm/Object.rs b/crates/js-sys/tests/wasm/Object.rs new file mode 100644 index 00000000..69f0d2e5 --- /dev/null +++ b/crates/js-sys/tests/wasm/Object.rs @@ -0,0 +1,129 @@ +use wasm_bindgen::prelude::*; +use wasm_bindgen_test::*; +use js_sys::*; + +#[wasm_bindgen] +extern { + type Foo42; + #[wasm_bindgen(method, setter, structural)] + fn set_foo(this: &Foo42, val: JsValue); +} + +#[wasm_bindgen(module = "tests/wasm/Object.js", version = "*")] +extern { + fn map_with_symbol_key() -> Object; + fn symbol_key() -> JsValue; + + type Foo; + #[wasm_bindgen(constructor)] + fn new() -> Foo; + + #[wasm_bindgen(js_name = prototype, js_namespace = Foo)] + static FOO_PROTOTYPE: Object; + #[wasm_bindgen(js_name = prototype, js_namespace = Bar)] + static BAR_PROTOTYPE: Object; +} + +fn foo_42() -> Object { + let foo = Foo42::from(JsValue::from(Object::new())); + foo.set_foo(42.into()); + JsValue::from(foo).into() +} + +#[wasm_bindgen_test] +fn new() { + assert!(JsValue::from(Object::new()).is_object()); +} + +#[wasm_bindgen_test] +fn has_own_property() { + assert!(foo_42().has_own_property(&"foo".into())); + assert!(!foo_42().has_own_property(&"bar".into())); + assert!(map_with_symbol_key().has_own_property(&symbol_key())); +} + +#[wasm_bindgen_test] +fn to_string() { + assert_eq!(Object::new().to_string(), "[object Object]"); + assert_eq!(foo_42().to_string(), "[object Object]"); +} + +#[wasm_bindgen_test] +fn is_extensible() { + let object = Object::new(); + assert!(Object::is_extensible(&object)); + Object::prevent_extensions(&object); + assert!(!Object::is_extensible(&object)); +} + +#[wasm_bindgen_test] +fn is_frozen() { + let object = Object::new(); + assert!(!Object::is_frozen(&object)); + Object::freeze(&object); + assert!(Object::is_frozen(&object)); +} + +#[wasm_bindgen_test] +fn is_sealed() { + let object = Object::new(); + assert!(!Object::is_sealed(&object)); + Object::seal(&object); + assert!(Object::is_sealed(&object)); +} + +#[wasm_bindgen_test] +fn is_prototype_of() { + let foo = JsValue::from(Foo::new()); + assert!(FOO_PROTOTYPE.is_prototype_of(&foo)); + assert!(!BAR_PROTOTYPE.is_prototype_of(&foo)); +} + +#[wasm_bindgen_test] +fn keys() { + let keys = Object::keys(&foo_42()); + assert_eq!(keys.length(), 1); + keys.for_each(&mut |x, _, _| { + assert_eq!(x, "foo"); + }); +} + +#[wasm_bindgen_test] +fn values() { + let values = Object::values(&foo_42()); + assert_eq!(values.length(), 1); + values.for_each(&mut |x, _, _| { + assert_eq!(x, 42); + }); +} + +#[wasm_bindgen_test] +fn property_is_enumerable() { + assert!(foo_42().property_is_enumerable(&"foo".into())); + assert!(!foo_42().property_is_enumerable(&42.into())); + assert!(!Object::new().property_is_enumerable(&"foo".into())); +} + +#[wasm_bindgen_test] +fn set_prototype_of() { + let a = foo_42(); + let b = foo_42(); + Object::set_prototype_of(&a, &b); + assert!(b.is_prototype_of(&a.into())); +} + +#[wasm_bindgen_test] +fn to_locale_string() { + assert_eq!(Object::new().to_locale_string(), "[object Object]"); +} + +#[wasm_bindgen_test] +fn value_of() { + let a = JsValue::from(foo_42()); + let b = JsValue::from(foo_42()); + let a2 = JsValue::from(Object::from(a.clone()).value_of()); + assert_eq!(a, a); + assert_eq!(a, a2); + assert_ne!(a, b); + assert_ne!(a2, b); +} diff --git a/crates/js-sys/tests/wasm/main.rs b/crates/js-sys/tests/wasm/main.rs index 0f1a0c46..b02c738f 100644 --- a/crates/js-sys/tests/wasm/main.rs +++ b/crates/js-sys/tests/wasm/main.rs @@ -21,3 +21,4 @@ pub mod Map; pub mod MapIterator; pub mod Math; pub mod Number; +pub mod Object;