зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
8e4b95eae3
Коммит
13c7bd6d2c
|
@ -435,38 +435,20 @@ bool MaybeCrossOriginObject<Base>::defineProperty(
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base>
|
template <typename Base>
|
||||||
JSObject* MaybeCrossOriginObject<Base>::enumerate(
|
bool MaybeCrossOriginObject<Base>::enumerate(JSContext* cx,
|
||||||
JSContext* cx, JS::Handle<JSObject*> proxy) const {
|
JS::Handle<JSObject*> proxy,
|
||||||
// We need to be a little careful here. We want to get our list of property
|
JS::AutoIdVector& props) const {
|
||||||
// keys in whatever Realm we're in right now (which might be different from
|
// Just get the property keys from ourselves, in whatever Realm we happen to
|
||||||
// the Realm of "proxy"), and invoke our ownPropertyKeys which will return the
|
// be in. It's important to not enter the Realm of "proxy" here, because that
|
||||||
// right list. In particular we do NOT want to invoke
|
// would affect the list of keys we claim to have. We wrap the proxy in the
|
||||||
// ForwardingProxyHandler::enumerate here, because that will get the keys from
|
// current compartment just to be safe; it doesn't affect behavior as far as
|
||||||
// our target, which may produce the wrong list.
|
// CrossOriginObjectWrapper and MaybeCrossOriginObject are concerned.
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
JS::Rooted<JSObject*> self(cx, proxy);
|
JS::Rooted<JSObject*> self(cx, proxy);
|
||||||
if (!MaybeWrapObject(cx, &self)) {
|
if (!MaybeWrapObject(cx, &self)) {
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
js::AutoIdVector props(cx);
|
return js::GetPropertyKeys(cx, self, 0, &props);
|
||||||
if (!js::GetPropertyKeys(cx, self, 0, &props)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return js::EnumeratedIdVectorToIterator(cx, self, props);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force instantiations of the out-of-line template methods we need.
|
// 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.
|
* 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
|
* Spidermonkey-internal hook used by Object.prototype.toString. Subclasses
|
||||||
|
|
|
@ -89,7 +89,8 @@ class CPOWProxyHandler : public BaseProxyHandler {
|
||||||
AutoIdVector& props) const override;
|
AutoIdVector& props) const override;
|
||||||
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
||||||
ObjectOpResult& result) const override;
|
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,
|
virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
|
||||||
ObjectOpResult& result) const override;
|
ObjectOpResult& result) const override;
|
||||||
virtual bool isExtensible(JSContext* cx, HandleObject proxy,
|
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);
|
return ok(cx, status, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* CPOWProxyHandler::enumerate(JSContext* cx, HandleObject proxy) const {
|
bool CPOWProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
|
||||||
// Using a CPOW for the Iterator would slow down for .. in performance,
|
AutoIdVector& props) const {
|
||||||
// instead call the base hook, that will use our implementation of
|
// Call the base hook. That will use our implementation of
|
||||||
// getOwnEnumerablePropertyKeys and follow the proto chain.
|
// 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,
|
bool CPOWProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id,
|
||||||
|
|
|
@ -337,7 +337,8 @@ class JS_FRIEND_API BaseProxyHandler {
|
||||||
const CallArgs& args) const;
|
const CallArgs& args) const;
|
||||||
|
|
||||||
/* SpiderMonkey extensions. */
|
/* 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,
|
virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
|
||||||
bool* bp) const;
|
bool* bp) const;
|
||||||
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
|
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
|
||||||
|
|
|
@ -55,7 +55,8 @@ class JS_FRIEND_API ForwardingProxyHandler : public BaseProxyHandler {
|
||||||
AutoIdVector& props) const override;
|
AutoIdVector& props) const override;
|
||||||
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
||||||
ObjectOpResult& result) const override;
|
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,
|
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
|
||||||
MutableHandleObject protop) const override;
|
MutableHandleObject protop) const override;
|
||||||
virtual bool setPrototype(JSContext* cx, HandleObject proxy,
|
virtual bool setPrototype(JSContext* cx, HandleObject proxy,
|
||||||
|
@ -193,8 +194,8 @@ class JS_FRIEND_API CrossCompartmentWrapper : public Wrapper {
|
||||||
AutoIdVector& props) const override;
|
AutoIdVector& props) const override;
|
||||||
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
|
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||||
ObjectOpResult& result) const override;
|
ObjectOpResult& result) const override;
|
||||||
virtual JSObject* enumerate(JSContext* cx,
|
virtual bool enumerate(JSContext* cx, HandleObject proxy,
|
||||||
HandleObject wrapper) const override;
|
AutoIdVector& props) const override;
|
||||||
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
|
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
|
||||||
MutableHandleObject protop) const override;
|
MutableHandleObject protop) const override;
|
||||||
virtual bool setPrototype(JSContext* cx, HandleObject proxy,
|
virtual bool setPrototype(JSContext* cx, HandleObject proxy,
|
||||||
|
@ -264,8 +265,8 @@ class JS_FRIEND_API OpaqueCrossCompartmentWrapper
|
||||||
AutoIdVector& props) const override;
|
AutoIdVector& props) const override;
|
||||||
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
|
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||||
ObjectOpResult& result) const override;
|
ObjectOpResult& result) const override;
|
||||||
virtual JSObject* enumerate(JSContext* cx,
|
virtual bool enumerate(JSContext* cx, HandleObject proxy,
|
||||||
HandleObject wrapper) const override;
|
AutoIdVector& props) const override;
|
||||||
virtual bool getPrototype(JSContext* cx, HandleObject wrapper,
|
virtual bool getPrototype(JSContext* cx, HandleObject wrapper,
|
||||||
MutableHandleObject protop) const override;
|
MutableHandleObject protop) const override;
|
||||||
virtual bool setPrototype(JSContext* cx, HandleObject wrapper,
|
virtual bool setPrototype(JSContext* cx, HandleObject wrapper,
|
||||||
|
|
|
@ -38,7 +38,8 @@ struct ProxyTraps {
|
||||||
bool (*delete_)(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
|
bool (*delete_)(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
JS::ObjectOpResult& result);
|
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 (*getPrototypeIfOrdinary)(JSContext* cx, JS::HandleObject proxy,
|
||||||
bool* isOrdinary,
|
bool* isOrdinary,
|
||||||
|
@ -99,10 +100,10 @@ static int HandlerFamily;
|
||||||
#define DEFER_TO_TRAP_OR_BASE_CLASS(_base) \
|
#define DEFER_TO_TRAP_OR_BASE_CLASS(_base) \
|
||||||
\
|
\
|
||||||
/* Standard internal methods. */ \
|
/* Standard internal methods. */ \
|
||||||
virtual JSObject* enumerate(JSContext* cx, JS::HandleObject proxy) \
|
virtual bool enumerate(JSContext* cx, JS::HandleObject proxy, \
|
||||||
const override { \
|
JS::AutoIdVector& props) const override { \
|
||||||
return mTraps.enumerate ? mTraps.enumerate(cx, proxy) \
|
return mTraps.enumerate ? mTraps.enumerate(cx, proxy, props) \
|
||||||
: _base::enumerate(cx, proxy); \
|
: _base::enumerate(cx, proxy, props); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
virtual bool has(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, \
|
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);
|
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 */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* jsfriendapi_h */
|
#endif /* jsfriendapi_h */
|
||||||
|
|
|
@ -268,17 +268,14 @@ bool BaseProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
|
||||||
return true;
|
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);
|
assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
|
||||||
|
|
||||||
// GetPropertyKeys will invoke getOwnEnumerablePropertyKeys along the proto
|
// GetPropertyKeys will invoke getOwnEnumerablePropertyKeys along the proto
|
||||||
// chain for us.
|
// chain for us.
|
||||||
AutoIdVector props(cx);
|
MOZ_ASSERT(props.empty());
|
||||||
if (!GetPropertyKeys(cx, proxy, 0, &props)) {
|
return GetPropertyKeys(cx, proxy, 0, &props);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EnumeratedIdVectorToIterator(cx, proxy, props);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseProxyHandler::call(JSContext* cx, HandleObject proxy,
|
bool BaseProxyHandler::call(JSContext* cx, HandleObject proxy,
|
||||||
|
|
|
@ -211,68 +211,10 @@ bool CrossCompartmentWrapper::getOwnEnumerablePropertyKeys(
|
||||||
MarkAtoms(cx, props));
|
MarkAtoms(cx, props));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
bool CrossCompartmentWrapper::enumerate(JSContext* cx, HandleObject wrapper,
|
||||||
* We can reify non-escaping iterator objects instead of having to wrap them.
|
AutoIdVector& props) const {
|
||||||
* This allows fast iteration over objects across a compartment boundary.
|
PIERCE(cx, wrapper, NOTHING, Wrapper::enumerate(cx, wrapper, props),
|
||||||
*/
|
MarkAtoms(cx, props));
|
||||||
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::call(JSContext* cx, HandleObject wrapper,
|
bool CrossCompartmentWrapper::call(JSContext* cx, HandleObject wrapper,
|
||||||
|
|
|
@ -35,9 +35,9 @@ bool OpaqueCrossCompartmentWrapper::delete_(JSContext* cx, HandleObject wrapper,
|
||||||
return result.succeed();
|
return result.succeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* OpaqueCrossCompartmentWrapper::enumerate(JSContext* cx,
|
bool OpaqueCrossCompartmentWrapper::enumerate(JSContext* cx, HandleObject proxy,
|
||||||
HandleObject wrapper) const {
|
AutoIdVector& props) const {
|
||||||
return BaseProxyHandler::enumerate(cx, wrapper);
|
return BaseProxyHandler::enumerate(cx, proxy, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpaqueCrossCompartmentWrapper::getPrototype(
|
bool OpaqueCrossCompartmentWrapper::getPrototype(
|
||||||
|
|
|
@ -441,49 +441,45 @@ bool Proxy::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
|
||||||
return handler->getOwnEnumerablePropertyKeys(cx, proxy, props);
|
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)) {
|
if (!CheckRecursionLimit(cx)) {
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
|
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
|
||||||
if (handler->hasPrototype()) {
|
if (handler->hasPrototype()) {
|
||||||
AutoIdVector props(cx);
|
|
||||||
if (!Proxy::getOwnEnumerablePropertyKeys(cx, proxy, props)) {
|
if (!Proxy::getOwnEnumerablePropertyKeys(cx, proxy, props)) {
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedObject proto(cx);
|
RootedObject proto(cx);
|
||||||
if (!GetPrototype(cx, proxy, &proto)) {
|
if (!GetPrototype(cx, proxy, &proto)) {
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
if (!proto) {
|
if (!proto) {
|
||||||
return EnumeratedIdVectorToIterator(cx, proxy, props);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx->check(proxy, proto);
|
cx->check(proxy, proto);
|
||||||
|
|
||||||
AutoIdVector protoProps(cx);
|
AutoIdVector protoProps(cx);
|
||||||
if (!GetPropertyKeys(cx, proto, 0, &protoProps)) {
|
if (!GetPropertyKeys(cx, proto, 0, &protoProps)) {
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
if (!AppendUnique(cx, props, protoProps)) {
|
return AppendUnique(cx, props, protoProps);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return EnumeratedIdVectorToIterator(cx, proxy, props);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE,
|
AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE,
|
||||||
BaseProxyHandler::ENUMERATE, true);
|
BaseProxyHandler::ENUMERATE, true);
|
||||||
|
|
||||||
// If the policy denies access but wants us to return true, we need
|
// 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.allowed()) {
|
||||||
if (!policy.returnValue()) {
|
MOZ_ASSERT(props.empty());
|
||||||
return nullptr;
|
return policy.returnValue();
|
||||||
}
|
}
|
||||||
return NewEmptyPropertyIterator(cx);
|
|
||||||
}
|
return handler->enumerate(cx, proxy, props);
|
||||||
return handler->enumerate(cx, proxy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Proxy::call(JSContext* cx, HandleObject proxy, const CallArgs& args) {
|
bool Proxy::call(JSContext* cx, HandleObject proxy, const CallArgs& args) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Proxy {
|
||||||
AutoIdVector& props);
|
AutoIdVector& props);
|
||||||
static bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
static bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
||||||
ObjectOpResult& result);
|
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 isExtensible(JSContext* cx, HandleObject proxy, bool* extensible);
|
||||||
static bool preventExtensions(JSContext* cx, HandleObject proxy,
|
static bool preventExtensions(JSContext* cx, HandleObject proxy,
|
||||||
ObjectOpResult& result);
|
ObjectOpResult& result);
|
||||||
|
|
|
@ -75,13 +75,13 @@ bool ForwardingProxyHandler::delete_(JSContext* cx, HandleObject proxy,
|
||||||
return DeleteProperty(cx, target, id, result);
|
return DeleteProperty(cx, target, id, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* ForwardingProxyHandler::enumerate(JSContext* cx,
|
bool ForwardingProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
|
||||||
HandleObject proxy) const {
|
AutoIdVector& props) const {
|
||||||
assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
|
assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
|
||||||
MOZ_ASSERT(
|
MOZ_ASSERT(
|
||||||
!hasPrototype()); // Should never be called if there's a prototype.
|
!hasPrototype()); // Should never be called if there's a prototype.
|
||||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||||
return GetIterator(cx, target);
|
return EnumerateProperties(cx, target, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ForwardingProxyHandler::getPrototype(JSContext* cx, HandleObject proxy,
|
bool ForwardingProxyHandler::getPrototype(JSContext* cx, HandleObject proxy,
|
||||||
|
|
|
@ -794,32 +794,6 @@ NativeIterator::NativeIterator(JSContext* cx,
|
||||||
MOZ_ASSERT(!*hadError);
|
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,
|
/* static */ bool IteratorHashPolicy::match(PropertyIteratorObject* obj,
|
||||||
const Lookup& lookup) {
|
const Lookup& lookup) {
|
||||||
NativeIterator* ni = obj->getNativeIterator();
|
NativeIterator* ni = obj->getNativeIterator();
|
||||||
|
@ -944,7 +918,22 @@ static MOZ_MUST_USE bool StoreInIteratorCache(JSContext* cx, JSObject* obj,
|
||||||
return true;
|
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;
|
uint32_t numGuards = 0;
|
||||||
if (PropertyIteratorObject* iterobj =
|
if (PropertyIteratorObject* iterobj =
|
||||||
LookupInIteratorCache(cx, obj, &numGuards)) {
|
LookupInIteratorCache(cx, obj, &numGuards)) {
|
||||||
|
@ -958,23 +947,22 @@ JSObject* js::GetIterator(JSContext* cx, HandleObject obj) {
|
||||||
numGuards = 0;
|
numGuards = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(!obj->is<PropertyIteratorObject>());
|
|
||||||
|
|
||||||
if (MOZ_UNLIKELY(obj->is<ProxyObject>())) {
|
|
||||||
return Proxy::enumerate(cx, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoIdVector keys(cx);
|
AutoIdVector keys(cx);
|
||||||
if (!Snapshot(cx, obj, 0, &keys)) {
|
if (!EnumerateProperties(cx, obj, keys)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* res = VectorToKeyIterator(cx, obj, keys, numGuards);
|
if (obj->isSingleton() && !JSObject::setIteratedSingleton(cx, obj)) {
|
||||||
if (!res) {
|
return nullptr;
|
||||||
|
}
|
||||||
|
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||||
|
|
||||||
|
PropertyIteratorObject* iterobj =
|
||||||
|
CreatePropertyIterator(cx, obj, keys, numGuards, 0);
|
||||||
|
if (!iterobj) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyIteratorObject* iterobj = &res->as<PropertyIteratorObject>();
|
|
||||||
cx->check(iterobj);
|
cx->check(iterobj);
|
||||||
|
|
||||||
// Cache the iterator object.
|
// 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
|
* that |for (var p in <null or undefined>) <loop>;| never executes
|
||||||
* <loop>, per ES5 12.6.4.
|
* <loop>, per ES5 12.6.4.
|
||||||
*/
|
*/
|
||||||
return NewEmptyPropertyIterator(cx);
|
AutoIdVector props(cx); // Empty
|
||||||
|
return CreatePropertyIterator(cx, nullptr, props, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
obj = ToObject(cx, vp);
|
obj = ToObject(cx, vp);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
|
@ -1512,35 +1501,13 @@ bool js::SuppressDeletedElement(JSContext* cx, HandleObject obj,
|
||||||
|
|
||||||
bool js::IteratorMore(JSContext* cx, HandleObject iterobj,
|
bool js::IteratorMore(JSContext* cx, HandleObject iterobj,
|
||||||
MutableHandleValue rval) {
|
MutableHandleValue rval) {
|
||||||
// Fast path for native iterators.
|
|
||||||
if (MOZ_LIKELY(iterobj->is<PropertyIteratorObject>())) {
|
|
||||||
NativeIterator* ni =
|
NativeIterator* ni =
|
||||||
iterobj->as<PropertyIteratorObject>().getNativeIterator();
|
iterobj->as<PropertyIteratorObject>().getNativeIterator();
|
||||||
|
|
||||||
rval.set(ni->nextIteratedValueAndAdvance());
|
rval.set(ni->nextIteratedValueAndAdvance());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const JSFunctionSpec iterator_proto_methods[] = {
|
static const JSFunctionSpec iterator_proto_methods[] = {
|
||||||
JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0), JS_FS_END};
|
JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0), JS_FS_END};
|
||||||
|
|
||||||
|
|
|
@ -365,12 +365,11 @@ class RegExpStringIteratorObject : public NativeObject {
|
||||||
RegExpStringIteratorObject* NewRegExpStringIteratorObject(
|
RegExpStringIteratorObject* NewRegExpStringIteratorObject(
|
||||||
JSContext* cx, NewObjectKind newKind = GenericObject);
|
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);
|
PropertyIteratorObject* LookupInIteratorCache(JSContext* cx, HandleObject obj);
|
||||||
|
|
||||||
JSObject* NewEmptyPropertyIterator(JSContext* cx);
|
|
||||||
|
|
||||||
JSObject* ValueToIterator(JSContext* cx, HandleValue vp);
|
JSObject* ValueToIterator(JSContext* cx, HandleValue vp);
|
||||||
|
|
||||||
void CloseIterator(JSObject* obj);
|
void CloseIterator(JSObject* obj);
|
||||||
|
|
|
@ -518,8 +518,8 @@ class SandboxProxyHandler : public js::Wrapper {
|
||||||
virtual bool getOwnEnumerablePropertyKeys(
|
virtual bool getOwnEnumerablePropertyKeys(
|
||||||
JSContext* cx, JS::Handle<JSObject*> proxy,
|
JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::AutoIdVector& props) const override;
|
JS::AutoIdVector& props) const override;
|
||||||
virtual JSObject* enumerate(JSContext* cx,
|
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<JSObject*> proxy) const override;
|
JS::AutoIdVector& props) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Implements the custom getPropertyDescriptor behavior. If the getOwn
|
// Implements the custom getPropertyDescriptor behavior. If the getOwn
|
||||||
|
@ -799,9 +799,9 @@ bool SandboxProxyHandler::getOwnEnumerablePropertyKeys(
|
||||||
return BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
|
return BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* SandboxProxyHandler::enumerate(JSContext* cx,
|
bool SandboxProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<JSObject*> proxy) const {
|
JS::AutoIdVector& props) const {
|
||||||
return BaseProxyHandler::enumerate(cx, proxy);
|
return BaseProxyHandler::enumerate(cx, proxy, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj) {
|
bool xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj) {
|
||||||
|
|
|
@ -162,14 +162,13 @@ bool FilteringWrapper<Base, Policy>::getOwnEnumerablePropertyKeys(
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base, typename Policy>
|
template <typename Base, typename Policy>
|
||||||
JSObject* FilteringWrapper<Base, Policy>::enumerate(
|
bool FilteringWrapper<Base, Policy>::enumerate(JSContext* cx,
|
||||||
JSContext* cx, HandleObject wrapper) const {
|
HandleObject wrapper,
|
||||||
|
JS::AutoIdVector& props) const {
|
||||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
|
||||||
// We refuse to trigger the enumerate hook across chrome wrappers because
|
// Trigger the default proxy enumerate trap, which will use
|
||||||
// we don't know how to censor custom iterator objects. Instead we trigger
|
// js::GetPropertyKeys for the list of (censored) ids.
|
||||||
// the default proxy enumerate trap, which will use js::GetPropertyKeys
|
return js::BaseProxyHandler::enumerate(cx, wrapper, props);
|
||||||
// for the list of (censored) ids.
|
|
||||||
return js::BaseProxyHandler::enumerate(cx, wrapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base, typename Policy>
|
template <typename Base, typename Policy>
|
||||||
|
|
|
@ -32,8 +32,8 @@ class FilteringWrapper : public Base {
|
||||||
virtual bool getOwnEnumerablePropertyKeys(
|
virtual bool getOwnEnumerablePropertyKeys(
|
||||||
JSContext* cx, JS::Handle<JSObject*> wrapper,
|
JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
JS::AutoIdVector& props) const override;
|
JS::AutoIdVector& props) const override;
|
||||||
virtual JSObject* enumerate(JSContext* cx,
|
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
JS::Handle<JSObject*> wrapper) const override;
|
JS::AutoIdVector& props) const override;
|
||||||
|
|
||||||
virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
const JS::CallArgs& args) const override;
|
const JS::CallArgs& args) const override;
|
||||||
|
|
|
@ -48,17 +48,6 @@ bool WaiveXrayWrapper::get(JSContext* cx, HandleObject wrapper,
|
||||||
WrapperFactory::WaiveXrayAndWrap(cx, vp);
|
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,
|
bool WaiveXrayWrapper::call(JSContext* cx, HandleObject wrapper,
|
||||||
const JS::CallArgs& args) const {
|
const JS::CallArgs& args) const {
|
||||||
return CrossCompartmentWrapper::call(cx, wrapper, args) &&
|
return CrossCompartmentWrapper::call(cx, wrapper, args) &&
|
||||||
|
|
|
@ -34,8 +34,6 @@ class WaiveXrayWrapper : public js::CrossCompartmentWrapper {
|
||||||
virtual bool construct(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
virtual bool construct(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
const JS::CallArgs& args) const override;
|
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,
|
virtual bool nativeCall(JSContext* cx, JS::IsAcceptableThis test,
|
||||||
JS::NativeImpl impl,
|
JS::NativeImpl impl,
|
||||||
const JS::CallArgs& args) const override;
|
const JS::CallArgs& args) const override;
|
||||||
|
|
|
@ -2126,10 +2126,9 @@ bool XrayWrapper<Base, Traits>::getOwnEnumerablePropertyKeys(
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base, typename Traits>
|
template <typename Base, typename Traits>
|
||||||
JSObject* XrayWrapper<Base, Traits>::enumerate(JSContext* cx,
|
bool XrayWrapper<Base, Traits>::enumerate(JSContext* cx, HandleObject wrapper,
|
||||||
HandleObject wrapper) const {
|
JS::AutoIdVector& props) const {
|
||||||
MOZ_CRASH("Shouldn't be called: we return true for hasPrototype()");
|
MOZ_CRASH("Shouldn't be called: we return true for hasPrototype()");
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base, typename Traits>
|
template <typename Base, typename Traits>
|
||||||
|
|
|
@ -390,8 +390,8 @@ class XrayWrapper : public Base {
|
||||||
virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
JS::Handle<jsid> id,
|
JS::Handle<jsid> id,
|
||||||
JS::ObjectOpResult& result) const override;
|
JS::ObjectOpResult& result) const override;
|
||||||
virtual JSObject* enumerate(JSContext* cx,
|
virtual bool enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
JS::Handle<JSObject*> wrapper) const override;
|
JS::AutoIdVector& props) const override;
|
||||||
virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
|
virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
|
||||||
JS::MutableHandleObject protop) const override;
|
JS::MutableHandleObject protop) const override;
|
||||||
virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
|
virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче