зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1112778, part 3 - Rename JSObject::preventExtensions -> js::PreventExtensions and a few others, and move them to jsobj.cpp. Uninline several functions that have no business being inlined. r=Waldo.
--HG-- extra : rebase_source : 72a7c9c5fd60b20a66fb4c98c062e9c0d8cf4391
This commit is contained in:
Родитель
ef7a22ceb7
Коммит
3e2999a0e8
|
@ -615,7 +615,7 @@ Collator(JSContext *cx, CallArgs args, bool construct)
|
|||
|
||||
// 10.1.2.1 step 5
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
|
@ -1101,7 +1101,7 @@ NumberFormat(JSContext *cx, CallArgs args, bool construct)
|
|||
|
||||
// 11.1.2.1 step 5
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
|
@ -1558,7 +1558,7 @@ DateTimeFormat(JSContext *cx, CallArgs args, bool construct)
|
|||
|
||||
// 12.1.2.1 step 5
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
|
|
|
@ -421,7 +421,7 @@ js::obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
/* Step 3. */
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, obj, &proto))
|
||||
if (!GetPrototype(cx, obj, &proto))
|
||||
return false;
|
||||
args.rval().setObjectOrNull(proto);
|
||||
return true;
|
||||
|
@ -467,7 +467,7 @@ obj_setPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObject newProto(cx, args[1].toObjectOrNull());
|
||||
|
||||
bool success;
|
||||
if (!JSObject::setProto(cx, obj, newProto, &success))
|
||||
if (!SetPrototype(cx, obj, newProto, &success))
|
||||
return false;
|
||||
|
||||
/* Step 7. */
|
||||
|
@ -859,7 +859,7 @@ obj_isExtensible(JSContext *cx, unsigned argc, Value *vp)
|
|||
// Step 2.
|
||||
if (args.get(0).isObject()) {
|
||||
RootedObject obj(cx, &args.get(0).toObject());
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(extensible);
|
||||
|
@ -881,7 +881,7 @@ obj_preventExtensions(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObject obj(cx, &args.get(0).toObject());
|
||||
|
||||
bool status;
|
||||
if (!JSObject::preventExtensions(cx, obj, &status))
|
||||
if (!PreventExtensions(cx, obj, &status))
|
||||
return false;
|
||||
|
||||
// Step 4.
|
||||
|
@ -978,7 +978,7 @@ ProtoGetter(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
RootedObject obj(cx, &args.thisv().toObject());
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, obj, &proto))
|
||||
if (!GetPrototype(cx, obj, &proto))
|
||||
return false;
|
||||
args.rval().setObjectOrNull(proto);
|
||||
return true;
|
||||
|
@ -1025,7 +1025,7 @@ ProtoSetter(JSContext *cx, unsigned argc, Value *vp)
|
|||
Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull());
|
||||
|
||||
bool success;
|
||||
if (!JSObject::setProto(cx, obj, newProto, &success))
|
||||
if (!SetPrototype(cx, obj, newProto, &success))
|
||||
return false;
|
||||
|
||||
if (!success) {
|
||||
|
|
|
@ -2211,7 +2211,7 @@ SetImmutablePrototype(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObject obj(cx, &args[0].toObject());
|
||||
|
||||
bool succeeded;
|
||||
if (!JSObject::setImmutablePrototype(cx, obj, &succeeded))
|
||||
if (!js::SetImmutablePrototype(cx, obj, &succeeded))
|
||||
return false;
|
||||
|
||||
args.rval().setBoolean(succeeded);
|
||||
|
|
|
@ -203,7 +203,7 @@ MutatePrototype(JSContext *cx, HandlePlainObject obj, HandleValue value)
|
|||
RootedObject newProto(cx, value.toObjectOrNull());
|
||||
|
||||
bool succeeded;
|
||||
if (!JSObject::setProto(cx, obj, newProto, &succeeded))
|
||||
if (!SetPrototype(cx, obj, newProto, &succeeded))
|
||||
return false;
|
||||
MOZ_ASSERT(succeeded);
|
||||
return true;
|
||||
|
|
|
@ -2018,7 +2018,7 @@ JS_GetInstancePrivate(JSContext *cx, HandleObject obj, const JSClass *clasp, Cal
|
|||
JS_PUBLIC_API(bool)
|
||||
JS_GetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> protop)
|
||||
{
|
||||
return JSObject::getProto(cx, obj, protop);
|
||||
return GetPrototype(cx, obj, protop);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -2029,7 +2029,7 @@ JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*>
|
|||
assertSameCompartment(cx, obj, proto);
|
||||
|
||||
bool succeeded;
|
||||
if (!JSObject::setProto(cx, obj, proto, &succeeded))
|
||||
if (!SetPrototype(cx, obj, proto, &succeeded))
|
||||
return false;
|
||||
|
||||
if (!succeeded) {
|
||||
|
@ -2041,6 +2041,18 @@ JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*>
|
|||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_IsExtensible(JSContext *cx, HandleObject obj, bool *extensible)
|
||||
{
|
||||
return IsExtensible(cx, obj, extensible);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded)
|
||||
{
|
||||
return PreventExtensions(cx, obj, succeeded);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetParent(JSObject *obj)
|
||||
{
|
||||
|
@ -2218,12 +2230,6 @@ JS_NewObjectForConstructor(JSContext *cx, const JSClass *clasp, const CallArgs&
|
|||
return CreateThis(cx, Valueify(clasp), obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_IsExtensible(JSContext *cx, HandleObject obj, bool *extensible)
|
||||
{
|
||||
return JSObject::isExtensible(cx, obj, extensible);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_IsNative(JSObject *obj)
|
||||
{
|
||||
|
@ -2254,7 +2260,7 @@ JS_DeepFreezeObject(JSContext *cx, HandleObject obj)
|
|||
|
||||
/* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return true;
|
||||
|
@ -6119,12 +6125,6 @@ JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length)
|
|||
return funobj;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded)
|
||||
{
|
||||
return JSObject::preventExtensions(cx, obj, succeeded);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::SetAsmJSCacheOps(JSRuntime *rt, const JS::AsmJSCacheOps *ops)
|
||||
{
|
||||
|
|
|
@ -453,7 +453,7 @@ array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, MutableHandle
|
|||
vp.setNumber(obj->as<ArrayObject>().length());
|
||||
return true;
|
||||
}
|
||||
if (!JSObject::getProto(cx, obj, &obj))
|
||||
if (!GetPrototype(cx, obj, &obj))
|
||||
return false;
|
||||
} while (obj);
|
||||
return true;
|
||||
|
|
|
@ -894,7 +894,7 @@ CreateFunctionPrototype(JSContext *cx, JSProtoKey key)
|
|||
bool succeeded;
|
||||
RootedFunction throwTypeError(cx, NewFunction(cx, tte, ThrowTypeError, 0,
|
||||
JSFunction::NATIVE_FUN, self, js::NullPtr()));
|
||||
if (!throwTypeError || !JSObject::preventExtensions(cx, throwTypeError, &succeeded))
|
||||
if (!throwTypeError || !PreventExtensions(cx, throwTypeError, &succeeded))
|
||||
return nullptr;
|
||||
if (!succeeded) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
|
||||
|
|
|
@ -352,7 +352,7 @@ Snapshot(JSContext *cx, HandleObject pobj_, unsigned flags, AutoIdVector *props)
|
|||
if (flags & JSITER_OWNONLY)
|
||||
break;
|
||||
|
||||
if (!JSObject::getProto(cx, pobj, &pobj))
|
||||
if (!GetPrototype(cx, pobj, &pobj))
|
||||
return false;
|
||||
|
||||
} while (pobj != nullptr);
|
||||
|
@ -1163,7 +1163,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
|
|||
* became visible as a result of this deletion.
|
||||
*/
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, obj, &proto))
|
||||
if (!GetPrototype(cx, obj, &proto))
|
||||
return false;
|
||||
if (proto) {
|
||||
RootedObject obj2(cx);
|
||||
|
|
148
js/src/jsobj.cpp
148
js/src/jsobj.cpp
|
@ -606,7 +606,7 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
|
|||
/* 8.12.9 steps 2-4. */
|
||||
if (!shape) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
|
||||
|
@ -1103,7 +1103,7 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
|
|||
MOZ_ASSERT(it == SEAL || it == FREEZE);
|
||||
|
||||
bool succeeded;
|
||||
if (!JSObject::preventExtensions(cx, obj, &succeeded))
|
||||
if (!PreventExtensions(cx, obj, &succeeded))
|
||||
return false;
|
||||
if (!succeeded) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY);
|
||||
|
@ -1202,7 +1202,7 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
|
|||
JSObject::isSealedOrFrozen(JSContext *cx, HandleObject obj, ImmutabilityType it, bool *resultp)
|
||||
{
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (extensible) {
|
||||
*resultp = false;
|
||||
|
@ -2153,7 +2153,7 @@ js::XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleNativeObject obj)
|
|||
uint32_t frozen;
|
||||
bool extensible;
|
||||
if (mode == XDR_ENCODE) {
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
frozen = extensible ? 0 : 1;
|
||||
}
|
||||
|
@ -3229,6 +3229,135 @@ JSObject::reportNotExtensible(JSContext *cx, unsigned report)
|
|||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
||||
/*** ES6 standard internal methods ***************************************************************/
|
||||
|
||||
bool
|
||||
js::SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succeeded)
|
||||
{
|
||||
/*
|
||||
* If |obj| has a "lazy" [[Prototype]], it is 1) a proxy 2) whose handler's
|
||||
* {get,set}PrototypeOf 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);
|
||||
}
|
||||
|
||||
/* Disallow mutation of immutable [[Prototype]]s. */
|
||||
if (obj->nonLazyPrototypeIsImmutable()) {
|
||||
*succeeded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow mutating the [[Prototype]] on ArrayBuffer objects, which
|
||||
* due to their complicated delegate-object shenanigans can't easily
|
||||
* have a mutable [[Prototype]].
|
||||
*/
|
||||
if (obj->is<ArrayBufferObject>()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
|
||||
"incompatible ArrayBuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow mutating the [[Prototype]] on Typed Objects, per the spec.
|
||||
*/
|
||||
if (obj->is<TypedObject>()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
|
||||
"incompatible TypedObject");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicitly disallow mutating the [[Prototype]] of Location objects
|
||||
* for flash-related security reasons.
|
||||
*/
|
||||
if (!strcmp(obj->getClass()->name, "Location")) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
|
||||
"incompatible Location object");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
|
||||
bool extensible;
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
*succeeded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 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 (!GetPrototype(cx, obj2, &obj2))
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
|
||||
*succeeded = SetClassAndProto(cx, obj, obj->getClass(), taggedProto);
|
||||
return *succeeded;
|
||||
}
|
||||
|
||||
bool
|
||||
js::PreventExtensions(JSContext *cx, HandleObject obj, bool *succeeded)
|
||||
{
|
||||
if (obj->is<ProxyObject>())
|
||||
return js::Proxy::preventExtensions(cx, obj, succeeded);
|
||||
|
||||
if (!obj->nonProxyIsExtensible()) {
|
||||
*succeeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force lazy properties to be resolved by iterating over the objects' own
|
||||
* properties.
|
||||
*/
|
||||
AutoIdVector props(cx);
|
||||
if (!js::GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, &props))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Convert all dense elements to sparse properties. This will shrink the
|
||||
* initialized length and capacity of the object to zero and ensure that no
|
||||
* new dense elements can be added without calling growElements(), which
|
||||
* checks isExtensible().
|
||||
*/
|
||||
if (obj->isNative() && !NativeObject::sparsifyDenseElements(cx, obj.as<NativeObject>()))
|
||||
return false;
|
||||
|
||||
*succeeded = true;
|
||||
return obj->setFlag(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE);
|
||||
}
|
||||
|
||||
|
||||
/*** SpiderMonkey nonstandard internal methods ***************************************************/
|
||||
|
||||
bool
|
||||
js::SetImmutablePrototype(ExclusiveContext *cx, HandleObject obj, bool *succeeded)
|
||||
{
|
||||
if (obj->hasLazyPrototype()) {
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
|
||||
}
|
||||
|
||||
if (!obj->setFlag(cx, BaseShape::IMMUTABLE_PROTOTYPE))
|
||||
return false;
|
||||
*succeeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSObject::defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
|
||||
{
|
||||
|
@ -3307,6 +3436,9 @@ js::NativeUnwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
|
|||
return UnwatchGuts(cx, obj, id);
|
||||
}
|
||||
|
||||
|
||||
/* * */
|
||||
|
||||
bool
|
||||
js::HasDataProperty(JSContext *cx, NativeObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
|
@ -3443,7 +3575,7 @@ js::IsDelegateOfObject(JSContext *cx, HandleObject protoObj, JSObject* obj, bool
|
|||
{
|
||||
RootedObject obj2(cx, obj);
|
||||
for (;;) {
|
||||
if (!JSObject::getProto(cx, obj2, &obj2))
|
||||
if (!GetPrototype(cx, obj2, &obj2))
|
||||
return false;
|
||||
if (!obj2) {
|
||||
*result = false;
|
||||
|
@ -3627,6 +3759,9 @@ js_ReportGetterOnlyAssignment(JSContext *cx, bool strict)
|
|||
JSMSG_GETTER_ONLY);
|
||||
}
|
||||
|
||||
|
||||
/*** Debugging routines **************************************************************************/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/*
|
||||
|
@ -3951,6 +4086,9 @@ js_DumpBacktrace(JSContext *cx)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* * */
|
||||
|
||||
void
|
||||
JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo *info)
|
||||
{
|
||||
|
|
|
@ -78,6 +78,10 @@ class NormalArgumentsObject;
|
|||
class SetObject;
|
||||
class StrictArgumentsObject;
|
||||
|
||||
// Forward declarations, required for later friend declarations.
|
||||
bool PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded);
|
||||
bool SetImmutablePrototype(js::ExclusiveContext *cx, JS::HandleObject obj, bool *succeeded);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
|
@ -113,6 +117,9 @@ class JSObject : public js::gc::Cell
|
|||
friend class js::GCMarker;
|
||||
friend class js::NewObjectCache;
|
||||
friend class js::Nursery;
|
||||
friend bool js::PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded);
|
||||
friend bool js::SetImmutablePrototype(js::ExclusiveContext *cx, JS::HandleObject obj,
|
||||
bool *succeeded);
|
||||
|
||||
/* Make the type object to use for LAZY_TYPE objects. */
|
||||
static js::types::TypeObject *makeLazyType(JSContext *cx, js::HandleObject obj);
|
||||
|
@ -337,7 +344,7 @@ class JSObject : public js::gc::Cell
|
|||
* 1. obj->getProto() returns the prototype, but asserts if obj is a proxy.
|
||||
* 2. obj->getTaggedProto() returns a TaggedProto, which can be tested to
|
||||
* check if the proto is an object, nullptr, or lazily computed.
|
||||
* 3. JSObject::getProto(cx, obj, &proto) computes the proto of an object.
|
||||
* 3. js::GetPrototype(cx, obj, &proto) computes the proto of an object.
|
||||
* If obj is a proxy and the proto is lazy, this code may allocate or
|
||||
* GC in order to compute the proto. Currently, it will not run JS code.
|
||||
*/
|
||||
|
@ -385,19 +392,6 @@ class JSObject : public js::gc::Cell
|
|||
return lastProperty()->hasObjectFlag(js::BaseShape::IMMUTABLE_PROTOTYPE);
|
||||
}
|
||||
|
||||
// Attempt to make |obj|'s [[Prototype]] immutable, such that subsequently
|
||||
// trying to change it will not work. If an internal error occurred,
|
||||
// returns false. Otherwise, |*succeeded| is set to true iff |obj|'s
|
||||
// [[Prototype]] is now immutable.
|
||||
static bool
|
||||
setImmutablePrototype(js::ExclusiveContext *cx, JS::HandleObject obj, bool *succeeded);
|
||||
|
||||
static inline bool getProto(JSContext *cx, js::HandleObject obj,
|
||||
js::MutableHandleObject protop);
|
||||
// Returns false on error, success of operation in outparam.
|
||||
static inline bool setProto(JSContext *cx, JS::HandleObject obj,
|
||||
JS::HandleObject proto, bool *succeeded);
|
||||
|
||||
// uninlinedSetType() is the same as setType(), but not inlined.
|
||||
inline void setType(js::types::TypeObject *newType);
|
||||
void uninlinedSetType(js::types::TypeObject *newType);
|
||||
|
@ -493,9 +487,6 @@ class JSObject : public js::gc::Cell
|
|||
*/
|
||||
|
||||
public:
|
||||
static inline bool
|
||||
isExtensible(js::ExclusiveContext *cx, js::HandleObject 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
|
||||
|
@ -507,12 +498,6 @@ class JSObject : public js::gc::Cell
|
|||
return !lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE);
|
||||
}
|
||||
|
||||
// Attempt to change the [[Extensible]] bit on |obj| to false. Indicate
|
||||
// success or failure through the |*succeeded| outparam, or actual error
|
||||
// through the return value.
|
||||
static bool
|
||||
preventExtensions(JSContext *cx, js::HandleObject obj, bool *succeeded);
|
||||
|
||||
private:
|
||||
enum ImmutabilityType { SEAL, FREEZE };
|
||||
|
||||
|
@ -891,8 +876,71 @@ class ValueArray {
|
|||
|
||||
namespace js {
|
||||
|
||||
/*** Standard internal methods ********************************************************************
|
||||
*
|
||||
* The functions below are the fundamental operations on objects.
|
||||
*
|
||||
* ES6 specifies 14 internal methods that define how objects behave. The spec
|
||||
* is actually quite good on this topic, though you may have to read it a few
|
||||
* times. See ES6 draft rev 29 (6 Dec 2014) 6.1.7.2 and 6.1.7.3.
|
||||
*
|
||||
* When 'obj' is an ordinary object, these functions have boring standard
|
||||
* behavior as specified by ES6 draft rev 29 section 9.1; see the section about
|
||||
* internal methods in vm/NativeObject.h.
|
||||
*
|
||||
* Proxies override the behavior of internal methods. So when 'obj' is a proxy,
|
||||
* any one of the functions below could do just about anything. See jsproxy.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ES6 [[GetPrototypeOf]]. Get obj's prototype, storing it in protop.
|
||||
*
|
||||
* If obj is definitely not a proxy, the infallible obj->getProto() can be used
|
||||
* instead. See the comment on JSObject::getTaggedProto().
|
||||
*/
|
||||
inline bool
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
extern bool
|
||||
SetPrototype(JSContext *cx, HandleObject obj, HandleObject proto, bool *succeeded);
|
||||
|
||||
/*
|
||||
* ES6 [[IsExtensible]]. Extensible objects can have new properties defined on
|
||||
* them. Inextensible objects can't, and their [[Prototype]] slot is fixed as
|
||||
* well.
|
||||
*/
|
||||
inline bool
|
||||
IsExtensible(ExclusiveContext *cx, HandleObject obj, bool *extensible);
|
||||
|
||||
/*
|
||||
* ES6 [[PreventExtensions]]. Attempt to change the [[Extensible]] bit on |obj|
|
||||
* to false. Indicate success or failure through the |*succeeded| outparam, or
|
||||
* actual error through the return value.
|
||||
*/
|
||||
extern bool
|
||||
PreventExtensions(JSContext *cx, HandleObject obj, bool *succeeded);
|
||||
|
||||
|
||||
/*** SpiderMonkey nonstandard internal methods ***************************************************/
|
||||
|
||||
/*
|
||||
* Attempt to make |obj|'s [[Prototype]] immutable, such that subsequently
|
||||
* trying to change it will not work. If an internal error occurred,
|
||||
* returns false. Otherwise, |*succeeded| is set to true iff |obj|'s
|
||||
* [[Prototype]] is now immutable.
|
||||
*/
|
||||
extern bool
|
||||
SetImmutablePrototype(js::ExclusiveContext *cx, JS::HandleObject obj, bool *succeeded);
|
||||
|
||||
/* Set *resultp to tell whether obj has an own property with the given id. */
|
||||
bool
|
||||
extern bool
|
||||
HasOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool *resultp);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
|
|
|
@ -164,8 +164,8 @@ JSObject::setType(js::types::TypeObject *newType)
|
|||
type_ = newType;
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::getProto(JSContext *cx, js::HandleObject obj, js::MutableHandleObject protop)
|
||||
inline bool
|
||||
js::GetPrototype(JSContext *cx, js::HandleObject obj, js::MutableHandleObject protop)
|
||||
{
|
||||
if (obj->getTaggedProto().isLazy()) {
|
||||
MOZ_ASSERT(obj->is<js::ProxyObject>());
|
||||
|
@ -176,89 +176,13 @@ JSObject::getProto(JSContext *cx, js::HandleObject obj, js::MutableHandleObject
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::setProto(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto, bool *succeeded)
|
||||
inline bool
|
||||
js::IsExtensible(ExclusiveContext *cx, HandleObject obj, bool *extensible)
|
||||
{
|
||||
/*
|
||||
* If |obj| has a "lazy" [[Prototype]], it is 1) a proxy 2) whose handler's
|
||||
* {get,set}PrototypeOf 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<js::ProxyObject>());
|
||||
return js::Proxy::setPrototypeOf(cx, obj, proto, succeeded);
|
||||
}
|
||||
|
||||
/* Disallow mutation of immutable [[Prototype]]s. */
|
||||
if (obj->nonLazyPrototypeIsImmutable()) {
|
||||
*succeeded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow mutating the [[Prototype]] on ArrayBuffer objects, which
|
||||
* due to their complicated delegate-object shenanigans can't easily
|
||||
* have a mutable [[Prototype]].
|
||||
*/
|
||||
if (obj->is<js::ArrayBufferObject>()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
|
||||
"incompatible ArrayBuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow mutating the [[Prototype]] on Typed Objects, per the spec.
|
||||
*/
|
||||
if (obj->is<js::TypedObject>()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
|
||||
"incompatible TypedObject");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicitly disallow mutating the [[Prototype]] of Location objects
|
||||
* for flash-related security reasons.
|
||||
*/
|
||||
if (!strcmp(obj->getClass()->name, "Location")) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL,
|
||||
"incompatible Location object");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
*succeeded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ES6 9.1.2 step 6 forbids generating cyclical prototype chains. */
|
||||
js::RootedObject obj2(cx);
|
||||
for (obj2 = proto; obj2; ) {
|
||||
if (obj2 == obj) {
|
||||
*succeeded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!JSObject::getProto(cx, obj2, &obj2))
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<js::TaggedProto> taggedProto(cx, js::TaggedProto(proto));
|
||||
*succeeded = SetClassAndProto(cx, obj, obj->getClass(), taggedProto);
|
||||
return *succeeded;
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::isExtensible(js::ExclusiveContext *cx, js::HandleObject obj, bool *extensible)
|
||||
{
|
||||
if (obj->is<js::ProxyObject>()) {
|
||||
if (obj->is<ProxyObject>()) {
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
return js::Proxy::isExtensible(cx->asJSContext(), obj, extensible);
|
||||
return Proxy::isExtensible(cx->asJSContext(), obj, extensible);
|
||||
}
|
||||
|
||||
*extensible = obj->nonProxyIsExtensible();
|
||||
|
|
|
@ -92,7 +92,7 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
|||
// The spec calls this variable "parent", but that word has weird
|
||||
// connotations in SpiderMonkey, so let's go with "proto".
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, proxy, &proto))
|
||||
if (!GetPrototype(cx, proxy, &proto))
|
||||
return false;
|
||||
if (proto)
|
||||
return JSObject::setGeneric(cx, proto, receiver, id, vp, strict);
|
||||
|
|
|
@ -84,7 +84,7 @@ CrossCompartmentWrapper::getPrototypeOf(JSContext *cx, HandleObject wrapper,
|
|||
{
|
||||
RootedObject wrapped(cx, wrappedObject(wrapper));
|
||||
AutoCompartment call(cx, wrapped);
|
||||
if (!JSObject::getProto(cx, wrapped, protop))
|
||||
if (!GetPrototype(cx, wrapped, protop))
|
||||
return false;
|
||||
if (protop)
|
||||
protop->setDelegate(cx);
|
||||
|
|
|
@ -117,35 +117,35 @@ bool
|
|||
DirectProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const
|
||||
{
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::getProto(cx, target, protop);
|
||||
return GetPrototype(cx, target, protop);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp) const
|
||||
{
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::setProto(cx, target, proto, bp);
|
||||
return SetPrototype(cx, target, proto, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::setImmutablePrototype(JSContext *cx, HandleObject proxy, bool *succeeded) const
|
||||
{
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::setImmutablePrototype(cx, target, succeeded);
|
||||
return SetImmutablePrototype(cx, target, succeeded);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy, bool *succeeded) const
|
||||
{
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::preventExtensions(cx, target, succeeded);
|
||||
return PreventExtensions(cx, target, succeeded);
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const
|
||||
{
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::isExtensible(cx, target, extensible);
|
||||
return IsExtensible(cx, target, extensible);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -87,7 +87,7 @@ js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id,
|
|||
#define INVOKE_ON_PROTOTYPE(cx, handler, proxy, protoCall) \
|
||||
JS_BEGIN_MACRO \
|
||||
RootedObject proto(cx); \
|
||||
if (!JSObject::getProto(cx, proxy, &proto)) \
|
||||
if (!GetPrototype(cx, proxy, &proto)) \
|
||||
return false; \
|
||||
if (!proto) \
|
||||
return true; \
|
||||
|
@ -370,7 +370,7 @@ Proxy::enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp)
|
|||
return false;
|
||||
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, proxy, &proto))
|
||||
if (!GetPrototype(cx, proxy, &proto))
|
||||
return false;
|
||||
if (!proto)
|
||||
return EnumeratedIdVectorToIterator(cx, proxy, 0, props, objp);
|
||||
|
|
|
@ -204,7 +204,7 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
|
|||
|
||||
// step v
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
if (!IsExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible && !isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_NEW);
|
||||
|
@ -251,7 +251,7 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
|
|||
|
||||
// step iii
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
if (!IsExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible && isFixed) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_E_AS_NE);
|
||||
|
@ -345,7 +345,7 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy,
|
|||
// Step 11.
|
||||
if (booleanTrapResult) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
if (!IsExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (extensible) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE);
|
||||
|
@ -396,7 +396,7 @@ ScriptedDirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool
|
|||
|
||||
// step 10-11
|
||||
bool targetResult;
|
||||
if (!JSObject::isExtensible(cx, target, &targetResult))
|
||||
if (!IsExtensible(cx, target, &targetResult))
|
||||
return false;
|
||||
|
||||
// step 12
|
||||
|
@ -423,7 +423,7 @@ ScriptedDirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject pr
|
|||
if (desc.object())
|
||||
return true;
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, proxy, &proto))
|
||||
if (!GetPrototype(cx, proxy, &proto))
|
||||
return false;
|
||||
if (!proto) {
|
||||
MOZ_ASSERT(!desc.object());
|
||||
|
@ -498,7 +498,7 @@ ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject
|
|||
|
||||
// substep c-e
|
||||
bool extensibleTarget;
|
||||
if (!JSObject::isExtensible(cx, target, &extensibleTarget))
|
||||
if (!IsExtensible(cx, target, &extensibleTarget))
|
||||
return false;
|
||||
if (!extensibleTarget) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_E_AS_NE);
|
||||
|
@ -512,7 +512,7 @@ ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject
|
|||
|
||||
// step 14-15
|
||||
bool extensibleTarget;
|
||||
if (!JSObject::isExtensible(cx, target, &extensibleTarget))
|
||||
if (!IsExtensible(cx, target, &extensibleTarget))
|
||||
return false;
|
||||
|
||||
// step 16-17
|
||||
|
@ -606,7 +606,7 @@ ScriptedDirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, Ha
|
|||
|
||||
// step 16-17
|
||||
bool extensibleTarget;
|
||||
if (!JSObject::isExtensible(cx, target, &extensibleTarget))
|
||||
if (!IsExtensible(cx, target, &extensibleTarget))
|
||||
return false;
|
||||
|
||||
// step 18-19
|
||||
|
@ -853,7 +853,7 @@ ScriptedDirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id,
|
|||
}
|
||||
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, target, &extensible))
|
||||
if (!IsExtensible(cx, target, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REPORT_E_AS_NE);
|
||||
|
|
|
@ -6234,7 +6234,7 @@ DebuggerObject_getProto(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObject proto(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, refobj);
|
||||
if (!JSObject::getProto(cx, refobj, &proto))
|
||||
if (!GetPrototype(cx, refobj, &proto))
|
||||
return false;
|
||||
}
|
||||
RootedValue protov(cx, ObjectOrNullValue(proto));
|
||||
|
@ -6708,7 +6708,7 @@ DebuggerObject_deleteProperty(JSContext *cx, unsigned argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
enum SealHelperOp { Seal, Freeze, PreventExtensions };
|
||||
enum SealHelperOp { OpSeal, OpFreeze, OpPreventExtensions };
|
||||
|
||||
static bool
|
||||
DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp op, const char *name)
|
||||
|
@ -6719,14 +6719,14 @@ DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp
|
|||
ac.emplace(cx, obj);
|
||||
ErrorCopier ec(ac);
|
||||
bool ok;
|
||||
if (op == Seal) {
|
||||
if (op == OpSeal) {
|
||||
ok = JSObject::seal(cx, obj);
|
||||
} else if (op == Freeze) {
|
||||
} else if (op == OpFreeze) {
|
||||
ok = JSObject::freeze(cx, obj);
|
||||
} else {
|
||||
MOZ_ASSERT(op == PreventExtensions);
|
||||
MOZ_ASSERT(op == OpPreventExtensions);
|
||||
bool succeeded;
|
||||
ok = JSObject::preventExtensions(cx, obj, &succeeded);
|
||||
ok = PreventExtensions(cx, obj, &succeeded);
|
||||
if (!ok)
|
||||
return false;
|
||||
if (!succeeded) {
|
||||
|
@ -6743,19 +6743,19 @@ DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp
|
|||
static bool
|
||||
DebuggerObject_seal(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return DebuggerObject_sealHelper(cx, argc, vp, Seal, "seal");
|
||||
return DebuggerObject_sealHelper(cx, argc, vp, OpSeal, "seal");
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_freeze(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return DebuggerObject_sealHelper(cx, argc, vp, Freeze, "freeze");
|
||||
return DebuggerObject_sealHelper(cx, argc, vp, OpFreeze, "freeze");
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_preventExtensions(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return DebuggerObject_sealHelper(cx, argc, vp, PreventExtensions, "preventExtensions");
|
||||
return DebuggerObject_sealHelper(cx, argc, vp, OpPreventExtensions, "preventExtensions");
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -6768,14 +6768,14 @@ DebuggerObject_isSealedHelper(JSContext *cx, unsigned argc, Value *vp, SealHelpe
|
|||
ac.emplace(cx, obj);
|
||||
ErrorCopier ec(ac);
|
||||
bool r;
|
||||
if (op == Seal) {
|
||||
if (op == OpSeal) {
|
||||
if (!JSObject::isSealed(cx, obj, &r))
|
||||
return false;
|
||||
} else if (op == Freeze) {
|
||||
} else if (op == OpFreeze) {
|
||||
if (!JSObject::isFrozen(cx, obj, &r))
|
||||
return false;
|
||||
} else {
|
||||
if (!JSObject::isExtensible(cx, obj, &r))
|
||||
if (!IsExtensible(cx, obj, &r))
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(r);
|
||||
|
@ -6785,19 +6785,19 @@ DebuggerObject_isSealedHelper(JSContext *cx, unsigned argc, Value *vp, SealHelpe
|
|||
static bool
|
||||
DebuggerObject_isSealed(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return DebuggerObject_isSealedHelper(cx, argc, vp, Seal, "isSealed");
|
||||
return DebuggerObject_isSealedHelper(cx, argc, vp, OpSeal, "isSealed");
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_isFrozen(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return DebuggerObject_isSealedHelper(cx, argc, vp, Freeze, "isFrozen");
|
||||
return DebuggerObject_isSealedHelper(cx, argc, vp, OpFreeze, "isFrozen");
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_isExtensible(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return DebuggerObject_isSealedHelper(cx, argc, vp, PreventExtensions, "isExtensible");
|
||||
return DebuggerObject_isSealedHelper(cx, argc, vp, OpPreventExtensions, "isExtensible");
|
||||
}
|
||||
|
||||
enum ApplyOrCallMode { ApplyMode, CallMode };
|
||||
|
|
|
@ -661,7 +661,7 @@ ProcessCallSiteObjOperation(JSContext *cx, RootedObject &cso, RootedObject &raw,
|
|||
RootedValue &rawValue)
|
||||
{
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, cso, &extensible))
|
||||
if (!IsExtensible(cx, cso, &extensible))
|
||||
return false;
|
||||
if (extensible) {
|
||||
JSAtom *name = cx->names().raw;
|
||||
|
|
|
@ -3157,7 +3157,7 @@ CASE(JSOP_MUTATEPROTO)
|
|||
MOZ_ASSERT(obj->is<PlainObject>());
|
||||
|
||||
bool succeeded;
|
||||
if (!JSObject::setProto(cx, obj, newProto, &succeeded))
|
||||
if (!SetPrototype(cx, obj, newProto, &succeeded))
|
||||
goto error;
|
||||
MOZ_ASSERT(succeeded);
|
||||
}
|
||||
|
|
|
@ -136,21 +136,6 @@ ObjectElements::MakeElementsCopyOnWrite(ExclusiveContext *cx, NativeObject *obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSObject::setImmutablePrototype(ExclusiveContext *cx, HandleObject obj, bool *succeeded)
|
||||
{
|
||||
if (obj->hasLazyPrototype()) {
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
|
||||
}
|
||||
|
||||
if (!obj->setFlag(cx, BaseShape::IMMUTABLE_PROTOTYPE))
|
||||
return false;
|
||||
*succeeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
js::NativeObject::checkShapeConsistency()
|
||||
|
@ -1852,7 +1837,7 @@ SetPropertyByDefining(JSContext *cx, HandleNativeObject obj, HandleObject receiv
|
|||
// enforced by [[DefineOwnProperty]], but we haven't implemented that yet.)
|
||||
if (!existing) {
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, receiver, &extensible))
|
||||
if (!IsExtensible(cx, receiver, &extensible))
|
||||
return false;
|
||||
if (!extensible) {
|
||||
// Error in strict mode code, warn with extra warnings option,
|
||||
|
|
|
@ -496,7 +496,7 @@ NativeObject::addProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
|
|||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return nullptr;
|
||||
if (!extensible) {
|
||||
if (cx->isJSContext())
|
||||
|
@ -735,7 +735,7 @@ NativeObject::putProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
|
|||
*/
|
||||
bool extensible;
|
||||
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return nullptr;
|
||||
|
||||
if (!extensible) {
|
||||
|
@ -1230,38 +1230,6 @@ Shape::setObjectMetadata(JSContext *cx, JSObject *metadata, TaggedProto proto, S
|
|||
return replaceLastProperty(cx, base, proto, lastRoot);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSObject::preventExtensions(JSContext *cx, HandleObject obj, bool *succeeded)
|
||||
{
|
||||
if (obj->is<ProxyObject>())
|
||||
return js::Proxy::preventExtensions(cx, obj, succeeded);
|
||||
|
||||
if (!obj->nonProxyIsExtensible()) {
|
||||
*succeeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force lazy properties to be resolved by iterating over the objects' own
|
||||
* properties.
|
||||
*/
|
||||
AutoIdVector props(cx);
|
||||
if (!js::GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, &props))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Convert all dense elements to sparse properties. This will shrink the
|
||||
* initialized length and capacity of the object to zero and ensure that no
|
||||
* new dense elements can be added without calling growElements(), which
|
||||
* checks isExtensible().
|
||||
*/
|
||||
if (obj->isNative() && !NativeObject::sparsifyDenseElements(cx, obj.as<NativeObject>()))
|
||||
return false;
|
||||
|
||||
*succeeded = true;
|
||||
return obj->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE);
|
||||
}
|
||||
|
||||
bool
|
||||
JSObject::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
|
||||
GenerateShape generateShape)
|
||||
|
|
Загрузка…
Ссылка в новой задаче