mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 783829 - Rename Proxy enumerate trap to getEnumerablePropertyKeys. r=efaust
This commit is contained in:
parent
153abdea91
commit
12ee966a97
@ -620,8 +620,6 @@ public:
|
||||
virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id,
|
||||
bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
bool *succeeded) const MOZ_OVERRIDE;
|
||||
@ -649,6 +647,8 @@ public:
|
||||
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
unsigned flags,
|
||||
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
||||
@ -829,22 +829,6 @@ nsOuterWindowProxy::delete_(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
return js::Wrapper::delete_(cx, proxy, id, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const
|
||||
{
|
||||
// Just our indexed stuff followed by our "normal" own property names.
|
||||
if (!AppendIndexedPropertyNames(cx, proxy, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::AutoIdVector innerProps(cx);
|
||||
if (!js::Wrapper::enumerate(cx, proxy, innerProps)) {
|
||||
return false;
|
||||
}
|
||||
return js::AppendUnique(cx, props, innerProps);
|
||||
}
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::preventExtensions(JSContext *cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
@ -942,6 +926,23 @@ nsOuterWindowProxy::getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObj
|
||||
return js::BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
|
||||
}
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::getEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const
|
||||
{
|
||||
// Just our indexed stuff followed by our "normal" own property names.
|
||||
if (!AppendIndexedPropertyNames(cx, proxy, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::AutoIdVector innerProps(cx);
|
||||
if (!js::Wrapper::getEnumerablePropertyKeys(cx, proxy, innerProps)) {
|
||||
return false;
|
||||
}
|
||||
return js::AppendUnique(cx, props, innerProps);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::iterate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
unsigned flags, JS::MutableHandle<JS::Value> vp) const
|
||||
|
@ -267,18 +267,6 @@ DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseDOMProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
AutoIdVector& props) const
|
||||
{
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
if (!JS_GetPrototype(cx, proxy, &proto)) {
|
||||
return false;
|
||||
}
|
||||
return getOwnEnumerablePropertyKeys(cx, proxy, props) &&
|
||||
(!proto || js::GetPropertyKeys(cx, proto, 0, &props));
|
||||
}
|
||||
|
||||
bool
|
||||
BaseDOMProxyHandler::watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::Handle<JSObject*> callable) const
|
||||
@ -308,6 +296,19 @@ BaseDOMProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
|
||||
return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
|
||||
}
|
||||
|
||||
bool
|
||||
BaseDOMProxyHandler::getEnumerablePropertyKeys(JSContext* cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
AutoIdVector& props) const
|
||||
{
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
if (!JS_GetPrototype(cx, proxy, &proto)) {
|
||||
return false;
|
||||
}
|
||||
return getOwnEnumerablePropertyKeys(cx, proxy, props) &&
|
||||
(!proto || js::GetPropertyKeys(cx, proto, 0, &props));
|
||||
}
|
||||
|
||||
bool
|
||||
DOMProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const
|
||||
{
|
||||
|
@ -57,8 +57,6 @@ public:
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector& props) const MOZ_OVERRIDE;
|
||||
|
||||
bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id,
|
||||
@ -71,6 +69,8 @@ public:
|
||||
// unnecessary work during enumeration.
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
bool getEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector& props) const MOZ_OVERRIDE;
|
||||
|
||||
bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
|
||||
|
@ -93,7 +93,6 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
|
||||
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
@ -109,6 +108,8 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool hasInstance(JSContext *cx, HandleObject proxy,
|
||||
MutableHandleValue v, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
|
||||
@ -262,18 +263,6 @@ WrapperOwner::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
return ok(cx, status);
|
||||
}
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const
|
||||
{
|
||||
FORWARD(enumerate, (cx, proxy, props));
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
{
|
||||
return getPropertyKeys(cx, proxy, 0, props);
|
||||
}
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const
|
||||
{
|
||||
@ -478,6 +467,18 @@ WrapperOwner::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, Au
|
||||
return getPropertyKeys(cx, proxy, JSITER_OWNONLY, props);
|
||||
}
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props) const
|
||||
{
|
||||
FORWARD(getEnumerablePropertyKeys, (cx, proxy, props));
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
{
|
||||
return getPropertyKeys(cx, proxy, 0, props);
|
||||
}
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const
|
||||
{
|
||||
|
@ -39,7 +39,6 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||
bool preventExtensions(JSContext *cx, JS::HandleObject proxy, bool *succeeded);
|
||||
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
||||
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||
@ -56,6 +55,8 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||
bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::HandleObject proxy,
|
||||
JS::AutoIdVector &props);
|
||||
bool getEnumerablePropertyKeys(JSContext *cx, JS::HandleObject proxy,
|
||||
JS::AutoIdVector &props);
|
||||
// We use "iterate" provided by the base class here.
|
||||
bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
|
||||
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
||||
|
@ -305,7 +305,7 @@ Snapshot(JSContext *cx, HandleObject pobj_, unsigned flags, AutoIdVector *props)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!Proxy::enumerate(cx, pobj, proxyProps))
|
||||
if (!Proxy::getEnumerablePropertyKeys(cx, pobj, proxyProps))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,6 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const = 0;
|
||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const = 0;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const = 0;
|
||||
|
||||
/*
|
||||
* These methods are standard, but the engine does not normally call them.
|
||||
@ -306,6 +305,8 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const = 0;
|
||||
virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp) const;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args) const;
|
||||
@ -367,8 +368,6 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
|
||||
MutableHandleObject protop) const MOZ_OVERRIDE;
|
||||
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
|
||||
@ -393,6 +392,8 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
|
||||
bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
|
@ -121,7 +121,6 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
|
||||
MutableHandleObject protop) const MOZ_OVERRIDE;
|
||||
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
|
||||
@ -144,6 +143,8 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
virtual bool hasOwn(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, HandleObject wrapper, unsigned flags,
|
||||
MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
|
@ -205,7 +205,7 @@ BaseProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
AutoIdVector props(cx);
|
||||
if ((flags & JSITER_OWNONLY)
|
||||
? !getOwnEnumerablePropertyKeys(cx, proxy, props)
|
||||
: !enumerate(cx, proxy, props)) {
|
||||
: !getEnumerablePropertyKeys(cx, proxy, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -77,15 +77,6 @@ CrossCompartmentWrapper::delete_(JSContext *cx, HandleObject wrapper, HandleId i
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const
|
||||
{
|
||||
PIERCE(cx, wrapper,
|
||||
NOTHING,
|
||||
Wrapper::enumerate(cx, wrapper, props),
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper,
|
||||
MutableHandleObject protop) const
|
||||
@ -197,6 +188,16 @@ CrossCompartmentWrapper::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObjec
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::getEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
PIERCE(cx, wrapper,
|
||||
NOTHING,
|
||||
Wrapper::getEnumerablePropertyKeys(cx, wrapper, props),
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
/*
|
||||
* We can reify non-escaping iterator objects instead of having to wrap them. This
|
||||
* allows fast iteration over objects across a compartment boundary.
|
||||
|
@ -54,7 +54,8 @@ DeadObjectProxy::delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool
|
||||
}
|
||||
|
||||
bool
|
||||
DeadObjectProxy::enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const
|
||||
DeadObjectProxy::getEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
|
@ -26,7 +26,6 @@ class DeadObjectProxy : public BaseProxyHandler
|
||||
virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
|
||||
MutableHandleObject protop) const MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
|
||||
@ -37,6 +36,8 @@ class DeadObjectProxy : public BaseProxyHandler
|
||||
/* SpiderMonkey extensions. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
CallArgs args) const MOZ_OVERRIDE;
|
||||
virtual bool hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
|
||||
|
@ -67,16 +67,6 @@ DirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool
|
||||
return JSObject::deleteGeneric(cx, target, id, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
|
||||
MOZ_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetPropertyKeys(cx, target, 0, &props);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args) const
|
||||
{
|
||||
@ -252,6 +242,16 @@ DirectProxyHandler::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject pro
|
||||
return GetPropertyKeys(cx, target, JSITER_OWNONLY, &props);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
|
||||
MOZ_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetPropertyKeys(cx, target, 0, &props);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp) const
|
||||
|
@ -206,24 +206,6 @@ js::AppendUnique(JSContext *cx, AutoIdVector &base, AutoIdVector &others)
|
||||
return base.appendAll(uniqueOthers);
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
|
||||
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE, BaseProxyHandler::ENUMERATE, true);
|
||||
if (!policy.allowed())
|
||||
return policy.returnValue();
|
||||
if (!handler->hasPrototype())
|
||||
return proxy->as<ProxyObject>().handler()->enumerate(cx, proxy, props);
|
||||
if (!handler->getOwnEnumerablePropertyKeys(cx, proxy, props))
|
||||
return false;
|
||||
AutoIdVector protoProps(cx);
|
||||
INVOKE_ON_PROTOTYPE(cx, handler, proxy,
|
||||
GetPropertyKeys(cx, proto, 0, &protoProps) &&
|
||||
AppendUnique(cx, props, protoProps));
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Proxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject proto)
|
||||
{
|
||||
@ -384,6 +366,24 @@ Proxy::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVec
|
||||
return handler->getOwnEnumerablePropertyKeys(cx, proxy, props);
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
|
||||
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE, BaseProxyHandler::ENUMERATE, true);
|
||||
if (!policy.allowed())
|
||||
return policy.returnValue();
|
||||
if (!handler->hasPrototype())
|
||||
return proxy->as<ProxyObject>().handler()->getEnumerablePropertyKeys(cx, proxy, props);
|
||||
if (!handler->getOwnEnumerablePropertyKeys(cx, proxy, props))
|
||||
return false;
|
||||
AutoIdVector protoProps(cx);
|
||||
INVOKE_ON_PROTOTYPE(cx, handler, proxy,
|
||||
GetPropertyKeys(cx, proto, 0, &protoProps) &&
|
||||
AppendUnique(cx, props, protoProps));
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp)
|
||||
{
|
||||
@ -406,7 +406,7 @@ Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleV
|
||||
// The other Proxy::foo methods do the prototype-aware work for us here.
|
||||
if ((flags & JSITER_OWNONLY)
|
||||
? !Proxy::getOwnEnumerablePropertyKeys(cx, proxy, props)
|
||||
: !Proxy::enumerate(cx, proxy, props)) {
|
||||
: !Proxy::getEnumerablePropertyKeys(cx, proxy, props)) {
|
||||
return false;
|
||||
}
|
||||
return EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp);
|
||||
|
@ -34,7 +34,6 @@ class Proxy
|
||||
MutableHandle<JSPropertyDescriptor> desc);
|
||||
static bool ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props);
|
||||
static bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
|
||||
static bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props);
|
||||
static bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible);
|
||||
static bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded);
|
||||
static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
|
||||
@ -56,6 +55,7 @@ class Proxy
|
||||
static bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
|
||||
static bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props);
|
||||
static bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props);
|
||||
static bool iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp);
|
||||
static bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args);
|
||||
static bool hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp);
|
||||
|
@ -761,7 +761,7 @@ ScriptedDirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId
|
||||
|
||||
// ES6 (22 May, 2014) 9.5.11 Proxy.[[Enumerate]]
|
||||
bool
|
||||
ScriptedDirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const
|
||||
ScriptedDirectProxyHandler::getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props) const
|
||||
{
|
||||
// step 1
|
||||
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
|
||||
@ -782,7 +782,7 @@ ScriptedDirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdV
|
||||
|
||||
// step 6
|
||||
if (trap.isUndefined())
|
||||
return DirectProxyHandler::enumerate(cx, proxy, props);
|
||||
return DirectProxyHandler::getEnumerablePropertyKeys(cx, proxy, props);
|
||||
|
||||
// step 7-8
|
||||
Value argv[] = {
|
||||
|
@ -26,7 +26,6 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
|
||||
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
|
||||
/* These two are standard internal methods but aren't implemented to spec yet. */
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
|
||||
@ -63,6 +62,8 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
|
||||
AutoIdVector &props) const MOZ_OVERRIDE {
|
||||
return BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
|
||||
}
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||
|
||||
|
@ -226,16 +226,6 @@ ScriptedIndirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleI
|
||||
ValueToBool(value, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const
|
||||
{
|
||||
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
|
||||
RootedValue fval(cx), value(cx);
|
||||
return GetFundamentalTrap(cx, handler, cx->names().enumerate, &fval) &&
|
||||
Trap(cx, handler, fval, 0, nullptr, &value) &&
|
||||
ArrayToIdVector(cx, value, props);
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const
|
||||
{
|
||||
@ -315,6 +305,17 @@ ScriptedIndirectProxyHandler::getOwnEnumerablePropertyKeys(JSContext *cx, Handle
|
||||
ArrayToIdVector(cx, value, props);
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
|
||||
RootedValue fval(cx), value(cx);
|
||||
return GetFundamentalTrap(cx, handler, cx->names().enumerate, &fval) &&
|
||||
Trap(cx, handler, fval, 0, nullptr, &value) &&
|
||||
ArrayToIdVector(cx, value, props);
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp) const
|
||||
|
@ -27,7 +27,6 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
|
||||
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
|
||||
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
@ -42,6 +41,8 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
|
||||
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
|
@ -1755,7 +1755,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
||||
return getScopePropertyNames(cx, proxy, props, JSITER_OWNONLY);
|
||||
}
|
||||
|
||||
bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE
|
||||
bool getEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE
|
||||
{
|
||||
return getScopePropertyNames(cx, proxy, props, 0);
|
||||
}
|
||||
|
@ -100,16 +100,6 @@ FilteringWrapper<Base, Policy>::ownPropertyKeys(JSContext *cx, HandleObject wrap
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Policy>
|
||||
bool
|
||||
FilteringWrapper<Base, Policy>::enumerate(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
||||
return Base::enumerate(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Policy>
|
||||
bool
|
||||
FilteringWrapper<Base, Policy>::getOwnEnumerablePropertyKeys(JSContext *cx,
|
||||
@ -121,6 +111,17 @@ FilteringWrapper<Base, Policy>::getOwnEnumerablePropertyKeys(JSContext *cx,
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Policy>
|
||||
bool
|
||||
FilteringWrapper<Base, Policy>::getEnumerablePropertyKeys(JSContext *cx,
|
||||
HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
||||
return Base::getEnumerablePropertyKeys(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Policy>
|
||||
bool
|
||||
FilteringWrapper<Base, Policy>::iterate(JSContext *cx, HandleObject wrapper,
|
||||
@ -238,7 +239,7 @@ CrossOriginXrayWrapper::ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wra
|
||||
// All properties on cross-origin objects are supposed |own|, despite what
|
||||
// the underlying native object may report. Override the inherited trap to
|
||||
// avoid passing JSITER_OWNONLY as a flag.
|
||||
return SecurityXrayDOM::enumerate(cx, wrapper, JSITER_HIDDEN, props);
|
||||
return SecurityXrayDOM::getPropertyKeys(cx, wrapper, JSITER_HIDDEN, props);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -259,8 +260,8 @@ CrossOriginXrayWrapper::delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
}
|
||||
|
||||
bool
|
||||
CrossOriginXrayWrapper::enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const
|
||||
CrossOriginXrayWrapper::getEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const
|
||||
{
|
||||
// Cross-origin properties are non-enumerable.
|
||||
return true;
|
||||
|
@ -33,14 +33,14 @@ class FilteringWrapper : public Base {
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||
virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
|
||||
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
||||
|
||||
@ -80,12 +80,12 @@ class CrossOriginXrayWrapper : public SecurityXrayDOM {
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2039,7 +2039,7 @@ XrayWrapper<Base, Traits>::ownPropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
||||
return enumerate(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props);
|
||||
return getPropertyKeys(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
@ -2063,37 +2063,6 @@ XrayWrapper<Base, Traits>::delete_(JSContext *cx, HandleObject wrapper,
|
||||
return Traits::singleton.delete_(cx, wrapper, id, bp);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::enumerate(JSContext *cx, HandleObject wrapper, unsigned flags,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
||||
|
||||
// Enumerate expando properties first. Note that the expando object lives
|
||||
// in the target compartment.
|
||||
RootedObject target(cx, Traits::singleton.getTargetObject(wrapper));
|
||||
RootedObject expando(cx);
|
||||
if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando))
|
||||
return false;
|
||||
|
||||
if (expando) {
|
||||
JSAutoCompartment ac(cx, expando);
|
||||
if (!js::GetPropertyKeys(cx, expando, flags, &props))
|
||||
return false;
|
||||
}
|
||||
|
||||
return Traits::singleton.enumerateNames(cx, wrapper, flags, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::enumerate(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
return enumerate(cx, wrapper, 0, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::get(JSContext *cx, HandleObject wrapper,
|
||||
@ -2147,6 +2116,14 @@ XrayWrapper<Base, Traits>::getOwnEnumerablePropertyKeys(JSContext *cx,
|
||||
return js::BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, wrapper, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::getEnumerablePropertyKeys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
return getPropertyKeys(cx, wrapper, 0, props);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::iterate(JSContext *cx, HandleObject wrapper,
|
||||
@ -2266,6 +2243,29 @@ XrayWrapper<Base, Traits>::setImmutablePrototype(JSContext *cx, JS::HandleObject
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::getPropertyKeys(JSContext *cx, HandleObject wrapper, unsigned flags,
|
||||
AutoIdVector &props) const
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
||||
|
||||
// Enumerate expando properties first. Note that the expando object lives
|
||||
// in the target compartment.
|
||||
RootedObject target(cx, Traits::singleton.getTargetObject(wrapper));
|
||||
RootedObject expando(cx);
|
||||
if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando))
|
||||
return false;
|
||||
|
||||
if (expando) {
|
||||
JSAutoCompartment ac(cx, expando);
|
||||
if (!js::GetPropertyKeys(cx, expando, flags, &props))
|
||||
return false;
|
||||
}
|
||||
|
||||
return Traits::singleton.enumerateNames(cx, wrapper, flags, props);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Permissive / Security variants should be used depending on whether the
|
||||
* compartment of the wrapper is guranteed to subsume the compartment of the
|
||||
|
@ -413,7 +413,6 @@ class XrayWrapper : public Base {
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::MutableHandleObject protop) const MOZ_OVERRIDE;
|
||||
virtual bool setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
|
||||
@ -440,6 +439,8 @@ class XrayWrapper : public Base {
|
||||
bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool getEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
|
||||
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
||||
|
||||
@ -473,8 +474,8 @@ class XrayWrapper : public Base {
|
||||
}
|
||||
|
||||
protected:
|
||||
bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
|
||||
JS::AutoIdVector &props) const;
|
||||
bool getPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
|
||||
JS::AutoIdVector &props) const;
|
||||
};
|
||||
|
||||
#define PermissiveXrayXPCWN xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::XPCWrappedNativeXrayTraits>
|
||||
|
Loading…
Reference in New Issue
Block a user