<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 https://mozilla.org/MPL/2.0/. */

//! Native representation of JS Promise values.
//!
//! This implementation differs from the traditional Rust DOM object, because the reflector
//! is provided by SpiderMonkey and has no knowledge of an associated native representation
//! (ie. dom::Promise). This means that native instances use native reference counting (Rc)
//! to ensure that no memory is leaked, which means that there can be multiple instances of
//! native Promise values that refer to the same JS value yet are distinct native objects
//! (ie. address equality for the native objects is meaningless).

use crate::dom::bindings::conversions::root_from_object;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomObject, MutDomObject, Reflector};
use crate::dom::bindings::utils::AsCCharPtrPtr;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promisenativehandler::PromiseNativeHandler;
use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible;
use js::jsapi::{AddRawValueRoot, CallArgs, GetFunctionNativeReserved};
use js::jsapi::{Heap, JS_ClearPendingException};
use js::jsapi::{JSAutoCompartment, JSContext, JSObject, JS_GetFunctionObject};
use js::jsapi::{JS_NewFunction, NewFunctionWithReserved, PromiseState};
use js::jsapi::{RemoveRawValueRoot, SetFunctionNativeReserved};
use js::jsval::{Int32Value, JSVal, ObjectValue, UndefinedValue};
use js::rust::wrappers::{
    AddPromiseReactions, CallOriginalPromiseReject, CallOriginalPromiseResolve,
};
use js::rust::wrappers::{GetPromiseState, IsPromiseObject};
use js::rust::wrappers::{NewPromiseObject, RejectPromise, ResolvePromise};
use js::rust::{HandleObject, HandleValue, MutableHandleObject, Runtime};
use std::ptr;
use std::rc::Rc;

#[dom_struct]
#[allow_unrooted_in_rc]
pub struct Promise {
    reflector: Reflector,
    /// Since Promise values are natively reference counted without the knowledge of
    /// the SpiderMonkey GC, an explicit root for the reflector is stored while any
    /// native instance exists. This ensures that the reflector will never be GCed
    /// while native code could still interact with its native representation.
    #[ignore_malloc_size_of = "SM handles JS values"]
    permanent_js_root: Heap<JSVal>,
}

/// Private helper to enable adding new methods to Rc<Promise>.
trait PromiseHelper {
    #[allow(unsafe_code)]
    unsafe fn initialize(&self, cx: *mut JSContext);
}

impl PromiseHelper for Rc<Promise> {
    #[allow(unsafe_code)]
    unsafe fn initialize(&self, cx: *mut JSContext) {
        let obj = self.reflector().get_jsobject();
        self.permanent_js_root.set(ObjectValue(*obj));
        assert!(AddRawValueRoot(
            cx,
            self.permanent_js_root.get_unsafe(),
            b"Promise::root\0".as_c_char_ptr()
        ));
    }
}

impl Drop for Promise {
    #[allow(unsafe_code)]
    fn drop(&mut self) {
        unsafe {
            let object = self.permanent_js_root.get().to_object();
            assert!(!object.is_null());
            let cx = Runtime::get();
            assert!(!cx.is_null());
            RemoveRawValueRoot(cx, self.permanent_js_root.get_unsafe());
        }
    }
}

impl Promise {
    #[allow(unsafe_code)]
    pub unsafe fn new_in_current_compartment(global: &GlobalScope) -> Rc<Promise> {
        let cx = global.get_cx();
        rooted!(in(cx) let mut obj = ptr::null_mut::<JSObject>());
        Promise::create_js_promise(cx, HandleObject::null(), obj.handle_mut());
        Promise::new_with_js_promise(obj.handle(), cx)
    }<commit_msg>Add new consructor with &JSAutoCompartment parameter<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 https://mozilla.org/MPL/2.0/. */

//! Native representation of JS Promise values.
//!
//! This implementation differs from the traditional Rust DOM object, because the reflector
//! is provided by SpiderMonkey and has no knowledge of an associated native representation
//! (ie. dom::Promise). This means that native instances use native reference counting (Rc)
//! to ensure that no memory is leaked, which means that there can be multiple instances of
//! native Promise values that refer to the same JS value yet are distinct native objects
//! (ie. address equality for the native objects is meaningless).

use crate::dom::bindings::conversions::root_from_object;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomObject, MutDomObject, Reflector};
use crate::dom::bindings::utils::AsCCharPtrPtr;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promisenativehandler::PromiseNativeHandler;
use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible;
use js::jsapi::{AddRawValueRoot, CallArgs, GetFunctionNativeReserved};
use js::jsapi::{Heap, JS_ClearPendingException};
use js::jsapi::{JSAutoCompartment, JSContext, JSObject, JS_GetFunctionObject};
use js::jsapi::{JS_NewFunction, NewFunctionWithReserved, PromiseState};
use js::jsapi::{RemoveRawValueRoot, SetFunctionNativeReserved};
use js::jsval::{Int32Value, JSVal, ObjectValue, UndefinedValue};
use js::rust::wrappers::{
    AddPromiseReactions, CallOriginalPromiseReject, CallOriginalPromiseResolve,
};
use js::rust::wrappers::{GetPromiseState, IsPromiseObject};
use js::rust::wrappers::{NewPromiseObject, RejectPromise, ResolvePromise};
use js::rust::{HandleObject, HandleValue, MutableHandleObject, Runtime};
use std::ptr;
use std::rc::Rc;

#[dom_struct]
#[allow_unrooted_in_rc]
pub struct Promise {
    reflector: Reflector,
    /// Since Promise values are natively reference counted without the knowledge of
    /// the SpiderMonkey GC, an explicit root for the reflector is stored while any
    /// native instance exists. This ensures that the reflector will never be GCed
    /// while native code could still interact with its native representation.
    #[ignore_malloc_size_of = "SM handles JS values"]
    permanent_js_root: Heap<JSVal>,
}

/// Private helper to enable adding new methods to Rc<Promise>.
trait PromiseHelper {
    #[allow(unsafe_code)]
    unsafe fn initialize(&self, cx: *mut JSContext);
}

impl PromiseHelper for Rc<Promise> {
    #[allow(unsafe_code)]
    unsafe fn initialize(&self, cx: *mut JSContext) {
        let obj = self.reflector().get_jsobject();
        self.permanent_js_root.set(ObjectValue(*obj));
        assert!(AddRawValueRoot(
            cx,
            self.permanent_js_root.get_unsafe(),
            b"Promise::root\0".as_c_char_ptr()
        ));
    }
}

impl Drop for Promise {
    #[allow(unsafe_code)]
    fn drop(&mut self) {
        unsafe {
            let object = self.permanent_js_root.get().to_object();
            assert!(!object.is_null());
            let cx = Runtime::get();
            assert!(!cx.is_null());
            RemoveRawValueRoot(cx, self.permanent_js_root.get_unsafe());
        }
    }
}

impl Promise {
    #[allow(unsafe_code)]
    pub fn new(global: &GlobalScope, _comp: &JSAutoCompartment) -> Rc<Promise> {
        unsafe { Promise::new_in_current_compartment(global) }
    }

    #[allow(unsafe_code)]
    pub unsafe fn new_in_current_compartment(global: &GlobalScope) -> Rc<Promise> {
        let cx = global.get_cx();
        rooted!(in(cx) let mut obj = ptr::null_mut::<JSObject>());
        Promise::create_js_promise(cx, HandleObject::null(), obj.handle_mut());
        Promise::new_with_js_promise(obj.handle(), cx)
    }
{'fraction_non_alphanumeric': 0.11986035686578743, 'fraction_numerical': 0.0018101887768295836, 'mean_word_length': 4.412876137158852, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 17, 'https://': 2, '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': '1057020', 'n_tokens_mistral': 2261, 'n_tokens_neox': 2280, 'n_words': 655}