1 use js_sys::*;
2 use std::f64::NAN;
3 use wasm_bindgen::prelude::*;
4 use wasm_bindgen::JsCast;
5 use wasm_bindgen_test::*;
6
7 #[wasm_bindgen]
8 extern "C" {
9 type Foo42;
10 #[wasm_bindgen(method, setter, structural)]
set_foo(this: &Foo42, val: JsValue)11 fn set_foo(this: &Foo42, val: JsValue);
12
13 #[wasm_bindgen(js_name = prototype, js_namespace = Object)]
14 static OBJECT_PROTOTYPE: JsValue;
15 #[wasm_bindgen(js_name = prototype, js_namespace = Array)]
16 static ARRAY_PROTOTYPE: JsValue;
17
18 type DefinePropertyAttrs;
19 #[wasm_bindgen(method, setter, structural)]
set_value(this: &DefinePropertyAttrs, val: &JsValue)20 fn set_value(this: &DefinePropertyAttrs, val: &JsValue);
21
22 type PropertyDescriptor;
23 #[wasm_bindgen(method, getter, structural)]
value(this: &PropertyDescriptor) -> JsValue24 fn value(this: &PropertyDescriptor) -> JsValue;
25 }
26
27 #[wasm_bindgen(module = "tests/wasm/Object.js")]
28 extern "C" {
map_with_symbol_key() -> Object29 fn map_with_symbol_key() -> Object;
symbol_key() -> JsValue30 fn symbol_key() -> JsValue;
31
32 type Foo;
33 #[wasm_bindgen(constructor)]
new() -> Foo34 fn new() -> Foo;
35
36 #[wasm_bindgen(js_name = prototype, js_namespace = Foo)]
37 static FOO_PROTOTYPE: Object;
38 #[wasm_bindgen(js_name = prototype, js_namespace = Bar)]
39 static BAR_PROTOTYPE: Object;
40 }
41
foo_42() -> Object42 fn foo_42() -> Object {
43 let foo = Foo42::from(JsValue::from(Object::new()));
44 foo.set_foo(42.into());
45 JsValue::from(foo).into()
46 }
47
48 #[wasm_bindgen_test]
new()49 fn new() {
50 assert!(JsValue::from(Object::new()).is_object());
51 }
52
53 #[wasm_bindgen_test]
assign()54 fn assign() {
55 let a = JsValue::from("a");
56 let b = JsValue::from("b");
57 let c = JsValue::from("c");
58
59 let target = Object::new();
60 Reflect::set(target.as_ref(), a.as_ref(), a.as_ref()).unwrap();
61
62 let src1 = Object::new();
63 Reflect::set(src1.as_ref(), &a, &c).unwrap();
64
65 let src2 = Object::new();
66 Reflect::set(src2.as_ref(), &b, &b).unwrap();
67
68 let src3 = Object::new();
69 Reflect::set(src3.as_ref(), &c, &c).unwrap();
70
71 let res = Object::assign3(&target, &src1, &src2, &src3);
72
73 assert!(Object::is(target.as_ref(), res.as_ref()));
74 assert_eq!(Reflect::get(target.as_ref(), &a).unwrap(), c);
75 assert_eq!(Reflect::get(target.as_ref(), &b).unwrap(), b);
76 assert_eq!(Reflect::get(target.as_ref(), &c).unwrap(), c);
77 }
78
79 #[wasm_bindgen_test]
create()80 fn create() {
81 let array_proto = eval("Array.prototype")
82 .unwrap()
83 .dyn_into::<Object>()
84 .unwrap();
85 let my_array = Object::create(&array_proto);
86 assert!(my_array.is_instance_of::<Array>());
87 }
88
89 #[wasm_bindgen_test]
define_property()90 fn define_property() {
91 let value = DefinePropertyAttrs::from(JsValue::from(Object::new()));
92 value.set_value(&43.into());
93 let descriptor = Object::from(JsValue::from(value));
94 let foo = foo_42();
95 let foo = Object::define_property(&foo, &"bar".into(), &descriptor);
96 assert!(foo.has_own_property(&"bar".into()));
97 }
98
99 #[wasm_bindgen_test]
define_properties()100 fn define_properties() {
101 let props = Object::new();
102 let descriptor = DefinePropertyAttrs::from(JsValue::from(Object::new()));
103 descriptor.set_value(&42.into());
104 let descriptor = JsValue::from(descriptor);
105 Reflect::set(props.as_ref(), &JsValue::from("bar"), &descriptor).unwrap();
106 Reflect::set(props.as_ref(), &JsValue::from("car"), &descriptor).unwrap();
107 let foo = foo_42();
108 let foo = Object::define_properties(&foo, &props);
109 assert!(foo.has_own_property(&"bar".into()));
110 assert!(foo.has_own_property(&"car".into()));
111 }
112
113 #[wasm_bindgen_test]
entries()114 fn entries() {
115 let entries = Object::entries(&foo_42());
116 assert_eq!(entries.length(), 1);
117 entries.for_each(&mut |x, _, _| {
118 assert!(x.is_object());
119 let array: Array = x.into();
120 assert_eq!(array.shift(), "foo");
121 assert_eq!(array.shift(), 42);
122 assert_eq!(array.length(), 0);
123 });
124 }
125
126 #[wasm_bindgen_test]
from_entries()127 fn from_entries() {
128 let array = Array::new();
129 let entry_one = Array::new();
130 let entry_two = Array::new();
131 entry_one.push(&"foo".into());
132 entry_one.push(&"bar".into());
133 entry_two.push(&"baz".into());
134 entry_two.push(&42.into());
135 array.push(&entry_one);
136 array.push(&entry_two);
137 let object = Object::from_entries(&array).unwrap();
138
139 assert_eq!(Reflect::get(object.as_ref(), &"foo".into()).unwrap(), "bar");
140 assert_eq!(Reflect::get(object.as_ref(), &"baz".into()).unwrap(), 42);
141
142 let not_iterable = Object::new();
143 let error = Object::from_entries(¬_iterable).unwrap_err();
144 assert!(error.is_instance_of::<TypeError>());
145 }
146
147 #[wasm_bindgen_test]
get_own_property_descriptor()148 fn get_own_property_descriptor() {
149 let foo = foo_42();
150 let desc = Object::get_own_property_descriptor(&foo, &"foo".into());
151 assert_eq!(PropertyDescriptor::from(desc).value(), 42);
152 let desc = Object::get_own_property_descriptor(&foo, &"bar".into());
153 assert!(desc.is_undefined());
154 }
155
156 #[wasm_bindgen_test]
get_own_property_descriptors()157 fn get_own_property_descriptors() {
158 let foo = foo_42();
159 let descriptors = Object::get_own_property_descriptors(&foo);
160 let foo_desc = Reflect::get(&descriptors, &"foo".into()).unwrap();
161 assert_eq!(PropertyDescriptor::from(foo_desc).value(), 42);
162 }
163
164 #[wasm_bindgen_test]
get_own_property_names()165 fn get_own_property_names() {
166 let names = Object::get_own_property_names(&foo_42());
167 assert_eq!(names.length(), 1);
168 names.for_each(&mut |x, _, _| {
169 assert_eq!(x, "foo");
170 });
171 }
172
173 #[wasm_bindgen_test]
get_own_property_symbols()174 fn get_own_property_symbols() {
175 let symbols = Object::get_own_property_symbols(&map_with_symbol_key());
176 assert_eq!(symbols.length(), 1);
177 }
178
179 #[wasm_bindgen_test]
get_prototype_of()180 fn get_prototype_of() {
181 let proto = JsValue::from(Object::get_prototype_of(&Object::new().into()));
182 assert_eq!(proto, *OBJECT_PROTOTYPE);
183 let proto = JsValue::from(Object::get_prototype_of(&Array::new().into()));
184 assert_eq!(proto, *ARRAY_PROTOTYPE);
185 }
186
187 #[wasm_bindgen_test]
has_own_property()188 fn has_own_property() {
189 assert!(foo_42().has_own_property(&"foo".into()));
190 assert!(!foo_42().has_own_property(&"bar".into()));
191 assert!(map_with_symbol_key().has_own_property(&symbol_key()));
192 }
193
194 #[wasm_bindgen_test]
to_string()195 fn to_string() {
196 assert_eq!(Object::new().to_string(), "[object Object]");
197 assert_eq!(foo_42().to_string(), "[object Object]");
198 }
199
200 #[wasm_bindgen_test]
is()201 fn is() {
202 let object = JsValue::from(Object::new());
203 assert!(Object::is(&object, &object));
204 assert!(Object::is(&JsValue::undefined(), &JsValue::undefined()));
205 assert!(Object::is(&JsValue::null(), &JsValue::null()));
206 assert!(Object::is(&JsValue::TRUE, &JsValue::TRUE));
207 assert!(Object::is(&JsValue::FALSE, &JsValue::FALSE));
208 assert!(Object::is(&"foo".into(), &"foo".into()));
209 assert!(Object::is(&JsValue::from(42), &JsValue::from(42)));
210 assert!(Object::is(&JsValue::from(NAN), &JsValue::from(NAN)));
211
212 let another_object = JsValue::from(Object::new());
213 assert!(!Object::is(&object, &another_object));
214 assert!(!Object::is(&JsValue::TRUE, &JsValue::FALSE));
215 assert!(!Object::is(&"foo".into(), &"bar".into()));
216 assert!(!Object::is(&JsValue::from(23), &JsValue::from(42)));
217 }
218
219 #[wasm_bindgen_test]
is_extensible()220 fn is_extensible() {
221 let object = Object::new();
222 assert!(Object::is_extensible(&object));
223 Object::prevent_extensions(&object);
224 assert!(!Object::is_extensible(&object));
225 }
226
227 #[wasm_bindgen_test]
is_frozen()228 fn is_frozen() {
229 let object = Object::new();
230 assert!(!Object::is_frozen(&object));
231 Object::freeze(&object);
232 assert!(Object::is_frozen(&object));
233 }
234
235 #[wasm_bindgen_test]
is_sealed()236 fn is_sealed() {
237 let object = Object::new();
238 assert!(!Object::is_sealed(&object));
239 Object::seal(&object);
240 assert!(Object::is_sealed(&object));
241 }
242
243 #[wasm_bindgen_test]
is_prototype_of()244 fn is_prototype_of() {
245 let foo = JsValue::from(Foo::new());
246 assert!(FOO_PROTOTYPE.is_prototype_of(&foo));
247 assert!(!BAR_PROTOTYPE.is_prototype_of(&foo));
248 }
249
250 #[wasm_bindgen_test]
keys()251 fn keys() {
252 let keys = Object::keys(&foo_42());
253 assert_eq!(keys.length(), 1);
254 keys.for_each(&mut |x, _, _| {
255 assert_eq!(x, "foo");
256 });
257 }
258
259 #[wasm_bindgen_test]
values()260 fn values() {
261 let values = Object::values(&foo_42());
262 assert_eq!(values.length(), 1);
263 values.for_each(&mut |x, _, _| {
264 assert_eq!(x, 42);
265 });
266 }
267
268 #[wasm_bindgen_test]
property_is_enumerable()269 fn property_is_enumerable() {
270 assert!(foo_42().property_is_enumerable(&"foo".into()));
271 assert!(!foo_42().property_is_enumerable(&42.into()));
272 assert!(!Object::new().property_is_enumerable(&"foo".into()));
273 }
274
275 #[wasm_bindgen_test]
set_prototype_of()276 fn set_prototype_of() {
277 let a = foo_42();
278 let b = foo_42();
279 Object::set_prototype_of(&a, &b);
280 assert!(b.is_prototype_of(&a.into()));
281 }
282
283 #[wasm_bindgen_test]
to_locale_string()284 fn to_locale_string() {
285 assert_eq!(Object::new().to_locale_string(), "[object Object]");
286 }
287
288 #[wasm_bindgen_test]
value_of()289 fn value_of() {
290 let a = JsValue::from(foo_42());
291 let b = JsValue::from(foo_42());
292 let a2 = JsValue::from(Object::from(a.clone()).value_of());
293 assert_eq!(a, a);
294 assert_eq!(a, a2);
295 assert_ne!(a, b);
296 assert_ne!(a2, b);
297 }
298