diff options
Diffstat (limited to '')
-rw-r--r-- | js/rust/tests/bigint.rs | 56 | ||||
-rw-r--r-- | js/rust/tests/callback.rs | 79 | ||||
-rw-r--r-- | js/rust/tests/enumerate.rs | 70 | ||||
-rw-r--r-- | js/rust/tests/evaluate.rs | 32 | ||||
-rw-r--r-- | js/rust/tests/panic.rs | 50 | ||||
-rw-r--r-- | js/rust/tests/rooting.rs | 105 | ||||
-rw-r--r-- | js/rust/tests/runtime.rs | 59 | ||||
-rw-r--r-- | js/rust/tests/stack_limit.rs | 44 | ||||
-rw-r--r-- | js/rust/tests/typedarray.rs | 104 | ||||
-rw-r--r-- | js/rust/tests/value.rs | 64 | ||||
-rw-r--r-- | js/rust/tests/vec_conversion.rs | 81 |
11 files changed, 744 insertions, 0 deletions
diff --git a/js/rust/tests/bigint.rs b/js/rust/tests/bigint.rs new file mode 100644 index 0000000000..3c8ef1ed29 --- /dev/null +++ b/js/rust/tests/bigint.rs @@ -0,0 +1,56 @@ +#[macro_use] +extern crate js; + +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS::CompartmentOptions; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsval::UndefinedValue; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; + +use std::ptr; + +#[test] +fn is_bigint() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &CompartmentOptions::default()) + ); + + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script(global.handle(), "BigInt(0)", "test", 1, rval.handle_mut()) + .is_ok()); + assert!(rval.is_bigint()); + } +} + +#[test] +fn is_not_bigint() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &CompartmentOptions::default()) + ); + + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script( + global.handle(), + "'not a BigInt'", + "test", + 1, + rval.handle_mut() + ) + .is_ok()); + assert!(!rval.is_bigint()); + } +} diff --git a/js/rust/tests/callback.rs b/js/rust/tests/callback.rs new file mode 100644 index 0000000000..de75f97d26 --- /dev/null +++ b/js/rust/tests/callback.rs @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; +extern crate libc; + +use js::ar::AutoRealm; +use js::glue::JSEncodeStringToUTF8; +use js::jsapi::root::JSContext; +use js::jsapi::root::JS_DefineFunction; +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS_ReportErrorASCII; +use js::jsapi::root::JS::CallArgs; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsapi::root::JS::RealmOptions; +use js::jsapi::root::JS::Value; +use js::jsval::UndefinedValue; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; + +use std::ffi::CStr; +use std::ptr; +use std::str; + +#[test] +fn callback() { + let runtime = Runtime::new(false).unwrap(); + let context = runtime.cx(); + let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = RealmOptions::default(); + + unsafe { + let global = JS_NewGlobalObject( + context, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &c_option, + ); + rooted!(in(context) let global_root = global); + let global = global_root.handle(); + let _ar = AutoRealm::with_obj(context, global.get()); + let function = JS_DefineFunction( + context, + global, + b"puts\0".as_ptr() as *const libc::c_char, + Some(puts), + 1, + 0, + ); + assert!(!function.is_null()); + let javascript = "puts('Test Iñtërnâtiônàlizætiøn ┬─┬ノ( º _ ºノ) ');"; + rooted!(in(context) let mut rval = UndefinedValue()); + let _ = runtime.evaluate_script(global, javascript, "test.js", 0, rval.handle_mut()); + } +} + +unsafe extern "C" fn puts(context: *mut JSContext, argc: u32, vp: *mut Value) -> bool { + let args = CallArgs::from_vp(vp, argc); + + if args._base.argc_ != 1 { + JS_ReportErrorASCII( + context, + b"puts() requires exactly 1 argument\0".as_ptr() as *const libc::c_char, + ); + return false; + } + + let arg = args.get(0); + let js = js::rust::ToString(context, arg); + rooted!(in(context) let message_root = js); + let message = JSEncodeStringToUTF8(context, message_root.handle()); + let message = CStr::from_ptr(message); + println!("{}", str::from_utf8(message.to_bytes()).unwrap()); + + args.rval().set(UndefinedValue()); + return true; +} diff --git a/js/rust/tests/enumerate.rs b/js/rust/tests/enumerate.rs new file mode 100644 index 0000000000..a1c8a6735d --- /dev/null +++ b/js/rust/tests/enumerate.rs @@ -0,0 +1,70 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::glue::RUST_JSID_IS_STRING; +use js::glue::RUST_JSID_TO_STRING; +use js::jsapi::root::js::GetPropertyKeys; +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS_StringEqualsAscii; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsapi::root::JS::RealmOptions; +use js::jsapi::root::JSITER_OWNONLY; +use js::jsval::UndefinedValue; +use js::rust::RootedIdVectorWrapper; +use js::rust::Runtime; +use js::rust::SIMPLE_GLOBAL_CLASS; +use std::ptr; + +#[test] +fn enumerate() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &RealmOptions::default()) + ); + + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script( + global.handle(), + "({ 'a': 7 })", + "test", + 1, + rval.handle_mut() + ) + .is_ok()); + assert!(rval.is_object()); + + rooted!(in(cx) let object = rval.to_object()); + let ids = RootedIdVectorWrapper::new(cx); + assert!(GetPropertyKeys( + cx, + object.handle(), + JSITER_OWNONLY, + ids.handle_mut() + )); + + assert_eq!(ids.len(), 1); + rooted!(in(cx) let id = ids[0]); + + assert!(RUST_JSID_IS_STRING(id.handle())); + rooted!(in(cx) let id = RUST_JSID_TO_STRING(id.handle())); + + let mut matches = false; + assert!(JS_StringEqualsAscii( + cx, + id.get(), + b"a\0" as *const _ as *const _, + &mut matches + )); + assert!(matches); + } +} diff --git a/js/rust/tests/evaluate.rs b/js/rust/tests/evaluate.rs new file mode 100644 index 0000000000..8ce4396ade --- /dev/null +++ b/js/rust/tests/evaluate.rs @@ -0,0 +1,32 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsapi::root::JS::RealmOptions; +use js::jsval::UndefinedValue; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; + +use std::ptr; + +#[test] +fn evaluate() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &RealmOptions::default()) + ); + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script(global.handle(), "1 + 1", "test", 1, rval.handle_mut()) + .is_ok()); + } +} diff --git a/js/rust/tests/panic.rs b/js/rust/tests/panic.rs new file mode 100644 index 0000000000..ecb5705017 --- /dev/null +++ b/js/rust/tests/panic.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::jsapi::*; +use js::jsval::UndefinedValue; +use js::panic::wrap_panic; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use std::ptr; +use std::str; + +#[test] +#[should_panic] +fn panic() { + let runtime = Runtime::new(false).unwrap(); + let context = runtime.cx(); + let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = JS::RealmOptions::default(); + + unsafe { + let global = JS_NewGlobalObject( + context, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &c_option, + ); + rooted!(in(context) let global_root = global); + let global = global_root.handle(); + let _ar = js::ar::AutoRealm::with_obj(context, global.get()); + let function = JS_DefineFunction( + context, + global, + b"test\0".as_ptr() as *const _, + Some(test), + 0, + 0, + ); + assert!(!function.is_null()); + rooted!(in(context) let mut rval = UndefinedValue()); + let _ = runtime.evaluate_script(global, "test();", "test.js", 0, rval.handle_mut()); + } +} + +unsafe extern "C" fn test(_cx: *mut JSContext, _argc: u32, _vp: *mut JS::Value) -> bool { + wrap_panic(|| panic!(), false) +} diff --git a/js/rust/tests/rooting.rs b/js/rust/tests/rooting.rs new file mode 100644 index 0000000000..868846fa02 --- /dev/null +++ b/js/rust/tests/rooting.rs @@ -0,0 +1,105 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#![cfg(feature = "debugmozjs")] + +#[macro_use] +extern crate js; +#[macro_use] +extern crate lazy_static; +extern crate libc; + +use js::jsapi::*; +use js::rust::{define_methods, Runtime, SIMPLE_GLOBAL_CLASS}; +use std::ptr; + +#[test] +fn rooting() { + unsafe { + let runtime = Runtime::new(false).unwrap(); + JS_SetGCZeal(runtime.cx(), 2, 1); + + let cx = runtime.cx(); + let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = JS::RealmOptions::default(); + + rooted!(in(cx) let global = JS_NewGlobalObject(cx, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &c_option)); + let _ar = js::ar::AutoRealm::with_obj(cx, global.get()); + rooted!(in(cx) let prototype_proto = JS::GetRealmObjectPrototype(cx)); + rooted!(in(cx) let proto = JS_NewObjectWithGivenProto(cx, + &CLASS as *const _, + prototype_proto.handle())); + define_methods(cx, proto.handle(), &METHODS[..]).unwrap(); + } +} + +unsafe extern "C" fn generic_method(_: *mut JSContext, _: u32, _: *mut JS::Value) -> bool { + true +} + +lazy_static! { + static ref METHODS: [JSFunctionSpec; 4] = [ + JSFunctionSpec { + name: JSFunctionSpec_Name { + string_: b"addEventListener\0" as *const u8 as *const libc::c_char, + }, + call: JSNativeWrapper { + op: Some(generic_method), + info: ptr::null() + }, + nargs: 2, + flags: JSPROP_ENUMERATE as u16, + selfHostedName: 0 as *const libc::c_char + }, + JSFunctionSpec { + name: JSFunctionSpec_Name { + string_: b"removeEventListener\0" as *const u8 as *const libc::c_char, + }, + call: JSNativeWrapper { + op: Some(generic_method), + info: ptr::null() + }, + nargs: 2, + flags: JSPROP_ENUMERATE as u16, + selfHostedName: 0 as *const libc::c_char + }, + JSFunctionSpec { + name: JSFunctionSpec_Name { + string_: b"dispatchEvent\0" as *const u8 as *const libc::c_char, + }, + call: JSNativeWrapper { + op: Some(generic_method), + info: ptr::null() + }, + nargs: 1, + flags: JSPROP_ENUMERATE as u16, + selfHostedName: 0 as *const libc::c_char + }, + JSFunctionSpec { + name: JSFunctionSpec_Name { + string_: ptr::null(), + }, + call: JSNativeWrapper { + op: None, + info: ptr::null() + }, + nargs: 0, + flags: 0, + selfHostedName: ptr::null() + } + ]; +} + +static CLASS: JSClass = JSClass { + name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char, + flags: 0, + cOps: 0 as *const _, + spec: 0 as *mut _, + ext: 0 as *mut _, + oOps: 0 as *mut _, +}; diff --git a/js/rust/tests/runtime.rs b/js/rust/tests/runtime.rs new file mode 100644 index 0000000000..ac69f5034b --- /dev/null +++ b/js/rust/tests/runtime.rs @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; +extern crate libc; + +use js::jsapi::*; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use std::ptr; + +#[test] +fn runtime() { + unsafe { + let runtime = Runtime::new(false).unwrap(); + + let cx = runtime.cx(); + let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = JS::RealmOptions::default(); + + rooted!(in(cx) let global = JS_NewGlobalObject(cx, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &c_option)); + let _ar = js::ar::AutoRealm::with_obj(cx, global.get()); + rooted!(in(cx) let _object = JS_NewObject(cx, &CLASS as *const _)); + } + + assert!(Runtime::new(false).is_err()); +} + +unsafe extern "C" fn finalize(_fop: *mut JSFreeOp, _object: *mut JSObject) { + assert!(!Runtime::get().is_null()); +} + +static CLASS_OPS: JSClassOps = JSClassOps { + addProperty: None, + delProperty: None, + enumerate: None, + newEnumerate: None, + resolve: None, + mayResolve: None, + finalize: Some(finalize), + call: None, + hasInstance: None, + construct: None, + trace: None, +}; + +static CLASS: JSClass = JSClass { + name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char, + flags: 0 | JSCLASS_FOREGROUND_FINALIZE, + cOps: &CLASS_OPS as *const JSClassOps, + spec: 0 as *mut _, + ext: 0 as *mut _, + oOps: 0 as *mut _, +}; diff --git a/js/rust/tests/stack_limit.rs b/js/rust/tests/stack_limit.rs new file mode 100644 index 0000000000..02613d3793 --- /dev/null +++ b/js/rust/tests/stack_limit.rs @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsapi::root::JS::RealmOptions; +use js::jsval::UndefinedValue; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; + +use std::ptr; + +#[test] +fn stack_limit() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = RealmOptions::default(); + let global = JS_NewGlobalObject( + cx, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &c_option, + ); + rooted!(in(cx) let global_root = global); + let global = global_root.handle(); + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script( + global, + "function f() { f.apply() } f()", + "test", + 1, + rval.handle_mut() + ) + .is_err()); + } +} diff --git a/js/rust/tests/typedarray.rs b/js/rust/tests/typedarray.rs new file mode 100644 index 0000000000..6cd759f5f3 --- /dev/null +++ b/js/rust/tests/typedarray.rs @@ -0,0 +1,104 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::jsapi::*; +use js::jsval::UndefinedValue; +use js::rust::Runtime as Runtime_; +use js::rust::SIMPLE_GLOBAL_CLASS; +use js::typedarray::{CreateWith, Uint32Array}; +use std::ptr; + +#[test] +fn typedarray() { + let rt = Runtime_::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + JS::OnNewGlobalHookOption::FireOnNewGlobalHook, + &JS::RealmOptions::default()) + ); + + let _ar = js::ar::AutoRealm::with_obj(cx, global.get()); + + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script( + global.handle(), + "new Uint8Array([0, 2, 4])", + "test", + 1, + rval.handle_mut() + ) + .is_ok()); + assert!(rval.is_object()); + + typedarray!(in(cx) let array: Uint8Array = rval.to_object()); + assert_eq!(array.unwrap().as_slice(), &[0, 2, 4][..]); + + typedarray!(in(cx) let array: Uint16Array = rval.to_object()); + assert!(array.is_err()); + + typedarray!(in(cx) let view: ArrayBufferView = rval.to_object()); + assert_eq!( + view.unwrap().get_array_type(), + js::jsapi::js::Scalar::Type::Uint8 + ); + + rooted!(in(cx) let mut rval = ptr::null_mut()); + assert!(Uint32Array::create(cx, CreateWith::Slice(&[1, 3, 5]), rval.handle_mut()).is_ok()); + + typedarray!(in(cx) let array: Uint32Array = rval.get()); + assert_eq!(array.unwrap().as_slice(), &[1, 3, 5][..]); + + typedarray!(in(cx) let mut array: Uint32Array = rval.get()); + array.as_mut().unwrap().update(&[2, 4, 6]); + assert_eq!(array.unwrap().as_slice(), &[2, 4, 6][..]); + + rooted!(in(cx) let rval = ptr::null_mut()); + typedarray!(in(cx) let array: Uint8Array = rval.get()); + assert!(array.is_err()); + + rooted!(in(cx) let mut rval = ptr::null_mut()); + assert!(Uint32Array::create(cx, CreateWith::Length(5), rval.handle_mut()).is_ok()); + + typedarray!(in(cx) let array: Uint32Array = rval.get()); + assert_eq!(array.unwrap().as_slice(), &[0, 0, 0, 0, 0]); + + typedarray!(in(cx) let mut array: Uint32Array = rval.get()); + array.as_mut().unwrap().update(&[0, 1, 2, 3]); + assert_eq!(array.unwrap().as_slice(), &[0, 1, 2, 3, 0]); + + typedarray!(in(cx) let view: ArrayBufferView = rval.get()); + assert_eq!( + view.unwrap().get_array_type(), + js::jsapi::js::Scalar::Type::Uint32 + ); + } +} + +#[test] +#[should_panic] +fn typedarray_update_panic() { + let rt = Runtime_::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + JS::OnNewGlobalHookOption::FireOnNewGlobalHook, + &JS::RealmOptions::default()) + ); + + let _ar = js::ar::AutoRealm::with_obj(cx, global.get()); + rooted!(in(cx) let mut rval = ptr::null_mut()); + let _ = Uint32Array::create(cx, CreateWith::Slice(&[1, 2, 3, 4, 5]), rval.handle_mut()); + typedarray!(in(cx) let mut array: Uint32Array = rval.get()); + array.as_mut().unwrap().update(&[0, 2, 4, 6, 8, 10]); + } +} diff --git a/js/rust/tests/value.rs b/js/rust/tests/value.rs new file mode 100644 index 0000000000..0622268cd8 --- /dev/null +++ b/js/rust/tests/value.rs @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsapi::root::JS::RealmOptions; +use js::jsval::UndefinedValue; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; + +use std::ptr; + +#[test] +fn is_symbol() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &RealmOptions::default()) + ); + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script( + global.handle(), + "Symbol('test')", + "test", + 1, + rval.handle_mut() + ) + .is_ok()); + assert!(rval.is_symbol()); + } +} + +#[test] +fn is_not_symbol() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + unsafe { + rooted!(in(cx) let global = + JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), + OnNewGlobalHookOption::FireOnNewGlobalHook, + &RealmOptions::default()) + ); + rooted!(in(cx) let mut rval = UndefinedValue()); + assert!(rt + .evaluate_script( + global.handle(), + "'not a symbol'", + "test", + 1, + rval.handle_mut() + ) + .is_ok()); + assert!(!rval.is_symbol()); + } +} diff --git a/js/rust/tests/vec_conversion.rs b/js/rust/tests/vec_conversion.rs new file mode 100644 index 0000000000..a4446799aa --- /dev/null +++ b/js/rust/tests/vec_conversion.rs @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate js; + +use js::ar::AutoRealm; +use js::conversions::ConversionBehavior; +use js::conversions::ConversionResult; +use js::conversions::FromJSValConvertible; +use js::conversions::ToJSValConvertible; +use js::jsapi::root::JS_NewGlobalObject; +use js::jsapi::root::JS::InitRealmStandardClasses; +use js::jsapi::root::JS::OnNewGlobalHookOption; +use js::jsapi::root::JS::RealmOptions; +use js::jsval::UndefinedValue; +use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; + +use std::ptr; + +fn assert_is_array(cx: *mut js::jsapi::root::JSContext, val: js::jsapi::root::JS::HandleValue) { + let mut is_array = false; + assert!(unsafe { js::jsapi::root::JS::IsArrayObject(cx, val, &mut is_array as *mut _) }); + assert!(is_array); +} + +#[test] +fn vec_conversion() { + let rt = Runtime::new(false).unwrap(); + let cx = rt.cx(); + + let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = RealmOptions::default(); + + unsafe { + let global = JS_NewGlobalObject( + cx, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &c_option, + ); + rooted!(in(cx) let global_root = global); + let global = global_root.handle(); + + let _ar = AutoRealm::with_obj(cx, global.get()); + assert!(InitRealmStandardClasses(cx)); + + rooted!(in(cx) let mut rval = UndefinedValue()); + + let orig_vec: Vec<f32> = vec![1.0, 2.9, 3.0]; + orig_vec.to_jsval(cx, rval.handle_mut()); + assert_is_array(cx, rval.handle()); + let converted = Vec::<f32>::from_jsval(cx, rval.handle(), ()).unwrap(); + assert_eq!(&orig_vec, converted.get_success_value().unwrap()); + + let orig_vec: Vec<i32> = vec![1, 2, 3]; + orig_vec.to_jsval(cx, rval.handle_mut()); + assert_is_array(cx, rval.handle()); + let converted = + Vec::<i32>::from_jsval(cx, rval.handle(), ConversionBehavior::Default).unwrap(); + + assert_eq!(&orig_vec, converted.get_success_value().unwrap()); + + rt.evaluate_script(global, "new Set([1, 2, 3])", "test", 1, rval.handle_mut()) + .unwrap(); + let converted = + Vec::<i32>::from_jsval(cx, rval.handle(), ConversionBehavior::Default).unwrap(); + + assert_eq!(&orig_vec, converted.get_success_value().unwrap()); + + rt.evaluate_script(global, "({})", "test", 1, rval.handle_mut()) + .unwrap(); + let converted = Vec::<i32>::from_jsval(cx, rval.handle(), ConversionBehavior::Default); + assert!(match converted { + Ok(ConversionResult::Failure(_)) => true, + _ => false, + }); + } +} |