Bug 1525674 part 1 - Change the enumerate proxy trap to return the jsid vector instead of an iterator. r=bzbarsky,evilpie

In vm/Iteration.cpp this inlines some functions because there's a single
caller now. Follow-up patches will do additional cleanup/optimization.

Differential Revision: https://phabricator.services.mozilla.com/D18926

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan de Mooij 2019-02-08 08:17:00 +00:00
Родитель 8e4b95eae3
Коммит 13c7bd6d2c
22 изменённых файлов: 110 добавлений и 243 удалений

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

@ -435,38 +435,20 @@ bool MaybeCrossOriginObject<Base>::defineProperty(
}
template <typename Base>
JSObject* MaybeCrossOriginObject<Base>::enumerate(
JSContext* cx, JS::Handle<JSObject*> proxy) const {
// We need to be a little careful here. We want to get our list of property
// keys in whatever Realm we're in right now (which might be different from
// the Realm of "proxy"), and invoke our ownPropertyKeys which will return the
// right list. In particular we do NOT want to invoke
// ForwardingProxyHandler::enumerate here, because that will get the keys from
// our target, which may produce the wrong list.
//
// Once we have the list, we want to create the iterator object targeting the
// representation of "proxy" in our current Realm, since that's what the
// caller is working with.
//
// We could handle parts of this this by overriding enumerate() in
// CrossOriginObjectWrapper, but we'd still need special-case code here, so
// let's just do all the work here.
//
// BaseProxyHandler::enumerate would do the right thing if we passed the right
// object to it, but it would assert that we've entered the policy of the
// proxy we passed it, which may be a CCW, not us, and the policy we actually
// entered is ours. So we basically reimplemnt it, but without that assert.
bool MaybeCrossOriginObject<Base>::enumerate(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props) const {
// Just get the property keys from ourselves, in whatever Realm we happen to
// be in. It's important to not enter the Realm of "proxy" here, because that
// would affect the list of keys we claim to have. We wrap the proxy in the
// current compartment just to be safe; it doesn't affect behavior as far as
// CrossOriginObjectWrapper and MaybeCrossOriginObject are concerned.
JS::Rooted<JSObject*> self(cx, proxy);
if (!MaybeWrapObject(cx, &self)) {
return nullptr;
return false;
}
js::AutoIdVector props(cx);
if (!js::GetPropertyKeys(cx, self, 0, &props)) {
return nullptr;
}
return js::EnumeratedIdVectorToIterator(cx, self, props);
return js::GetPropertyKeys(cx, self, 0, &props);
}
// Force instantiations of the out-of-line template methods we need.

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

@ -315,7 +315,8 @@ class MaybeCrossOriginObject : public Base,
/**
* Spidermonkey-internal hook for enumerating objects.
*/
JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const final;
bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props) const final;
/**
* Spidermonkey-internal hook used by Object.prototype.toString. Subclasses

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

@ -89,7 +89,8 @@ class CPOWProxyHandler : public BaseProxyHandler {
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
ObjectOpResult& result) const override;
virtual JSObject* enumerate(JSContext* cx, HandleObject proxy) const override;
virtual bool enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
ObjectOpResult& result) const override;
virtual bool isExtensible(JSContext* cx, HandleObject proxy,
@ -247,11 +248,11 @@ bool WrapperOwner::delete_(JSContext* cx, HandleObject proxy, HandleId id,
return ok(cx, status, result);
}
JSObject* CPOWProxyHandler::enumerate(JSContext* cx, HandleObject proxy) const {
// Using a CPOW for the Iterator would slow down for .. in performance,
// instead call the base hook, that will use our implementation of
bool CPOWProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const {
// Call the base hook. That will use our implementation of
// getOwnEnumerablePropertyKeys and follow the proto chain.
return BaseProxyHandler::enumerate(cx, proxy);
return BaseProxyHandler::enumerate(cx, proxy, props);
}
bool CPOWProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id,

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

@ -337,7 +337,8 @@ class JS_FRIEND_API BaseProxyHandler {
const CallArgs& args) const;
/* SpiderMonkey extensions. */
virtual JSObject* enumerate(JSContext* cx, HandleObject proxy) const;
virtual bool enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const;
virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
bool* bp) const;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,

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

@ -55,7 +55,8 @@ class JS_FRIEND_API ForwardingProxyHandler : public BaseProxyHandler {
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
ObjectOpResult& result) const override;
virtual JSObject* enumerate(JSContext* cx, HandleObject proxy) const override;
virtual bool enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, HandleObject proxy,
@ -193,8 +194,8 @@ class JS_FRIEND_API CrossCompartmentWrapper : public Wrapper {
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
ObjectOpResult& result) const override;
virtual JSObject* enumerate(JSContext* cx,
HandleObject wrapper) const override;
virtual bool enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, HandleObject proxy,
@ -264,8 +265,8 @@ class JS_FRIEND_API OpaqueCrossCompartmentWrapper
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
ObjectOpResult& result) const override;
virtual JSObject* enumerate(JSContext* cx,
HandleObject wrapper) const override;
virtual bool enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool getPrototype(JSContext* cx, HandleObject wrapper,
MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, HandleObject wrapper,

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

@ -38,7 +38,8 @@ struct ProxyTraps {
bool (*delete_)(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
JS::ObjectOpResult& result);
JSObject* (*enumerate)(JSContext* cx, JS::HandleObject proxy);
bool (*enumerate)(JSContext* cx, JS::HandleObject proxy,
JS::AutoIdVector& props);
bool (*getPrototypeIfOrdinary)(JSContext* cx, JS::HandleObject proxy,
bool* isOrdinary,
@ -99,10 +100,10 @@ static int HandlerFamily;
#define DEFER_TO_TRAP_OR_BASE_CLASS(_base) \
\
/* Standard internal methods. */ \
virtual JSObject* enumerate(JSContext* cx, JS::HandleObject proxy) \
const override { \
return mTraps.enumerate ? mTraps.enumerate(cx, proxy) \
: _base::enumerate(cx, proxy); \
virtual bool enumerate(JSContext* cx, JS::HandleObject proxy, \
JS::AutoIdVector& props) const override { \
return mTraps.enumerate ? mTraps.enumerate(cx, proxy, props) \
: _base::enumerate(cx, proxy, props); \
} \
\
virtual bool has(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, \

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

@ -2795,12 +2795,6 @@ extern JS_FRIEND_API void LogDtor(void* self, const char* type, uint32_t sz);
*/
extern JS_FRIEND_API uint64_t GetGCHeapUsageForObjectZone(JSObject* obj);
/**
* Create an iterator for the given list of props and the given object
* being iterated.
*/
extern JS_FRIEND_API JSObject* EnumeratedIdVectorToIterator(
JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& props);
} /* namespace js */
#endif /* jsfriendapi_h */

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

@ -268,17 +268,14 @@ bool BaseProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
return true;
}
JSObject* BaseProxyHandler::enumerate(JSContext* cx, HandleObject proxy) const {
bool BaseProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const {
assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
// GetPropertyKeys will invoke getOwnEnumerablePropertyKeys along the proto
// chain for us.
AutoIdVector props(cx);
if (!GetPropertyKeys(cx, proxy, 0, &props)) {
return nullptr;
}
return EnumeratedIdVectorToIterator(cx, proxy, props);
MOZ_ASSERT(props.empty());
return GetPropertyKeys(cx, proxy, 0, &props);
}
bool BaseProxyHandler::call(JSContext* cx, HandleObject proxy,

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

@ -211,68 +211,10 @@ bool CrossCompartmentWrapper::getOwnEnumerablePropertyKeys(
MarkAtoms(cx, props));
}
/*
* We can reify non-escaping iterator objects instead of having to wrap them.
* This allows fast iteration over objects across a compartment boundary.
*/
static bool CanReify(HandleObject obj) {
return obj->is<PropertyIteratorObject>();
}
static JSObject* Reify(JSContext* cx, JS::Compartment* origin,
HandleObject iter) {
// Ensure iterator gets closed.
auto autoCloseIterator = mozilla::MakeScopeExit([=] { CloseIterator(iter); });
NativeIterator* ni = iter->as<PropertyIteratorObject>().getNativeIterator();
RootedObject obj(cx, ni->objectBeingIterated());
// Wrap iteratee.
if (!origin->wrap(cx, &obj)) {
return nullptr;
}
// Wrap the elements in the iterator's snapshot.
size_t length = ni->numKeys();
AutoIdVector keys(cx);
if (length > 0) {
if (!keys.reserve(length)) {
return nullptr;
}
RootedId id(cx);
RootedValue v(cx);
for (size_t i = 0; i < length; ++i) {
v.setString(ni->propertiesBegin()[i]);
if (!ValueToId<CanGC>(cx, v, &id)) {
return nullptr;
}
cx->markId(id);
keys.infallibleAppend(id);
}
}
// Return iterator in current compartment.
return EnumeratedIdVectorToIterator(cx, obj, keys);
}
JSObject* CrossCompartmentWrapper::enumerate(JSContext* cx,
HandleObject wrapper) const {
RootedObject res(cx);
{
AutoRealm call(cx, wrappedObject(wrapper));
res = Wrapper::enumerate(cx, wrapper);
if (!res) {
return nullptr;
}
}
if (CanReify(res)) {
return Reify(cx, cx->compartment(), res);
}
if (!cx->compartment()->wrap(cx, &res)) {
return nullptr;
}
return res;
bool CrossCompartmentWrapper::enumerate(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const {
PIERCE(cx, wrapper, NOTHING, Wrapper::enumerate(cx, wrapper, props),
MarkAtoms(cx, props));
}
bool CrossCompartmentWrapper::call(JSContext* cx, HandleObject wrapper,

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

@ -35,9 +35,9 @@ bool OpaqueCrossCompartmentWrapper::delete_(JSContext* cx, HandleObject wrapper,
return result.succeed();
}
JSObject* OpaqueCrossCompartmentWrapper::enumerate(JSContext* cx,
HandleObject wrapper) const {
return BaseProxyHandler::enumerate(cx, wrapper);
bool OpaqueCrossCompartmentWrapper::enumerate(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const {
return BaseProxyHandler::enumerate(cx, proxy, props);
}
bool OpaqueCrossCompartmentWrapper::getPrototype(

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

@ -441,49 +441,45 @@ bool Proxy::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
return handler->getOwnEnumerablePropertyKeys(cx, proxy, props);
}
JSObject* Proxy::enumerate(JSContext* cx, HandleObject proxy) {
bool Proxy::enumerate(JSContext* cx, HandleObject proxy, AutoIdVector& props) {
if (!CheckRecursionLimit(cx)) {
return nullptr;
return false;
}
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
if (handler->hasPrototype()) {
AutoIdVector props(cx);
if (!Proxy::getOwnEnumerablePropertyKeys(cx, proxy, props)) {
return nullptr;
return false;
}
RootedObject proto(cx);
if (!GetPrototype(cx, proxy, &proto)) {
return nullptr;
return false;
}
if (!proto) {
return EnumeratedIdVectorToIterator(cx, proxy, props);
return true;
}
cx->check(proxy, proto);
AutoIdVector protoProps(cx);
if (!GetPropertyKeys(cx, proto, 0, &protoProps)) {
return nullptr;
return false;
}
if (!AppendUnique(cx, props, protoProps)) {
return nullptr;
}
return EnumeratedIdVectorToIterator(cx, proxy, props);
return AppendUnique(cx, props, protoProps);
}
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE,
BaseProxyHandler::ENUMERATE, true);
// If the policy denies access but wants us to return true, we need
// to hand a valid (empty) iterator object to the caller.
// to return an empty |props| list.
if (!policy.allowed()) {
if (!policy.returnValue()) {
return nullptr;
}
return NewEmptyPropertyIterator(cx);
MOZ_ASSERT(props.empty());
return policy.returnValue();
}
return handler->enumerate(cx, proxy);
return handler->enumerate(cx, proxy, props);
}
bool Proxy::call(JSContext* cx, HandleObject proxy, const CallArgs& args) {

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

@ -36,7 +36,7 @@ class Proxy {
AutoIdVector& props);
static bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
ObjectOpResult& result);
static JSObject* enumerate(JSContext* cx, HandleObject proxy);
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,
ObjectOpResult& result);

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

@ -75,13 +75,13 @@ bool ForwardingProxyHandler::delete_(JSContext* cx, HandleObject proxy,
return DeleteProperty(cx, target, id, result);
}
JSObject* ForwardingProxyHandler::enumerate(JSContext* cx,
HandleObject proxy) const {
bool ForwardingProxyHandler::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 GetIterator(cx, target);
return EnumerateProperties(cx, target, props);
}
bool ForwardingProxyHandler::getPrototype(JSContext* cx, HandleObject proxy,

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

@ -794,32 +794,6 @@ NativeIterator::NativeIterator(JSContext* cx,
MOZ_ASSERT(!*hadError);
}
static inline PropertyIteratorObject* VectorToKeyIterator(JSContext* cx,
HandleObject obj,
AutoIdVector& props,
uint32_t numGuards) {
MOZ_ASSERT(cx->compartment() == obj->compartment(),
"We may end up allocating shapes in the wrong zone!");
if (obj->isSingleton() && !JSObject::setIteratedSingleton(cx, obj)) {
return nullptr;
}
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
return CreatePropertyIterator(cx, obj, props, numGuards, 0);
}
JS_FRIEND_API JSObject* js::EnumeratedIdVectorToIterator(JSContext* cx,
HandleObject obj,
AutoIdVector& props) {
return VectorToKeyIterator(cx, obj, props, 0);
}
// Mainly used for .. in over null/undefined
JSObject* js::NewEmptyPropertyIterator(JSContext* cx) {
AutoIdVector props(cx); // Empty
return CreatePropertyIterator(cx, nullptr, props, 0, 0);
}
/* static */ bool IteratorHashPolicy::match(PropertyIteratorObject* obj,
const Lookup& lookup) {
NativeIterator* ni = obj->getNativeIterator();
@ -944,7 +918,22 @@ static MOZ_MUST_USE bool StoreInIteratorCache(JSContext* cx, JSObject* obj,
return true;
}
JSObject* js::GetIterator(JSContext* cx, HandleObject obj) {
bool js::EnumerateProperties(JSContext* cx, HandleObject obj,
AutoIdVector& props) {
MOZ_ASSERT(props.empty());
if (MOZ_UNLIKELY(obj->is<ProxyObject>())) {
return Proxy::enumerate(cx, obj, props);
}
return Snapshot(cx, obj, 0, &props);
}
static JSObject* GetIterator(JSContext* cx, HandleObject obj) {
MOZ_ASSERT(!obj->is<PropertyIteratorObject>());
MOZ_ASSERT(cx->compartment() == obj->compartment(),
"We may end up allocating shapes in the wrong zone!");
uint32_t numGuards = 0;
if (PropertyIteratorObject* iterobj =
LookupInIteratorCache(cx, obj, &numGuards)) {
@ -958,23 +947,22 @@ JSObject* js::GetIterator(JSContext* cx, HandleObject obj) {
numGuards = 0;
}
MOZ_ASSERT(!obj->is<PropertyIteratorObject>());
if (MOZ_UNLIKELY(obj->is<ProxyObject>())) {
return Proxy::enumerate(cx, obj);
}
AutoIdVector keys(cx);
if (!Snapshot(cx, obj, 0, &keys)) {
if (!EnumerateProperties(cx, obj, keys)) {
return nullptr;
}
JSObject* res = VectorToKeyIterator(cx, obj, keys, numGuards);
if (!res) {
if (obj->isSingleton() && !JSObject::setIteratedSingleton(cx, obj)) {
return nullptr;
}
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
PropertyIteratorObject* iterobj =
CreatePropertyIterator(cx, obj, keys, numGuards, 0);
if (!iterobj) {
return nullptr;
}
PropertyIteratorObject* iterobj = &res->as<PropertyIteratorObject>();
cx->check(iterobj);
// Cache the iterator object.
@ -1272,7 +1260,8 @@ JSObject* js::ValueToIterator(JSContext* cx, HandleValue vp) {
* that |for (var p in <null or undefined>) <loop>;| never executes
* <loop>, per ES5 12.6.4.
*/
return NewEmptyPropertyIterator(cx);
AutoIdVector props(cx); // Empty
return CreatePropertyIterator(cx, nullptr, props, 0, 0);
} else {
obj = ToObject(cx, vp);
if (!obj) {
@ -1512,33 +1501,11 @@ bool js::SuppressDeletedElement(JSContext* cx, HandleObject obj,
bool js::IteratorMore(JSContext* cx, HandleObject iterobj,
MutableHandleValue rval) {
// Fast path for native iterators.
if (MOZ_LIKELY(iterobj->is<PropertyIteratorObject>())) {
NativeIterator* ni =
iterobj->as<PropertyIteratorObject>().getNativeIterator();
rval.set(ni->nextIteratedValueAndAdvance());
return true;
}
NativeIterator* ni =
iterobj->as<PropertyIteratorObject>().getNativeIterator();
if (JS_IsDeadWrapper(iterobj)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
return false;
}
MOZ_ASSERT(IsWrapper(iterobj));
RootedObject obj(cx, CheckedUnwrap(iterobj));
if (!obj) {
return false;
}
MOZ_RELEASE_ASSERT(obj->is<PropertyIteratorObject>());
{
AutoRealm ar(cx, obj);
NativeIterator* ni = obj->as<PropertyIteratorObject>().getNativeIterator();
rval.set(ni->nextIteratedValueAndAdvance());
}
return cx->compartment()->wrap(cx, rval);
rval.set(ni->nextIteratedValueAndAdvance());
return true;
}
static const JSFunctionSpec iterator_proto_methods[] = {

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

@ -365,12 +365,11 @@ class RegExpStringIteratorObject : public NativeObject {
RegExpStringIteratorObject* NewRegExpStringIteratorObject(
JSContext* cx, NewObjectKind newKind = GenericObject);
JSObject* GetIterator(JSContext* cx, HandleObject obj);
MOZ_MUST_USE bool EnumerateProperties(JSContext* cx, HandleObject obj,
AutoIdVector& props);
PropertyIteratorObject* LookupInIteratorCache(JSContext* cx, HandleObject obj);
JSObject* NewEmptyPropertyIterator(JSContext* cx);
JSObject* ValueToIterator(JSContext* cx, HandleValue vp);
void CloseIterator(JSObject* obj);

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

@ -518,8 +518,8 @@ class SandboxProxyHandler : public js::Wrapper {
virtual bool getOwnEnumerablePropertyKeys(
JSContext* cx, JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props) const override;
virtual JSObject* enumerate(JSContext* cx,
JS::Handle<JSObject*> proxy) const override;
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props) const override;
private:
// Implements the custom getPropertyDescriptor behavior. If the getOwn
@ -799,9 +799,9 @@ bool SandboxProxyHandler::getOwnEnumerablePropertyKeys(
return BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
}
JSObject* SandboxProxyHandler::enumerate(JSContext* cx,
JS::Handle<JSObject*> proxy) const {
return BaseProxyHandler::enumerate(cx, proxy);
bool SandboxProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props) const {
return BaseProxyHandler::enumerate(cx, proxy, props);
}
bool xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj) {

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

@ -162,14 +162,13 @@ bool FilteringWrapper<Base, Policy>::getOwnEnumerablePropertyKeys(
}
template <typename Base, typename Policy>
JSObject* FilteringWrapper<Base, Policy>::enumerate(
JSContext* cx, HandleObject wrapper) const {
bool FilteringWrapper<Base, Policy>::enumerate(JSContext* cx,
HandleObject wrapper,
JS::AutoIdVector& props) const {
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
// We refuse to trigger the enumerate hook across chrome wrappers because
// we don't know how to censor custom iterator objects. Instead we trigger
// the default proxy enumerate trap, which will use js::GetPropertyKeys
// for the list of (censored) ids.
return js::BaseProxyHandler::enumerate(cx, wrapper);
// Trigger the default proxy enumerate trap, which will use
// js::GetPropertyKeys for the list of (censored) ids.
return js::BaseProxyHandler::enumerate(cx, wrapper, props);
}
template <typename Base, typename Policy>

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

@ -32,8 +32,8 @@ class FilteringWrapper : public Base {
virtual bool getOwnEnumerablePropertyKeys(
JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual JSObject* enumerate(JSContext* cx,
JS::Handle<JSObject*> wrapper) const override;
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
const JS::CallArgs& args) const override;

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

@ -48,17 +48,6 @@ bool WaiveXrayWrapper::get(JSContext* cx, HandleObject wrapper,
WrapperFactory::WaiveXrayAndWrap(cx, vp);
}
JSObject* WaiveXrayWrapper::enumerate(JSContext* cx, HandleObject proxy) const {
RootedObject obj(cx, CrossCompartmentWrapper::enumerate(cx, proxy));
if (!obj) {
return nullptr;
}
if (!WrapperFactory::WaiveXrayAndWrap(cx, &obj)) {
return nullptr;
}
return obj;
}
bool WaiveXrayWrapper::call(JSContext* cx, HandleObject wrapper,
const JS::CallArgs& args) const {
return CrossCompartmentWrapper::call(cx, wrapper, args) &&

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

@ -34,8 +34,6 @@ class WaiveXrayWrapper : public js::CrossCompartmentWrapper {
virtual bool construct(JSContext* cx, JS::Handle<JSObject*> wrapper,
const JS::CallArgs& args) const override;
virtual JSObject* enumerate(JSContext* cx,
JS::Handle<JSObject*> proxy) const override;
virtual bool nativeCall(JSContext* cx, JS::IsAcceptableThis test,
JS::NativeImpl impl,
const JS::CallArgs& args) const override;

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

@ -2126,10 +2126,9 @@ bool XrayWrapper<Base, Traits>::getOwnEnumerablePropertyKeys(
}
template <typename Base, typename Traits>
JSObject* XrayWrapper<Base, Traits>::enumerate(JSContext* cx,
HandleObject wrapper) const {
bool XrayWrapper<Base, Traits>::enumerate(JSContext* cx, HandleObject wrapper,
JS::AutoIdVector& props) const {
MOZ_CRASH("Shouldn't be called: we return true for hasPrototype()");
return nullptr;
}
template <typename Base, typename Traits>

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

@ -390,8 +390,8 @@ class XrayWrapper : public Base {
virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::ObjectOpResult& result) const override;
virtual JSObject* enumerate(JSContext* cx,
JS::Handle<JSObject*> wrapper) const override;
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,