diff options
Diffstat (limited to 'components/script/dom/bindings/iterable.rs')
-rw-r--r-- | components/script/dom/bindings/iterable.rs | 123 |
1 files changed, 71 insertions, 52 deletions
diff --git a/components/script/dom/bindings/iterable.rs b/components/script/dom/bindings/iterable.rs index 845ecbaa8cd..2eac830a4bb 100644 --- a/components/script/dom/bindings/iterable.rs +++ b/components/script/dom/bindings/iterable.rs @@ -1,28 +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/. */ + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #![allow(unsafe_code)] //! Implementation of `iterable<...>` and `iterable<..., ...>` WebIDL declarations. -use core::nonzero::NonZero; -use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyAndValueResult; -use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyOrValueResult; -use dom::bindings::error::Fallible; -use dom::bindings::js::{JS, Root}; -use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bindings::trace::JSTraceable; -use dom::globalscope::GlobalScope; +use crate::dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyAndValueResult; +use crate::dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyOrValueResult; +use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::reflector::{ + reflect_dom_object, DomObjectIteratorWrap, DomObjectWrap, Reflector, +}; +use crate::dom::bindings::root::{Dom, DomRoot, Root}; +use crate::dom::bindings::trace::{JSTraceable, RootedTraceableBox}; +use crate::dom::globalscope::GlobalScope; +use crate::script_runtime::JSContext; use dom_struct::dom_struct; use js::conversions::ToJSValConvertible; -use js::jsapi::{HandleValue, Heap, JSContext, JSObject, MutableHandleObject}; +use js::jsapi::{Heap, JSObject}; use js::jsval::UndefinedValue; +use js::rust::{HandleValue, MutableHandleObject}; use std::cell::Cell; use std::ptr; +use std::ptr::NonNull; /// The values that an iterator will iterate over. -#[derive(JSTraceable, HeapSizeOf)] +#[derive(JSTraceable, MallocSizeOf)] pub enum IteratorType { /// The keys of the iterable object. Keys, @@ -49,93 +53,108 @@ pub trait Iterable { /// An iterator over the iterable entries of a given DOM interface. //FIXME: #12811 prevents dom_struct with type parameters #[dom_struct] -pub struct IterableIterator<T: DomObject + JSTraceable + Iterable> { +pub struct IterableIterator<T: DomObjectIteratorWrap + JSTraceable + Iterable> { reflector: Reflector, - iterable: JS<T>, + iterable: Dom<T>, type_: IteratorType, index: Cell<u32>, } -impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> { +impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> IterableIterator<T> { /// Create a new iterator instance for the provided iterable DOM interface. - pub fn new(iterable: &T, - type_: IteratorType, - wrap: unsafe fn(*mut JSContext, &GlobalScope, Box<IterableIterator<T>>) - -> Root<Self>) -> Root<Self> { - let iterator = box IterableIterator { + pub fn new(iterable: &T, type_: IteratorType) -> DomRoot<Self> { + let iterator = Box::new(IterableIterator { reflector: Reflector::new(), type_: type_, - iterable: JS::from_ref(iterable), + iterable: Dom::from_ref(iterable), index: Cell::new(0), - }; - reflect_dom_object(iterator, &*iterable.global(), wrap) + }); + reflect_dom_object(iterator, &*iterable.global()) } /// Return the next value from the iterable object. #[allow(non_snake_case)] - pub fn Next(&self, cx: *mut JSContext) -> Fallible<NonZero<*mut JSObject>> { + pub fn Next(&self, cx: JSContext) -> Fallible<NonNull<JSObject>> { let index = self.index.get(); - rooted!(in(cx) let mut value = UndefinedValue()); - rooted!(in(cx) let mut rval = ptr::null_mut()); + rooted!(in(*cx) let mut value = UndefinedValue()); + rooted!(in(*cx) let mut rval = ptr::null_mut::<JSObject>()); let result = if index >= self.iterable.get_iterable_length() { dict_return(cx, rval.handle_mut(), true, value.handle()) } else { match self.type_ { IteratorType::Keys => { unsafe { - self.iterable.get_key_at_index(index).to_jsval(cx, value.handle_mut()); + self.iterable + .get_key_at_index(index) + .to_jsval(*cx, value.handle_mut()); } dict_return(cx, rval.handle_mut(), false, value.handle()) - } + }, IteratorType::Values => { unsafe { - self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut()); + self.iterable + .get_value_at_index(index) + .to_jsval(*cx, value.handle_mut()); } dict_return(cx, rval.handle_mut(), false, value.handle()) - } + }, IteratorType::Entries => { - rooted!(in(cx) let mut key = UndefinedValue()); + rooted!(in(*cx) let mut key = UndefinedValue()); unsafe { - self.iterable.get_key_at_index(index).to_jsval(cx, key.handle_mut()); - self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut()); + self.iterable + .get_key_at_index(index) + .to_jsval(*cx, key.handle_mut()); + self.iterable + .get_value_at_index(index) + .to_jsval(*cx, value.handle_mut()); } key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle()) - } + }, } }; self.index.set(index + 1); - result.map(|_| { - assert!(!rval.is_null()); - unsafe { NonZero::new(rval.get()) } - }) + result.map(|_| NonNull::new(rval.get()).expect("got a null pointer")) } } -fn dict_return(cx: *mut JSContext, - result: MutableHandleObject, - done: bool, - value: HandleValue) -> Fallible<()> { - let mut dict = unsafe { IterableKeyOrValueResult::empty(cx) }; +impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> DomObjectWrap for IterableIterator<T> { + const WRAP: unsafe fn(JSContext, &GlobalScope, Box<Self>) -> Root<Dom<Self>> = T::ITER_WRAP; +} + +fn dict_return( + cx: JSContext, + mut result: MutableHandleObject, + done: bool, + value: HandleValue, +) -> Fallible<()> { + let mut dict = IterableKeyOrValueResult::empty(); dict.done = done; dict.value.set(value.get()); - rooted!(in(cx) let mut dict_value = UndefinedValue()); + rooted!(in(*cx) let mut dict_value = UndefinedValue()); unsafe { - dict.to_jsval(cx, dict_value.handle_mut()); + dict.to_jsval(*cx, dict_value.handle_mut()); } result.set(dict_value.to_object()); Ok(()) } -fn key_and_value_return(cx: *mut JSContext, - result: MutableHandleObject, - key: HandleValue, - value: HandleValue) -> Fallible<()> { - let mut dict = unsafe { IterableKeyAndValueResult::empty(cx) }; +fn key_and_value_return( + cx: JSContext, + mut result: MutableHandleObject, + key: HandleValue, + value: HandleValue, +) -> Fallible<()> { + let mut dict = IterableKeyAndValueResult::empty(); dict.done = false; - dict.value = Some(vec![Heap::new(key.get()), Heap::new(value.get())]); - rooted!(in(cx) let mut dict_value = UndefinedValue()); + dict.value = Some( + vec![key, value] + .into_iter() + .map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get()))) + .collect(), + ); + rooted!(in(*cx) let mut dict_value = UndefinedValue()); unsafe { - dict.to_jsval(cx, dict_value.handle_mut()); + dict.to_jsval(*cx, dict_value.handle_mut()); } result.set(dict_value.to_object()); Ok(()) |