mirror of
https://github.com/servo/servo.git
synced 2025-06-17 21:04:28 +00:00
feat(script): Implement [[Set]]
for Location
This commit is contained in:
parent
80cda12a87
commit
4bc3453174
2 changed files with 123 additions and 3 deletions
|
@ -3554,6 +3554,10 @@ class CGDefineProxyHandler(CGAbstractMethod):
|
|||
# confused with ECMAScript's `[[SetImmutablePrototype]]`) always fails.
|
||||
# This is the desired behavior, so we don't override it.
|
||||
|
||||
customSet = 'None'
|
||||
if self.descriptor.isMaybeCrossOriginObject():
|
||||
customSet = 'Some(set)'
|
||||
|
||||
getOwnEnumerablePropertyKeys = "own_property_keys"
|
||||
if self.descriptor.interface.getExtendedAttribute("LegacyUnenumerableNamedProperties"):
|
||||
getOwnEnumerablePropertyKeys = "getOwnEnumerablePropertyKeys"
|
||||
|
@ -3564,6 +3568,7 @@ class CGDefineProxyHandler(CGAbstractMethod):
|
|||
"getPrototypeIfOrdinary": customGetPrototypeIfOrdinary,
|
||||
"getPrototype": customGetPrototype,
|
||||
"setPrototype": customSetPrototype,
|
||||
"set": customSet,
|
||||
"getOwnEnumerablePropertyKeys": getOwnEnumerablePropertyKeys,
|
||||
"trace": TRACE_HOOK_NAME,
|
||||
"finalize": FINALIZE_HOOK_NAME,
|
||||
|
@ -3585,7 +3590,7 @@ let traps = ProxyTraps {
|
|||
isExtensible: Some(proxyhandler::is_extensible),
|
||||
has: None,
|
||||
get: Some(get),
|
||||
set: None,
|
||||
set: %(set)s,
|
||||
call: None,
|
||||
construct: None,
|
||||
hasOwn: Some(hasOwn),
|
||||
|
@ -5951,12 +5956,61 @@ return true;""" % (maybeCrossOriginGet, getIndexedOrExpando, getNamed)
|
|||
return CGGeneric(self.getBody())
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler_set(CGAbstractExternMethod):
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('*mut JSContext', 'cx'), Argument('RawHandleObject', 'proxy'),
|
||||
Argument('RawHandleId', 'id'), Argument('RawHandleValue', 'v'),
|
||||
Argument('RawHandleValue', 'receiver'),
|
||||
Argument('*mut ObjectOpResult', 'opresult')]
|
||||
CGAbstractExternMethod.__init__(self, descriptor, "set", "bool", args)
|
||||
self.descriptor = descriptor
|
||||
|
||||
def getBody(self):
|
||||
descriptor = self.descriptor
|
||||
|
||||
# `CGDOMJSProxyHandler_set` doesn't support legacy platform objects'
|
||||
# `[[Set]]` (https://heycam.github.io/webidl/#legacy-platform-object-set) yet.
|
||||
#
|
||||
assert descriptor.isMaybeCrossOriginObject()
|
||||
assert not descriptor.operations['IndexedGetter']
|
||||
assert not descriptor.operations['NamedGetter']
|
||||
|
||||
maybeCrossOriginSet = dedent(
|
||||
"""
|
||||
if !proxyhandler::is_platform_object_same_origin(cx, proxy) {
|
||||
return proxyhandler::cross_origin_set(cx, proxy, id, v, receiver, opresult);
|
||||
}
|
||||
|
||||
// Safe to enter the Realm of proxy now.
|
||||
let _ac = JSAutoRealm::new(*cx, proxy.get());
|
||||
""")
|
||||
|
||||
return dedent(
|
||||
"""
|
||||
let cx = SafeJSContext::from_ptr(cx);
|
||||
%(maybeCrossOriginSet)s
|
||||
|
||||
// OrdinarySet
|
||||
// <https://tc39.es/ecma262/#sec-ordinaryset>
|
||||
rooted!(in(*cx) let mut own_desc = PropertyDescriptor::default());
|
||||
if !getOwnPropertyDescriptor(*cx, proxy, id, own_desc.handle_mut().into()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
js::jsapi::SetPropertyIgnoringNamedGetter(
|
||||
*cx, proxy, id, v, receiver, own_desc.handle().into(), opresult)
|
||||
""") % { "maybeCrossOriginSet": maybeCrossOriginSet }
|
||||
|
||||
def definition_body(self):
|
||||
return CGGeneric(self.getBody())
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler_getPrototype(CGAbstractExternMethod):
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('*mut JSContext', 'cx'), Argument('RawHandleObject', 'proxy'),
|
||||
Argument('RawMutableHandleObject', 'proto')]
|
||||
CGAbstractExternMethod.__init__(self, descriptor, "getPrototype", "bool", args)
|
||||
assert self.descriptor.isMaybeCrossOriginObject()
|
||||
assert descriptor.isMaybeCrossOriginObject()
|
||||
self.descriptor = descriptor
|
||||
|
||||
def getBody(self):
|
||||
|
@ -6636,7 +6690,7 @@ class CGDescriptor(CGThing):
|
|||
|
||||
if descriptor.isMaybeCrossOriginObject():
|
||||
cgThings.append(CGDOMJSProxyHandler_getPrototype(descriptor))
|
||||
# TODO: CGDOMJSProxyHandler_set(descriptor),
|
||||
cgThings.append(CGDOMJSProxyHandler_set(descriptor))
|
||||
pass
|
||||
|
||||
# cgThings.append(CGDOMJSProxyHandler(descriptor))
|
||||
|
|
|
@ -436,12 +436,78 @@ pub unsafe fn cross_origin_get(
|
|||
)
|
||||
}
|
||||
|
||||
/// Implementation of [`CrossOriginSet`].
|
||||
///
|
||||
/// [`CrossOriginSet`]: https://html.spec.whatwg.org/multipage/#crossoriginset-(-o,-p,-v,-receiver-)
|
||||
pub unsafe fn cross_origin_set(
|
||||
cx: SafeJSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
v: RawHandleValue,
|
||||
receiver: RawHandleValue,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
// > 1. Let desc be ? O.[[GetOwnProperty]](P).
|
||||
rooted!(in(*cx) let mut descriptor = PropertyDescriptor::default());
|
||||
if !InvokeGetOwnPropertyDescriptor(
|
||||
GetProxyHandler(*proxy),
|
||||
*cx,
|
||||
proxy,
|
||||
id,
|
||||
descriptor.handle_mut().into(),
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// > 2. Assert: desc is not undefined.
|
||||
assert!(
|
||||
!descriptor.obj.is_null(),
|
||||
"Callees should throw in all cases when they are not finding \
|
||||
a property decriptor"
|
||||
);
|
||||
|
||||
// > 3. If desc.[[Set]] is present and its value is not undefined,
|
||||
// > then: [...]
|
||||
rooted!(in(*cx) let mut setter = ptr::null_mut::<JSObject>());
|
||||
get_setter_object(&descriptor, setter.handle_mut().into());
|
||||
if setter.get().is_null() {
|
||||
// > 4. Throw a "SecurityError" DOMException.
|
||||
return report_cross_origin_denial(cx, id, "set");
|
||||
}
|
||||
|
||||
rooted!(in(*cx) let mut setter_jsval = UndefinedValue());
|
||||
setter.get().to_jsval(*cx, setter_jsval.handle_mut());
|
||||
|
||||
// > 3.1. Perform ? Call(setter, Receiver, «V»).
|
||||
// >
|
||||
// > 3.2. Return true.
|
||||
rooted!(in(*cx) let mut ignored = UndefinedValue());
|
||||
if !jsapi::Call(
|
||||
*cx,
|
||||
receiver,
|
||||
setter_jsval.handle().into(),
|
||||
&jsapi::HandleValueArray::from_rooted_slice(&[v.get()]),
|
||||
ignored.handle_mut().into(),
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
(*result).code_ = 0 /* OkCode */;
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn get_getter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) {
|
||||
if (d.attrs & jsapi::JSPROP_GETTER as u32) != 0 {
|
||||
out.set(std::mem::transmute(d.getter));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_setter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) {
|
||||
if (d.attrs & jsapi::JSPROP_SETTER as u32) != 0 {
|
||||
out.set(std::mem::transmute(d.setter));
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://tc39.es/ecma262/#sec-isaccessordescriptor>
|
||||
fn is_accessor_descriptor(d: &PropertyDescriptor) -> bool {
|
||||
d.attrs & (jsapi::JSPROP_GETTER as u32 | jsapi::JSPROP_SETTER as u32) != 0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue