Bug 1085566 - Make the preventExtensions hook return succeeded/failed rather than always indicate failure by reporting an error. r=efaust

--HG--
extra : rebase_source : 487b569d23ce18f39fc53697e5f25cc789885803
This commit is contained in:
Jeff Walden 2014-10-19 01:18:43 -07:00
parent dc01ba9c13
commit 63e44a7975
34 changed files with 136 additions and 95 deletions

View File

@ -20,12 +20,11 @@ public:
{ {
} }
virtual bool virtual bool
preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy) const MOZ_OVERRIDE preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy,
bool *succeeded) const MOZ_OVERRIDE
{ {
// Throw a TypeError, per WebIDL. *succeeded = false;
JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr, return true;
JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
} }
virtual bool virtual bool
getOwnPropDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy, getOwnPropDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy,

View File

@ -623,7 +623,8 @@ public:
virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible) virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
const MOZ_OVERRIDE; const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, virtual bool preventExtensions(JSContext *cx,
JS::Handle<JSObject*> proxy) const MOZ_OVERRIDE; JS::Handle<JSObject*> proxy,
bool *succeeded) const MOZ_OVERRIDE;
virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy, virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE; JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JS::Handle<JSObject*> proxy, virtual bool get(JSContext *cx, JS::Handle<JSObject*> proxy,
@ -719,12 +720,12 @@ nsOuterWindowProxy::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy,
bool bool
nsOuterWindowProxy::preventExtensions(JSContext *cx, nsOuterWindowProxy::preventExtensions(JSContext *cx,
JS::Handle<JSObject*> proxy) const JS::Handle<JSObject*> proxy,
bool *succeeded) const
{ {
// See above. // See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, *succeeded = false;
JSMSG_CANT_CHANGE_EXTENSIBILITY); return true;
return false;
} }
const char * const char *

View File

@ -149,12 +149,11 @@ DOMProxyHandler::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *
} }
bool bool
DOMProxyHandler::preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy) const DOMProxyHandler::preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy,
bool *succeeded) const
{ {
// Throw a TypeError, per WebIDL. *succeeded = false;
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, return true;
JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
} }
bool bool

View File

@ -117,7 +117,8 @@ public:
JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE; JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible) bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
const MOZ_OVERRIDE; const MOZ_OVERRIDE;
bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy) const MOZ_OVERRIDE; bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy,
bool *succeeded) const MOZ_OVERRIDE;
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
bool* bp) const MOZ_OVERRIDE; bool* bp) const MOZ_OVERRIDE;
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver, bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,

View File

@ -35,8 +35,10 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
/*** IPC handlers ***/ /*** IPC handlers ***/
bool RecvPreventExtensions(const uint64_t &objId, ReturnStatus *rs) { bool RecvPreventExtensions(const uint64_t &objId, ReturnStatus *rs,
return Answer::RecvPreventExtensions(ObjectId::deserialize(objId), rs); bool *succeeded) {
return Answer::RecvPreventExtensions(ObjectId::deserialize(objId), rs,
succeeded);
} }
bool RecvGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id, bool RecvGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id,
ReturnStatus *rs, ReturnStatus *rs,
@ -131,8 +133,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
bool SendDropObject(const ObjectId &objId) { bool SendDropObject(const ObjectId &objId) {
return Base::SendDropObject(objId.serialize()); return Base::SendDropObject(objId.serialize());
} }
bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs) { bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs,
return Base::SendPreventExtensions(objId.serialize(), rs); bool *succeeded) {
return Base::SendPreventExtensions(objId.serialize(), rs, succeeded);
} }
bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id, bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, ReturnStatus *rs,

View File

@ -24,7 +24,7 @@ both:
async DropObject(uint64_t objId); async DropObject(uint64_t objId);
// These roughly map to the ProxyHandler hooks that CPOWs need. // These roughly map to the ProxyHandler hooks that CPOWs need.
prio(high) sync PreventExtensions(uint64_t objId) returns (ReturnStatus rs); prio(high) sync PreventExtensions(uint64_t objId) returns (ReturnStatus rs, bool result);
prio(high) sync GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result); prio(high) sync GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
prio(high) sync GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result); prio(high) sync GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
prio(high) sync DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs); prio(high) sync DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);

View File

@ -58,17 +58,20 @@ WrapperAnswer::ok(ReturnStatus *rs)
} }
bool bool
WrapperAnswer::RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs) WrapperAnswer::RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs,
bool *succeeded)
{ {
AutoSafeJSContext cx; AutoSafeJSContext cx;
JSAutoRequest request(cx); JSAutoRequest request(cx);
*succeeded = false;
RootedObject obj(cx, findObjectById(cx, objId)); RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) if (!obj)
return fail(cx, rs); return fail(cx, rs);
JSAutoCompartment comp(cx, obj); JSAutoCompartment comp(cx, obj);
if (!JS_PreventExtensions(cx, obj)) if (!JS_PreventExtensions(cx, obj, succeeded))
return fail(cx, rs); return fail(cx, rs);
LOG("%s.preventExtensions()", ReceiverObj(objId)); LOG("%s.preventExtensions()", ReceiverObj(objId));

View File

@ -18,7 +18,8 @@ class WrapperAnswer : public virtual JavaScriptShared
public: public:
explicit WrapperAnswer(JSRuntime *rt) : JavaScriptShared(rt) {} explicit WrapperAnswer(JSRuntime *rt) : JavaScriptShared(rt) {}
bool RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs); bool RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs,
bool *succeeded);
bool RecvGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id, bool RecvGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, ReturnStatus *rs,
PPropertyDescriptor *out); PPropertyDescriptor *out);

View File

@ -72,7 +72,7 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const MOZ_OVERRIDE; HandleId id, MutableHandleValue vp) const MOZ_OVERRIDE;
@ -113,18 +113,18 @@ const CPOWProxyHandler CPOWProxyHandler::singleton;
return owner->call args; return owner->call args;
bool bool
CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) const CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const
{ {
FORWARD(preventExtensions, (cx, proxy)); FORWARD(preventExtensions, (cx, proxy, succeeded));
} }
bool bool
WrapperOwner::preventExtensions(JSContext *cx, HandleObject proxy) WrapperOwner::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded)
{ {
ObjectId objId = idOf(proxy); ObjectId objId = idOf(proxy);
ReturnStatus status; ReturnStatus status;
if (!SendPreventExtensions(objId, &status)) if (!SendPreventExtensions(objId, &status, succeeded))
return ipcfail(cx); return ipcfail(cx);
LOG_STACK(); LOG_STACK();

View File

@ -41,7 +41,7 @@ class WrapperOwner : public virtual JavaScriptShared
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp); bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props); bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible); bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
bool preventExtensions(JSContext *cx, JS::HandleObject proxy); bool preventExtensions(JSContext *cx, JS::HandleObject proxy, bool *succeeded);
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp); bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver, bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp); JS::HandleId id, JS::MutableHandleValue vp);
@ -106,7 +106,8 @@ class WrapperOwner : public virtual JavaScriptShared
/*** Dummy call handlers ***/ /*** Dummy call handlers ***/
public: public:
virtual bool SendDropObject(const ObjectId &objId) = 0; virtual bool SendDropObject(const ObjectId &objId) = 0;
virtual bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0; virtual bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs,
bool *succeeded) = 0;
virtual bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id, virtual bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, ReturnStatus *rs,
PPropertyDescriptor *out) = 0; PPropertyDescriptor *out) = 0;

View File

@ -1012,7 +1012,7 @@ obj_isExtensible(JSContext *cx, unsigned argc, Value *vp)
return true; return true;
} }
// ES6 draft rev27 (2014/08/24) 19.1.2.15 Object.preventExtensions(O) // ES6 20141014 draft 19.1.2.15 Object.preventExtensions(O)
static bool static bool
obj_preventExtensions(JSContext *cx, unsigned argc, Value *vp) obj_preventExtensions(JSContext *cx, unsigned argc, Value *vp)
{ {
@ -1023,10 +1023,21 @@ obj_preventExtensions(JSContext *cx, unsigned argc, Value *vp)
if (!args.get(0).isObject()) if (!args.get(0).isObject())
return true; return true;
// Steps 2-5. // Steps 2-3.
RootedObject obj(cx, &args.get(0).toObject()); RootedObject obj(cx, &args.get(0).toObject());
return JSObject::preventExtensions(cx, obj); bool status;
if (!JSObject::preventExtensions(cx, obj, &status))
return false;
// Step 4.
if (!status) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
}
// Step 5.
return true;
} }
// ES6 draft rev27 (2014/08/24) 19.1.2.5 Object.freeze(O) // ES6 draft rev27 (2014/08/24) 19.1.2.5 Object.freeze(O)

View File

@ -6458,9 +6458,9 @@ JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length)
} }
JS_PUBLIC_API(bool) JS_PUBLIC_API(bool)
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj) JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded)
{ {
return JSObject::preventExtensions(cx, obj); return JSObject::preventExtensions(cx, obj, succeeded);
} }
JS_PUBLIC_API(void) JS_PUBLIC_API(void)

View File

@ -2795,7 +2795,7 @@ extern JS_PUBLIC_API(bool)
JS_FreezeObject(JSContext *cx, JS::Handle<JSObject*> obj); JS_FreezeObject(JSContext *cx, JS::Handle<JSObject*> obj);
extern JS_PUBLIC_API(bool) extern JS_PUBLIC_API(bool)
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj); JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded);
extern JS_PUBLIC_API(JSObject *) extern JS_PUBLIC_API(JSObject *)
JS_New(JSContext *cx, JS::HandleObject ctor, const JS::HandleValueArray& args); JS_New(JSContext *cx, JS::HandleObject ctor, const JS::HandleValueArray& args);

View File

@ -868,10 +868,17 @@ CreateFunctionPrototype(JSContext *cx, JSProtoKey key)
SingletonObject)); SingletonObject));
if (!tte) if (!tte)
return nullptr; return nullptr;
bool succeeded;
RootedFunction throwTypeError(cx, NewFunction(cx, tte, ThrowTypeError, 0, RootedFunction throwTypeError(cx, NewFunction(cx, tte, ThrowTypeError, 0,
JSFunction::NATIVE_FUN, self, js::NullPtr())); JSFunction::NATIVE_FUN, self, js::NullPtr()));
if (!throwTypeError || !JSObject::preventExtensions(cx, throwTypeError)) if (!throwTypeError || !JSObject::preventExtensions(cx, throwTypeError, &succeeded))
return nullptr; return nullptr;
if (!succeeded) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return nullptr;
}
self->setThrowTypeError(throwTypeError); self->setThrowTypeError(throwTypeError);
return functionProto; return functionProto;

View File

@ -1229,8 +1229,13 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
assertSameCompartment(cx, obj); assertSameCompartment(cx, obj);
MOZ_ASSERT(it == SEAL || it == FREEZE); MOZ_ASSERT(it == SEAL || it == FREEZE);
if (!JSObject::preventExtensions(cx, obj)) bool succeeded;
if (!JSObject::preventExtensions(cx, obj, &succeeded))
return false; return false;
if (!succeeded) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
}
AutoIdVector props(cx); AutoIdVector props(cx);
if (!GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY | JSITER_SYMBOLS, &props)) if (!GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY | JSITER_SYMBOLS, &props))

View File

@ -514,10 +514,11 @@ class JSObject : public js::gc::Cell
return !lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE); return !lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE);
} }
// Attempt to change the [[Extensible]] bit on |obj| to false. Callers // Attempt to change the [[Extensible]] bit on |obj| to false. Indicate
// must ensure that |obj| is currently extensible before calling this! // success or failure through the |*succeeded| outparam, or actual error
// through the return value.
static bool static bool
preventExtensions(JSContext *cx, js::HandleObject obj); preventExtensions(JSContext *cx, js::HandleObject obj, bool *succeeded);
private: private:
enum ImmutabilityType { SEAL, FREEZE }; enum ImmutabilityType { SEAL, FREEZE };

View File

@ -257,7 +257,7 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const = 0; virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const = 0;
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const = 0; virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const = 0;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const = 0; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const = 0;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const = 0; virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const = 0;
/* /*
* These methods are standard, but the engine does not normally call them. * These methods are standard, but the engine does not normally call them.
@ -369,7 +369,7 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
virtual bool enumerate(JSContext *cx, HandleObject proxy, virtual bool enumerate(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const MOZ_OVERRIDE; AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE; MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,

View File

@ -123,7 +123,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject wrapper, bool *succeeded) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE; MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
@ -185,7 +185,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE; MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject wrapper, bool *succeeded) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,
bool *bp) const MOZ_OVERRIDE; bool *bp) const MOZ_OVERRIDE;
virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE; virtual bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;

View File

@ -37,11 +37,12 @@ CrossCompartmentWrapper::isExtensible(JSContext *cx, HandleObject wrapper, bool
} }
bool bool
CrossCompartmentWrapper::preventExtensions(JSContext *cx, HandleObject wrapper) const CrossCompartmentWrapper::preventExtensions(JSContext *cx, HandleObject wrapper,
bool *succeeded) const
{ {
PIERCE(cx, wrapper, PIERCE(cx, wrapper,
NOTHING, NOTHING,
Wrapper::preventExtensions(cx, wrapper), Wrapper::preventExtensions(cx, wrapper, succeeded),
NOTHING); NOTHING);
} }

View File

@ -24,7 +24,7 @@ DeadObjectProxy::isExtensible(JSContext *cx, HandleObject proxy, bool *extensibl
} }
bool bool
DeadObjectProxy::preventExtensions(JSContext *cx, HandleObject proxy) const DeadObjectProxy::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const
{ {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT); JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
return false; return false;

View File

@ -28,7 +28,7 @@ class DeadObjectProxy : public BaseProxyHandler
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE; MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE; virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;

View File

@ -251,10 +251,10 @@ DirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extens
} }
bool bool
DirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) const DirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const
{ {
RootedObject target(cx, proxy->as<ProxyObject>().target()); RootedObject target(cx, proxy->as<ProxyObject>().target());
return JSObject::preventExtensions(cx, target); return JSObject::preventExtensions(cx, target, succeeded);
} }
bool bool

View File

@ -387,11 +387,11 @@ Proxy::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
} }
bool bool
Proxy::preventExtensions(JSContext *cx, HandleObject proxy) Proxy::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded)
{ {
JS_CHECK_RECURSION(cx, return false); JS_CHECK_RECURSION(cx, return false);
const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler(); const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
return handler->preventExtensions(cx, proxy); return handler->preventExtensions(cx, proxy, succeeded);
} }
bool bool

View File

@ -36,7 +36,7 @@ class Proxy
static bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp); static bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
static bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props); 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, bool *succeeded);
static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop); static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
static bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp); static bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp);
static bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded); static bool setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded);

View File

@ -273,32 +273,31 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
return true; return true;
} }
// ES6 (22 May, 2014) 9.5.4 Proxy.[[PreventExtensions]]() // ES6 20141014 9.5.4 Proxy.[[PreventExtensions]]()
bool bool
ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) const ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy,
bool *succeeded) const
{ {
// step 1 // Steps 1-3.
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
if (!handler) { if (!handler) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false; return false;
} }
// step 3 // Step 4.
RootedObject target(cx, proxy->as<ProxyObject>().target()); RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 4-5 // Steps 5-6.
RootedValue trap(cx); RootedValue trap(cx);
if (!JSObject::getProperty(cx, handler, handler, cx->names().preventExtensions, &trap)) if (!JSObject::getProperty(cx, handler, handler, cx->names().preventExtensions, &trap))
return false; return false;
// step 6 // Step 7.
if (trap.isUndefined()) if (trap.isUndefined())
return DirectProxyHandler::preventExtensions(cx, proxy); return DirectProxyHandler::preventExtensions(cx, proxy, succeeded);
// step 7, 9 // Steps 8, 10.
Value argv[] = { Value argv[] = {
ObjectValue(*target) ObjectValue(*target)
}; };
@ -306,10 +305,11 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult)) if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
return false; return false;
// step 8 // Step 9.
bool success = ToBoolean(trapResult); bool booleanTrapResult = ToBoolean(trapResult);
if (success) {
// step 10 // Step 11.
if (booleanTrapResult) {
bool extensible; bool extensible;
if (!JSObject::isExtensible(cx, target, &extensible)) if (!JSObject::isExtensible(cx, target, &extensible))
return false; return false;
@ -317,15 +317,11 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE); JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE);
return false; return false;
} }
// step 11 "return true"
return true;
} }
// step 11 "return false" // Step 12.
// This actually corresponds to 19.1.2.5 step 4. We cannot pass the failure back, so throw here *succeeded = booleanTrapResult;
// directly instead. return true;
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
} }
// ES6 implements both getPrototypeOf and setPrototypeOf traps. We don't have them yet (see bug // ES6 implements both getPrototypeOf and setPrototypeOf traps. We don't have them yet (see bug

View File

@ -28,7 +28,7 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
/* These two are standard internal methods but aren't implemented to spec yet. */ /* These two are standard internal methods but aren't implemented to spec yet. */
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,

View File

@ -140,11 +140,11 @@ ScriptedIndirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy,
} }
bool bool
ScriptedIndirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) const ScriptedIndirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const
{ {
// See above. // See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY); *succeeded = false;
return false; return true;
} }
static bool static bool

View File

@ -29,7 +29,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE;
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE; virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id, virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp) const MOZ_OVERRIDE; MutableHandleValue vp) const MOZ_OVERRIDE;

View File

@ -24,11 +24,12 @@ SecurityWrapper<Base>::isExtensible(JSContext *cx, HandleObject wrapper, bool *e
template <class Base> template <class Base>
bool bool
SecurityWrapper<Base>::preventExtensions(JSContext *cx, HandleObject wrapper) const SecurityWrapper<Base>::preventExtensions(JSContext *cx, HandleObject wrapper,
bool *succeeded) const
{ {
// See above. // See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED); *succeeded = false;
return false; return true;
} }
template <class Base> template <class Base>

View File

@ -5863,7 +5863,14 @@ DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp
ok = JSObject::freeze(cx, obj); ok = JSObject::freeze(cx, obj);
} else { } else {
MOZ_ASSERT(op == PreventExtensions); MOZ_ASSERT(op == PreventExtensions);
ok = JSObject::preventExtensions(cx, obj); bool succeeded;
ok = JSObject::preventExtensions(cx, obj, &succeeded);
if (!ok)
return false;
if (!succeeded) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
}
} }
if (!ok) if (!ok)
return false; return false;

View File

@ -1513,11 +1513,11 @@ class DebugScopeProxy : public BaseProxyHandler
return true; return true;
} }
bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE bool preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const MOZ_OVERRIDE
{ {
// See above. // See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY); *succeeded = false;
return false; return true;
} }
bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,

View File

@ -1345,13 +1345,15 @@ Shape::setObjectMetadata(JSContext *cx, JSObject *metadata, TaggedProto proto, S
} }
/* static */ bool /* static */ bool
JSObject::preventExtensions(JSContext *cx, HandleObject obj) JSObject::preventExtensions(JSContext *cx, HandleObject obj, bool *succeeded)
{ {
if (obj->is<ProxyObject>()) if (obj->is<ProxyObject>())
return js::Proxy::preventExtensions(cx, obj); return js::Proxy::preventExtensions(cx, obj, succeeded);
if (!obj->nonProxyIsExtensible()) if (!obj->nonProxyIsExtensible()) {
*succeeded = true;
return true; return true;
}
/* /*
* Force lazy properties to be resolved by iterating over the objects' own * Force lazy properties to be resolved by iterating over the objects' own
@ -1370,6 +1372,7 @@ JSObject::preventExtensions(JSContext *cx, HandleObject obj)
if (obj->isNative() && !NativeObject::sparsifyDenseElements(cx, obj.as<NativeObject>())) if (obj->isNative() && !NativeObject::sparsifyDenseElements(cx, obj.as<NativeObject>()))
return false; return false;
*succeeded = true;
return obj->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE); return obj->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE);
} }

View File

@ -1759,11 +1759,12 @@ XrayWrapper<Base, Traits>::isExtensible(JSContext *cx, JS::Handle<JSObject*> wra
template <typename Base, typename Traits> template <typename Base, typename Traits>
bool bool
XrayWrapper<Base, Traits>::preventExtensions(JSContext *cx, HandleObject wrapper) const XrayWrapper<Base, Traits>::preventExtensions(JSContext *cx, HandleObject wrapper, bool *succeeded)
const
{ {
// See above. // See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY); *succeeded = false;
return false; return true;
} }
template <typename Base, typename Traits> template <typename Base, typename Traits>

View File

@ -415,7 +415,7 @@ class XrayWrapper : public Base {
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE; JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> wrapper, bool *extensible) const MOZ_OVERRIDE; virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> wrapper, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper) const MOZ_OVERRIDE; virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper, bool *succeeded) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const MOZ_OVERRIDE; JS::MutableHandleObject protop) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, JS::HandleObject wrapper, virtual bool setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,