mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
Issue #1742 - Part 3: use JS::PropertyResult instead of Shape*
This is the meat of the issue and switches using raw shape pointers out for PropertyResult objects where feasible.
This commit is contained in:
parent
c48b8e8932
commit
574b295d15
33 changed files with 367 additions and 328 deletions
|
|
@ -539,7 +539,7 @@ namespace js {
|
|||
|
||||
typedef bool
|
||||
(* LookupPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
|
||||
JS::MutableHandleObject objp, JS::MutableHandle<JS::PropertyResult> propp);
|
||||
typedef bool
|
||||
(* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::Handle<JS::PropertyDescriptor> desc,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class MOZ_STACK_CLASS SourceBufferHolder;
|
|||
class HandleValueArray;
|
||||
|
||||
class ObjectOpResult;
|
||||
class PropertyResult;
|
||||
|
||||
class Symbol;
|
||||
enum class SymbolCode: uint32_t;
|
||||
|
|
@ -150,6 +151,7 @@ using JS::FalseHandleValue;
|
|||
using JS::HandleValueArray;
|
||||
|
||||
using JS::ObjectOpResult;
|
||||
using JS::PropertyResult;
|
||||
|
||||
using JS::Zone;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,18 +69,18 @@ js::obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp)
|
|||
JSObject* obj = &args.thisv().toObject();
|
||||
|
||||
/* Step 3. */
|
||||
Shape* shape;
|
||||
PropertyResult prop;
|
||||
if (obj->isNative() &&
|
||||
NativeLookupOwnProperty<NoGC>(cx, &obj->as<NativeObject>(), id, &shape))
|
||||
NativeLookupOwnProperty<NoGC>(cx, &obj->as<NativeObject>(), id, &prop))
|
||||
{
|
||||
/* Step 4. */
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Step 5. */
|
||||
unsigned attrs = GetShapeAttributes(obj, shape);
|
||||
unsigned attrs = GetPropertyAttributes(obj, prop);
|
||||
args.rval().setBoolean((attrs & JSPROP_ENUMERATE) != 0);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -582,11 +582,11 @@ js::obj_hasOwnProperty(JSContext* cx, unsigned argc, Value* vp)
|
|||
jsid id;
|
||||
if (args.thisv().isObject() && ValueToId<NoGC>(cx, idValue, &id)) {
|
||||
JSObject* obj = &args.thisv().toObject();
|
||||
Shape* prop;
|
||||
PropertyResult prop;
|
||||
if (obj->isNative() &&
|
||||
NativeLookupOwnProperty<NoGC>(cx, &obj->as<NativeObject>(), id, &prop))
|
||||
{
|
||||
args.rval().setBoolean(!!prop);
|
||||
args.rval().setBoolean(prop.isFound());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -839,7 +839,7 @@ EnumerableOwnProperties(JSContext* cx, const JS::CallArgs& args, EnumerableOwnPr
|
|||
value = nobj->getDenseOrTypedArrayElement(JSID_TO_INT(id));
|
||||
} else {
|
||||
shape = nobj->lookup(cx, id);
|
||||
if (!shape || !(GetShapeAttributes(nobj, shape) & JSPROP_ENUMERATE))
|
||||
if (!shape || !(shape->attributes() & JSPROP_ENUMERATE))
|
||||
continue;
|
||||
if (!shape->isAccessorShape()) {
|
||||
if (!NativeGetExistingProperty(cx, nobj, nobj, shape, &value))
|
||||
|
|
|
|||
|
|
@ -1671,10 +1671,10 @@ TypeDescr::hasProperty(const JSAtomState& names, jsid id)
|
|||
|
||||
/* static */ bool
|
||||
TypedObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
|
||||
MarkNonNativePropertyFound<CanGC>(propp);
|
||||
propp.setNonNativeProperty();
|
||||
objp.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1682,7 +1682,7 @@ TypedObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ class TypedObject : public ShapedObject
|
|||
|
||||
static MOZ_MUST_USE bool obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp);
|
||||
MutableHandle<PropertyResult> propp);
|
||||
|
||||
static MOZ_MUST_USE bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
|
|
|
|||
|
|
@ -1145,9 +1145,9 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
|||
return true;
|
||||
bool needsAtomize = checkAtomize<T>(keyVal);
|
||||
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &prop))
|
||||
return false;
|
||||
if (!holder || (holder != obj && !holder->isNative()))
|
||||
return true;
|
||||
|
|
@ -1214,6 +1214,8 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
|||
if (!holder->isNative())
|
||||
return true;
|
||||
|
||||
RootedShape shape(cx, prop.shape());
|
||||
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
bool isFixedSlot;
|
||||
uint32_t offset;
|
||||
|
|
@ -1264,13 +1266,14 @@ TryAttachNativeGetAccessorElemStub(JSContext* cx, HandleScript script, jsbytecod
|
|||
return true;
|
||||
bool needsAtomize = checkAtomize<T>(keyVal);
|
||||
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject baseHolder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &baseHolder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &baseHolder, &prop))
|
||||
return false;
|
||||
if (!baseHolder || !baseHolder->isNative())
|
||||
return true;
|
||||
|
||||
RootedShape shape(cx, prop.shape());
|
||||
HandleNativeObject holder = baseHolder.as<NativeObject>();
|
||||
|
||||
bool getterIsScripted = false;
|
||||
|
|
@ -3348,11 +3351,17 @@ TryAttachNativeInStub(JSContext* cx, HandleScript outerScript, ICIn_Fallback* st
|
|||
return true;
|
||||
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &prop))
|
||||
return false;
|
||||
|
||||
if (prop.isNonNativeProperty()) {
|
||||
MOZ_ASSERT(!IsCacheableProtoChain(obj, holder, false));
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedShape shape(cx, prop.maybeShape());
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
ICStub::Kind kind = (obj == holder) ? ICStub::In_Native
|
||||
: ICStub::In_NativePrototype;
|
||||
|
|
@ -4259,14 +4268,17 @@ TryAttachSetValuePropStub(JSContext* cx, HandleScript script, jsbytecode* pc, IC
|
|||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &prop))
|
||||
return false;
|
||||
if (obj != holder)
|
||||
return true;
|
||||
|
||||
if (!obj->isNative()) {
|
||||
RootedShape shape(cx);
|
||||
if (obj->isNative()) {
|
||||
shape = prop.shape();
|
||||
} else {
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
|
||||
if (expando) {
|
||||
|
|
@ -4365,11 +4377,17 @@ TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
|||
MOZ_ASSERT(!*attached);
|
||||
MOZ_ASSERT(!*isTemporarilyUnoptimizable);
|
||||
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &prop))
|
||||
return false;
|
||||
|
||||
if (prop.isNonNativeProperty()) {
|
||||
MOZ_ASSERT(!IsCacheableProtoChain(obj, holder));
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedShape shape(cx, prop.maybeShape());
|
||||
bool isScripted = false;
|
||||
bool cacheableCall = IsCacheableSetPropCall(cx, obj, holder, shape,
|
||||
&isScripted, isTemporarilyUnoptimizable);
|
||||
|
|
|
|||
|
|
@ -109,7 +109,8 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
|
|||
// only miss out on shape hashification, which is only a temporary perf cost.
|
||||
// The limits were arbitrarily set, anyways.
|
||||
JSObject* baseHolder = nullptr;
|
||||
if (!LookupPropertyPure(cx, obj, id, &baseHolder, shape.address()))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, id, &baseHolder, &prop))
|
||||
return CanAttachNone;
|
||||
|
||||
MOZ_ASSERT(!holder);
|
||||
|
|
@ -118,8 +119,9 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
|
|||
return CanAttachNone;
|
||||
holder.set(&baseHolder->as<NativeObject>());
|
||||
}
|
||||
shape.set(prop.maybeShape());
|
||||
|
||||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, shape) ||
|
||||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop) ||
|
||||
IsCacheableNoProperty(cx, obj, holder, shape, id, pc))
|
||||
{
|
||||
return CanAttachReadSlot;
|
||||
|
|
|
|||
|
|
@ -468,11 +468,12 @@ jit::IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder)
|
|||
}
|
||||
|
||||
bool
|
||||
jit::IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder, Shape* shape)
|
||||
jit::IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder, PropertyResult prop)
|
||||
{
|
||||
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
||||
if (!prop || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
||||
return false;
|
||||
|
||||
Shape* shape = prop.shape();
|
||||
if (!shape->hasSlot() || !shape->hasDefaultGetter())
|
||||
return false;
|
||||
|
||||
|
|
@ -480,10 +481,10 @@ jit::IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder,
|
|||
}
|
||||
|
||||
static bool
|
||||
IsCacheableNoProperty(JSObject* obj, JSObject* holder, Shape* shape, jsbytecode* pc,
|
||||
IsCacheableNoProperty(JSObject* obj, JSObject* holder, PropertyResult prop, jsbytecode* pc,
|
||||
const TypedOrValueRegister& output)
|
||||
{
|
||||
if (shape)
|
||||
if (prop)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(!holder);
|
||||
|
|
@ -751,7 +752,7 @@ CheckDOMProxyExpandoDoesNotShadow(JSContext* cx, MacroAssembler& masm, JSObject*
|
|||
static void
|
||||
GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
||||
IonCache::StubAttacher& attacher, MaybeCheckTDZ checkTDZ,
|
||||
JSObject* obj, JSObject* holder, Shape* shape, Register object,
|
||||
JSObject* obj, JSObject* holder, PropertyResult prop, Register object,
|
||||
TypedOrValueRegister output, Label* failures = nullptr)
|
||||
{
|
||||
// If there's a single jump to |failures|, we can patch the shape guard
|
||||
|
|
@ -778,7 +779,7 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
|||
|
||||
if (obj != holder ||
|
||||
obj->is<UnboxedPlainObject>() ||
|
||||
!holder->as<NativeObject>().isFixedSlot(shape->slot()))
|
||||
!holder->as<NativeObject>().isFixedSlot(prop.shape()->slot()))
|
||||
{
|
||||
if (output.hasValue()) {
|
||||
scratchReg = output.valueReg().scratchReg();
|
||||
|
|
@ -793,7 +794,7 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
|||
|
||||
// Fast path: single failure jump, no prototype guards.
|
||||
if (!multipleFailureJumps) {
|
||||
EmitLoadSlot(masm, &holder->as<NativeObject>(), shape, object, output, scratchReg);
|
||||
EmitLoadSlot(masm, &holder->as<NativeObject>(), prop.shape(), object, output, scratchReg);
|
||||
if (restoreScratch)
|
||||
masm.pop(scratchReg);
|
||||
attacher.jumpRejoin(masm);
|
||||
|
|
@ -848,7 +849,8 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
|||
|
||||
// Slot access.
|
||||
if (holder) {
|
||||
EmitLoadSlot(masm, &holder->as<NativeObject>(), shape, holderReg, output, scratchReg);
|
||||
EmitLoadSlot(masm, &holder->as<NativeObject>(), prop.shape(), holderReg, output,
|
||||
scratchReg);
|
||||
if (checkTDZ && output.hasValue())
|
||||
masm.branchTestMagic(Assembler::Equal, output.valueReg(), failures);
|
||||
} else {
|
||||
|
|
@ -1294,7 +1296,8 @@ CanAttachNativeGetProp(JSContext* cx, const GetPropCache& cache,
|
|||
// only miss out on shape hashification, which is only a temporary perf cost.
|
||||
// The limits were arbitrarily set, anyways.
|
||||
JSObject* baseHolder = nullptr;
|
||||
if (!LookupPropertyPure(cx, obj, id, &baseHolder, shape.address()))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, id, &baseHolder, &prop))
|
||||
return GetPropertyIC::CanAttachNone;
|
||||
|
||||
MOZ_ASSERT(!holder);
|
||||
|
|
@ -1303,12 +1306,13 @@ CanAttachNativeGetProp(JSContext* cx, const GetPropCache& cache,
|
|||
return GetPropertyIC::CanAttachNone;
|
||||
holder.set(&baseHolder->as<NativeObject>());
|
||||
}
|
||||
shape.set(prop.maybeShape());
|
||||
|
||||
RootedScript script(cx);
|
||||
jsbytecode* pc;
|
||||
cache.getScriptedLocation(&script, &pc);
|
||||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, shape) ||
|
||||
IsCacheableNoProperty(obj, holder, shape, pc, cache.output()))
|
||||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop) ||
|
||||
IsCacheableNoProperty(obj, holder, prop, pc, cache.output()))
|
||||
{
|
||||
return GetPropertyIC::CanAttachReadSlot;
|
||||
}
|
||||
|
|
@ -1505,7 +1509,7 @@ GetPropertyIC::tryAttachNative(JSContext* cx, HandleScript outerScript, IonScrip
|
|||
switch (type) {
|
||||
case CanAttachReadSlot:
|
||||
GenerateReadSlot(cx, ion, masm, attacher, DontCheckTDZ, obj, holder,
|
||||
shape, object(), output(), maybeFailures);
|
||||
PropertyResult(shape), object(), output(), maybeFailures);
|
||||
attachKind = idempotent() ? "idempotent reading"
|
||||
: "non idempotent reading";
|
||||
outcome = JS::TrackedOutcome::ICGetPropStub_ReadSlot;
|
||||
|
|
@ -1588,7 +1592,7 @@ GetPropertyIC::tryAttachUnboxedExpando(JSContext* cx, HandleScript outerScript,
|
|||
|
||||
StubAttacher attacher(*this);
|
||||
GenerateReadSlot(cx, ion, masm, attacher, DontCheckTDZ, obj, obj,
|
||||
shape, object(), output(), maybeFailures);
|
||||
PropertyResult(shape), object(), output(), maybeFailures);
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "read unboxed expando",
|
||||
JS::TrackedOutcome::ICGetPropStub_UnboxedReadExpando);
|
||||
}
|
||||
|
|
@ -2927,12 +2931,14 @@ IsCacheableDOMProxyUnshadowedSetterCall(JSContext* cx, HandleObject obj, HandleI
|
|||
if (!checkObj)
|
||||
return false;
|
||||
|
||||
if (!LookupPropertyPure(cx, obj, id, holder.address(), shape.address()))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, id, holder.address(), &prop))
|
||||
return false;
|
||||
|
||||
if (!holder)
|
||||
if (!holder || !holder->isNative())
|
||||
return false;
|
||||
|
||||
shape.set(prop.shape());
|
||||
return IsCacheableSetPropCallNative(checkObj, holder, shape) ||
|
||||
IsCacheableSetPropCallPropertyOp(checkObj, holder, shape) ||
|
||||
IsCacheableSetPropCallScripted(checkObj, holder, shape);
|
||||
|
|
@ -3344,22 +3350,26 @@ CanAttachNativeSetProp(JSContext* cx, HandleObject obj, HandleId id, const Const
|
|||
|
||||
// If we couldn't find the property on the object itself, do a full, but
|
||||
// still pure lookup for setters.
|
||||
if (!LookupPropertyPure(cx, obj, id, holder.address(), shape.address()))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!LookupPropertyPure(cx, obj, id, holder.address(), prop.address()))
|
||||
return SetPropertyIC::CanAttachNone;
|
||||
|
||||
// If the object doesn't have the property, we don't know if we can attach
|
||||
// a stub to add the property until we do the VM call to add. If the
|
||||
// property exists as a data property on the prototype, we should add
|
||||
// a new, shadowing property.
|
||||
if (obj->isNative() && (!shape || (obj != holder && holder->isNative() &&
|
||||
shape->hasDefaultSetter() && shape->hasSlot())))
|
||||
if (obj->isNative() &&
|
||||
(!prop || (obj != holder && holder->isNative() &&
|
||||
prop.shape()->hasDefaultSetter() && prop.shape()->hasSlot())))
|
||||
{
|
||||
shape.set(prop.maybeShape());
|
||||
return SetPropertyIC::MaybeCanAttachAddSlot;
|
||||
}
|
||||
|
||||
if (IsImplicitNonNativeProperty(shape))
|
||||
if (prop.isNonNativeProperty())
|
||||
return SetPropertyIC::CanAttachNone;
|
||||
|
||||
shape.set(prop.maybeShape());
|
||||
if (IsCacheableSetPropCallPropertyOp(obj, holder, shape) ||
|
||||
IsCacheableSetPropCallNative(obj, holder, shape) ||
|
||||
IsCacheableSetPropCallScripted(obj, holder, shape))
|
||||
|
|
@ -4836,7 +4846,7 @@ BindNameIC::update(JSContext* cx, HandleScript outerScript, size_t cacheIndex,
|
|||
bool
|
||||
NameIC::attachReadSlot(JSContext* cx, HandleScript outerScript, IonScript* ion,
|
||||
HandleObject envChain, HandleObject holderBase,
|
||||
HandleNativeObject holder, HandleShape shape)
|
||||
HandleNativeObject holder, Handle<PropertyResult> prop)
|
||||
{
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
Label failures;
|
||||
|
|
@ -4854,7 +4864,7 @@ NameIC::attachReadSlot(JSContext* cx, HandleScript outerScript, IonScript* ion,
|
|||
// doesn't generate the extra guard.
|
||||
//
|
||||
// NAME ops must do their own TDZ checks.
|
||||
GenerateReadSlot(cx, ion, masm, attacher, CheckTDZ, holderBase, holder, shape, scratchReg,
|
||||
GenerateReadSlot(cx, ion, masm, attacher, CheckTDZ, holderBase, holder, prop, scratchReg,
|
||||
outputReg(), failures.used() ? &failures : nullptr);
|
||||
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "generic",
|
||||
|
|
@ -4880,26 +4890,26 @@ IsCacheableEnvironmentChain(JSObject* envChain, JSObject* obj)
|
|||
}
|
||||
|
||||
static bool
|
||||
IsCacheableNameReadSlot(HandleObject envChain, HandleObject obj,
|
||||
HandleObject holder, HandleShape shape, jsbytecode* pc,
|
||||
IsCacheableNameReadSlot(JSContext* cx, HandleObject envChain, HandleObject obj,
|
||||
HandleObject holder, Handle<PropertyResult> prop, jsbytecode* pc,
|
||||
const TypedOrValueRegister& output)
|
||||
{
|
||||
if (!shape)
|
||||
if (!prop)
|
||||
return false;
|
||||
if (!obj->isNative())
|
||||
return false;
|
||||
|
||||
if (obj->is<GlobalObject>()) {
|
||||
// Support only simple property lookups.
|
||||
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, shape) &&
|
||||
!IsCacheableNoProperty(obj, holder, shape, pc, output))
|
||||
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop) &&
|
||||
!IsCacheableNoProperty(obj, holder, prop, pc, output))
|
||||
return false;
|
||||
} else if (obj->is<ModuleEnvironmentObject>()) {
|
||||
// We don't yet support lookups in a module environment.
|
||||
return false;
|
||||
} else if (obj->is<CallObject>()) {
|
||||
MOZ_ASSERT(obj == holder);
|
||||
if (!shape->hasDefaultGetter())
|
||||
if (!prop.shape()->hasDefaultGetter())
|
||||
return false;
|
||||
} else {
|
||||
// We don't yet support lookups on Block or DeclEnv objects.
|
||||
|
|
@ -4942,9 +4952,9 @@ NameIC::attachCallGetter(JSContext* cx, HandleScript outerScript, IonScript* ion
|
|||
|
||||
static bool
|
||||
IsCacheableNameCallGetter(HandleObject envChain, HandleObject obj, HandleObject holder,
|
||||
HandleShape shape)
|
||||
Handle<PropertyResult> prop)
|
||||
{
|
||||
if (!shape)
|
||||
if (!prop)
|
||||
return false;
|
||||
if (!obj->is<GlobalObject>())
|
||||
return false;
|
||||
|
|
@ -4952,6 +4962,10 @@ IsCacheableNameCallGetter(HandleObject envChain, HandleObject obj, HandleObject
|
|||
if (!IsCacheableEnvironmentChain(envChain, obj))
|
||||
return false;
|
||||
|
||||
if (!prop || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
||||
return false;
|
||||
|
||||
Shape* shape = prop.shape();
|
||||
return IsCacheableGetPropCallNative(obj, holder, shape) ||
|
||||
IsCacheableGetPropCallPropertyOp(obj, holder, shape) ||
|
||||
IsCacheableGetPropCallScripted(obj, holder, shape);
|
||||
|
|
@ -4996,10 +5010,10 @@ NameIC::attachTypeOfNoProperty(JSContext* cx, HandleScript outerScript, IonScrip
|
|||
|
||||
static bool
|
||||
IsCacheableNameNoProperty(HandleObject envChain, HandleObject obj,
|
||||
HandleObject holder, HandleShape shape, jsbytecode* pc,
|
||||
HandleObject holder, Handle<PropertyResult> prop, jsbytecode* pc,
|
||||
NameIC& cache)
|
||||
{
|
||||
if (cache.isTypeOf() && !shape) {
|
||||
if (cache.isTypeOf() && !prop) {
|
||||
MOZ_ASSERT(!obj);
|
||||
MOZ_ASSERT(!holder);
|
||||
MOZ_ASSERT(envChain);
|
||||
|
|
@ -5029,34 +5043,35 @@ NameIC::update(JSContext* cx, HandleScript outerScript, size_t cacheIndex, Handl
|
|||
|
||||
RootedObject obj(cx);
|
||||
RootedObject holder(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupName(cx, name, envChain, &obj, &holder, &shape))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!LookupName(cx, name, envChain, &obj, &holder, &prop))
|
||||
return false;
|
||||
|
||||
// Look first. Don't generate cache entries if the lookup fails.
|
||||
if (cache.isTypeOf()) {
|
||||
if (!FetchName<true>(cx, obj, holder, name, shape, vp))
|
||||
if (!FetchName<true>(cx, obj, holder, name, prop, vp))
|
||||
return false;
|
||||
} else {
|
||||
if (!FetchName<false>(cx, obj, holder, name, shape, vp))
|
||||
if (!FetchName<false>(cx, obj, holder, name, prop, vp))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cache.canAttachStub()) {
|
||||
if (IsCacheableNameReadSlot(envChain, obj, holder, shape, pc, cache.outputReg())) {
|
||||
if (IsCacheableNameReadSlot(cx, envChain, obj, holder, prop, pc, cache.outputReg())) {
|
||||
if (!cache.attachReadSlot(cx, outerScript, ion, envChain, obj,
|
||||
holder.as<NativeObject>(), shape))
|
||||
holder.as<NativeObject>(), prop))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else if (IsCacheableNameCallGetter(envChain, obj, holder, shape)) {
|
||||
} else if (IsCacheableNameCallGetter(envChain, obj, holder, prop)) {
|
||||
void* returnAddr = GetReturnAddressToIonCode(cx);
|
||||
RootedShape shape(cx, prop.shape());
|
||||
if (!cache.attachCallGetter(cx, outerScript, ion, envChain, obj, holder, shape,
|
||||
returnAddr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else if (IsCacheableNameNoProperty(envChain, obj, holder, shape, pc, cache)) {
|
||||
} else if (IsCacheableNameNoProperty(envChain, obj, holder, prop, pc, cache)) {
|
||||
if (!cache.attachTypeOfNoProperty(cx, outerScript, ion, envChain))
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -806,7 +806,7 @@ class NameIC : public IonCache
|
|||
|
||||
MOZ_MUST_USE bool attachReadSlot(JSContext* cx, HandleScript outerScript, IonScript* ion,
|
||||
HandleObject envChain, HandleObject holderBase,
|
||||
HandleNativeObject holder, HandleShape shape);
|
||||
HandleNativeObject holder, Handle<PropertyResult> prop);
|
||||
|
||||
MOZ_MUST_USE bool attachCallGetter(JSContext* cx, HandleScript outerScript, IonScript* ion,
|
||||
HandleObject envChain, HandleObject obj,
|
||||
|
|
@ -839,7 +839,7 @@ IONCACHE_KIND_LIST(CACHE_CASTS)
|
|||
#undef OPCODE_CASTS
|
||||
|
||||
bool IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder);
|
||||
bool IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder, Shape* shape);
|
||||
bool IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder, PropertyResult prop);
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
|
|
|||
|
|
@ -2192,12 +2192,12 @@ GetDOMProxyProto(JSObject* obj)
|
|||
// existence of the property on the object.
|
||||
bool
|
||||
EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject holder, MutableHandleShape shape,
|
||||
MutableHandleObject holder, MutableHandle<PropertyResult> prop,
|
||||
bool* checkDOMProxy,
|
||||
DOMProxyShadowsResult* shadowsResult,
|
||||
bool* domProxyHasGeneration)
|
||||
{
|
||||
shape.set(nullptr);
|
||||
prop.setNotFound();
|
||||
holder.set(nullptr);
|
||||
|
||||
if (checkDOMProxy) {
|
||||
|
|
@ -2231,11 +2231,11 @@ EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (LookupPropertyPure(cx, checkObj, id, holder.address(), shape.address()))
|
||||
if (LookupPropertyPure(cx, checkObj, id, holder.address(), prop.address()))
|
||||
return true;
|
||||
|
||||
holder.set(nullptr);
|
||||
shape.set(nullptr);
|
||||
prop.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2421,15 +2421,16 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, SharedStubInfo* info,
|
|||
bool isDOMProxy;
|
||||
bool domProxyHasGeneration;
|
||||
DOMProxyShadowsResult domProxyShadowsResult;
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject holder(cx);
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape, &isDOMProxy,
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &prop, &isDOMProxy,
|
||||
&domProxyShadowsResult, &domProxyHasGeneration))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedShape shape(cx, prop.maybeShape());
|
||||
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
|
||||
|
||||
bool isScripted = false;
|
||||
|
|
@ -2492,7 +2493,7 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, SharedStubInfo* info,
|
|||
MOZ_ASSERT(ToWindowIfWindowProxy(obj) == cx->global());
|
||||
obj = cx->global();
|
||||
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape, &isDOMProxy,
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &prop, &isDOMProxy,
|
||||
&domProxyShadowsResult, &domProxyHasGeneration))
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2249,7 +2249,7 @@ StripPreliminaryObjectStubs(JSContext* cx, ICFallbackStub* stub);
|
|||
|
||||
MOZ_MUST_USE bool
|
||||
EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandleId name,
|
||||
MutableHandleObject holder, MutableHandleShape shape,
|
||||
MutableHandleObject holder, MutableHandle<PropertyResult> prop,
|
||||
bool* checkDOMProxy=nullptr,
|
||||
DOMProxyShadowsResult* shadowsResult=nullptr,
|
||||
bool* domProxyHasGeneration=nullptr);
|
||||
|
|
|
|||
|
|
@ -583,11 +583,11 @@ GetDynamicName(JSContext* cx, JSObject* envChain, JSString* str, Value* vp)
|
|||
return;
|
||||
}
|
||||
|
||||
Shape* shape = nullptr;
|
||||
PropertyResult prop;
|
||||
JSObject* scope = nullptr;
|
||||
JSObject* pobj = nullptr;
|
||||
if (LookupNameNoGC(cx, atom->asPropertyName(), envChain, &scope, &pobj, &shape)) {
|
||||
if (FetchNameNoGC(pobj, shape, MutableHandleValue::fromMarkedLocation(vp)))
|
||||
if (LookupNameNoGC(cx, atom->asPropertyName(), envChain, &scope, &pobj, &prop)) {
|
||||
if (FetchNameNoGC(pobj, prop, MutableHandleValue::fromMarkedLocation(vp)))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2947,9 +2947,9 @@ JS_AlreadyHasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool*
|
|||
return js::HasOwnProperty(cx, obj, id, foundp);
|
||||
|
||||
RootedNativeObject nativeObj(cx, &obj->as<NativeObject>());
|
||||
RootedShape prop(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
NativeLookupOwnPropertyNoResolve(cx, nativeObj, id, &prop);
|
||||
*foundp = !!prop;
|
||||
*foundp = prop.isFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
|
|||
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_LookupProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp,
|
||||
JS::MutableHandle<Shape*> propp);
|
||||
JS::MutableHandle<JS::PropertyResult> propp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_DefineProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::Handle<JS::PropertyDescriptor> desc,
|
||||
|
|
|
|||
104
js/src/jsobj.cpp
104
js/src/jsobj.cpp
|
|
@ -2116,7 +2116,7 @@ JSObject::constructHook() const
|
|||
|
||||
bool
|
||||
js::LookupProperty(JSContext* cx, HandleObject obj, js::HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
/* NB: The logic of lookupProperty is implicitly reflected in
|
||||
* BaselineIC.cpp's |EffectlesslyLookupProperty| logic.
|
||||
|
|
@ -2129,7 +2129,7 @@ js::LookupProperty(JSContext* cx, HandleObject obj, js::HandleId id,
|
|||
|
||||
bool
|
||||
js::LookupName(JSContext* cx, HandlePropertyName name, HandleObject envChain,
|
||||
MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandleObject pobjp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
|
||||
|
|
@ -2144,13 +2144,13 @@ js::LookupName(JSContext* cx, HandlePropertyName name, HandleObject envChain,
|
|||
|
||||
objp.set(nullptr);
|
||||
pobjp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupNameNoGC(JSContext* cx, PropertyName* name, JSObject* envChain,
|
||||
JSObject** objp, JSObject** pobjp, Shape** propp)
|
||||
JSObject** objp, JSObject** pobjp, PropertyResult* propp)
|
||||
{
|
||||
AutoAssertNoException nogc(cx);
|
||||
|
||||
|
|
@ -2177,13 +2177,13 @@ js::LookupNameWithGlobalDefault(JSContext* cx, HandlePropertyName name, HandleOb
|
|||
RootedId id(cx, NameToId(name));
|
||||
|
||||
RootedObject pobj(cx);
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
|
||||
RootedObject env(cx, envChain);
|
||||
for (; !env->is<GlobalObject>(); env = env->enclosingEnvironment()) {
|
||||
if (!LookupProperty(cx, env, id, &pobj, &shape))
|
||||
if (!LookupProperty(cx, env, id, &pobj, &prop))
|
||||
return false;
|
||||
if (shape)
|
||||
if (prop)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -2198,20 +2198,20 @@ js::LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject e
|
|||
RootedId id(cx, NameToId(name));
|
||||
|
||||
RootedObject pobj(cx);
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
|
||||
RootedObject env(cx, envChain);
|
||||
for (; !env->isUnqualifiedVarObj(); env = env->enclosingEnvironment()) {
|
||||
if (!LookupProperty(cx, env, id, &pobj, &shape))
|
||||
if (!LookupProperty(cx, env, id, &pobj, &prop))
|
||||
return false;
|
||||
if (shape)
|
||||
if (prop)
|
||||
break;
|
||||
}
|
||||
|
||||
// See note above RuntimeLexicalErrorObject.
|
||||
if (pobj == env) {
|
||||
bool isTDZ = false;
|
||||
if (shape && name != cx->names().dotThis) {
|
||||
if (prop && name != cx->names().dotThis) {
|
||||
// Treat Debugger environments specially for TDZ checks, as they
|
||||
// look like non-native environments but in fact wrap native
|
||||
// environments.
|
||||
|
|
@ -2222,7 +2222,7 @@ js::LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject e
|
|||
return false;
|
||||
isTDZ = IsUninitializedLexical(v);
|
||||
} else {
|
||||
isTDZ = IsUninitializedLexicalSlot(env, shape);
|
||||
isTDZ = IsUninitializedLexicalSlot(env, prop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2230,7 +2230,7 @@ js::LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject e
|
|||
env = RuntimeLexicalErrorObject::create(cx, env, JSMSG_UNINITIALIZED_LEXICAL);
|
||||
if (!env)
|
||||
return false;
|
||||
} else if (env->is<LexicalEnvironmentObject>() && !shape->writable()) {
|
||||
} else if (env->is<LexicalEnvironmentObject>() && !prop.shape()->writable()) {
|
||||
// Assigning to a named lambda callee name is a no-op in sloppy mode.
|
||||
Rooted<LexicalEnvironmentObject*> lexicalEnv(cx, &env->as<LexicalEnvironmentObject>());
|
||||
if (lexicalEnv->isExtensible() ||
|
||||
|
|
@ -2262,16 +2262,16 @@ js::HasOwnProperty(JSContext* cx, HandleObject obj, HandleId id, bool* result)
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedShape shape(cx);
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj.as<NativeObject>(), id, &shape))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj.as<NativeObject>(), id, &prop))
|
||||
return false;
|
||||
*result = (shape != nullptr);
|
||||
*result = prop.isFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject** objp,
|
||||
Shape** propp)
|
||||
PropertyResult* propp)
|
||||
{
|
||||
bool isTypedArrayOutOfRange = false;
|
||||
do {
|
||||
|
|
@ -2292,12 +2292,12 @@ js::LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject**
|
|||
} while (obj);
|
||||
|
||||
*objp = nullptr;
|
||||
*propp = nullptr;
|
||||
propp->setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape** propp,
|
||||
js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, PropertyResult* propp,
|
||||
bool* isTypedArrayOutOfRange /* = nullptr */)
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
|
@ -2308,7 +2308,7 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
|
|||
// Search for a native dense element, typed array element, or property.
|
||||
|
||||
if (JSID_IS_INT(id) && obj->as<NativeObject>().containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
|
||||
propp->setDenseOrTypedArrayElement();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2316,9 +2316,9 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
|
|||
uint64_t index;
|
||||
if (IsTypedArrayIndex(id, &index)) {
|
||||
if (index < obj->as<TypedArrayObject>().length()) {
|
||||
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
|
||||
propp->setDenseOrTypedArrayElement();
|
||||
} else {
|
||||
*propp = nullptr;
|
||||
propp->setNotFound();
|
||||
if (isTypedArrayOutOfRange)
|
||||
*isTypedArrayOutOfRange = true;
|
||||
}
|
||||
|
|
@ -2327,7 +2327,7 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
|
|||
}
|
||||
|
||||
if (Shape* shape = obj->as<NativeObject>().lookupPure(id)) {
|
||||
*propp = shape;
|
||||
propp->setNativeProperty(shape);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2337,31 +2337,31 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
|
|||
return false;
|
||||
} else if (obj->is<UnboxedPlainObject>()) {
|
||||
if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
|
||||
MarkNonNativePropertyFound<NoGC>(propp);
|
||||
propp->setNonNativeProperty();
|
||||
return true;
|
||||
}
|
||||
} else if (obj->is<UnboxedArrayObject>()) {
|
||||
if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
|
||||
MarkNonNativePropertyFound<NoGC>(propp);
|
||||
propp->setNonNativeProperty();
|
||||
return true;
|
||||
}
|
||||
} else if (obj->is<TypedObject>()) {
|
||||
if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
|
||||
MarkNonNativePropertyFound<NoGC>(propp);
|
||||
propp->setNonNativeProperty();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
*propp = nullptr;
|
||||
propp->setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
NativeGetPureInline(NativeObject* pobj, jsid id, Shape* shape, Value* vp)
|
||||
NativeGetPureInline(NativeObject* pobj, jsid id, PropertyResult prop, Value* vp)
|
||||
{
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
// For simplicity we ignore the TypedArray with string index case.
|
||||
if (!JSID_IS_INT(id))
|
||||
return false;
|
||||
|
|
@ -2371,6 +2371,7 @@ NativeGetPureInline(NativeObject* pobj, jsid id, Shape* shape, Value* vp)
|
|||
}
|
||||
|
||||
// Fail if we have a custom getter.
|
||||
Shape* shape = prop.shape();
|
||||
if (!shape->hasDefaultGetter())
|
||||
return false;
|
||||
|
||||
|
|
@ -2388,22 +2389,23 @@ bool
|
|||
js::GetPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Value* vp)
|
||||
{
|
||||
JSObject* pobj;
|
||||
Shape* shape;
|
||||
if (!LookupPropertyPure(cx, obj, id, &pobj, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
vp->setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
return pobj->isNative() && NativeGetPureInline(&pobj->as<NativeObject>(), id, shape, vp);
|
||||
return pobj->isNative() && NativeGetPureInline(&pobj->as<NativeObject>(), id, prop, vp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
NativeGetGetterPureInline(Shape* shape, JSFunction** fp)
|
||||
NativeGetGetterPureInline(PropertyResult prop, JSFunction** fp)
|
||||
{
|
||||
if (!IsImplicitDenseOrTypedArrayElement(shape) && shape->hasGetterObject()) {
|
||||
if (!prop.isDenseOrTypedArrayElement() && prop.shape()->hasGetterObject()) {
|
||||
Shape* shape = prop.shape();
|
||||
if (shape->getterObject()->is<JSFunction>()) {
|
||||
*fp = &shape->getterObject()->as<JSFunction>();
|
||||
return true;
|
||||
|
|
@ -2420,32 +2422,32 @@ js::GetGetterPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSFunction** fp)
|
|||
/* Just like GetPropertyPure, but get getter function, without invoking
|
||||
* it. */
|
||||
JSObject* pobj;
|
||||
Shape* shape;
|
||||
if (!LookupPropertyPure(cx, obj, id, &pobj, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
*fp = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return pobj->isNative() && NativeGetGetterPureInline(shape, fp);
|
||||
return prop.isNativeProperty() && NativeGetGetterPureInline(prop, fp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetOwnGetterPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSFunction** fp)
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
Shape* shape;
|
||||
if (!LookupOwnPropertyPure(cx, obj, id, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupOwnPropertyPure(cx, obj, id, &prop))
|
||||
return false;
|
||||
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
*fp = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return NativeGetGetterPureInline(shape, fp);
|
||||
return prop.isNativeProperty() && NativeGetGetterPureInline(prop, fp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2453,14 +2455,14 @@ js::GetOwnNativeGetterPure(JSContext* cx, JSObject* obj, jsid id, JSNative* nati
|
|||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
*native = nullptr;
|
||||
Shape* shape;
|
||||
if (!LookupOwnPropertyPure(cx, obj, id, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupOwnPropertyPure(cx, obj, id, &prop))
|
||||
return false;
|
||||
|
||||
if (!shape || IsImplicitDenseOrTypedArrayElement(shape) || !shape->hasGetterObject())
|
||||
if (!prop || prop.isDenseOrTypedArrayElement() || !prop.shape()->hasGetterObject())
|
||||
return true;
|
||||
|
||||
JSObject* getterObj = shape->getterObject();
|
||||
JSObject* getterObj = prop.shape()->getterObject();
|
||||
if (!getterObj->is<JSFunction>())
|
||||
return true;
|
||||
|
||||
|
|
@ -2475,12 +2477,12 @@ js::GetOwnNativeGetterPure(JSContext* cx, JSObject* obj, jsid id, JSNative* nati
|
|||
bool
|
||||
js::HasOwnDataPropertyPure(JSContext* cx, JSObject* obj, jsid id, bool* result)
|
||||
{
|
||||
Shape* shape = nullptr;
|
||||
if (!LookupOwnPropertyPure(cx, obj, id, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupOwnPropertyPure(cx, obj, id, &prop))
|
||||
return false;
|
||||
|
||||
*result = shape && !IsImplicitDenseOrTypedArrayElement(shape) && shape->hasDefaultGetter() &&
|
||||
shape->hasSlot();
|
||||
*result = prop && !prop.isDenseOrTypedArrayElement() && prop.shape()->hasDefaultGetter() &&
|
||||
prop.shape()->hasSlot();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -999,11 +999,11 @@ GetPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
|||
*/
|
||||
extern bool
|
||||
LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp);
|
||||
|
||||
inline bool
|
||||
LookupProperty(JSContext* cx, HandleObject obj, PropertyName* name,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return LookupProperty(cx, obj, id, objp, propp);
|
||||
|
|
@ -1195,11 +1195,11 @@ ReadPropertyDescriptors(JSContext* cx, HandleObject props, bool checkAccessors,
|
|||
/* Read the name using a dynamic lookup on the scopeChain. */
|
||||
extern bool
|
||||
LookupName(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
|
||||
MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp);
|
||||
MutableHandleObject objp, MutableHandleObject pobjp, MutableHandle<PropertyResult> propp);
|
||||
|
||||
extern bool
|
||||
LookupNameNoGC(JSContext* cx, PropertyName* name, JSObject* scopeChain,
|
||||
JSObject** objp, JSObject** pobjp, Shape** propp);
|
||||
JSObject** objp, JSObject** pobjp, PropertyResult* propp);
|
||||
|
||||
/*
|
||||
* Like LookupName except returns the global object if 'name' is not found in
|
||||
|
|
@ -1233,10 +1233,10 @@ FindVariableScope(JSContext* cx, JSFunction** funp);
|
|||
|
||||
bool
|
||||
LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject** objp,
|
||||
Shape** propp);
|
||||
PropertyResult* propp);
|
||||
|
||||
bool
|
||||
LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape** propp,
|
||||
LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, PropertyResult* propp,
|
||||
bool* isTypedArrayOutOfRange = nullptr);
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -585,11 +585,11 @@ HasNoToPrimitiveMethodPure(JSObject* obj, JSContext* cx)
|
|||
{
|
||||
jsid id = SYMBOL_TO_JSID(cx->wellKnownSymbols().toPrimitive);
|
||||
JSObject* pobj;
|
||||
Shape* shape;
|
||||
if (!LookupPropertyPure(cx, obj, id, &pobj, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
return !shape;
|
||||
return !prop;
|
||||
}
|
||||
|
||||
/* ES6 draft rev 28 (2014 Oct 14) 7.1.14 */
|
||||
|
|
|
|||
|
|
@ -445,9 +445,9 @@ JO(JSContext* cx, HandleObject obj, StringifyContext* scx)
|
|||
#ifdef DEBUG
|
||||
if (scx->maybeSafely) {
|
||||
RootedNativeObject nativeObj(cx, &obj->as<NativeObject>());
|
||||
RootedShape prop(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
NativeLookupOwnPropertyNoResolve(cx, nativeObj, id, &prop);
|
||||
MOZ_ASSERT(prop && prop->isDataDescriptor());
|
||||
MOZ_ASSERT(prop && prop.isNativeProperty() && prop.shape()->isDataDescriptor());
|
||||
}
|
||||
#endif // DEBUG
|
||||
if (!GetProperty(cx, obj, obj, id, &outputValue))
|
||||
|
|
|
|||
|
|
@ -530,18 +530,18 @@ Proxy::trace(JSTracer* trc, JSObject* proxy)
|
|||
|
||||
bool
|
||||
js::proxy_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<JS::PropertyResult> propp)
|
||||
{
|
||||
bool found;
|
||||
if (!Proxy::has(cx, obj, id, &found))
|
||||
return false;
|
||||
|
||||
if (found) {
|
||||
MarkNonNativePropertyFound<CanGC>(propp);
|
||||
propp.setNonNativeProperty();
|
||||
objp.set(obj);
|
||||
} else {
|
||||
propp.setNotFound();
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10098,12 +10098,14 @@ DebuggerObject::forceLexicalInitializationByName(JSContext* cx, HandleDebuggerOb
|
|||
|
||||
RootedObject globalLexical(cx, &referent->lexicalEnvironment());
|
||||
RootedObject pobj(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupProperty(cx, globalLexical, id, &pobj, &shape))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!LookupProperty(cx, globalLexical, id, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
result = false;
|
||||
if (shape) {
|
||||
if (prop) {
|
||||
MOZ_ASSERT(prop.isNativeProperty());
|
||||
Shape* shape = prop.shape();
|
||||
Value v = globalLexical->as<NativeObject>().getSlot(shape->slot());
|
||||
if (shape->hasSlot() && v.isMagic() && v.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
|
||||
globalLexical->as<NativeObject>().setSlot(shape->slot(), UndefinedValue());
|
||||
|
|
|
|||
|
|
@ -518,14 +518,14 @@ ModuleEnvironmentObject::fixEnclosingEnvironmentAfterCompartmentMerge(GlobalObje
|
|||
|
||||
/* static */ bool
|
||||
ModuleEnvironmentObject::lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
const IndirectBindingMap& bindings = obj->as<ModuleEnvironmentObject>().importBindings();
|
||||
Shape* shape;
|
||||
ModuleEnvironmentObject* env;
|
||||
if (bindings.lookup(id, &env, &shape)) {
|
||||
objp.set(env);
|
||||
propp.set(shape);
|
||||
propp.setNativeProperty(shape);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -688,13 +688,13 @@ CheckUnscopables(JSContext *cx, HandleObject obj, HandleId id, bool *scopable)
|
|||
|
||||
static bool
|
||||
with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
// SpiderMonkey-specific: consider internal '.generator' and '.this' names
|
||||
// to be unscopable.
|
||||
if (IsUnscopableDotName(cx, id)) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -708,7 +708,7 @@ with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
return false;
|
||||
if (!scopable) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1104,7 +1104,7 @@ ReportRuntimeLexicalErrorId(JSContext* cx, unsigned errorNumber, HandleId id)
|
|||
|
||||
static bool
|
||||
lexicalError_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ class ModuleEnvironmentObject : public EnvironmentObject
|
|||
|
||||
private:
|
||||
static bool lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
MutableHandleObject objp, MutableHandle<PropertyResult> propp);
|
||||
static bool hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
|
||||
static bool getProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
|
|
|
|||
|
|
@ -363,12 +363,14 @@ js::CheckStarGeneratorResumptionValue(JSContext* cx, HandleValue v)
|
|||
|
||||
// It should have `value` data property, but the type doesn't matter
|
||||
JSObject* ignored;
|
||||
Shape* shape;
|
||||
if (!LookupPropertyPure(cx, obj, NameToId(cx->names().value), &ignored, &shape))
|
||||
PropertyResult prop;
|
||||
if (!LookupPropertyPure(cx, obj, NameToId(cx->names().value), &ignored, &prop))
|
||||
return false;
|
||||
if (!shape)
|
||||
if (!prop)
|
||||
return false;
|
||||
if (!shape->hasDefaultGetter())
|
||||
if (!prop.isNativeProperty())
|
||||
return false;
|
||||
if (!prop.shape()->hasDefaultGetter())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -78,17 +78,18 @@ IsUninitializedLexical(const Value& val)
|
|||
}
|
||||
|
||||
static inline bool
|
||||
IsUninitializedLexicalSlot(HandleObject obj, HandleShape shape)
|
||||
IsUninitializedLexicalSlot(HandleObject obj, Handle<PropertyResult> prop)
|
||||
{
|
||||
MOZ_ASSERT(shape);
|
||||
MOZ_ASSERT(prop);
|
||||
if (obj->is<WithEnvironmentObject>())
|
||||
return false;
|
||||
// We check for IsImplicitDenseOrTypedArrayElement even though the shape
|
||||
// is always a non-indexed property because proxy hooks may return a
|
||||
// "non-native property found" shape, which happens to be encoded in the
|
||||
// same way as the "dense element" shape. See MarkNonNativePropertyFound.
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape) ||
|
||||
!shape->hasSlot() ||
|
||||
|
||||
// Proxy hooks may return a non-native property.
|
||||
if (prop.isNonNativeProperty())
|
||||
return false;
|
||||
|
||||
Shape* shape = prop.shape();
|
||||
if (!shape->hasSlot() ||
|
||||
!shape->hasDefaultGetter() ||
|
||||
!shape->hasDefaultSetter())
|
||||
{
|
||||
|
|
@ -174,9 +175,9 @@ GetLengthProperty(const Value& lval, MutableHandleValue vp)
|
|||
|
||||
template <bool TypeOf> inline bool
|
||||
FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName name,
|
||||
HandleShape shape, MutableHandleValue vp)
|
||||
Handle<PropertyResult> prop, MutableHandleValue vp)
|
||||
{
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
if (TypeOf) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
|
|
@ -190,6 +191,7 @@ FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName
|
|||
if (!GetProperty(cx, obj, obj, id, vp))
|
||||
return false;
|
||||
} else {
|
||||
RootedShape shape(cx, prop.shape());
|
||||
RootedObject normalized(cx, obj);
|
||||
if (normalized->is<WithEnvironmentObject>() && !shape->hasDefaultGetter())
|
||||
normalized = &normalized->as<WithEnvironmentObject>().object();
|
||||
|
|
@ -213,9 +215,13 @@ FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName
|
|||
}
|
||||
|
||||
inline bool
|
||||
FetchNameNoGC(JSObject* pobj, Shape* shape, MutableHandleValue vp)
|
||||
FetchNameNoGC(JSObject* pobj, PropertyResult prop, MutableHandleValue vp)
|
||||
{
|
||||
if (!shape || !pobj->isNative() || !shape->isDataDescriptor() || !shape->hasDefaultGetter())
|
||||
if (!prop || !pobj->isNative())
|
||||
return false;
|
||||
|
||||
Shape* shape = prop.shape();
|
||||
if (!shape->isDataDescriptor() || !shape->hasDefaultGetter())
|
||||
return false;
|
||||
|
||||
vp.set(pobj->as<NativeObject>().getSlot(shape->slot()));
|
||||
|
|
@ -361,7 +367,7 @@ DefVarOperation(JSContext* cx, HandleObject varobj, HandlePropertyName dn, unsig
|
|||
}
|
||||
#endif
|
||||
|
||||
RootedShape prop(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject obj2(cx);
|
||||
if (!LookupProperty(cx, varobj, dn, &obj2, &prop))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -210,27 +210,27 @@ GetNameOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHan
|
|||
if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasNonSyntacticScope())
|
||||
obj = &obj->global().lexicalEnvironment();
|
||||
|
||||
Shape* shape = nullptr;
|
||||
PropertyResult prop;
|
||||
JSObject* env = nullptr;
|
||||
JSObject* pobj = nullptr;
|
||||
if (LookupNameNoGC(cx, name, obj, &env, &pobj, &shape)) {
|
||||
if (FetchNameNoGC(pobj, shape, vp))
|
||||
if (LookupNameNoGC(cx, name, obj, &env, &pobj, &prop)) {
|
||||
if (FetchNameNoGC(pobj, prop, vp))
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject objRoot(cx, obj), envRoot(cx), pobjRoot(cx);
|
||||
RootedPropertyName nameRoot(cx, name);
|
||||
RootedShape shapeRoot(cx);
|
||||
Rooted<PropertyResult> propRoot(cx);
|
||||
|
||||
if (!LookupName(cx, nameRoot, objRoot, &envRoot, &pobjRoot, &shapeRoot))
|
||||
if (!LookupName(cx, nameRoot, objRoot, &envRoot, &pobjRoot, &propRoot))
|
||||
return false;
|
||||
|
||||
/* Kludge to allow (typeof foo == "undefined") tests. */
|
||||
JSOp op2 = JSOp(pc[JSOP_GETNAME_LENGTH]);
|
||||
if (op2 == JSOP_TYPEOF)
|
||||
return FetchName<true>(cx, envRoot, pobjRoot, nameRoot, shapeRoot, vp);
|
||||
return FetchName<true>(cx, envRoot, pobjRoot, nameRoot, propRoot, vp);
|
||||
|
||||
return FetchName<false>(cx, envRoot, pobjRoot, nameRoot, shapeRoot, vp);
|
||||
return FetchName<false>(cx, envRoot, pobjRoot, nameRoot, propRoot, vp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
@ -238,12 +238,12 @@ GetImportOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableH
|
|||
{
|
||||
RootedObject obj(cx, fp->environmentChain()), env(cx), pobj(cx);
|
||||
RootedPropertyName name(cx, fp->script()->getName(pc));
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
|
||||
MOZ_ALWAYS_TRUE(LookupName(cx, name, obj, &env, &pobj, &shape));
|
||||
MOZ_ALWAYS_TRUE(LookupName(cx, name, obj, &env, &pobj, &prop));
|
||||
MOZ_ASSERT(env && env->is<ModuleEnvironmentObject>());
|
||||
MOZ_ASSERT(env->as<ModuleEnvironmentObject>().hasImportBinding(name));
|
||||
return FetchName<false>(cx, env, pobj, name, shape, vp);
|
||||
return FetchName<false>(cx, env, pobj, name, prop, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -4388,12 +4388,12 @@ bool
|
|||
js::GetEnvironmentName(JSContext* cx, HandleObject envChain, HandlePropertyName name,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject obj(cx), pobj(cx);
|
||||
if (!LookupName(cx, name, envChain, &obj, &pobj, &shape))
|
||||
if (!LookupName(cx, name, envChain, &obj, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
if (!shape)
|
||||
if (!prop)
|
||||
return ReportIsNotDefined(cx, name);
|
||||
|
||||
if (!GetProperty(cx, obj, obj, name, vp))
|
||||
|
|
@ -4415,12 +4415,12 @@ bool
|
|||
js::GetEnvironmentNameForTypeOf(JSContext* cx, HandleObject envChain, HandlePropertyName name,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject obj(cx), pobj(cx);
|
||||
if (!LookupName(cx, name, envChain, &obj, &pobj, &shape))
|
||||
if (!LookupName(cx, name, envChain, &obj, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
vp.set(UndefinedValue());
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4478,9 +4478,9 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
|
|||
/* ES5 10.5 (NB: with subsequent errata). */
|
||||
RootedPropertyName name(cx, fun->explicitName()->asPropertyName());
|
||||
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedObject pobj(cx);
|
||||
if (!LookupProperty(cx, parent, name, &pobj, &shape))
|
||||
if (!LookupProperty(cx, parent, name, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
RootedValue rval(cx, ObjectValue(*fun));
|
||||
|
|
@ -4494,7 +4494,7 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
|
|||
: JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
|
||||
/* Steps 5d, 5f. */
|
||||
if (!shape || pobj != parent) {
|
||||
if (!prop || pobj != parent) {
|
||||
if (!DefineProperty(cx, parent, name, rval, nullptr, nullptr, attrs))
|
||||
return false;
|
||||
|
||||
|
|
@ -4512,6 +4512,7 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
|
|||
*/
|
||||
MOZ_ASSERT(parent->isNative() || parent->is<DebugEnvironmentProxy>());
|
||||
if (parent->is<GlobalObject>()) {
|
||||
Shape* shape = prop.shape();
|
||||
if (shape->configurable()) {
|
||||
if (!DefineProperty(cx, parent, name, rval, nullptr, nullptr, attrs))
|
||||
return false;
|
||||
|
|
@ -4716,8 +4717,8 @@ js::DeleteNameOperation(JSContext* cx, HandlePropertyName name, HandleObject sco
|
|||
MutableHandleValue res)
|
||||
{
|
||||
RootedObject scope(cx), pobj(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupName(cx, name, scopeObj, &scope, &pobj, &shape))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!LookupName(cx, name, scopeObj, &scope, &pobj, &prop))
|
||||
return false;
|
||||
|
||||
if (!scope) {
|
||||
|
|
|
|||
|
|
@ -382,8 +382,8 @@ NewNativeObjectWithClassProto(ExclusiveContext* cx, const Class* clasp, HandleOb
|
|||
* *recursedp = false and return true.
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
CallResolveOp(JSContext* cx, HandleNativeObject obj, HandleId id, MutableHandleShape propp,
|
||||
bool* recursedp)
|
||||
CallResolveOp(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
MutableHandle<PropertyResult> propp, bool* recursedp)
|
||||
{
|
||||
// Avoid recursion on (obj, id) already being resolved on cx.
|
||||
AutoResolving resolving(cx, obj, id);
|
||||
|
|
@ -407,13 +407,18 @@ CallResolveOp(JSContext* cx, HandleNativeObject obj, HandleId id, MutableHandleS
|
|||
obj->getClass()->getMayResolve()(cx->names(), id, obj));
|
||||
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkDenseOrTypedArrayElementFound<CanGC>(propp);
|
||||
propp.setDenseOrTypedArrayElement();
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!obj->is<TypedArrayObject>());
|
||||
|
||||
propp.set(obj->lookup(cx, id));
|
||||
RootedShape shape(cx, obj->lookup(cx, id));
|
||||
if (shape)
|
||||
propp.setNativeProperty(shape);
|
||||
else
|
||||
propp.setNotFound();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -444,12 +449,12 @@ static MOZ_ALWAYS_INLINE bool
|
|||
LookupOwnPropertyInline(ExclusiveContext* cx,
|
||||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp,
|
||||
typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp,
|
||||
bool* donep)
|
||||
{
|
||||
// Check for a native dense element.
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkDenseOrTypedArrayElementFound<allowGC>(propp);
|
||||
propp.setDenseOrTypedArrayElement();
|
||||
*donep = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -460,11 +465,10 @@ LookupOwnPropertyInline(ExclusiveContext* cx,
|
|||
if (obj->template is<TypedArrayObject>()) {
|
||||
uint64_t index;
|
||||
if (IsTypedArrayIndex(id, &index)) {
|
||||
if (index < obj->template as<TypedArrayObject>().length()) {
|
||||
MarkDenseOrTypedArrayElementFound<allowGC>(propp);
|
||||
} else {
|
||||
propp.set(nullptr);
|
||||
}
|
||||
if (index < obj->template as<TypedArrayObject>().length())
|
||||
propp.setDenseOrTypedArrayElement();
|
||||
else
|
||||
propp.setNotFound();
|
||||
*donep = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -472,7 +476,7 @@ LookupOwnPropertyInline(ExclusiveContext* cx,
|
|||
|
||||
// Check for a native property.
|
||||
if (Shape* shape = obj->lookup(cx, id)) {
|
||||
propp.set(shape);
|
||||
propp.setNativeProperty(shape);
|
||||
*donep = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -486,14 +490,14 @@ LookupOwnPropertyInline(ExclusiveContext* cx,
|
|||
if (!CallResolveOp(cx->asJSContext(),
|
||||
MaybeRooted<NativeObject*, allowGC>::toHandle(obj),
|
||||
MaybeRooted<jsid, allowGC>::toHandle(id),
|
||||
MaybeRooted<Shape*, allowGC>::toMutableHandle(propp),
|
||||
MaybeRooted<PropertyResult, allowGC>::toMutableHandle(propp),
|
||||
&recursed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recursed) {
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
*donep = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -504,7 +508,7 @@ LookupOwnPropertyInline(ExclusiveContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
*donep = false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -515,11 +519,11 @@ LookupOwnPropertyInline(ExclusiveContext* cx,
|
|||
*/
|
||||
static inline void
|
||||
NativeLookupOwnPropertyNoResolve(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
|
||||
MutableHandleShape result)
|
||||
MutableHandle<PropertyResult> result)
|
||||
{
|
||||
// Check for a native dense element.
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkDenseOrTypedArrayElementFound<CanGC>(result);
|
||||
result.setDenseOrTypedArrayElement();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -528,15 +532,18 @@ NativeLookupOwnPropertyNoResolve(ExclusiveContext* cx, HandleNativeObject obj, H
|
|||
uint64_t index;
|
||||
if (IsTypedArrayIndex(id, &index)) {
|
||||
if (index < obj->as<TypedArrayObject>().length())
|
||||
MarkDenseOrTypedArrayElementFound<CanGC>(result);
|
||||
result.setDenseOrTypedArrayElement();
|
||||
else
|
||||
result.set(nullptr);
|
||||
result.setNotFound();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a native property.
|
||||
result.set(obj->lookup(cx, id));
|
||||
if (Shape* shape = obj->lookup(cx, id))
|
||||
result.setNativeProperty(shape);
|
||||
else
|
||||
result.setNotFound();
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
|
|
@ -545,7 +552,7 @@ LookupPropertyInline(ExclusiveContext* cx,
|
|||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
/* NB: The logic of this procedure is implicitly reflected in
|
||||
* BaselineIC.cpp's |EffectlesslyLookupProperty| logic.
|
||||
|
|
@ -578,14 +585,14 @@ LookupPropertyInline(ExclusiveContext* cx,
|
|||
MaybeRooted<JSObject*, allowGC>::toHandle(proto),
|
||||
MaybeRooted<jsid, allowGC>::toHandle(id),
|
||||
MaybeRooted<JSObject*, allowGC>::toMutableHandle(objp),
|
||||
MaybeRooted<Shape*, allowGC>::toMutableHandle(propp));
|
||||
MaybeRooted<PropertyResult, allowGC>::toMutableHandle(propp));
|
||||
}
|
||||
|
||||
current = &proto->template as<NativeObject>();
|
||||
}
|
||||
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1044,7 +1044,7 @@ bool
|
|||
js::NativeLookupOwnProperty(ExclusiveContext* cx,
|
||||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
bool done;
|
||||
return LookupOwnPropertyInline<allowGC>(cx, obj, id, propp, &done);
|
||||
|
|
@ -1052,11 +1052,11 @@ js::NativeLookupOwnProperty(ExclusiveContext* cx,
|
|||
|
||||
template bool
|
||||
js::NativeLookupOwnProperty<CanGC>(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
|
||||
MutableHandleShape propp);
|
||||
MutableHandle<PropertyResult> propp);
|
||||
|
||||
template bool
|
||||
js::NativeLookupOwnProperty<NoGC>(ExclusiveContext* cx, NativeObject* const& obj, const jsid& id,
|
||||
FakeMutableHandle<Shape*> propp);
|
||||
FakeMutableHandle<PropertyResult> propp);
|
||||
|
||||
/*** [[DefineOwnProperty]] ***********************************************************************/
|
||||
|
||||
|
|
@ -1279,19 +1279,20 @@ GetExistingProperty(JSContext* cx,
|
|||
|
||||
static bool
|
||||
GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
|
||||
HandleShape shape, MutableHandleValue vp)
|
||||
Handle<PropertyResult> prop, MutableHandleValue vp)
|
||||
{
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
vp.set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
|
||||
return true;
|
||||
}
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(shape->propid() == id);
|
||||
MOZ_ASSERT(obj->contains(cx, shape));
|
||||
MOZ_ASSERT(prop.shape()->propid() == id);
|
||||
MOZ_ASSERT(obj->contains(cx, prop.shape()));
|
||||
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
RootedShape shape(cx, prop.shape());
|
||||
return GetExistingProperty<CanGC>(cx->asJSContext(), receiver, obj, shape, vp);
|
||||
}
|
||||
|
||||
|
|
@ -1302,7 +1303,7 @@ GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
*/
|
||||
static bool
|
||||
DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
|
||||
HandleShape shape, unsigned shapeAttrs,
|
||||
Handle<PropertyResult> prop, unsigned shapeAttrs,
|
||||
Handle<PropertyDescriptor> desc, bool *redundant)
|
||||
{
|
||||
*redundant = false;
|
||||
|
|
@ -1319,16 +1320,16 @@ DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
if (desc.hasValue()) {
|
||||
// Get the current value of the existing property.
|
||||
RootedValue currentValue(cx);
|
||||
if (!IsImplicitDenseOrTypedArrayElement(shape) &&
|
||||
shape->hasSlot() &&
|
||||
shape->hasDefaultGetter())
|
||||
if (!prop.isDenseOrTypedArrayElement() &&
|
||||
prop.shape()->hasSlot() &&
|
||||
prop.shape()->hasDefaultGetter())
|
||||
{
|
||||
// Inline GetExistingPropertyValue in order to omit a type
|
||||
// correctness assertion that's too strict for this particular
|
||||
// call site. For details, see bug 1125624 comments 13-16.
|
||||
currentValue.set(obj->getSlot(shape->slot()));
|
||||
currentValue.set(obj->getSlot(prop.shape()->slot()));
|
||||
} else {
|
||||
if (!GetExistingPropertyValue(cx, obj, id, shape, ¤tValue))
|
||||
if (!GetExistingPropertyValue(cx, obj, id, prop, ¤tValue))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1339,22 +1340,24 @@ DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
}
|
||||
|
||||
GetterOp existingGetterOp =
|
||||
IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->getter();
|
||||
prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->getter();
|
||||
if (desc.getter() != existingGetterOp)
|
||||
return true;
|
||||
|
||||
SetterOp existingSetterOp =
|
||||
IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->setter();
|
||||
prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->setter();
|
||||
if (desc.setter() != existingSetterOp)
|
||||
return true;
|
||||
} else {
|
||||
if (desc.hasGetterObject()) {
|
||||
if (!(shapeAttrs & JSPROP_GETTER) || desc.getterObject() != shape->getterObject())
|
||||
return true;
|
||||
if (desc.hasGetterObject() &&
|
||||
(!(shapeAttrs & JSPROP_GETTER) || desc.getterObject() != prop.shape()->getterObject()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (desc.hasSetterObject()) {
|
||||
if (!(shapeAttrs & JSPROP_SETTER) || desc.setterObject() != shape->setterObject())
|
||||
return true;
|
||||
if (desc.hasSetterObject() &&
|
||||
(!(shapeAttrs & JSPROP_SETTER) || desc.setterObject() != prop.shape()->setterObject()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1421,14 +1424,14 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
}
|
||||
|
||||
// 9.1.6.1 OrdinaryDefineOwnProperty steps 1-2.
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (desc_.attributes() & JSPROP_RESOLVING) {
|
||||
// We are being called from a resolve or enumerate hook to reify a
|
||||
// lazily-resolved property. To avoid reentering the resolve hook and
|
||||
// recursing forever, skip the resolve hook when doing this lookup.
|
||||
NativeLookupOwnPropertyNoResolve(cx, obj, id, &shape);
|
||||
NativeLookupOwnPropertyNoResolve(cx, obj, id, &prop);
|
||||
} else {
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1443,7 +1446,7 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
Rooted<PropertyDescriptor> desc(cx, desc_);
|
||||
|
||||
// Step 2.
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
if (!obj->nonProxyIsExtensible())
|
||||
return result.fail(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE);
|
||||
|
||||
|
|
@ -1455,21 +1458,20 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
return result.succeed();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
// Steps 3-4. (Step 3 is a special case of step 4.) We use shapeAttrs as a
|
||||
// stand-in for shape in many places below, since shape might not be a
|
||||
// pointer to a real Shape (see IsImplicitDenseOrTypedArrayElement).
|
||||
unsigned shapeAttrs = GetShapeAttributes(obj, shape);
|
||||
unsigned shapeAttrs = GetPropertyAttributes(obj, prop);
|
||||
bool redundant;
|
||||
if (!DefinePropertyIsRedundant(cx, obj, id, shape, shapeAttrs, desc, &redundant))
|
||||
if (!DefinePropertyIsRedundant(cx, obj, id, prop, shapeAttrs, desc, &redundant))
|
||||
return false;
|
||||
if (redundant) {
|
||||
// In cases involving JSOP_NEWOBJECT and JSOP_INITPROP, obj can have a
|
||||
// type for this property that doesn't match the value in the slot.
|
||||
// Update the type here, even though this DefineProperty call is
|
||||
// otherwise a no-op. (See bug 1125624 comment 13.)
|
||||
if (!IsImplicitDenseOrTypedArrayElement(shape) && desc.hasValue()) {
|
||||
if (!prop.isDenseOrTypedArrayElement() && desc.hasValue()) {
|
||||
RootedShape shape(cx, prop.shape());
|
||||
if (!UpdateShapeTypeAndValue(cx, obj, shape, desc.value()))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1512,24 +1514,24 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
MOZ_ASSERT(!desc.hasSetterObject());
|
||||
if (IsDataDescriptor(shapeAttrs)) {
|
||||
RootedValue currentValue(cx);
|
||||
if (!GetExistingPropertyValue(cx, obj, id, shape, ¤tValue))
|
||||
if (!GetExistingPropertyValue(cx, obj, id, prop, ¤tValue))
|
||||
return false;
|
||||
desc.setValue(currentValue);
|
||||
desc.setWritable(IsWritable(shapeAttrs));
|
||||
} else {
|
||||
desc.setGetterObject(shape->getterObject());
|
||||
desc.setSetterObject(shape->setterObject());
|
||||
desc.setGetterObject(prop.shape()->getterObject());
|
||||
desc.setSetterObject(prop.shape()->setterObject());
|
||||
}
|
||||
} else if (desc.isDataDescriptor() != IsDataDescriptor(shapeAttrs)) {
|
||||
// Step 7.
|
||||
if (!IsConfigurable(shapeAttrs) && !skipRedefineChecks)
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
MOZ_ASSERT(!obj->is<TypedArrayObject>());
|
||||
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
|
||||
return false;
|
||||
shape = obj->lookup(cx, id);
|
||||
prop.setNativeProperty(obj->lookup(cx, id));
|
||||
}
|
||||
|
||||
// Fill in desc fields with default values (steps 7.b.i and 7.c.i).
|
||||
|
|
@ -1541,15 +1543,15 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
|
||||
if (frozen || !desc.hasValue()) {
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
MOZ_ASSERT(!obj->is<TypedArrayObject>());
|
||||
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
|
||||
return false;
|
||||
shape = obj->lookup(cx, id);
|
||||
prop.setNativeProperty(obj->lookup(cx, id));
|
||||
}
|
||||
|
||||
RootedValue currentValue(cx);
|
||||
if (!GetExistingPropertyValue(cx, obj, id, shape, ¤tValue))
|
||||
if (!GetExistingPropertyValue(cx, obj, id, prop, ¤tValue))
|
||||
return false;
|
||||
|
||||
if (!desc.hasValue()) {
|
||||
|
|
@ -1571,32 +1573,32 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
desc.setWritable(IsWritable(shapeAttrs));
|
||||
} else {
|
||||
// Step 9.
|
||||
MOZ_ASSERT(shape->isAccessorDescriptor());
|
||||
MOZ_ASSERT(prop.shape()->isAccessorDescriptor());
|
||||
MOZ_ASSERT(desc.isAccessorDescriptor());
|
||||
|
||||
// The spec says to use SameValue, but since the values in
|
||||
// question are objects, we can just compare pointers.
|
||||
if (desc.hasSetterObject()) {
|
||||
if (!IsConfigurable(shapeAttrs) &&
|
||||
desc.setterObject() != shape->setterObject() &&
|
||||
desc.setterObject() != prop.shape()->setterObject() &&
|
||||
!skipRedefineChecks)
|
||||
{
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
}
|
||||
} else {
|
||||
// Fill in desc.[[Set]] from shape.
|
||||
desc.setSetterObject(shape->setterObject());
|
||||
desc.setSetterObject(prop.shape()->setterObject());
|
||||
}
|
||||
if (desc.hasGetterObject()) {
|
||||
if (!IsConfigurable(shapeAttrs) &&
|
||||
desc.getterObject() != shape->getterObject() &&
|
||||
desc.getterObject() != prop.shape()->getterObject() &&
|
||||
!skipRedefineChecks)
|
||||
{
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
}
|
||||
} else {
|
||||
// Fill in desc.[[Get]] from shape.
|
||||
desc.setGetterObject(shape->getterObject());
|
||||
desc.setGetterObject(prop.shape()->getterObject());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1681,18 +1683,18 @@ bool
|
|||
js::NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* foundp)
|
||||
{
|
||||
RootedNativeObject pobj(cx, obj);
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
|
||||
// This loop isn't explicit in the spec algorithm. See the comment on step
|
||||
// 7.a. below.
|
||||
for (;;) {
|
||||
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
|
||||
bool done;
|
||||
if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done))
|
||||
if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &prop, &done))
|
||||
return false;
|
||||
|
||||
// Step 4.
|
||||
if (shape) {
|
||||
if (prop) {
|
||||
*foundp = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1733,15 +1735,15 @@ bool
|
|||
js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc)
|
||||
{
|
||||
RootedShape shape(cx);
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop))
|
||||
return false;
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
desc.object().set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
desc.setAttributes(GetShapeAttributes(obj, shape));
|
||||
desc.setAttributes(GetPropertyAttributes(obj, prop));
|
||||
if (desc.isAccessorDescriptor()) {
|
||||
MOZ_ASSERT(desc.isShared());
|
||||
|
||||
|
|
@ -1754,13 +1756,13 @@ js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, Handle
|
|||
// than return true with desc incomplete, we fill out the missing
|
||||
// getter or setter with a null, following CompletePropertyDescriptor.
|
||||
if (desc.hasGetterObject()) {
|
||||
desc.setGetterObject(shape->getterObject());
|
||||
desc.setGetterObject(prop.shape()->getterObject());
|
||||
} else {
|
||||
desc.setGetterObject(nullptr);
|
||||
desc.attributesRef() |= JSPROP_GETTER;
|
||||
}
|
||||
if (desc.hasSetterObject()) {
|
||||
desc.setSetterObject(shape->setterObject());
|
||||
desc.setSetterObject(prop.shape()->setterObject());
|
||||
} else {
|
||||
desc.setSetterObject(nullptr);
|
||||
desc.attributesRef() |= JSPROP_SETTER;
|
||||
|
|
@ -1776,9 +1778,10 @@ js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, Handle
|
|||
desc.setSetter(nullptr);
|
||||
desc.attributesRef() &= ~JSPROP_SHARED;
|
||||
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
desc.value().set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
|
||||
} else {
|
||||
RootedShape shape(cx, prop.shape());
|
||||
if (!NativeGetExistingProperty(cx, obj, obj, shape, desc.value()))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2058,23 +2061,25 @@ NativeGetPropertyInline(JSContext* cx,
|
|||
typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
|
||||
{
|
||||
typename MaybeRooted<NativeObject*, allowGC>::RootType pobj(cx, obj);
|
||||
typename MaybeRooted<Shape*, allowGC>::RootType shape(cx);
|
||||
typename MaybeRooted<PropertyResult, allowGC>::RootType prop(cx);
|
||||
|
||||
// This loop isn't explicit in the spec algorithm. See the comment on step
|
||||
// 4.d below.
|
||||
for (;;) {
|
||||
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
|
||||
bool done;
|
||||
if (!LookupOwnPropertyInline<allowGC>(cx, pobj, id, &shape, &done))
|
||||
if (!LookupOwnPropertyInline<allowGC>(cx, pobj, id, &prop, &done))
|
||||
return false;
|
||||
|
||||
if (shape) {
|
||||
if (prop) {
|
||||
// Steps 5-8. Special case for dense elements because
|
||||
// GetExistingProperty doesn't support those.
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
vp.set(pobj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
|
||||
return true;
|
||||
}
|
||||
|
||||
typename MaybeRooted<Shape*, allowGC>::RootType shape(cx, prop.shape());
|
||||
return GetExistingProperty<allowGC>(cx, receiver, pobj, shape, vp);
|
||||
}
|
||||
|
||||
|
|
@ -2366,11 +2371,11 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
|
|||
*/
|
||||
static bool
|
||||
SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v,
|
||||
HandleValue receiver, HandleNativeObject pobj, HandleShape shape,
|
||||
HandleValue receiver, HandleNativeObject pobj, Handle<PropertyResult> prop,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
// Step 5 for dense elements.
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
// Step 5.a.
|
||||
if (pobj->getElementsHeader()->isFrozen())
|
||||
return result.fail(JSMSG_READ_ONLY);
|
||||
|
|
@ -2384,6 +2389,7 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa
|
|||
}
|
||||
|
||||
// Step 5 for all other properties.
|
||||
RootedShape shape(cx, prop.shape());
|
||||
if (shape->isDataDescriptor()) {
|
||||
// Step 5.a.
|
||||
if (!shape->writable())
|
||||
|
|
@ -2441,7 +2447,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
|
|||
// Step numbers below reference ES6 rev 27 9.1.9, the [[Set]] internal
|
||||
// method for ordinary objects. We substitute our own names for these names
|
||||
// used in the spec: O -> pobj, P -> id, ownDesc -> shape.
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
RootedNativeObject pobj(cx, obj);
|
||||
|
||||
// This loop isn't explicit in the spec algorithm. See the comment on step
|
||||
|
|
@ -2450,12 +2456,12 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
|
|||
for (;;) {
|
||||
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
|
||||
bool done;
|
||||
if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done))
|
||||
if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &prop, &done))
|
||||
return false;
|
||||
|
||||
if (shape) {
|
||||
if (prop) {
|
||||
// Steps 5-6.
|
||||
return SetExistingProperty(cx, obj, id, v, receiver, pobj, shape, result);
|
||||
return SetExistingProperty(cx, obj, id, v, receiver, pobj, prop, result);
|
||||
}
|
||||
|
||||
// Steps 4.a-b. The check for 'done' on this next line is tricky.
|
||||
|
|
@ -2513,12 +2519,12 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
ObjectOpResult& result)
|
||||
{
|
||||
// Steps 2-3.
|
||||
RootedShape shape(cx);
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
|
||||
Rooted<PropertyResult> prop(cx);
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop))
|
||||
return false;
|
||||
|
||||
// Step 4.
|
||||
if (!shape) {
|
||||
if (!prop) {
|
||||
// If no property call the class's delProperty hook, passing succeeded
|
||||
// as the result parameter. This always succeeds when there is no hook.
|
||||
return CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id, result);
|
||||
|
|
@ -2527,7 +2533,7 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
cx->runtime()->gc.poke();
|
||||
|
||||
// Step 6. Non-configurable property.
|
||||
if (GetShapeAttributes(obj, shape) & JSPROP_PERMANENT)
|
||||
if (GetPropertyAttributes(obj, prop) & JSPROP_PERMANENT)
|
||||
return result.failCantDelete();
|
||||
|
||||
if (!CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id, result))
|
||||
|
|
@ -2536,7 +2542,7 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
return true;
|
||||
|
||||
// Step 5.
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
// Typed array elements are non-configurable.
|
||||
MOZ_ASSERT(!obj->is<TypedArrayObject>());
|
||||
|
||||
|
|
|
|||
|
|
@ -1459,7 +1459,7 @@ extern bool
|
|||
NativeLookupOwnProperty(ExclusiveContext* cx,
|
||||
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
|
||||
typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp);
|
||||
|
||||
/*
|
||||
* Get a property from `receiver`, after having already done a lookup and found
|
||||
|
|
|
|||
|
|
@ -191,17 +191,17 @@ AutoRooterGetterSetter::AutoRooterGetterSetter(ExclusiveContext* cx, uint8_t att
|
|||
}
|
||||
|
||||
static inline uint8_t
|
||||
GetShapeAttributes(JSObject* obj, Shape* shape)
|
||||
GetPropertyAttributes(JSObject* obj, PropertyResult prop)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
if (IsImplicitDenseOrTypedArrayElement(shape)) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
if (obj->is<TypedArrayObject>())
|
||||
return JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
return obj->as<NativeObject>().getElementsHeader()->elementAttributes();
|
||||
}
|
||||
|
||||
return shape->attributes();
|
||||
return prop.shape()->attributes();
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
|||
|
|
@ -1771,3 +1771,10 @@ JS::ubi::Concrete<js::BaseShape>::size(mozilla::MallocSizeOf mallocSizeOf) const
|
|||
{
|
||||
return js::gc::Arena::thingSize(get().asTenured().getAllocKind());
|
||||
}
|
||||
|
||||
void
|
||||
PropertyResult::trace(JSTracer* trc)
|
||||
{
|
||||
if (isNativeProperty())
|
||||
TraceRoot(trc, &shape_, "PropertyResult::shape_");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1541,38 +1541,6 @@ Shape::matches(const StackShape& other) const
|
|||
other.rawGetter, other.rawSetter);
|
||||
}
|
||||
|
||||
// Property lookup hooks on objects are required to return a non-nullptr shape
|
||||
// to signify that the property has been found. For cases where the property is
|
||||
// not actually represented by a Shape, use a dummy value. This includes all
|
||||
// properties of non-native objects, and dense elements for native objects.
|
||||
// Use separate APIs for these two cases.
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static inline void
|
||||
MarkNonNativePropertyFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
propp.set(reinterpret_cast<Shape*>(1));
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static inline void
|
||||
MarkDenseOrTypedArrayElementFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
propp.set(reinterpret_cast<Shape*>(1));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsImplicitDenseOrTypedArrayElement(Shape* prop)
|
||||
{
|
||||
return prop == reinterpret_cast<Shape*>(1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsImplicitNonNativeProperty(Shape* prop)
|
||||
{
|
||||
return prop == reinterpret_cast<Shape*>(1);
|
||||
}
|
||||
|
||||
Shape*
|
||||
ReshapeForAllocKind(JSContext* cx, Shape* shape, TaggedProto proto,
|
||||
gc::AllocKind allocKind);
|
||||
|
|
|
|||
|
|
@ -720,10 +720,10 @@ UnboxedPlainObject::createWithProperties(ExclusiveContext* cx, HandleObjectGroup
|
|||
/* static */ bool
|
||||
UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp)
|
||||
MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
|
||||
MarkNonNativePropertyFound<CanGC>(propp);
|
||||
propp.setNonNativeProperty();
|
||||
objp.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -731,7 +731,7 @@ UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
|
|||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1411,10 +1411,10 @@ UnboxedArrayObject::containsProperty(ExclusiveContext* cx, jsid id)
|
|||
/* static */ bool
|
||||
UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp)
|
||||
MutableHandle<PropertyResult> propp)
|
||||
{
|
||||
if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
|
||||
MarkNonNativePropertyFound<CanGC>(propp);
|
||||
propp.setNonNativeProperty();
|
||||
objp.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1422,7 +1422,7 @@ UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
|
|||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
propp.setNotFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ class UnboxedPlainObject : public JSObject
|
|||
|
||||
static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp);
|
||||
MutableHandle<PropertyResult> propp);
|
||||
|
||||
static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
|
|
@ -378,7 +378,7 @@ class UnboxedArrayObject : public JSObject
|
|||
|
||||
static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
|
||||
HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp);
|
||||
MutableHandle<PropertyResult> propp);
|
||||
|
||||
static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue