Bug 1113369, part 7 - [[SetPrototypeOf]] ObjectOpResult support. r=Waldo, r=bz in dom, r=dvander in js/ipc, r=bholley in js/xpconnect.

This commit is contained in:
Jason Orendorff 2015-02-05 16:36:50 -06:00
parent 3322381e4f
commit e218a3988f
33 changed files with 160 additions and 183 deletions

View File

@ -96,8 +96,8 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
bool RecvClassName(const uint64_t &objId, nsString *result) {
return Answer::RecvClassName(ObjectId::deserialize(objId), result);
}
bool RecvGetPrototypeOf(const uint64_t &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
return Answer::RecvGetPrototypeOf(ObjectId::deserialize(objId), rs, result);
bool RecvGetPrototype(const uint64_t &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
return Answer::RecvGetPrototype(ObjectId::deserialize(objId), rs, result);
}
bool RecvRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
return Answer::RecvRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
@ -186,9 +186,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
bool SendClassName(const ObjectId &objId, nsString *result) {
return Base::SendClassName(objId.serialize(), result);
}
bool SendGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
return Base::SendGetPrototypeOf(objId.serialize(), rs, result);
}
bool SendGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
return Base::SendGetPrototype(objId.serialize(), rs, result);
}
bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
nsString *source, uint32_t *flags) {

View File

@ -40,7 +40,7 @@ both:
prio(high) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
prio(high) sync ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
prio(high) sync ClassName(uint64_t objId) returns (nsString name);
prio(high) sync GetPrototypeOf(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result);
prio(high) sync GetPrototype(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result);
prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
prio(high) sync GetPropertyKeys(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, JSIDVariant[] ids);

View File

@ -542,7 +542,7 @@ WrapperAnswer::RecvClassName(const ObjectId &objId, nsString *name)
}
bool
WrapperAnswer::RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result)
WrapperAnswer::RecvGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result)
{
*result = NullVariant();
@ -562,7 +562,7 @@ WrapperAnswer::RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, Objec
if (!toObjectOrNullVariant(cx, proto, result))
return fail(cx, rs);
LOG("getPrototypeOf(%s)", ReceiverObj(objId));
LOG("getPrototype(%s)", ReceiverObj(objId));
return ok(rs);
}

View File

@ -50,7 +50,7 @@ class WrapperAnswer : public virtual JavaScriptShared
bool RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result);
bool RecvClassName(const ObjectId &objId, nsString *result);
bool RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result);
bool RecvGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result);
bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
bool RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,

View File

@ -124,7 +124,7 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual void objectMoved(JSObject *proxy, const JSObject *old) const MOZ_OVERRIDE;
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE;
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const MOZ_OVERRIDE;
static const char family;
static const CPOWProxyHandler singleton;
@ -687,19 +687,19 @@ WrapperOwner::className(JSContext *cx, HandleObject proxy)
}
bool
CPOWProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const
CPOWProxyHandler::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const
{
FORWARD(getPrototypeOf, (cx, proxy, objp));
FORWARD(getPrototype, (cx, proxy, objp));
}
bool
WrapperOwner::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject objp)
WrapperOwner::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject objp)
{
ObjectId objId = idOf(proxy);
ObjectOrNullVariant val;
ReturnStatus status;
if (!SendGetPrototypeOf(objId, &status, &val))
if (!SendGetPrototype(objId, &status, &val))
return ipcfail(cx);
LOG_STACK();
@ -1030,7 +1030,7 @@ WrapperOwner::fromRemoteObjectVariant(JSContext *cx, RemoteObject objVar)
RootedObject junkScope(cx, xpc::PrivilegedJunkScope());
JSAutoCompartment ac(cx, junkScope);
RootedValue v(cx, UndefinedValue());
// We need to setLazyProto for the getPrototypeOf hook.
// We need to setLazyProto for the getPrototype hook.
ProxyOptions options;
options.setLazyProto(true);
obj = NewProxyObject(cx,

View File

@ -56,7 +56,7 @@ class WrapperOwner : public virtual JavaScriptShared
bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
const char* className(JSContext *cx, JS::HandleObject proxy);
bool getPrototypeOf(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleObject protop);
bool getPrototype(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleObject protop);
bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
@ -141,7 +141,7 @@ class WrapperOwner : public virtual JavaScriptShared
virtual bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) = 0;
virtual bool SendClassName(const ObjectId &objId, nsString *result) = 0;
virtual bool SendGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) = 0;
virtual bool SendGetPrototype(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) = 0;
virtual bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
uint32_t *flags) = 0;

View File

@ -128,13 +128,13 @@ class JS_FRIEND_API(Wrapper);
* 2. A proxy can implement more complicated prototype semantics (if, for
* example, it wants to delegate the prototype lookup to a wrapped object)
* by passing Proxy::LazyProto as the prototype at create time. This
* guarantees that the getPrototypeOf() handler method will be called every
* guarantees that the getPrototype() handler method will be called every
* time the object's prototype chain is accessed.
*
* This system is implemented with two methods: {get,set}PrototypeOf. The
* default implementation of setPrototypeOf throws a TypeError. Since it is
* This system is implemented with two methods: {get,set}Prototype. The
* default implementation of setPrototype throws a TypeError. Since it is
* not possible to create an object without a sense of prototype chain,
* handlers must implement getPrototypeOf if opting in to the dynamic
* handlers must implement getPrototype if opting in to the dynamic
* prototype system.
*/
@ -271,12 +271,13 @@ class JS_FRIEND_API(BaseProxyHandler)
* These methods are standard, but the engine does not normally call them.
* They're opt-in. See "Proxy prototype chains" above.
*
* getPrototypeOf() crashes if called. setPrototypeOf() throws a TypeError.
* getPrototype() crashes if called. setPrototype() throws a TypeError.
*/
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp) const;
virtual bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const;
virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const;
/* Non-standard but conceptual kin to {g,s}etPrototypeOf, so lives here. */
/* Non-standard but conceptual kin to {g,s}etPrototype, so lives here. */
virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
@ -380,10 +381,10 @@ class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject proxy,
MutableHandleObject objp) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
bool *bp) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy,
bool *succeeded) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy,

View File

@ -444,25 +444,12 @@ obj_setPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
return true;
}
/* Step 5-6. */
/* Step 5-7. */
RootedObject obj(cx, &args[0].toObject());
RootedObject newProto(cx, args[1].toObjectOrNull());
bool success;
if (!SetPrototype(cx, obj, newProto, &success))
if (!SetPrototype(cx, obj, newProto))
return false;
/* Step 7. */
if (!success) {
UniquePtr<char[], JS::FreePolicy> bytes(DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
args[0], NullPtr()));
if (!bytes)
return false;
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
bytes.get());
return false;
}
/* Step 8. */
args.rval().set(args[0]);
return true;
@ -1031,16 +1018,9 @@ ProtoSetter(JSContext *cx, unsigned argc, Value *vp)
}
Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull());
bool success;
if (!SetPrototype(cx, obj, newProto, &success))
if (!SetPrototype(cx, obj, newProto))
return false;
if (!success) {
ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, thisv, js::NullPtr());
return false;
}
args.rval().setUndefined();
return true;
}

View File

@ -183,12 +183,7 @@ MutatePrototype(JSContext *cx, HandlePlainObject obj, HandleValue value)
return true;
RootedObject newProto(cx, value.toObjectOrNull());
bool succeeded;
if (!SetPrototype(cx, obj, newProto, &succeeded))
return false;
MOZ_ASSERT(succeeded);
return true;
return SetPrototype(cx, obj, newProto);
}
bool

View File

@ -95,7 +95,9 @@ MSG_DEF(JSMSG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one")
MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value")
MSG_DEF(JSMSG_WRONG_VALUE, 2, JSEXN_ERR, "expected {0} but found {1}")
MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}")
MSG_DEF(JSMSG_CANT_SET_PROTO, 0, JSEXN_TYPEERR, "can't set prototype of this object")
MSG_DEF(JSMSG_CANT_SET_PROTO_OF, 1, JSEXN_TYPEERR, "can't set prototype of {0}")
MSG_DEF(JSMSG_CANT_SET_PROTO_CYCLE, 0, JSEXN_TYPEERR, "can't set prototype: it would cause a prototype chain cycle")
MSG_DEF(JSMSG_INVALID_ARG_TYPE, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
MSG_DEF(JSMSG_TERMINATED, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")

View File

@ -1792,17 +1792,7 @@ JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*>
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, proto);
bool succeeded;
if (!SetPrototype(cx, obj, proto, &succeeded))
return false;
if (!succeeded) {
RootedValue val(cx, ObjectValue(*obj));
ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, val, js::NullPtr());
return false;
}
return true;
return SetPrototype(cx, obj, proto);
}
JS_PUBLIC_API(bool)

View File

@ -3087,23 +3087,22 @@ JSObject::reportNotExtensible(JSContext *cx, unsigned report)
/*** ES6 standard internal methods ***************************************************************/
bool
js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succeeded)
js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, JS::ObjectOpResult &result)
{
/*
* If |obj| has a "lazy" [[Prototype]], it is 1) a proxy 2) whose handler's
* {get,set}PrototypeOf and setImmutablePrototype methods mediate access to
* {get,set}Prototype and setImmutablePrototype methods mediate access to
* |obj.[[Prototype]]|. The Proxy subsystem is responsible for responding
* to such attempts.
*/
if (obj->hasLazyPrototype()) {
MOZ_ASSERT(obj->is<ProxyObject>());
return Proxy::setPrototypeOf(cx, obj, proto, succeeded);
return Proxy::setPrototype(cx, obj, proto, result);
}
/* Disallow mutation of immutable [[Prototype]]s. */
if (obj->nonLazyPrototypeIsImmutable()) {
*succeeded = false;
return true;
return result.fail(JSMSG_CANT_SET_PROTO);
}
/*
@ -3112,7 +3111,7 @@ js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succ
* have a mutable [[Prototype]].
*/
if (obj->is<ArrayBufferObject>()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
"incompatible ArrayBuffer");
return false;
}
@ -3121,7 +3120,7 @@ js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succ
* Disallow mutating the [[Prototype]] on Typed Objects, per the spec.
*/
if (obj->is<TypedObject>()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
"incompatible TypedObject");
return false;
}
@ -3131,7 +3130,7 @@ js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succ
* for flash-related security reasons.
*/
if (!strcmp(obj->getClass()->name, "Location")) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
"incompatible Location object");
return false;
}
@ -3140,18 +3139,14 @@ js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succ
bool extensible;
if (!IsExtensible(cx, obj, &extensible))
return false;
if (!extensible) {
*succeeded = false;
return true;
}
if (!extensible)
return result.fail(JSMSG_CANT_SET_PROTO);
/* ES6 9.1.2 step 6 forbids generating cyclical prototype chains. */
RootedObject obj2(cx);
for (obj2 = proto; obj2; ) {
if (obj2 == obj) {
*succeeded = false;
return true;
}
if (obj2 == obj)
return result.fail(JSMSG_CANT_SET_PROTO_CYCLE);
if (!GetPrototype(cx, obj2, &obj2))
return false;
@ -3163,8 +3158,17 @@ js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succ
return false;
Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
*succeeded = SetClassAndProto(cx, obj, obj->getClass(), taggedProto);
return *succeeded;
if (!SetClassAndProto(cx, obj, obj->getClass(), taggedProto))
return false;
return result.succeed();
}
bool
js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto)
{
ObjectOpResult result;
return SetPrototype(cx, obj, proto, result) && result.checkStrict(cx, obj);
}
bool

View File

@ -344,7 +344,7 @@ class JSObject : public js::gc::Cell
//
// Proxies that don't have such a simple [[Prototype]] instead have a
// "lazy" [[Prototype]]. Accessing the [[Prototype]] of such an object
// requires going through the proxy handler {get,set}PrototypeOf and
// requires going through the proxy handler {get,set}Prototype and
// setImmutablePrototype methods. This is most commonly useful for proxies
// that are wrappers around other objects. If the [[Prototype]] of the
// underlying object changes, the [[Prototype]] of the wrapper must also
@ -708,12 +708,17 @@ GetPrototype(JSContext *cx, HandleObject obj, MutableHandleObject protop);
/*
* ES6 [[SetPrototypeOf]]. Change obj's prototype to proto.
*
* Returns false on error, success of operation in outparam. For example, if
* Returns false on error, success of operation in *result. For example, if
* obj is not extensible, its prototype is fixed. js::SetPrototype will return
* true, because no exception is thrown for this; but *succeeded will be false.
* true, because no exception is thrown for this; but *result will be false.
*/
extern bool
SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succeeded);
SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto,
ObjectOpResult &result);
/* Convenience function: like the above, but throw on failure. */
extern bool
SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto);
/*
* ES6 [[IsExtensible]]. Extensible objects can have new properties defined on

View File

@ -133,7 +133,7 @@ js::GetPrototype(JSContext *cx, js::HandleObject obj, js::MutableHandleObject pr
{
if (obj->getTaggedProto().isLazy()) {
MOZ_ASSERT(obj->is<js::ProxyObject>());
return js::Proxy::getPrototypeOf(cx, obj, protop);
return js::Proxy::getPrototype(cx, obj, protop);
} else {
protop.set(obj->getTaggedProto().toObjectOrNull());
return true;

View File

@ -124,10 +124,10 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
bool *bp) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy,
bool *succeeded) const MOZ_OVERRIDE;
@ -190,8 +190,8 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
bool *bp) const MOZ_OVERRIDE;
virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,

View File

@ -338,18 +338,19 @@ BaseProxyHandler::weakmapKeyDelegate(JSObject *proxy) const
}
bool
BaseProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
BaseProxyHandler::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
{
MOZ_CRASH("Must override getPrototypeOf with lazy prototype.");
MOZ_CRASH("Must override getPrototype with lazy prototype.");
}
bool
BaseProxyHandler::setPrototypeOf(JSContext *cx, HandleObject, HandleObject, bool *) const
BaseProxyHandler::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const
{
// Disallow sets of protos on proxies with lazy protos, but no hook.
// This keeps us away from the footgun of having the first proto set opt
// you out of having dynamic protos altogether.
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
"incompatible Proxy");
return false;
}

View File

@ -80,8 +80,8 @@ CrossCompartmentWrapper::delete_(JSContext *cx, HandleObject wrapper, HandleId i
}
bool
CrossCompartmentWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper,
MutableHandleObject protop) const
CrossCompartmentWrapper::getPrototype(JSContext *cx, HandleObject wrapper,
MutableHandleObject protop) const
{
{
RootedObject wrapped(cx, wrappedObject(wrapper));
@ -96,13 +96,13 @@ CrossCompartmentWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper,
}
bool
CrossCompartmentWrapper::setPrototypeOf(JSContext *cx, HandleObject wrapper,
HandleObject proto, bool *bp) const
CrossCompartmentWrapper::setPrototype(JSContext *cx, HandleObject wrapper,
HandleObject proto, ObjectOpResult &result) const
{
RootedObject protoCopy(cx, proto);
PIERCE(cx, wrapper,
cx->compartment()->wrap(cx, &protoCopy),
Wrapper::setPrototypeOf(cx, wrapper, protoCopy, bp),
Wrapper::setPrototype(cx, wrapper, protoCopy, result),
NOTHING);
}

View File

@ -63,7 +63,7 @@ DeadObjectProxy::enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObj
}
bool
DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
DeadObjectProxy::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
{
protop.set(nullptr);
return true;

View File

@ -29,8 +29,8 @@ class DeadObjectProxy : public BaseProxyHandler
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject wrapper, MutableHandleObject objp) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;

View File

@ -112,17 +112,18 @@ DirectProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandle
}
bool
DirectProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
DirectProxyHandler::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
{
RootedObject target(cx, proxy->as<ProxyObject>().target());
return GetPrototype(cx, target, protop);
}
bool
DirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp) const
DirectProxyHandler::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const
{
RootedObject target(cx, proxy->as<ProxyObject>().target());
return SetPrototype(cx, target, proto, bp);
return SetPrototype(cx, target, proto, result);
}
bool

View File

@ -194,19 +194,19 @@ js::AppendUnique(JSContext *cx, AutoIdVector &base, AutoIdVector &others)
}
/* static */ bool
Proxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject proto)
Proxy::getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject proto)
{
MOZ_ASSERT(proxy->hasLazyPrototype());
JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->getPrototypeOf(cx, proxy, proto);
return proxy->as<ProxyObject>().handler()->getPrototype(cx, proxy, proto);
}
/* static */ bool
Proxy::setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp)
Proxy::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto, ObjectOpResult &result)
{
MOZ_ASSERT(proxy->hasLazyPrototype());
JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->setPrototypeOf(cx, proxy, proto, bp);
return proxy->as<ProxyObject>().handler()->setPrototype(cx, proxy, proto, result);
}
/* static */ bool

View File

@ -35,8 +35,9 @@ class Proxy
static bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp);
static bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible);
static bool preventExtensions(JSContext *cx, HandleObject proxy, ObjectOpResult &result);
static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
static bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp);
static bool getPrototype(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
static bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result);
static bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded);
static bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
static bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,

View File

@ -263,11 +263,11 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
return true;
}
// ES6 implements both getPrototypeOf and setPrototypeOf traps. We don't have them yet (see bug
// ES6 implements both getPrototype and setPrototype traps. We don't have them yet (see bug
// 888969). For now, use these, to account for proxy revocation.
bool
ScriptedDirectProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const
ScriptedDirectProxyHandler::getPrototype(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const
{
RootedObject target(cx, proxy->as<ProxyObject>().target());
// Though handler is used elsewhere, spec mandates that both get set to null.
@ -276,12 +276,12 @@ ScriptedDirectProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy,
return false;
}
return DirectProxyHandler::getPrototypeOf(cx, proxy, protop);
return DirectProxyHandler::getPrototype(cx, proxy, protop);
}
bool
ScriptedDirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy,
HandleObject proto, bool *bp) const
ScriptedDirectProxyHandler::setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const
{
RootedObject target(cx, proxy->as<ProxyObject>().target());
if (!target) {
@ -289,7 +289,7 @@ ScriptedDirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy,
return false;
}
return DirectProxyHandler::setPrototypeOf(cx, proxy, proto, bp);
return DirectProxyHandler::setPrototype(cx, proxy, proto, result);
}
// Not yet part of ES6, but hopefully to be standards-tracked -- and needed to
@ -406,7 +406,7 @@ ScriptedDirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool
return true;
}
// Corresponds to the "standard" property descriptor getOwn getPrototypeOf dance. It's so explicit
// Corresponds to the "standard" property descriptor getOwn/getPrototype dance. It's so explicit
// here because ScriptedDirectProxyHandler allows script visibility for this operation.
bool
ScriptedDirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,

View File

@ -31,10 +31,10 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const MOZ_OVERRIDE;
/* These two are standard internal methods but aren't implemented to spec yet. */
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
bool *bp) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototype(JSContext *cx, HandleObject proxy, HandleObject proto,
ObjectOpResult &result) const MOZ_OVERRIDE;
/* Non-standard, but needed to handle revoked proxies. */
virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy,
bool *succeeded) const MOZ_OVERRIDE;

View File

@ -32,8 +32,8 @@ SecurityWrapper<Base>::nativeCall(JSContext *cx, IsAcceptableThis test, NativeIm
template <class Base>
bool
SecurityWrapper<Base>::setPrototypeOf(JSContext *cx, HandleObject wrapper,
HandleObject proto, bool *bp) const
SecurityWrapper<Base>::setPrototype(JSContext *cx, HandleObject wrapper, HandleObject proto,
ObjectOpResult &result) const
{
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
return false;

View File

@ -3207,10 +3207,8 @@ CASE(JSOP_MUTATEPROTO)
obj = &REGS.sp[-2].toObject();
MOZ_ASSERT(obj->is<PlainObject>());
bool succeeded;
if (!SetPrototype(cx, obj, newProto, &succeeded))
if (!SetPrototype(cx, obj, newProto))
goto error;
MOZ_ASSERT(succeeded);
}
REGS.sp--;

View File

@ -29,11 +29,11 @@ namespace js {
*
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 244;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 245;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
static_assert(JSErr_Limit == 381,
static_assert(JSErr_Limit == 383,
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
"removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "

View File

@ -164,8 +164,8 @@ FilteringWrapper<Base, Policy>::defaultValue(JSContext *cx, HandleObject obj,
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const
FilteringWrapper<Base, Policy>::getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const
{
// Filtering wrappers do not allow access to the prototype.
protop.set(nullptr);

View File

@ -53,8 +53,8 @@ class FilteringWrapper : public Base {
virtual bool defaultValue(JSContext *cx, JS::Handle<JSObject*> obj, JSType hint,
JS::MutableHandleValue vp) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const MOZ_OVERRIDE;
static const FilteringWrapper singleton;
};

View File

@ -91,9 +91,9 @@ WaiveXrayWrapper::nativeCall(JSContext *cx, JS::IsAcceptableThis test,
}
bool
WaiveXrayWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper, MutableHandleObject protop) const
WaiveXrayWrapper::getPrototype(JSContext *cx, HandleObject wrapper, MutableHandleObject protop) const
{
return CrossCompartmentWrapper::getPrototypeOf(cx, wrapper, protop) &&
return CrossCompartmentWrapper::getPrototype(cx, wrapper, protop) &&
(!protop || WrapperFactory::WaiveXrayAndWrap(cx, protop));
}

View File

@ -20,8 +20,8 @@ class WaiveXrayWrapper : public js::CrossCompartmentWrapper {
virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::MutableHandle<JSObject*> protop) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::MutableHandle<JSObject*> protop) const MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
virtual bool call(JSContext *cx, JS::Handle<JSObject*> wrapper,

View File

@ -1633,9 +1633,9 @@ DOMXrayTraits::construct(JSContext *cx, HandleObject wrapper,
}
bool
DOMXrayTraits::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
DOMXrayTraits::getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
{
return mozilla::dom::XrayGetNativeProto(cx, target, protop);
}
@ -2143,15 +2143,15 @@ XrayWrapper<Base, Traits>::defaultValue(JSContext *cx, HandleObject wrapper,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const
XrayWrapper<Base, Traits>::getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const
{
// We really only want this override for non-SecurityWrapper-inheriting
// |Base|. But doing that statically with templates requires partial method
// specializations (and therefore a helper class), which is all more trouble
// than it's worth. Do a dynamic check.
if (Base::hasSecurityPolicy())
return Base::getPrototypeOf(cx, wrapper, protop);
return Base::getPrototype(cx, wrapper, protop);
RootedObject target(cx, Traits::getTargetObject(wrapper));
RootedObject expando(cx);
@ -2168,7 +2168,7 @@ XrayWrapper<Base, Traits>::getPrototypeOf(JSContext *cx, JS::HandleObject wrappe
v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE);
}
if (v.isUndefined())
return getPrototypeOfHelper(cx, wrapper, target, protop);
return getPrototypeHelper(cx, wrapper, target, protop);
protop.set(v.toObjectOrNull());
return JS_WrapObject(cx, protop);
@ -2176,13 +2176,13 @@ XrayWrapper<Base, Traits>::getPrototypeOf(JSContext *cx, JS::HandleObject wrappe
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject proto, bool *bp) const
XrayWrapper<Base, Traits>::setPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject proto, JS::ObjectOpResult &result) const
{
// Do this only for non-SecurityWrapper-inheriting |Base|. See the comment
// in getPrototypeOf().
// in getPrototype().
if (Base::hasSecurityPolicy())
return Base::setPrototypeOf(cx, wrapper, proto, bp);
return Base::setPrototype(cx, wrapper, proto, result);
RootedObject target(cx, Traits::getTargetObject(wrapper));
RootedObject expando(cx, Traits::singleton.ensureExpandoObject(cx, wrapper, target));
@ -2196,8 +2196,7 @@ XrayWrapper<Base, Traits>::setPrototypeOf(JSContext *cx, JS::HandleObject wrappe
if (!JS_WrapValue(cx, &v))
return false;
JS_SetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE, v);
*bp = true;
return true;
return result.succeed();
}
template <typename Base, typename Traits>

View File

@ -187,9 +187,9 @@ public:
static bool construct(JSContext *cx, JS::HandleObject wrapper,
const JS::CallArgs &args, const js::Wrapper& baseInstance);
static bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop);
static bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop);
virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE;
@ -253,9 +253,9 @@ public:
return false;
}
bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
{
JS::RootedObject holder(cx, ensureHolder(cx, wrapper));
JSProtoKey key = getProtoKey(holder);
@ -368,9 +368,9 @@ public:
return false;
}
bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target,
JS::MutableHandleObject protop)
{
// Opaque wrappers just get targetGlobal.Object.prototype as their
// prototype. This is preferable to using a null prototype because it
@ -420,10 +420,10 @@ class XrayWrapper : public Base {
JS::Handle<jsid> id, JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::MutableHandle<JSObject*> objp) 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,
JS::HandleObject proto, bool *bp) const MOZ_OVERRIDE;
virtual bool getPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototype(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject proto, JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool setImmutablePrototype(JSContext *cx, JS::HandleObject wrapper,
bool *succeeded) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper,
@ -459,23 +459,23 @@ class XrayWrapper : public Base {
private:
template <bool HasPrototype>
typename mozilla::EnableIf<HasPrototype, bool>::Type
getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target, JS::MutableHandleObject protop) const
getPrototypeHelper(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target, JS::MutableHandleObject protop) const
{
return Traits::singleton.getPrototypeOf(cx, wrapper, target, protop);
return Traits::singleton.getPrototype(cx, wrapper, target, protop);
}
template <bool HasPrototype>
typename mozilla::EnableIf<!HasPrototype, bool>::Type
getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target, JS::MutableHandleObject protop) const
getPrototypeHelper(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target, JS::MutableHandleObject protop) const
{
return Base::getPrototypeOf(cx, wrapper, protop);
return Base::getPrototype(cx, wrapper, protop);
}
bool getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target, JS::MutableHandleObject protop) const
bool getPrototypeHelper(JSContext *cx, JS::HandleObject wrapper,
JS::HandleObject target, JS::MutableHandleObject protop) const
{
return getPrototypeOfHelper<Traits::HasPrototype>(cx, wrapper, target,
protop);
return getPrototypeHelper<Traits::HasPrototype>(cx, wrapper, target,
protop);
}
protected: