feat(script): implement the last step of CrossOriginOwnPropertyKeys

This commit is contained in:
yvt 2021-07-17 14:20:31 +09:00
parent 1bcbdae27b
commit 75242d6c4c

View file

@ -46,7 +46,7 @@ use js::rust::wrappers::JS_AlreadyHasOwnPropertyById;
use js::rust::wrappers::JS_NewObjectWithGivenProto; use js::rust::wrappers::JS_NewObjectWithGivenProto;
use js::rust::wrappers::{AppendToIdVector, RUST_INTERNED_STRING_TO_JSID}; use js::rust::wrappers::{AppendToIdVector, RUST_INTERNED_STRING_TO_JSID};
use js::rust::{get_context_realm, Handle, HandleObject, MutableHandle, MutableHandleObject}; use js::rust::{get_context_realm, Handle, HandleObject, MutableHandle, MutableHandleObject};
use std::{ffi::CStr, ptr}; use std::{ffi::CStr, os::raw::c_char, ptr};
/// Determine if this id shadows any existing properties for this proxy. /// Determine if this id shadows any existing properties for this proxy.
pub unsafe extern "C" fn shadow_check_callback( pub unsafe extern "C" fn shadow_check_callback(
@ -294,6 +294,8 @@ pub unsafe fn cross_origin_own_property_keys(
cross_origin_properties: &'static CrossOriginProperties, cross_origin_properties: &'static CrossOriginProperties,
props: RawMutableHandleIdVector, props: RawMutableHandleIdVector,
) -> bool { ) -> bool {
// > 2. For each `e` of `! CrossOriginProperties(O)`, append
// > `e.[[Property]]` to `keys`.
for key in cross_origin_properties.keys() { for key in cross_origin_properties.keys() {
let jsstring = JS_AtomizeAndPinString(*cx, key); let jsstring = JS_AtomizeAndPinString(*cx, key);
rooted!(in(*cx) let rooted = jsstring); rooted!(in(*cx) let rooted = jsstring);
@ -301,6 +303,11 @@ pub unsafe fn cross_origin_own_property_keys(
RUST_INTERNED_STRING_TO_JSID(*cx, rooted.handle().get(), rooted_jsid.handle_mut()); RUST_INTERNED_STRING_TO_JSID(*cx, rooted.handle().get(), rooted_jsid.handle_mut());
AppendToIdVector(props, rooted_jsid.handle()); 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 true
} }
@ -626,13 +633,13 @@ pub unsafe fn cross_origin_property_fallback(
report_cross_origin_denial(cx, id, "access") report_cross_origin_denial(cx, id, "access")
} }
unsafe fn is_cross_origin_allowlisted_prop(cx: SafeJSContext, id: RawHandleId) -> bool {
const ALLOWLISTED_SYMBOL_CODES: &[SymbolCode] = &[ const ALLOWLISTED_SYMBOL_CODES: &[SymbolCode] = &[
SymbolCode::toStringTag, SymbolCode::toStringTag,
SymbolCode::hasInstance, SymbolCode::hasInstance,
SymbolCode::isConcatSpreadable, SymbolCode::isConcatSpreadable,
]; ];
unsafe fn is_cross_origin_allowlisted_prop(cx: SafeJSContext, id: RawHandleId) -> bool {
crate::dom::bindings::conversions::jsid_to_string(*cx, Handle::from_raw(id)) crate::dom::bindings::conversions::jsid_to_string(*cx, Handle::from_raw(id))
.filter(|st| st == "then") .filter(|st| st == "then")
.is_some() || .is_some() ||
@ -650,6 +657,31 @@ unsafe fn is_cross_origin_allowlisted_prop(cx: SafeJSContext, id: RawHandleId) -
} }
} }
/// Append `« "then", @@toStringTag, @@hasInstance, @@isConcatSpreadable »` to
/// `props`. This is used to implement [`CrossOriginOwnPropertyKeys`].
///
/// [`CrossOriginOwnPropertyKeys`]: https://html.spec.whatwg.org/multipage/#crossoriginownpropertykeys-(-o-)
unsafe fn append_cross_origin_allowlisted_prop_keys(
cx: SafeJSContext,
props: RawMutableHandleIdVector,
) {
rooted!(in(*cx) let mut id: jsid);
{
let jsstring = JS_AtomizeAndPinString(*cx, b"then\0".as_ptr() as *const c_char);
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() {
RUST_SYMBOL_TO_JSID(
GetWellKnownSymbol(*cx, allowed_code),
id.handle_mut().into(),
);
AppendToIdVector(props, id.handle());
}
}
/// Get the holder for cross-origin properties for the current global of the /// 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 /// `JSContext`, creating one and storing it in a slot of the proxy object if it
/// doesn't exist yet. /// doesn't exist yet.