Bug 1822712 - Implment ProxyGetOwnPropertyDescriptorFromExpando as its accessible under some circumstances r=jandem

Originally proxy support was implemented such that we expected to never invoke
getOwnPropertyDescriptor for a proxy with a private field expando. However, it
turns out that when the proxy returns true for hasPrototype() this is actually
possible; implementation is relatively simple fortunately.

Differential Revision: https://phabricator.services.mozilla.com/D173563
This commit is contained in:
Matthew Gaudet 2023-03-27 15:12:13 +00:00
Родитель 6ddf4bfdad
Коммит 93629f90e9
2 изменённых файлов: 47 добавлений и 4 удалений

Просмотреть файл

@ -59,6 +59,18 @@ static bool ProxySetOnExpando(JSContext* cx, HandleObject proxy, HandleId id,
ownDesc, result);
}
static bool ProxyGetOwnPropertyDescriptorFromExpando(
JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<mozilla::Maybe<PropertyDescriptor>> desc) {
RootedObject expando(cx, proxy->as<ProxyObject>().expando().toObjectOrNull());
if (!expando) {
return true;
}
return GetOwnPropertyDescriptor(cx, expando, id, desc);
}
static bool ProxyGetOnExpando(JSContext* cx, HandleObject proxy,
HandleValue receiver, HandleId id,
MutableHandleValue vp) {
@ -185,10 +197,9 @@ bool Proxy::getOwnPropertyDescriptor(
return policy.returnValue();
}
// Unless we implment ProxyGetOwnPropertyDescriptorFromExpando,
// this would be incorrect.
MOZ_ASSERT_IF(handler->useProxyExpandoObjectForPrivateFields(),
!id.isPrivateName());
if (handler->useProxyExpandoObjectForPrivateFields() && id.isPrivateName()) {
return ProxyGetOwnPropertyDescriptorFromExpando(cx, proxy, id, desc);
}
return handler->getOwnPropertyDescriptor(cx, proxy, id, desc);
}

32
js/src/tests/non262/PrivateName/prototype-proxy.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,32 @@
// |reftest| skip-if(!this.hasOwnProperty("wrapWithProto"))
const o0 = {};
const v2 = new Proxy(o0, o0);
// v8 is a forwarding proxy with "prototype" behaviour;
// see the comment for mHasPrototype on BaseProxyHandler
// in Proxy.h.
//
// Private Fields don't interact with the hasPrototype
// behaviour (to minimize the overhead, and since private
// fields are always own properties).
const v8 = this.wrapWithProto(v2, {});
function f9(a10) {
return v8;
}
class C11 extends f9 {
#b = 12;
static {
const v13 = new this();
const val = v8.#b; // Get
assertEq(val, 12);
v8.#b = 0; // Set
assertEq(v8.#b, 0);
assertEq(#b in v8, true); // HasOwn.
}
}
if (typeof reportCompare === 'function') reportCompare(0, 0);