<commit_before>/* 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/. */

//! Smart pointers for the JS-managed DOM objects.
//!
//! The DOM is made up of DOM objects whose lifetime is entirely controlled by
//! the whims of the SpiderMonkey garbage collector. The types in this module
//! are designed to ensure that any interactions with said Rust types only
//! occur on values that will remain alive the entire time.
//!
//! Here is a brief overview of the important types:
//!
//! - `JSRef<T>`: a freely-copyable reference to a rooted DOM object.
//! - `Root<T>`: a stack-based reference to a rooted DOM object.
//! - `JS<T>`: a reference to a DOM object that can automatically be traced by
//!   the GC when encountered as a field of a Rust structure.
//! - `Temporary<T>`: a reference to a DOM object that will remain rooted for
//!   the duration of its lifetime.
//!
//! The rule of thumb is as follows:
//!
//! - All methods return `Temporary<T>`, to ensure the value remains alive
//!   until it is stored somewhere that is reachable by the GC.
//! - All functions take `JSRef<T>` arguments, to ensure that they will remain
//!   uncollected for the duration of their usage.
//! - All DOM structs contain `JS<T>` fields and derive the `JSTraceable`
//!   trait, to ensure that they are transitively marked as reachable by the GC
//!   if the enclosing value is reachable.
//! - All methods for type `T` are implemented for `JSRef<T>`, to ensure that
//!   the self value will not be collected for the duration of the method call.
//!
//! Both `Temporary<T>` and `JS<T>` do not allow access to their inner value
//! without explicitly creating a stack-based root via the `root` method. This
//! returns a `Root<T>`, which causes the JS-owned value to be uncollectable
//! for the duration of the `Root` object's lifetime. A `JSRef<T>` can be
//! obtained from a `Root<T>` by calling the `r` method. These `JSRef<T>`
//! values are not allowed to outlive their originating `Root<T>`, to ensure
//! that all interactions with the enclosed value only occur when said value is
//! uncollectable, and will cause static lifetime errors if misused.
//!
//! Other miscellaneous helper traits:
//!
//! - `OptionalRootable` and `OptionalRootedRootable`: make rooting `Option`
//!   values easy via a `root` method
//! - `ResultRootable`: make rooting successful `Result` values easy
//! - `TemporaryPushable`: allows mutating vectors of `JS<T>` with new elements
//!   of `JSRef`/`Temporary`
//! - `RootedReference`: makes obtaining an `Option<JSRef<T>>` from an
//!   `Option<Root<T>>` easy

use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflector, Reflectable};
use dom::node::Node;
use js::jsapi::JSObject;
use js::jsval::JSVal;
use layout_interface::TrustedNodeAddress;
use script_task::STACK_ROOTS;

use util::smallvec::{SmallVec, SmallVec32};

use core::nonzero::NonZero;
use std::cell::{Cell, UnsafeCell};
use std::default::Default;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;

/// An unrooted, JS-owned value. Must not be held across a GC.
///
/// This is used in particular to wrap pointers extracted from a reflector.
#[must_root]
pub struct Unrooted<T> {
    ptr: NonZero<*const T>
}

impl<T: Reflectable> Unrooted<T> {
    /// Create a new JS-owned value wrapped from a raw Rust pointer.
    pub unsafe fn from_raw(raw: *const T) -> Unrooted<T> {
        assert!(!raw.is_null());
        Unrooted {
            ptr: NonZero::new(raw)
        }
    }

    /// Create a new unrooted value from a `JS<T>`.
    #[allow(unrooted_must_root)]
    pub fn from_js(ptr: JS<T>) -> Unrooted<T> {
        Unrooted {
            ptr: ptr.ptr
        }
    }

    /// Create a new unrooted value from a `Temporary<T>`.
    #[allow(unrooted_must_root)]
    pub fn from_temporary(ptr: Temporary<T>) -> Unrooted<T> {
        Unrooted::from_js(ptr.inner)
    }

    /// Get the `Reflector` for this pointer.
    pub fn reflector<'a>(&'a self) -> &'a Reflector {
        unsafe {
            (**self.ptr).reflector()
        }
    }

    /// Returns an unsafe pointer to the interior of this object.
    pub unsafe fn unsafe_get(&self) -> *const T {
        *self.ptr
    }

    /// Create a stack-bounded root for this value.
    pub fn root(self) -> Root<T> {
        STACK_ROOTS.with(|ref collection| {
            let RootCollectionPtr(collection) = collection.get().unwrap();
            unsafe {
                Root::new(&*collection, self.ptr)
            }
        })
    }
}

impl<T> Copy for Unrooted<T> {}

/// A type that represents a JS-owned value that is rooted for the lifetime of
/// this value. Importantly, it requires explicit rooting in order to interact
/// with the inner value. Can be assigned into JS-owned member fields (i.e.
/// `JS<T>` types) safely via the `JS<T>::assign` method or
/// `OptionalSettable::assign` (for `Option<JS<T>>` fields).
#[allow(unrooted_must_root)]
pub struct Temporary<T> {
    inner: JS<T>,
    /// On-stack JS pointer to assuage conservative stack scanner
    _js_ptr: *mut JSObject,
}

impl<T> Clone for Temporary<T> {
    fn clone(&self) -> Temporary<T> {
        Temporary {
            inner: self.inner,
            _js_ptr: self._js_ptr,
        }
    }
}

impl<T> PartialEq for Temporary<T> {
    fn eq(&self, other: &Temporary<T>) -> bool {
        self.inner == other.inner
    }
}

impl<T: Reflectable> Temporary<T> {
    /// Create a new `Temporary` value from a JS-owned value.
    pub fn new(inner: JS<T>) -> Temporary<T> {
        Temporary {
            inner: inner,
            _js_ptr: inner.reflector().get_jsobject(),
        }
    }

    /// Create a new `Temporary` value from an unrooted value.
    #[allow(unrooted_must_root)]
    pub fn from_unrooted(unrooted: Unrooted<T>) -> Temporary<T> {
        Temporary {
            inner: JS { ptr: unrooted.ptr },
            _js_ptr: unrooted.reflector().get_jsobject(),
        }
    }

    /// Create a new `Temporary` value from a rooted value.
    pub fn from_rooted<'a>(root: JSRef<'a, T>) -> Temporary<T> {
        Temporary::new(JS::from_rooted(root))
    }

    /// Create a stack-bounded root for this value.
    pub fn root(self) -> Root<T> {
        STACK_ROOTS.with(|ref collection| {
            let RootCollectionPtr(collection) = collection.get().unwrap();
            unsafe {
                Root::new(&*collection, self.inner.ptr)
            }
        })
    }

    unsafe fn inner(&self) -> JS<T> {
        self.inner.clone()
    }

    /// Returns `self` as a `Temporary` of another type. For use by
    /// `InheritTypes` only.<commit_msg>Don't consume self when calling root on a Temporary<T>.<commit_after>/* 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/. */

//! Smart pointers for the JS-managed DOM objects.
//!
//! The DOM is made up of DOM objects whose lifetime is entirely controlled by
//! the whims of the SpiderMonkey garbage collector. The types in this module
//! are designed to ensure that any interactions with said Rust types only
//! occur on values that will remain alive the entire time.
//!
//! Here is a brief overview of the important types:
//!
//! - `JSRef<T>`: a freely-copyable reference to a rooted DOM object.
//! - `Root<T>`: a stack-based reference to a rooted DOM object.
//! - `JS<T>`: a reference to a DOM object that can automatically be traced by
//!   the GC when encountered as a field of a Rust structure.
//! - `Temporary<T>`: a reference to a DOM object that will remain rooted for
//!   the duration of its lifetime.
//!
//! The rule of thumb is as follows:
//!
//! - All methods return `Temporary<T>`, to ensure the value remains alive
//!   until it is stored somewhere that is reachable by the GC.
//! - All functions take `JSRef<T>` arguments, to ensure that they will remain
//!   uncollected for the duration of their usage.
//! - All DOM structs contain `JS<T>` fields and derive the `JSTraceable`
//!   trait, to ensure that they are transitively marked as reachable by the GC
//!   if the enclosing value is reachable.
//! - All methods for type `T` are implemented for `JSRef<T>`, to ensure that
//!   the self value will not be collected for the duration of the method call.
//!
//! Both `Temporary<T>` and `JS<T>` do not allow access to their inner value
//! without explicitly creating a stack-based root via the `root` method. This
//! returns a `Root<T>`, which causes the JS-owned value to be uncollectable
//! for the duration of the `Root` object's lifetime. A `JSRef<T>` can be
//! obtained from a `Root<T>` by calling the `r` method. These `JSRef<T>`
//! values are not allowed to outlive their originating `Root<T>`, to ensure
//! that all interactions with the enclosed value only occur when said value is
//! uncollectable, and will cause static lifetime errors if misused.
//!
//! Other miscellaneous helper traits:
//!
//! - `OptionalRootable` and `OptionalRootedRootable`: make rooting `Option`
//!   values easy via a `root` method
//! - `ResultRootable`: make rooting successful `Result` values easy
//! - `TemporaryPushable`: allows mutating vectors of `JS<T>` with new elements
//!   of `JSRef`/`Temporary`
//! - `RootedReference`: makes obtaining an `Option<JSRef<T>>` from an
//!   `Option<Root<T>>` easy

use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflector, Reflectable};
use dom::node::Node;
use js::jsapi::JSObject;
use js::jsval::JSVal;
use layout_interface::TrustedNodeAddress;
use script_task::STACK_ROOTS;

use util::smallvec::{SmallVec, SmallVec32};

use core::nonzero::NonZero;
use std::cell::{Cell, UnsafeCell};
use std::default::Default;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;

/// An unrooted, JS-owned value. Must not be held across a GC.
///
/// This is used in particular to wrap pointers extracted from a reflector.
#[must_root]
pub struct Unrooted<T> {
    ptr: NonZero<*const T>
}

impl<T: Reflectable> Unrooted<T> {
    /// Create a new JS-owned value wrapped from a raw Rust pointer.
    pub unsafe fn from_raw(raw: *const T) -> Unrooted<T> {
        assert!(!raw.is_null());
        Unrooted {
            ptr: NonZero::new(raw)
        }
    }

    /// Create a new unrooted value from a `JS<T>`.
    #[allow(unrooted_must_root)]
    pub fn from_js(ptr: JS<T>) -> Unrooted<T> {
        Unrooted {
            ptr: ptr.ptr
        }
    }

    /// Create a new unrooted value from a `Temporary<T>`.
    #[allow(unrooted_must_root)]
    pub fn from_temporary(ptr: Temporary<T>) -> Unrooted<T> {
        Unrooted::from_js(ptr.inner)
    }

    /// Get the `Reflector` for this pointer.
    pub fn reflector<'a>(&'a self) -> &'a Reflector {
        unsafe {
            (**self.ptr).reflector()
        }
    }

    /// Returns an unsafe pointer to the interior of this object.
    pub unsafe fn unsafe_get(&self) -> *const T {
        *self.ptr
    }

    /// Create a stack-bounded root for this value.
    pub fn root(self) -> Root<T> {
        STACK_ROOTS.with(|ref collection| {
            let RootCollectionPtr(collection) = collection.get().unwrap();
            unsafe {
                Root::new(&*collection, self.ptr)
            }
        })
    }
}

impl<T> Copy for Unrooted<T> {}

/// A type that represents a JS-owned value that is rooted for the lifetime of
/// this value. Importantly, it requires explicit rooting in order to interact
/// with the inner value. Can be assigned into JS-owned member fields (i.e.
/// `JS<T>` types) safely via the `JS<T>::assign` method or
/// `OptionalSettable::assign` (for `Option<JS<T>>` fields).
#[allow(unrooted_must_root)]
pub struct Temporary<T> {
    inner: JS<T>,
    /// On-stack JS pointer to assuage conservative stack scanner
    _js_ptr: *mut JSObject,
}

impl<T> Clone for Temporary<T> {
    fn clone(&self) -> Temporary<T> {
        Temporary {
            inner: self.inner,
            _js_ptr: self._js_ptr,
        }
    }
}

impl<T> PartialEq for Temporary<T> {
    fn eq(&self, other: &Temporary<T>) -> bool {
        self.inner == other.inner
    }
}

impl<T: Reflectable> Temporary<T> {
    /// Create a new `Temporary` value from a JS-owned value.
    pub fn new(inner: JS<T>) -> Temporary<T> {
        Temporary {
            inner: inner,
            _js_ptr: inner.reflector().get_jsobject(),
        }
    }

    /// Create a new `Temporary` value from an unrooted value.
    #[allow(unrooted_must_root)]
    pub fn from_unrooted(unrooted: Unrooted<T>) -> Temporary<T> {
        Temporary {
            inner: JS { ptr: unrooted.ptr },
            _js_ptr: unrooted.reflector().get_jsobject(),
        }
    }

    /// Create a new `Temporary` value from a rooted value.
    pub fn from_rooted<'a>(root: JSRef<'a, T>) -> Temporary<T> {
        Temporary::new(JS::from_rooted(root))
    }

    /// Create a stack-bounded root for this value.
    pub fn root(&self) -> Root<T> {
        STACK_ROOTS.with(|ref collection| {
            let RootCollectionPtr(collection) = collection.get().unwrap();
            unsafe {
                Root::new(&*collection, self.inner.ptr)
            }
        })
    }

    unsafe fn inner(&self) -> JS<T> {
        self.inner.clone()
    }

    /// Returns `self` as a `Temporary` of another type. For use by
    /// `InheritTypes` only.
{'fraction_non_alphanumeric': 0.13117772703837371, 'fraction_numerical': 0.0008838476835825292, 'mean_word_length': 2.7906197654941374, 'pattern_counts': {'":': 0, '<': 120, '<?xml version=': 0, '>': 146, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4994352', 'n_tokens_mistral': 4316, 'n_tokens_neox': 4156, 'n_words': 1507}