mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 888106 - Add too-much-recursion detection to isExtensible tests, and make the isExtensible hook capable of failing. r=bholley, r=ejpbruel
--HG-- extra : rebase_source : fe7345322f87dd214aa5122ea8704750e8b2375a
This commit is contained in:
parent
453bb904cf
commit
63dbd9617f
@ -569,7 +569,8 @@ public:
|
||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
|
||||
|
||||
// Fundamental traps
|
||||
virtual bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
||||
MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx,
|
||||
JS::Handle<JSObject*> proxy) MOZ_OVERRIDE;
|
||||
virtual bool getPropertyDescriptor(JSContext* cx,
|
||||
@ -641,11 +642,13 @@ protected:
|
||||
};
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::isExtensible(JSObject *proxy)
|
||||
nsOuterWindowProxy::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
bool *extensible)
|
||||
{
|
||||
// If [[Extensible]] could be false, then navigating a window could navigate
|
||||
// to a window that's [[Extensible]] after being at one that wasn't: an
|
||||
// invariant violation. So always report true for this.
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -144,9 +144,11 @@ DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
}
|
||||
|
||||
bool
|
||||
DOMProxyHandler::isExtensible(JSObject *proxy)
|
||||
DOMProxyHandler::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
||||
{
|
||||
return true; // always extensible per WebIDL
|
||||
// always extensible per WebIDL
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
JS::Handle<jsid> id, bool* bp) MOZ_OVERRIDE;
|
||||
bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy, JS::AutoIdVector& props) MOZ_OVERRIDE;
|
||||
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) MOZ_OVERRIDE;
|
||||
bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
|
||||
bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible) MOZ_OVERRIDE;
|
||||
|
||||
static JSObject* GetExpandoObject(JSObject* obj)
|
||||
{
|
||||
|
@ -603,7 +603,10 @@ Collator(JSContext *cx, CallArgs args, bool construct)
|
||||
return false;
|
||||
|
||||
// 10.1.2.1 step 5
|
||||
if (!obj->isExtensible())
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
} else {
|
||||
// 10.1.2.1 step 3.a
|
||||
@ -1081,7 +1084,10 @@ NumberFormat(JSContext *cx, CallArgs args, bool construct)
|
||||
return false;
|
||||
|
||||
// 11.1.2.1 step 5
|
||||
if (!obj->isExtensible())
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
} else {
|
||||
// 11.1.2.1 step 3.a
|
||||
@ -1531,7 +1537,10 @@ DateTimeFormat(JSContext *cx, CallArgs args, bool construct)
|
||||
return false;
|
||||
|
||||
// 12.1.2.1 step 5
|
||||
if (!obj->isExtensible())
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
} else {
|
||||
// 12.1.2.1 step 3.a
|
||||
|
@ -885,7 +885,10 @@ obj_isExtensible(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!GetFirstArgumentAsObject(cx, args, "Object.isExtensible", &obj))
|
||||
return false;
|
||||
|
||||
args.rval().setBoolean(obj->isExtensible());
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
args.rval().setBoolean(extensible);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -898,7 +901,11 @@ obj_preventExtensions(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
if (!obj->isExtensible())
|
||||
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return true;
|
||||
|
||||
return JSObject::preventExtensions(cx, obj);
|
||||
|
@ -3336,7 +3336,7 @@ IsCacheableSetPropAddSlot(JSContext *cx, HandleObject obj, HandleShape oldShape,
|
||||
return false;
|
||||
|
||||
// Object must be extensible, oldShape must be immediate parent of curShape.
|
||||
if (!obj->isExtensible() || obj->lastProperty()->previous() != oldShape)
|
||||
if (!obj->nonProxyIsExtensible() || obj->lastProperty()->previous() != oldShape)
|
||||
return false;
|
||||
|
||||
// Basic shape checks.
|
||||
|
@ -2065,7 +2065,7 @@ IsPropertyAddInlineable(JSContext *cx, HandleObject obj, HandleId id, uint32_t o
|
||||
if (obj->getClass()->addProperty != JS_PropertyStub)
|
||||
return false;
|
||||
|
||||
if (!obj->isExtensible() || !shape->writable())
|
||||
if (!obj->nonProxyIsExtensible() || !shape->writable())
|
||||
return false;
|
||||
|
||||
// walk up the object prototype chain and ensure that all prototypes
|
||||
|
@ -3363,9 +3363,13 @@ JS_NewObjectForConstructor(JSContext *cx, JSClass *clasp, const jsval *vp)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsExtensible(JSObject *obj)
|
||||
JS_IsExtensible(JSContext *cx, HandleObject obj, JSBool *extensible)
|
||||
{
|
||||
return obj->isExtensible();
|
||||
bool isExtensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &isExtensible))
|
||||
return false;
|
||||
*extensible = isExtensible;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
@ -3400,7 +3404,10 @@ JS_DeepFreezeObject(JSContext *cx, JSObject *objArg)
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
/* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
|
||||
if (!obj->isExtensible())
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return true;
|
||||
|
||||
if (!JSObject::freeze(cx, obj))
|
||||
|
@ -3185,7 +3185,7 @@ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
|
||||
|
||||
/* Queries the [[Extensible]] property of the object. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsExtensible(JSObject *obj);
|
||||
JS_IsExtensible(JSContext *cx, JS::HandleObject obj, JSBool *extensible);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsNative(JSObject *obj);
|
||||
|
@ -566,7 +566,7 @@ js::CheckDefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValu
|
||||
if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
|
||||
return false;
|
||||
|
||||
// This does not have to check obj->isExtensible() when !desc.obj (steps
|
||||
// This does not have to check obj's extensibility when !desc.obj (steps
|
||||
// 2-3) because the low-level methods JSObject::{add,put}Property check
|
||||
// for that.
|
||||
if (desc.obj && (desc.attrs & JSPROP_PERMANENT)) {
|
||||
@ -608,7 +608,10 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
||||
|
||||
/* 8.12.9 steps 2-4. */
|
||||
if (!shape) {
|
||||
if (!obj->isExtensible())
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
|
||||
|
||||
*rval = true;
|
||||
@ -1131,7 +1134,10 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
|
||||
assertSameCompartment(cx, obj);
|
||||
JS_ASSERT(it == SEAL || it == FREEZE);
|
||||
|
||||
if (obj->isExtensible() && !JSObject::preventExtensions(cx, obj))
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (extensible && !JSObject::preventExtensions(cx, obj))
|
||||
return false;
|
||||
|
||||
AutoIdVector props(cx);
|
||||
@ -1220,7 +1226,10 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
|
||||
/* static */ bool
|
||||
JSObject::isSealedOrFrozen(JSContext *cx, HandleObject obj, ImmutabilityType it, bool *resultp)
|
||||
{
|
||||
if (obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (extensible) {
|
||||
*resultp = false;
|
||||
return true;
|
||||
}
|
||||
@ -2730,7 +2739,7 @@ JSObject::maybeDensifySparseElements(JSContext *cx, HandleObject obj)
|
||||
return ED_SPARSE;
|
||||
|
||||
/* Watch for conditions under which an object's elements cannot be dense. */
|
||||
if (!obj->isExtensible() || obj->watched())
|
||||
if (!obj->nonProxyIsExtensible() || obj->watched())
|
||||
return ED_SPARSE;
|
||||
|
||||
/*
|
||||
@ -2853,7 +2862,7 @@ ReallocateElements(ThreadSafeContext *tcx, JSObject *obj, ObjectElements *oldHea
|
||||
bool
|
||||
JSObject::growElements(ThreadSafeContext *tcx, uint32_t newcap)
|
||||
{
|
||||
JS_ASSERT(isExtensible());
|
||||
JS_ASSERT(nonProxyIsExtensible());
|
||||
|
||||
/*
|
||||
* When an object with CAPACITY_DOUBLING_MAX or fewer elements needs to
|
||||
@ -4466,7 +4475,10 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
}
|
||||
|
||||
if (!shape) {
|
||||
if (!obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
/* Error in strict mode code, warn with extra warnings option, otherwise do nothing. */
|
||||
if (strict)
|
||||
return obj->reportNotExtensible(cx);
|
||||
@ -5192,7 +5204,7 @@ JSObject::dump()
|
||||
|
||||
fprintf(stderr, "flags:");
|
||||
if (obj->isDelegate()) fprintf(stderr, " delegate");
|
||||
if (!obj->isExtensible()) fprintf(stderr, " not_extensible");
|
||||
if (!obj->isProxy() && !obj->nonProxyIsExtensible()) fprintf(stderr, " not_extensible");
|
||||
if (obj->isIndexed()) fprintf(stderr, " indexed");
|
||||
|
||||
if (obj->isNative()) {
|
||||
|
@ -687,7 +687,7 @@ class JSObject : public js::ObjectImpl
|
||||
*
|
||||
* Notes:
|
||||
* 1. getter and setter must be normalized based on flags (see jsscope.cpp).
|
||||
* 2. !isExtensible() checking must be done by callers.
|
||||
* 2. Checks for non-extensibility must be done by callers.
|
||||
*/
|
||||
static js::Shape *addPropertyInternal(JSContext *cx,
|
||||
JS::HandleObject obj, JS::HandleId id,
|
||||
|
@ -384,7 +384,7 @@ JSObject::extendDenseElements(js::ThreadSafeContext *tcx,
|
||||
* elements can be added/written with no extensible or watchpoint checks as
|
||||
* long as there is capacity for them.
|
||||
*/
|
||||
if (!isExtensible() || watched()) {
|
||||
if (!nonProxyIsExtensible() || watched()) {
|
||||
JS_ASSERT(getDenseCapacity() == 0);
|
||||
return ED_SPARSE;
|
||||
}
|
||||
|
@ -625,9 +625,10 @@ DirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::isExtensible(JSObject *proxy)
|
||||
DirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||
{
|
||||
return GetProxyTargetObject(proxy)->isExtensible();
|
||||
RootedObject target(cx, GetProxyTargetObject(proxy));
|
||||
return JSObject::isExtensible(cx, target, extensible);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -787,7 +788,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
|
||||
MutableHandleValue vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
|
||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
@ -811,9 +812,10 @@ ScriptedIndirectProxyHandler::~ScriptedIndirectProxyHandler()
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::isExtensible(JSObject *proxy)
|
||||
ScriptedIndirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||
{
|
||||
// Scripted indirect proxies don't support extensibility changes.
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1394,7 +1396,10 @@ TrapGetOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!target->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
bool found;
|
||||
if (!HasOwn(cx, target, id, &found))
|
||||
return false;
|
||||
@ -1414,7 +1419,10 @@ TrapGetOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle
|
||||
return false;
|
||||
|
||||
// step 9
|
||||
if (target->isExtensible() && !isFixed) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (extensible && !isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_NEW);
|
||||
return false;
|
||||
}
|
||||
@ -1495,7 +1503,10 @@ TrapDefineOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHan
|
||||
if (!HasOwn(cx, target, id, &isFixed))
|
||||
return false;
|
||||
|
||||
if (!target->isExtensible() && !isFixed) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible && !isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_DEFINE_NEW);
|
||||
return false;
|
||||
}
|
||||
@ -1581,7 +1592,10 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
|
||||
return false;
|
||||
|
||||
// step v
|
||||
if (!target->isExtensible() && !isFixed) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible && !isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_NEW);
|
||||
return false;
|
||||
}
|
||||
@ -1625,7 +1639,10 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
|
||||
return false;
|
||||
|
||||
// step iii
|
||||
if (!target->isExtensible() && isFixed) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible && isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_E_AS_NE);
|
||||
return false;
|
||||
}
|
||||
@ -1674,7 +1691,10 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
|
||||
bool success = ToBoolean(trapResult);
|
||||
if (success) {
|
||||
// step g
|
||||
if (target->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (extensible) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE);
|
||||
return false;
|
||||
}
|
||||
@ -1919,7 +1939,10 @@ ScriptedDirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!target->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
bool isFixed;
|
||||
if (!HasOwn(cx, target, id, &isFixed))
|
||||
return false;
|
||||
@ -1979,7 +2002,10 @@ ScriptedDirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId i
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!target->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
bool isFixed;
|
||||
if (!HasOwn(cx, target, id, &isFixed))
|
||||
return false;
|
||||
@ -1988,13 +2014,18 @@ ScriptedDirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId i
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (!target->isExtensible()) {
|
||||
bool isFixed;
|
||||
if (!HasOwn(cx, target, id, &isFixed))
|
||||
return false;
|
||||
if (!isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_NEW);
|
||||
} else {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
bool isFixed;
|
||||
if (!HasOwn(cx, target, id, &isFixed))
|
||||
return false;
|
||||
if (!isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_NEW);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2578,9 +2609,10 @@ Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleV
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::isExtensible(JSObject *proxy)
|
||||
Proxy::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||
{
|
||||
return GetProxyHandler(proxy)->isExtensible(proxy);
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
return GetProxyHandler(proxy)->isExtensible(cx, proxy, extensible);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -129,7 +129,7 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
MutableHandleValue vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool isExtensible(JSObject *proxy) = 0;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) = 0;
|
||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args);
|
||||
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args);
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args);
|
||||
@ -190,7 +190,7 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
|
||||
MutableHandleValue vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
|
||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
@ -242,7 +242,7 @@ class Proxy
|
||||
static bool iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
static bool isExtensible(JSObject *proxy);
|
||||
static bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible);
|
||||
static bool call(JSContext *cx, HandleObject proxy, const CallArgs &args);
|
||||
static bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args);
|
||||
static bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args);
|
||||
|
@ -191,18 +191,12 @@ bool CrossCompartmentWrapper::finalizeInBackground(Value priv)
|
||||
#define NOTHING (true)
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::isExtensible(JSObject *wrapper)
|
||||
CrossCompartmentWrapper::isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible)
|
||||
{
|
||||
// The lack of a context to enter a compartment here is troublesome. We
|
||||
// don't know anything about the wrapped object (it might even be a
|
||||
// proxy!), and embeddings' proxy handlers could theoretically trigger
|
||||
// compartment mismatches here (because isExtensible wouldn't be called in
|
||||
// the wrapped object's compartment. But that's probably not very likely.
|
||||
// (Famous last words.)
|
||||
//
|
||||
// Given that we're likely going to make this method take a context and
|
||||
// maybe be fallible at some point, punt on the issue for now.
|
||||
return wrappedObject(wrapper)->isExtensible();
|
||||
PIERCE(cx, wrapper,
|
||||
NOTHING,
|
||||
Wrapper::isExtensible(cx, wrapper, extensible),
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -605,11 +599,12 @@ SecurityWrapper<Base>::SecurityWrapper(unsigned flags)
|
||||
|
||||
template <class Base>
|
||||
bool
|
||||
SecurityWrapper<Base>::isExtensible(JSObject *wrapper)
|
||||
SecurityWrapper<Base>::isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible)
|
||||
{
|
||||
// Just like BaseProxyHandler, SecurityWrappers claim by default to always
|
||||
// be extensible, so as not to leak information about the state of the
|
||||
// underlying wrapped thing.
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -691,10 +686,11 @@ DeadObjectProxy::DeadObjectProxy()
|
||||
}
|
||||
|
||||
bool
|
||||
DeadObjectProxy::isExtensible(JSObject *proxy)
|
||||
DeadObjectProxy::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||
{
|
||||
// This is kind of meaningless, but dead-object semantics aside,
|
||||
// [[Extensible]] always being true is consistent with other proxy types.
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
MutableHandleValue vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) MOZ_OVERRIDE;
|
||||
virtual bool call(JSContext *cx, HandleObject wrapper, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, HandleObject wrapper, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
@ -139,7 +139,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
|
||||
public:
|
||||
SecurityWrapper(unsigned flags);
|
||||
|
||||
virtual bool isExtensible(JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper) MOZ_OVERRIDE;
|
||||
virtual bool enter(JSContext *cx, HandleObject wrapper, HandleId id, Wrapper::Action act,
|
||||
bool *bp) MOZ_OVERRIDE;
|
||||
@ -185,7 +185,7 @@ class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
|
||||
virtual bool enumerate(JSContext *cx, HandleObject wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool isExtensible(JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
|
||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
|
||||
|
@ -4776,7 +4776,10 @@ DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp
|
||||
ok = JSObject::freeze(cx, obj);
|
||||
} else {
|
||||
JS_ASSERT(op == PreventExtensions);
|
||||
if (!obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
@ -4823,7 +4826,8 @@ DebuggerObject_isSealedHelper(JSContext *cx, unsigned argc, Value *vp, SealHelpe
|
||||
if (!JSObject::isFrozen(cx, obj, &r))
|
||||
return false;
|
||||
} else {
|
||||
r = obj->isExtensible();
|
||||
if (!JSObject::isExtensible(cx, obj, &r))
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(r);
|
||||
return true;
|
||||
|
@ -124,7 +124,10 @@ ProtoSetterImpl(JSContext *cx, CallArgs args)
|
||||
Rooted<JSObject*> obj(cx, &args.thisv().toObject());
|
||||
|
||||
/* ES5 8.6.2 forbids changing [[Prototype]] if not [[Extensible]]. */
|
||||
if (!obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
obj->reportNotExtensible(cx);
|
||||
return false;
|
||||
}
|
||||
|
@ -39,15 +39,27 @@ js::ObjectImpl::nativeContainsPure(Shape *shape)
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::isExtensible() const
|
||||
js::ObjectImpl::nonProxyIsExtensible() const
|
||||
{
|
||||
if (this->isProxy())
|
||||
return Proxy::isExtensible(const_cast<JSObject*>(this->asObjectPtr()));
|
||||
MOZ_ASSERT(!isProxy());
|
||||
|
||||
// [[Extensible]] for ordinary non-proxy objects is an object flag.
|
||||
return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
js::ObjectImpl::isExtensible(JSContext *cx, js::Handle<ObjectImpl*> obj, bool *extensible)
|
||||
{
|
||||
if (obj->isProxy()) {
|
||||
HandleObject h =
|
||||
HandleObject::fromMarkedLocation(reinterpret_cast<JSObject* const*>(obj.address()));
|
||||
return Proxy::isExtensible(cx, h, extensible);
|
||||
}
|
||||
|
||||
*extensible = obj->nonProxyIsExtensible();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::isNative() const
|
||||
{
|
||||
|
@ -481,7 +481,10 @@ DenseElementsHeader::defineElement(JSContext *cx, Handle<ObjectImpl*> obj, uint3
|
||||
* If the element doesn't exist, we can only add it if the object is
|
||||
* extensible.
|
||||
*/
|
||||
if (!obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
*succeeded = false;
|
||||
if (!shouldThrow)
|
||||
return true;
|
||||
|
@ -1239,7 +1239,14 @@ class ObjectImpl : public gc::Cell
|
||||
return type_->clasp;
|
||||
}
|
||||
|
||||
inline bool isExtensible() const;
|
||||
static inline bool
|
||||
isExtensible(JSContext *cx, Handle<ObjectImpl*> obj, bool *extensible);
|
||||
|
||||
// Indicates whether a non-proxy is extensible. Don't call on proxies!
|
||||
// This method really shouldn't exist -- but there are a few internal
|
||||
// places that want it (JITs and the like), and it'd be a pain to mark them
|
||||
// all as friends.
|
||||
inline bool nonProxyIsExtensible() const;
|
||||
|
||||
// Attempt to change the [[Extensible]] bit on |obj| to false. Callers
|
||||
// must ensure that |obj| is currently extensible before calling this!
|
||||
|
@ -1358,10 +1358,11 @@ class DebugScopeProxy : public BaseProxyHandler
|
||||
|
||||
DebugScopeProxy() : BaseProxyHandler(&family) {}
|
||||
|
||||
bool isExtensible(JSObject *proxy) MOZ_OVERRIDE
|
||||
bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE
|
||||
{
|
||||
// always [[Extensible]], can't be made non-[[Extensible]], like most
|
||||
// proxies
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -446,7 +446,10 @@ JSObject::addProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
{
|
||||
JS_ASSERT(!JSID_IS_VOID(id));
|
||||
|
||||
if (!obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return NULL;
|
||||
if (!extensible) {
|
||||
obj->reportNotExtensible(cx);
|
||||
return NULL;
|
||||
}
|
||||
@ -610,7 +613,10 @@ JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
* You can't add properties to a non-extensible object, but you can change
|
||||
* attributes of properties in such objects.
|
||||
*/
|
||||
if (!obj->isExtensible()) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return NULL;
|
||||
if (!extensible) {
|
||||
obj->reportNotExtensible(cx);
|
||||
return NULL;
|
||||
}
|
||||
@ -1077,9 +1083,14 @@ Shape::setObjectMetadata(JSContext *cx, JSObject *metadata, TaggedProto proto, S
|
||||
/* static */ bool
|
||||
js::ObjectImpl::preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj)
|
||||
{
|
||||
MOZ_ASSERT(obj->isExtensible(),
|
||||
#ifdef DEBUG
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
MOZ_ASSERT(extensible,
|
||||
"Callers must ensure |obj| is extensible before calling "
|
||||
"preventExtensions");
|
||||
#endif
|
||||
|
||||
if (obj->isProxy()) {
|
||||
RootedObject object(cx, obj->asObjectPtr());
|
||||
|
@ -1306,13 +1306,14 @@ DEBUG_CheckXBLLookup(JSContext *cx, JSPropertyDescriptor *desc)
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::isExtensible(JSObject *wrapper)
|
||||
XrayWrapper<Base, Traits>::isExtensible(JSContext *cx, JS::Handle<JSObject*> wrapper, bool *extensible)
|
||||
{
|
||||
// Xray wrappers are supposed to provide a clean view of the target
|
||||
// reflector, hiding any modifications by script in the target scope. So
|
||||
// even if that script freezes the reflector, we don't want to make that
|
||||
// visible to the caller. DOM reflectors are always extensible by default,
|
||||
// so we can just return true here.
|
||||
*extensible = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class XrayWrapper : public Base {
|
||||
virtual ~XrayWrapper();
|
||||
|
||||
/* Fundamental proxy traps. */
|
||||
virtual bool isExtensible(JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> wrapper, bool *extensible) MOZ_OVERRIDE;
|
||||
virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper) MOZ_OVERRIDE;
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
|
||||
js::PropertyDescriptor *desc, unsigned flags);
|
||||
|
Loading…
Reference in New Issue
Block a user