Skip to content

Commit

Permalink
Merge pull request #887 from fitzgen/iterating-over-js-values
Browse files Browse the repository at this point in the history
Iterating over js values
  • Loading branch information
fitzgen committed Sep 25, 2018
2 parents d50e2f8 + a920656 commit ee0e4bc
Show file tree
Hide file tree
Showing 16 changed files with 431 additions and 128 deletions.
4 changes: 3 additions & 1 deletion crates/backend/src/codegen.rs
Expand Up @@ -1210,11 +1210,13 @@ impl ToTokens for ast::DictionaryField {
(quote! {
pub fn #name(&mut self, val: #ty) -> &mut Self {
use wasm_bindgen::JsValue;
::js_sys::Reflect::set(
let r = ::js_sys::Reflect::set(
self.obj.as_ref(),
&JsValue::from(stringify!(#name)),
&JsValue::from(val),
);
debug_assert!(r.is_ok(), "setting properties should never fail on our dictionary objects");
let _ = r;
self
}
}).to_tokens(tokens);
Expand Down
230 changes: 166 additions & 64 deletions crates/js-sys/src/lib.rs

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions crates/js-sys/tests/wasm/Iterator.js
@@ -0,0 +1,19 @@
exports.get_iterable = () => ["one", "two", "three"];

exports.get_not_iterable = () => new Object;

exports.get_symbol_iterator_throws = () => ({
[Symbol.iterator]: () => { throw new Error("nope"); },
});

exports.get_symbol_iterator_not_function = () => ({
[Symbol.iterator]: 5,
});

exports.get_symbol_iterator_returns_not_object = () => ({
[Symbol.iterator]: () => 5,
});

exports.get_symbol_iterator_returns_object_without_next = () => ({
[Symbol.iterator]: () => new Object,
});
36 changes: 36 additions & 0 deletions crates/js-sys/tests/wasm/Iterator.rs
@@ -0,0 +1,36 @@
use js_sys::*;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;

#[wasm_bindgen(module = "tests/wasm/Iterator.js")]
extern "C" {
fn get_iterable() -> JsValue;

fn get_not_iterable() -> JsValue;

fn get_symbol_iterator_throws() -> JsValue;

fn get_symbol_iterator_not_function() -> JsValue;

fn get_symbol_iterator_returns_not_object() -> JsValue;

fn get_symbol_iterator_returns_object_without_next() -> JsValue;
}

#[wasm_bindgen_test]
fn try_iter_handles_iteration_protocol() {
assert_eq!(
try_iter(&get_iterable())
.unwrap()
.unwrap()
.map(|x| x.unwrap().as_string().unwrap())
.collect::<Vec<_>>(),
vec!["one", "two", "three"]
);

assert!(try_iter(&get_not_iterable()).unwrap().is_none());
assert!(try_iter(&get_symbol_iterator_throws()).is_err());
assert!(try_iter(&get_symbol_iterator_not_function()).unwrap().is_none());
assert!(try_iter(&get_symbol_iterator_returns_not_object()).unwrap().is_none());
assert!(try_iter(&get_symbol_iterator_returns_object_without_next()).unwrap().is_none());
}
2 changes: 1 addition & 1 deletion crates/js-sys/tests/wasm/JSON.rs
Expand Up @@ -72,7 +72,7 @@ fn stringify() {
fn stringify_error() {
let func = Function::new_no_args("throw new Error(\"rust really rocks\")");
let obj = Object::new();
Reflect::set(obj.as_ref(), &JsValue::from("toJSON"), func.as_ref());
Reflect::set(obj.as_ref(), &JsValue::from("toJSON"), func.as_ref()).unwrap();

let result = JSON::stringify(&JsValue::from(obj));
assert!(result.is_err());
Expand Down
20 changes: 10 additions & 10 deletions crates/js-sys/tests/wasm/JsString.rs
Expand Up @@ -168,7 +168,7 @@ fn locale_compare() {
assert!(js_b.locale_compare(a, &locales, &options) < 0);

locales.push(&"en".into());
Reflect::set(options.as_ref(), &"sensitivity".into(), &"base".into());
Reflect::set(options.as_ref(), &"sensitivity".into(), &"base".into()).unwrap();

assert_eq!(js_a.locale_compare(a, &locales, &options), 0);
assert_eq!(js_a.locale_compare(b, &locales, &options), 0);
Expand Down Expand Up @@ -211,7 +211,7 @@ fn locale_compare() {
assert!(js_ten.locale_compare(two, &locales, &options) > 0);

let locales = Array::new();
Reflect::set(options.as_ref(), &"numeric".into(), &JsValue::TRUE);
Reflect::set(options.as_ref(), &"numeric".into(), &JsValue::TRUE).unwrap();

assert!(js_two.locale_compare(ten, &locales, &options) < 0);
assert!(js_ten.locale_compare(two, &locales, &options) > 0);
Expand All @@ -224,8 +224,8 @@ fn match_() {
let result = JsString::from(s).match_(&re);
let obj = result.unwrap();

assert_eq!(Reflect::get(obj.as_ref(), &"0".into()), "T");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()), "I");
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "T");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "I");

let result = JsString::from("foo").match_(&re);
assert!(result.is_none());
Expand All @@ -235,11 +235,11 @@ fn match_() {
let result = JsString::from(s).match_(&re);
let obj = result.unwrap();

assert_eq!(Reflect::get(obj.as_ref(), &"0".into()), "see Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()), "Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()), ".1");
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()), 22);
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()), s);
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "see Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()).unwrap(), ".1");
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()).unwrap(), 22);
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);
}

#[wasm_bindgen_test]
Expand Down Expand Up @@ -494,7 +494,7 @@ fn value_of() {
fn raw() {
let call_site = Object::new();
let raw = Array::of3(&"foo".into(), &"bar".into(), &"123".into());
Reflect::set(&call_site.as_ref(), &"raw".into(), &raw.into());
Reflect::set(&call_site.as_ref(), &"raw".into(), &raw.into()).unwrap();
assert_eq!(JsString::raw_2(&call_site, "5", "JavaScript").unwrap(), "foo5barJavaScript123");
let substitutions = Array::of2(&"5".into(), &"JavaScript".into());
assert_eq!(JsString::raw(&call_site, &substitutions).unwrap(), "foo5barJavaScript123");
Expand Down
4 changes: 2 additions & 2 deletions crates/js-sys/tests/wasm/MapIterator.rs
Expand Up @@ -11,8 +11,8 @@ fn entries() {
let next = entries.next().unwrap();
assert_eq!(next.done(), false);
assert!(next.value().is_object());
assert_eq!(Reflect::get(&next.value(), &0.into()), "uno");
assert_eq!(Reflect::get(&next.value(), &1.into()), 1);
assert_eq!(Reflect::get(&next.value(), &0.into()).unwrap(), "uno");
assert_eq!(Reflect::get(&next.value(), &1.into()).unwrap(), 1);

let next = entries.next().unwrap();
assert!(next.done());
Expand Down
20 changes: 10 additions & 10 deletions crates/js-sys/tests/wasm/Object.rs
Expand Up @@ -57,23 +57,23 @@ fn assign() {
let c = JsValue::from("c");

let target = Object::new();
Reflect::set(target.as_ref(), a.as_ref(), a.as_ref());
Reflect::set(target.as_ref(), a.as_ref(), a.as_ref()).unwrap();

let src1 = Object::new();
Reflect::set(src1.as_ref(), &a, &c);
Reflect::set(src1.as_ref(), &a, &c).unwrap();

let src2 = Object::new();
Reflect::set(src2.as_ref(), &b, &b);
Reflect::set(src2.as_ref(), &b, &b).unwrap();

let src3 = Object::new();
Reflect::set(src3.as_ref(), &c, &c);
Reflect::set(src3.as_ref(), &c, &c).unwrap();

let res = Object::assign3(&target, &src1, &src2, &src3);

assert!(Object::is(target.as_ref(), res.as_ref()));
assert_eq!(Reflect::get(target.as_ref(), &a), c);
assert_eq!(Reflect::get(target.as_ref(), &b), b);
assert_eq!(Reflect::get(target.as_ref(), &c), c);
assert_eq!(Reflect::get(target.as_ref(), &a).unwrap(), c);
assert_eq!(Reflect::get(target.as_ref(), &b).unwrap(), b);
assert_eq!(Reflect::get(target.as_ref(), &c).unwrap(), c);
}

#[wasm_bindgen_test]
Expand Down Expand Up @@ -102,8 +102,8 @@ fn define_properties() {
let descriptor = DefinePropertyAttrs::from(JsValue::from(Object::new()));
descriptor.set_value(&42.into());
let descriptor = JsValue::from(descriptor);
Reflect::set(props.as_ref(), &JsValue::from("bar"), &descriptor);
Reflect::set(props.as_ref(), &JsValue::from("car"), &descriptor);
Reflect::set(props.as_ref(), &JsValue::from("bar"), &descriptor).unwrap();
Reflect::set(props.as_ref(), &JsValue::from("car"), &descriptor).unwrap();
let foo = foo_42();
let foo = Object::define_properties(&foo, &props);
assert!(foo.has_own_property(&"bar".into()));
Expand Down Expand Up @@ -136,7 +136,7 @@ fn get_own_property_descriptor() {
fn get_own_property_descriptors() {
let foo = foo_42();
let descriptors = Object::get_own_property_descriptors(&foo);
let foo_desc = Reflect::get(&descriptors, &"foo".into());
let foo_desc = Reflect::get(&descriptors, &"foo".into()).unwrap();
assert_eq!(PropertyDescriptor::from(foo_desc).value(), 42);
}

Expand Down
16 changes: 16 additions & 0 deletions crates/js-sys/tests/wasm/Reflect.js
Expand Up @@ -23,3 +23,19 @@ exports.Rectangle2 = class {
return x === y;
}
};

exports.throw_all_the_time = () => new Proxy({}, {
getPrototypeOf() { throw new Error("nope"); },
setPrototypeOf() { throw new Error("nope"); },
isExtensible() { throw new Error("nope"); },
preventExtensions() { throw new Error("nope"); },
getOwnPropertyDescriptor() { throw new Error("nope"); },
defineProperty() { throw new Error("nope"); },
has() { throw new Error("nope"); },
get() { throw new Error("nope"); },
set() { throw new Error("nope"); },
deleteProperty() { throw new Error("nope"); },
ownKeys() { throw new Error("nope"); },
apply() { throw new Error("nope"); },
construct() { throw new Error("nope"); },
});

0 comments on commit ee0e4bc

Please sign in to comment.