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.
|
# confused with ECMAScript's `[[SetImmutablePrototype]]`) always fails.
|
||||||
# This is the desired behavior, so we don't override it.
|
# This is the desired behavior, so we don't override it.
|
||||||
|
|
||||||
|
customSet = 'None'
|
||||||
|
if self.descriptor.isMaybeCrossOriginObject():
|
||||||
|
customSet = 'Some(set)'
|
||||||
|
|
||||||
getOwnEnumerablePropertyKeys = "own_property_keys"
|
getOwnEnumerablePropertyKeys = "own_property_keys"
|
||||||
if self.descriptor.interface.getExtendedAttribute("LegacyUnenumerableNamedProperties"):
|
if self.descriptor.interface.getExtendedAttribute("LegacyUnenumerableNamedProperties"):
|
||||||
getOwnEnumerablePropertyKeys = "getOwnEnumerablePropertyKeys"
|
getOwnEnumerablePropertyKeys = "getOwnEnumerablePropertyKeys"
|
||||||
|
@ -3564,6 +3568,7 @@ class CGDefineProxyHandler(CGAbstractMethod):
|
||||||
"getPrototypeIfOrdinary": customGetPrototypeIfOrdinary,
|
"getPrototypeIfOrdinary": customGetPrototypeIfOrdinary,
|
||||||
"getPrototype": customGetPrototype,
|
"getPrototype": customGetPrototype,
|
||||||
"setPrototype": customSetPrototype,
|
"setPrototype": customSetPrototype,
|
||||||
|
"set": customSet,
|
||||||
"getOwnEnumerablePropertyKeys": getOwnEnumerablePropertyKeys,
|
"getOwnEnumerablePropertyKeys": getOwnEnumerablePropertyKeys,
|
||||||
"trace": TRACE_HOOK_NAME,
|
"trace": TRACE_HOOK_NAME,
|
||||||
"finalize": FINALIZE_HOOK_NAME,
|
"finalize": FINALIZE_HOOK_NAME,
|
||||||
|
@ -3585,7 +3590,7 @@ let traps = ProxyTraps {
|
||||||
isExtensible: Some(proxyhandler::is_extensible),
|
isExtensible: Some(proxyhandler::is_extensible),
|
||||||
has: None,
|
has: None,
|
||||||
get: Some(get),
|
get: Some(get),
|
||||||
set: None,
|
set: %(set)s,
|
||||||
call: None,
|
call: None,
|
||||||
construct: None,
|
construct: None,
|
||||||
hasOwn: Some(hasOwn),
|
hasOwn: Some(hasOwn),
|
||||||
|
@ -5951,12 +5956,61 @@ return true;""" % (maybeCrossOriginGet, getIndexedOrExpando, getNamed)
|
||||||
return CGGeneric(self.getBody())
|
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):
|
class CGDOMJSProxyHandler_getPrototype(CGAbstractExternMethod):
|
||||||
def __init__(self, descriptor):
|
def __init__(self, descriptor):
|
||||||
args = [Argument('*mut JSContext', 'cx'), Argument('RawHandleObject', 'proxy'),
|
args = [Argument('*mut JSContext', 'cx'), Argument('RawHandleObject', 'proxy'),
|
||||||
Argument('RawMutableHandleObject', 'proto')]
|
Argument('RawMutableHandleObject', 'proto')]
|
||||||
CGAbstractExternMethod.__init__(self, descriptor, "getPrototype", "bool", args)
|
CGAbstractExternMethod.__init__(self, descriptor, "getPrototype", "bool", args)
|
||||||
assert self.descriptor.isMaybeCrossOriginObject()
|
assert descriptor.isMaybeCrossOriginObject()
|
||||||
self.descriptor = descriptor
|
self.descriptor = descriptor
|
||||||
|
|
||||||
def getBody(self):
|
def getBody(self):
|
||||||
|
@ -6636,7 +6690,7 @@ class CGDescriptor(CGThing):
|
||||||
|
|
||||||
if descriptor.isMaybeCrossOriginObject():
|
if descriptor.isMaybeCrossOriginObject():
|
||||||
cgThings.append(CGDOMJSProxyHandler_getPrototype(descriptor))
|
cgThings.append(CGDOMJSProxyHandler_getPrototype(descriptor))
|
||||||
# TODO: CGDOMJSProxyHandler_set(descriptor),
|
cgThings.append(CGDOMJSProxyHandler_set(descriptor))
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# cgThings.append(CGDOMJSProxyHandler(descriptor))
|
# 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) {
|
unsafe fn get_getter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) {
|
||||||
if (d.attrs & jsapi::JSPROP_GETTER as u32) != 0 {
|
if (d.attrs & jsapi::JSPROP_GETTER as u32) != 0 {
|
||||||
out.set(std::mem::transmute(d.getter));
|
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>
|
/// <https://tc39.es/ecma262/#sec-isaccessordescriptor>
|
||||||
fn is_accessor_descriptor(d: &PropertyDescriptor) -> bool {
|
fn is_accessor_descriptor(d: &PropertyDescriptor) -> bool {
|
||||||
d.attrs & (jsapi::JSPROP_GETTER as u32 | jsapi::JSPROP_SETTER as u32) != 0
|
d.attrs & (jsapi::JSPROP_GETTER as u32 | jsapi::JSPROP_SETTER as u32) != 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue