mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
More miscellaneous script splitting changes (#36220)
* script: Move HasParent to script_bindings and update imports for InheritTypes. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make principal creation generic over DOM interface. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Move a bunch of proxy-related code to script_bindings. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make some proxy-related code generic over the DOM interface. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Move DomSlice to script_bindings. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Move some utility bindings code to script_bindings. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make enumerating and resolving globals generic over the DOM interface. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make realm helpers generic over the DOM interface. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Move implementations on concrete DOM types to concrete bindings. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make additional codegen helpers generic over the DOM interface. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make iterator creation generic over the DOM interface. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make reporting an exception a generic operation. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Move AsCCharPtrPtr to script_bindings. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * Formatting. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * Address clippy warnings. Signed-off-by: Josh Matthews <josh@joshmatthews.net> --------- Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
971490084e
commit
b445053a7c
33 changed files with 806 additions and 628 deletions
494
components/script_bindings/proxyhandler.rs
Normal file
494
components/script_bindings/proxyhandler.rs
Normal file
|
@ -0,0 +1,494 @@
|
|||
/* 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/. */
|
||||
|
||||
//! Utilities for the implementation of JSAPI proxy handlers.
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr;
|
||||
|
||||
use js::glue::{GetProxyHandlerFamily, GetProxyPrivate, SetProxyPrivate};
|
||||
use js::jsapi::{
|
||||
DOMProxyShadowsResult, GetStaticPrototype, GetWellKnownSymbol, Handle as RawHandle,
|
||||
HandleId as RawHandleId, HandleObject as RawHandleObject, JS_AtomizeAndPinString,
|
||||
JS_DefinePropertyById, JS_GetOwnPropertyDescriptorById, JSContext, JSErrNum, JSFunctionSpec,
|
||||
JSObject, JSPropertySpec, MutableHandle as RawMutableHandle,
|
||||
MutableHandleIdVector as RawMutableHandleIdVector,
|
||||
MutableHandleObject as RawMutableHandleObject, ObjectOpResult, PropertyDescriptor,
|
||||
SetDOMProxyInformation, SymbolCode, jsid,
|
||||
};
|
||||
use js::jsid::SymbolId;
|
||||
use js::jsval::{ObjectValue, UndefinedValue};
|
||||
use js::rust::wrappers::{
|
||||
AppendToIdVector, JS_AlreadyHasOwnPropertyById, JS_NewObjectWithGivenProto,
|
||||
RUST_INTERNED_STRING_TO_JSID, SetDataPropertyDescriptor,
|
||||
};
|
||||
use js::rust::{Handle, HandleObject, HandleValue, MutableHandle, MutableHandleObject};
|
||||
use js::{jsapi, rooted};
|
||||
|
||||
use crate::conversions::{is_dom_proxy, jsid_to_string, jsstring_to_str};
|
||||
use crate::script_runtime::JSContext as SafeJSContext;
|
||||
use crate::str::DOMString;
|
||||
use crate::utils::delete_property_by_id;
|
||||
|
||||
/// Determine if this id shadows any existing properties for this proxy.
|
||||
///
|
||||
/// # Safety
|
||||
/// `cx` must point to a valid, non-null JSContext.
|
||||
pub unsafe extern "C" fn shadow_check_callback(
|
||||
cx: *mut JSContext,
|
||||
object: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
) -> DOMProxyShadowsResult {
|
||||
// TODO: support OverrideBuiltins when #12978 is fixed.
|
||||
|
||||
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
|
||||
get_expando_object(object, expando.handle_mut());
|
||||
if !expando.get().is_null() {
|
||||
let mut has_own = false;
|
||||
let raw_id = Handle::from_raw(id);
|
||||
|
||||
if !JS_AlreadyHasOwnPropertyById(cx, expando.handle(), raw_id, &mut has_own) {
|
||||
return DOMProxyShadowsResult::ShadowCheckFailed;
|
||||
}
|
||||
|
||||
if has_own {
|
||||
return DOMProxyShadowsResult::ShadowsViaDirectExpando;
|
||||
}
|
||||
}
|
||||
|
||||
// Our expando, if any, didn't shadow, so we're not shadowing at all.
|
||||
DOMProxyShadowsResult::DoesntShadow
|
||||
}
|
||||
|
||||
/// Initialize the infrastructure for DOM proxy objects.
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
SetDOMProxyInformation(
|
||||
GetProxyHandlerFamily(),
|
||||
Some(shadow_check_callback),
|
||||
ptr::null(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines an expando on the given `proxy`.
|
||||
///
|
||||
/// # Safety
|
||||
/// `cx` must point to a valid, non-null JSContext.
|
||||
/// `result` must point to a valid, non-null ObjectOpResult.
|
||||
pub unsafe extern "C" fn define_property(
|
||||
cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
desc: RawHandle<PropertyDescriptor>,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
|
||||
ensure_expando_object(cx, proxy, expando.handle_mut());
|
||||
JS_DefinePropertyById(cx, expando.handle().into(), id, desc, result)
|
||||
}
|
||||
|
||||
/// Deletes an expando off the given `proxy`.
|
||||
///
|
||||
/// # Safety
|
||||
/// `cx` must point to a valid, non-null JSContext.
|
||||
/// `bp` must point to a valid, non-null ObjectOpResult.
|
||||
pub unsafe extern "C" fn delete(
|
||||
cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
bp: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
|
||||
get_expando_object(proxy, expando.handle_mut());
|
||||
if expando.is_null() {
|
||||
(*bp).code_ = 0 /* OkCode */;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete_property_by_id(cx, expando.handle(), Handle::from_raw(id), bp)
|
||||
}
|
||||
|
||||
/// Controls whether the Extensible bit can be changed
|
||||
///
|
||||
/// # Safety
|
||||
/// `result` must point to a valid, non-null ObjectOpResult.
|
||||
pub unsafe extern "C" fn prevent_extensions(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
(*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as ::libc::uintptr_t;
|
||||
true
|
||||
}
|
||||
|
||||
/// Reports whether the object is Extensible
|
||||
///
|
||||
/// # Safety
|
||||
/// `succeeded` must point to a valid, non-null bool.
|
||||
pub unsafe extern "C" fn is_extensible(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
succeeded: *mut bool,
|
||||
) -> bool {
|
||||
*succeeded = true;
|
||||
true
|
||||
}
|
||||
|
||||
/// If `proxy` (underneath any functionally-transparent wrapper proxies) has as
|
||||
/// its `[[GetPrototypeOf]]` trap the ordinary `[[GetPrototypeOf]]` behavior
|
||||
/// defined for ordinary objects, set `*is_ordinary` to true and store `obj`'s
|
||||
/// prototype in `proto`. Otherwise set `*isOrdinary` to false. In case of
|
||||
/// error, both outparams have unspecified value.
|
||||
///
|
||||
/// This implementation always handles the case of the ordinary
|
||||
/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
|
||||
/// necessary for maybe-cross-origin objects.
|
||||
///
|
||||
/// # Safety
|
||||
/// `is_ordinary` must point to a valid, non-null bool.
|
||||
pub unsafe extern "C" fn get_prototype_if_ordinary(
|
||||
_: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
is_ordinary: *mut bool,
|
||||
proto: RawMutableHandleObject,
|
||||
) -> bool {
|
||||
*is_ordinary = true;
|
||||
proto.set(GetStaticPrototype(proxy.get()));
|
||||
true
|
||||
}
|
||||
|
||||
/// Get the expando object, or null if there is none.
|
||||
pub fn get_expando_object(obj: RawHandleObject, mut expando: MutableHandleObject) {
|
||||
unsafe {
|
||||
assert!(is_dom_proxy(obj.get()));
|
||||
let val = &mut UndefinedValue();
|
||||
GetProxyPrivate(obj.get(), val);
|
||||
expando.set(if val.is_undefined() {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
val.to_object()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the expando object, or create it if it doesn't exist yet.
|
||||
/// Fails on JSAPI failure.
|
||||
///
|
||||
/// # Safety
|
||||
/// `cx` must point to a valid, non-null JSContext.
|
||||
pub unsafe fn ensure_expando_object(
|
||||
cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
mut expando: MutableHandleObject,
|
||||
) {
|
||||
assert!(is_dom_proxy(obj.get()));
|
||||
get_expando_object(obj, expando.reborrow());
|
||||
if expando.is_null() {
|
||||
expando.set(JS_NewObjectWithGivenProto(
|
||||
cx,
|
||||
ptr::null_mut(),
|
||||
HandleObject::null(),
|
||||
));
|
||||
assert!(!expando.is_null());
|
||||
|
||||
SetProxyPrivate(obj.get(), &ObjectValue(expando.get()));
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the property descriptor's object to `obj` and set it to enumerable,
|
||||
/// and writable if `readonly` is true.
|
||||
pub fn set_property_descriptor(
|
||||
desc: MutableHandle<PropertyDescriptor>,
|
||||
value: HandleValue,
|
||||
attrs: u32,
|
||||
is_none: &mut bool,
|
||||
) {
|
||||
unsafe {
|
||||
SetDataPropertyDescriptor(desc, value, attrs);
|
||||
}
|
||||
*is_none = false;
|
||||
}
|
||||
|
||||
pub fn id_to_source(cx: SafeJSContext, id: RawHandleId) -> Option<DOMString> {
|
||||
unsafe {
|
||||
rooted!(in(*cx) let mut value = UndefinedValue());
|
||||
rooted!(in(*cx) let mut jsstr = ptr::null_mut::<jsapi::JSString>());
|
||||
jsapi::JS_IdToValue(*cx, id.get(), value.handle_mut().into())
|
||||
.then(|| {
|
||||
jsstr.set(jsapi::JS_ValueToSource(*cx, value.handle().into()));
|
||||
jsstr.get()
|
||||
})
|
||||
.and_then(ptr::NonNull::new)
|
||||
.map(|jsstr| jsstring_to_str(*cx, jsstr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Property and method specs that correspond to the elements of
|
||||
/// [`CrossOriginProperties(O)`].
|
||||
///
|
||||
/// [`CrossOriginProperties(O)`]: https://html.spec.whatwg.org/multipage/#crossoriginproperties-(-o-)
|
||||
pub struct CrossOriginProperties {
|
||||
pub attributes: &'static [JSPropertySpec],
|
||||
pub methods: &'static [JSFunctionSpec],
|
||||
}
|
||||
|
||||
impl CrossOriginProperties {
|
||||
/// Enumerate the property keys defined by `self`.
|
||||
fn keys(&self) -> impl Iterator<Item = *const c_char> + '_ {
|
||||
// Safety: All cross-origin property keys are strings, not symbols
|
||||
self.attributes
|
||||
.iter()
|
||||
.map(|spec| unsafe { spec.name.string_ })
|
||||
.chain(self.methods.iter().map(|spec| unsafe { spec.name.string_ }))
|
||||
.filter(|ptr| !ptr.is_null())
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of [`CrossOriginOwnPropertyKeys`].
|
||||
///
|
||||
/// [`CrossOriginOwnPropertyKeys`]: https://html.spec.whatwg.org/multipage/#crossoriginownpropertykeys-(-o-)
|
||||
pub fn cross_origin_own_property_keys(
|
||||
cx: SafeJSContext,
|
||||
_proxy: RawHandleObject,
|
||||
cross_origin_properties: &'static CrossOriginProperties,
|
||||
props: RawMutableHandleIdVector,
|
||||
) -> bool {
|
||||
// > 2. For each `e` of `! CrossOriginProperties(O)`, append
|
||||
// > `e.[[Property]]` to `keys`.
|
||||
for key in cross_origin_properties.keys() {
|
||||
unsafe {
|
||||
rooted!(in(*cx) let rooted = JS_AtomizeAndPinString(*cx, key));
|
||||
rooted!(in(*cx) let mut rooted_jsid: jsid);
|
||||
RUST_INTERNED_STRING_TO_JSID(*cx, rooted.handle().get(), rooted_jsid.handle_mut());
|
||||
AppendToIdVector(props, rooted_jsid.handle());
|
||||
}
|
||||
}
|
||||
|
||||
// > 3. Return the concatenation of `keys` and `« "then", @@toStringTag,
|
||||
// > @@hasInstance, @@isConcatSpreadable »`.
|
||||
append_cross_origin_allowlisted_prop_keys(cx, props);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// `is_ordinary` must point to a valid, non-null bool.
|
||||
pub unsafe extern "C" fn maybe_cross_origin_get_prototype_if_ordinary_rawcx(
|
||||
_: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
is_ordinary: *mut bool,
|
||||
_proto: RawMutableHandleObject,
|
||||
) -> bool {
|
||||
// We have a custom `[[GetPrototypeOf]]`, so return `false`
|
||||
*is_ordinary = false;
|
||||
true
|
||||
}
|
||||
|
||||
/// Implementation of `[[SetPrototypeOf]]` for [`Location`] and [`WindowProxy`].
|
||||
///
|
||||
/// [`Location`]: https://html.spec.whatwg.org/multipage/#location-setprototypeof
|
||||
/// [`WindowProxy`]: https://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof
|
||||
///
|
||||
/// # Safety
|
||||
/// `result` must point to a valid, non-null ObjectOpResult.
|
||||
pub unsafe extern "C" fn maybe_cross_origin_set_prototype_rawcx(
|
||||
cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
proto: RawHandleObject,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
// > 1. Return `! SetImmutablePrototype(this, V)`.
|
||||
//
|
||||
// <https://tc39.es/ecma262/#sec-set-immutable-prototype>:
|
||||
//
|
||||
// > 1. Assert: Either `Type(V)` is Object or `Type(V)` is Null.
|
||||
//
|
||||
// > 2. Let current be `? O.[[GetPrototypeOf]]()`.
|
||||
rooted!(in(cx) let mut current = ptr::null_mut::<JSObject>());
|
||||
if !jsapi::GetObjectProto(cx, proxy, current.handle_mut().into()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// > 3. If `SameValue(V, current)` is true, return true.
|
||||
if proto.get() == current.get() {
|
||||
(*result).code_ = 0 /* OkCode */;
|
||||
return true;
|
||||
}
|
||||
|
||||
// > 4. Return false.
|
||||
(*result).code_ = JSErrNum::JSMSG_CANT_SET_PROTO as usize;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn get_getter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) {
|
||||
if d.hasGetter_() {
|
||||
out.set(d.getter_);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_setter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) {
|
||||
if d.hasSetter_() {
|
||||
out.set(d.setter_);
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://tc39.es/ecma262/#sec-isaccessordescriptor>
|
||||
pub fn is_accessor_descriptor(d: &PropertyDescriptor) -> bool {
|
||||
d.hasSetter_() || d.hasGetter_()
|
||||
}
|
||||
|
||||
/// <https://tc39.es/ecma262/#sec-isdatadescriptor>
|
||||
pub fn is_data_descriptor(d: &PropertyDescriptor) -> bool {
|
||||
d.hasWritable_() || d.hasValue_()
|
||||
}
|
||||
|
||||
/// Evaluate `CrossOriginGetOwnPropertyHelper(proxy, id) != null`.
|
||||
/// SpiderMonkey-specific.
|
||||
///
|
||||
/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy
|
||||
/// for a maybe-cross-origin object.
|
||||
///
|
||||
/// # Safety
|
||||
/// `bp` must point to a valid, non-null bool.
|
||||
pub unsafe fn cross_origin_has_own(
|
||||
cx: SafeJSContext,
|
||||
_proxy: RawHandleObject,
|
||||
cross_origin_properties: &'static CrossOriginProperties,
|
||||
id: RawHandleId,
|
||||
bp: *mut bool,
|
||||
) -> bool {
|
||||
// TODO: Once we have the slot for the holder, it'd be more efficient to
|
||||
// use `ensure_cross_origin_property_holder`. We'll need `_proxy` to
|
||||
// do that.
|
||||
*bp = jsid_to_string(*cx, Handle::from_raw(id)).is_some_and(|key| {
|
||||
cross_origin_properties.keys().any(|defined_key| {
|
||||
let defined_key = CStr::from_ptr(defined_key);
|
||||
defined_key.to_bytes() == key.as_bytes()
|
||||
})
|
||||
});
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Implementation of [`CrossOriginGetOwnPropertyHelper`].
|
||||
///
|
||||
/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy
|
||||
/// for a maybe-cross-origin object.
|
||||
///
|
||||
/// [`CrossOriginGetOwnPropertyHelper`]: https://html.spec.whatwg.org/multipage/#crossorigingetownpropertyhelper-(-o,-p-)
|
||||
pub fn cross_origin_get_own_property_helper(
|
||||
cx: SafeJSContext,
|
||||
proxy: RawHandleObject,
|
||||
cross_origin_properties: &'static CrossOriginProperties,
|
||||
id: RawHandleId,
|
||||
desc: RawMutableHandle<PropertyDescriptor>,
|
||||
is_none: &mut bool,
|
||||
) -> bool {
|
||||
rooted!(in(*cx) let mut holder = ptr::null_mut::<JSObject>());
|
||||
|
||||
ensure_cross_origin_property_holder(
|
||||
cx,
|
||||
proxy,
|
||||
cross_origin_properties,
|
||||
holder.handle_mut().into(),
|
||||
);
|
||||
|
||||
unsafe { JS_GetOwnPropertyDescriptorById(*cx, holder.handle().into(), id, desc, is_none) }
|
||||
}
|
||||
|
||||
const ALLOWLISTED_SYMBOL_CODES: &[SymbolCode] = &[
|
||||
SymbolCode::toStringTag,
|
||||
SymbolCode::hasInstance,
|
||||
SymbolCode::isConcatSpreadable,
|
||||
];
|
||||
|
||||
pub fn is_cross_origin_allowlisted_prop(cx: SafeJSContext, id: RawHandleId) -> bool {
|
||||
unsafe {
|
||||
if jsid_to_string(*cx, Handle::from_raw(id)).is_some_and(|st| st == "then") {
|
||||
return true;
|
||||
}
|
||||
|
||||
rooted!(in(*cx) let mut allowed_id: jsid);
|
||||
ALLOWLISTED_SYMBOL_CODES.iter().any(|&allowed_code| {
|
||||
allowed_id.set(SymbolId(GetWellKnownSymbol(*cx, allowed_code)));
|
||||
// `jsid`s containing `JS::Symbol *` can be compared by
|
||||
// referential equality
|
||||
allowed_id.get().asBits_ == id.asBits_
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Append `« "then", @@toStringTag, @@hasInstance, @@isConcatSpreadable »` to
|
||||
/// `props`. This is used to implement [`CrossOriginOwnPropertyKeys`].
|
||||
///
|
||||
/// [`CrossOriginOwnPropertyKeys`]: https://html.spec.whatwg.org/multipage/#crossoriginownpropertykeys-(-o-)
|
||||
fn append_cross_origin_allowlisted_prop_keys(cx: SafeJSContext, props: RawMutableHandleIdVector) {
|
||||
unsafe {
|
||||
rooted!(in(*cx) let mut id: jsid);
|
||||
|
||||
let jsstring = JS_AtomizeAndPinString(*cx, c"then".as_ptr());
|
||||
rooted!(in(*cx) let rooted = jsstring);
|
||||
RUST_INTERNED_STRING_TO_JSID(*cx, rooted.handle().get(), id.handle_mut());
|
||||
AppendToIdVector(props, id.handle());
|
||||
|
||||
for &allowed_code in ALLOWLISTED_SYMBOL_CODES.iter() {
|
||||
id.set(SymbolId(GetWellKnownSymbol(*cx, allowed_code)));
|
||||
AppendToIdVector(props, id.handle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the holder for cross-origin properties for the current global of the
|
||||
/// `JSContext`, creating one and storing it in a slot of the proxy object if it
|
||||
/// doesn't exist yet.
|
||||
///
|
||||
/// This essentially creates a cache of [`CrossOriginGetOwnPropertyHelper`]'s
|
||||
/// results for all property keys.
|
||||
///
|
||||
/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy
|
||||
/// for a maybe-cross-origin object. The `out_holder` return value will always
|
||||
/// be in the Realm of `cx`.
|
||||
///
|
||||
/// [`CrossOriginGetOwnPropertyHelper`]: https://html.spec.whatwg.org/multipage/#crossorigingetownpropertyhelper-(-o,-p-)
|
||||
fn ensure_cross_origin_property_holder(
|
||||
cx: SafeJSContext,
|
||||
_proxy: RawHandleObject,
|
||||
cross_origin_properties: &'static CrossOriginProperties,
|
||||
out_holder: RawMutableHandleObject,
|
||||
) -> bool {
|
||||
// TODO: We don't have the slot to store the holder yet. For now,
|
||||
// the holder is constructed every time this function is called,
|
||||
// which is not only inefficient but also deviates from the
|
||||
// specification in a subtle yet observable way.
|
||||
|
||||
// Create a holder for the current Realm
|
||||
unsafe {
|
||||
out_holder.set(jsapi::JS_NewObjectWithGivenProto(
|
||||
*cx,
|
||||
ptr::null_mut(),
|
||||
RawHandleObject::null(),
|
||||
));
|
||||
|
||||
if out_holder.get().is_null() ||
|
||||
!jsapi::JS_DefineProperties(
|
||||
*cx,
|
||||
out_holder.handle(),
|
||||
cross_origin_properties.attributes.as_ptr(),
|
||||
) ||
|
||||
!jsapi::JS_DefineFunctions(
|
||||
*cx,
|
||||
out_holder.handle(),
|
||||
cross_origin_properties.methods.as_ptr(),
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Store the holder in the slot that we don't have yet.
|
||||
|
||||
true
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue