Make Property uses GC safe
Change-Id: I5aa41a07a2d25e5c8a2d64bfa58a55fcd7aaf77e Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
parent
965fac4418
commit
74c658bb63
|
|
@ -142,7 +142,7 @@ bool QJSValueIterator::next()
|
|||
return false;
|
||||
d_ptr->currentName = d_ptr->nextName;
|
||||
d_ptr->currentIndex = d_ptr->nextIndex;
|
||||
d_ptr->currentProperty.copy(d_ptr->nextProperty, d_ptr->nextAttributes);
|
||||
d_ptr->currentProperty.copy(&d_ptr->nextProperty, d_ptr->nextAttributes);
|
||||
d_ptr->currentAttributes = d_ptr->nextAttributes;
|
||||
|
||||
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
|
||||
|
|
|
|||
|
|
@ -48,10 +48,12 @@ public:
|
|||
|
||||
QJSValue value;
|
||||
QV4::PersistentValue iterator;
|
||||
// ### GC
|
||||
QV4::Property currentProperty;
|
||||
QV4::PropertyAttributes currentAttributes;
|
||||
QV4::StringValue currentName;
|
||||
uint currentIndex;
|
||||
// ### GC
|
||||
QV4::Property nextProperty;
|
||||
QV4::PropertyAttributes nextAttributes;
|
||||
QV4::StringValue nextName;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ void ArgumentsObject::fullyCreate()
|
|||
d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
|
||||
for (uint i = 0; i < (uint)numAccessors; ++i) {
|
||||
mappedArguments()->data[i] = context()->callData->args[i];
|
||||
arraySet(i, context()->engine->argumentsAccessors[i], Attr_Accessor);
|
||||
arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
|
||||
}
|
||||
arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors);
|
||||
for (uint i = numAccessors; i < argCount; ++i)
|
||||
|
|
@ -97,13 +97,13 @@ void ArgumentsObject::fullyCreate()
|
|||
d()->fullyCreated = true;
|
||||
}
|
||||
|
||||
bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, const Property &desc, PropertyAttributes attrs)
|
||||
bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs)
|
||||
{
|
||||
fullyCreate();
|
||||
|
||||
Scope scope(engine);
|
||||
Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
|
||||
Property map;
|
||||
ScopedProperty map(scope);
|
||||
PropertyAttributes mapAttrs;
|
||||
bool isMapped = false;
|
||||
uint numAccessors = qMin((int)context()->function->formalParameterCount(), context()->realArgumentCount);
|
||||
|
|
@ -114,7 +114,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
|
|||
if (isMapped) {
|
||||
Q_ASSERT(arrayData());
|
||||
mapAttrs = arrayData()->attributes(index);
|
||||
map.copy(*pd, mapAttrs);
|
||||
map->copy(pd, mapAttrs);
|
||||
setArrayAttributes(index, Attr_Data);
|
||||
pd = arrayData()->getProperty(index);
|
||||
pd->value = mappedArguments()->data[index];
|
||||
|
|
@ -127,10 +127,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
|
|||
|
||||
if (isMapped && attrs.isData()) {
|
||||
Q_ASSERT(arrayData());
|
||||
ScopedFunctionObject setter(scope, map.setter());
|
||||
ScopedFunctionObject setter(scope, map->setter());
|
||||
ScopedCallData callData(scope, 1);
|
||||
callData->thisObject = this->asReturnedValue();
|
||||
callData->args[0] = desc.value;
|
||||
callData->args[0] = desc->value;
|
||||
setter->call(callData);
|
||||
|
||||
if (attrs.isWritable()) {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ struct ArgumentsObject: Object {
|
|||
!static_cast<ArgumentsObject *>(m)->context()->strictMode;
|
||||
}
|
||||
|
||||
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property &desc, PropertyAttributes attrs);
|
||||
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
|
||||
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
|
||||
static void putIndexed(Managed *m, uint index, const ValueRef value);
|
||||
static bool deleteIndexedProperty(Managed *m, uint index);
|
||||
|
|
|
|||
|
|
@ -784,7 +784,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const ValueRef
|
|||
thisObject->initSparseArray();
|
||||
while (n != sparse->sparse()->end()) {
|
||||
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
|
||||
thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
|
||||
thisObject->arraySet(n->value, reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
|
||||
|
||||
n = n->nextNode();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
|
|||
|
||||
if (activation->hasProperty(name))
|
||||
return;
|
||||
Property desc(Primitive::undefinedValue());
|
||||
ScopedProperty desc(scope);
|
||||
PropertyAttributes attrs(Attr_Data);
|
||||
attrs.setConfigurable(deletable);
|
||||
activation->__defineOwnProperty__(scope.engine, name, desc, attrs);
|
||||
|
|
|
|||
|
|
@ -464,7 +464,9 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
|
|||
f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
|
||||
|
||||
if (scope->d()->strictMode) {
|
||||
Property pd(s.engine->thrower, s.engine->thrower);
|
||||
ScopedProperty pd(s);
|
||||
pd->value = s.engine->thrower;
|
||||
pd->set = s.engine->thrower;
|
||||
f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
|
||||
f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
|
||||
}
|
||||
|
|
@ -632,9 +634,9 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb
|
|||
len = 0;
|
||||
f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
|
||||
|
||||
ExecutionEngine *v4 = s.engine;
|
||||
|
||||
Property pd(v4->thrower, v4->thrower);
|
||||
ScopedProperty pd(s);
|
||||
pd->value = s.engine->thrower;
|
||||
pd->set = s.engine->thrower;
|
||||
f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
|
||||
f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ void Object::ensureMemberIndex(uint idx)
|
|||
d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx);
|
||||
}
|
||||
|
||||
void Object::insertMember(String *s, const Property &p, PropertyAttributes attributes)
|
||||
void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes)
|
||||
{
|
||||
uint idx;
|
||||
InternalClass::addMember(this, s, attributes, &idx);
|
||||
|
|
@ -212,10 +212,10 @@ void Object::insertMember(String *s, const Property &p, PropertyAttributes attri
|
|||
if (attributes.isAccessor()) {
|
||||
setHasAccessorProperty();
|
||||
Property *pp = propertyAt(idx);
|
||||
pp->value = p.value;
|
||||
pp->set = p.set;
|
||||
pp->value = p->value;
|
||||
pp->set = p->set;
|
||||
} else {
|
||||
d()->memberData->data[idx] = p.value;
|
||||
d()->memberData->data[idx] = p->value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +540,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
|
|||
it->arrayIndex = k + 1;
|
||||
*index = k;
|
||||
*attrs = a;
|
||||
pd->copy(*p, a);
|
||||
pd->copy(p, a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -577,7 +577,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
|
|||
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
|
||||
*name = m->engine()->newString(n->string);
|
||||
*attrs = a;
|
||||
pd->copy(*p, a);
|
||||
pd->copy(p, a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -846,7 +846,7 @@ bool Object::internalDeleteIndexedProperty(uint index)
|
|||
}
|
||||
|
||||
// Section 8.12.9
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Property &p, PropertyAttributes attrs)
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs)
|
||||
{
|
||||
uint idx = name->asArrayIndex();
|
||||
if (idx != UINT_MAX)
|
||||
|
|
@ -863,16 +863,16 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
|
|||
Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length));
|
||||
Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex);
|
||||
cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex;
|
||||
if (attrs.isEmpty() || p.isSubset(attrs, *lp, *cattrs))
|
||||
if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs))
|
||||
return true;
|
||||
if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
|
||||
goto reject;
|
||||
bool succeeded = true;
|
||||
if (attrs.type() == PropertyAttributes::Data) {
|
||||
bool ok;
|
||||
uint l = p.value.asArrayLength(&ok);
|
||||
uint l = p->value.asArrayLength(&ok);
|
||||
if (!ok) {
|
||||
ScopedValue v(scope, p.value);
|
||||
ScopedValue v(scope, p->value);
|
||||
engine->throwRangeError(v);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -897,9 +897,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
|
|||
if (!isExtensible())
|
||||
goto reject;
|
||||
// clause 4
|
||||
Property pd;
|
||||
pd.copy(p, attrs);
|
||||
pd.fullyPopulated(&attrs);
|
||||
ScopedProperty pd(scope);
|
||||
pd->copy(p, attrs);
|
||||
pd->fullyPopulated(&attrs);
|
||||
insertMember(name, pd, attrs);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -911,7 +911,7 @@ reject:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs)
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
|
||||
{
|
||||
// 15.4.5.1, 4b
|
||||
if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable())
|
||||
|
|
@ -927,7 +927,7 @@ reject:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs)
|
||||
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
|
||||
{
|
||||
Property *current = 0;
|
||||
|
||||
|
|
@ -943,12 +943,12 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
|
|||
if (!isExtensible())
|
||||
goto reject;
|
||||
// clause 4
|
||||
Property pp;
|
||||
pp.copy(p, attrs);
|
||||
pp.fullyPopulated(&attrs);
|
||||
Scope scope(engine);
|
||||
ScopedProperty pp(scope);
|
||||
pp->copy(p, attrs);
|
||||
pp->fullyPopulated(&attrs);
|
||||
if (attrs == Attr_Data) {
|
||||
Scope scope(engine);
|
||||
ScopedValue v(scope, pp.value);
|
||||
ScopedValue v(scope, pp->value);
|
||||
arraySet(index, v);
|
||||
} else {
|
||||
arraySet(index, pp, attrs);
|
||||
|
|
@ -963,7 +963,7 @@ reject:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property &p, PropertyAttributes attrs)
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs)
|
||||
{
|
||||
// clause 5
|
||||
if (attrs.isEmpty())
|
||||
|
|
@ -980,7 +980,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
|
|||
}
|
||||
|
||||
// clause 6
|
||||
if (p.isSubset(attrs, *current, cattrs))
|
||||
if (p->isSubset(attrs, current, cattrs))
|
||||
return true;
|
||||
|
||||
// clause 7
|
||||
|
|
@ -1026,15 +1026,15 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
|
|||
}
|
||||
} else if (cattrs.isData() && attrs.isData()) { // clause 10
|
||||
if (!cattrs.isConfigurable() && !cattrs.isWritable()) {
|
||||
if (attrs.isWritable() || !current->value.sameValue(p.value))
|
||||
if (attrs.isWritable() || !current->value.sameValue(p->value))
|
||||
goto reject;
|
||||
}
|
||||
} else { // clause 10
|
||||
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
|
||||
if (!cattrs.isConfigurable()) {
|
||||
if (!p.value.isEmpty() && current->value.val != p.value.val)
|
||||
if (!p->value.isEmpty() && current->value.val != p->value.val)
|
||||
goto reject;
|
||||
if (!p.set.isEmpty() && current->set.val != p.set.val)
|
||||
if (!p->set.isEmpty() && current->set.val != p->set.val)
|
||||
goto reject;
|
||||
}
|
||||
}
|
||||
|
|
@ -1057,7 +1057,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
|
|||
}
|
||||
|
||||
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property &p, PropertyAttributes attrs)
|
||||
bool Object::__defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs)
|
||||
{
|
||||
Scope scope(engine);
|
||||
ScopedString s(scope, engine->newString(name));
|
||||
|
|
|
|||
|
|
@ -93,11 +93,11 @@ struct Q_QML_EXPORT Object: Managed {
|
|||
bool hasOwnProperty(String *name) const;
|
||||
bool hasOwnProperty(uint index) const;
|
||||
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property &p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property &p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property &p, PropertyAttributes attrs);
|
||||
bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
|
||||
bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs);
|
||||
bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
|
||||
|
||||
//
|
||||
// helpers
|
||||
|
|
@ -131,10 +131,12 @@ struct Q_QML_EXPORT Object: Managed {
|
|||
}
|
||||
|
||||
void insertMember(String *s, const ValueRef v, PropertyAttributes attributes = Attr_Data) {
|
||||
Property p(*v);
|
||||
Scope scope(engine());
|
||||
ScopedProperty p(scope);
|
||||
p->value = *v;
|
||||
insertMember(s, p, attributes);
|
||||
}
|
||||
void insertMember(String *s, const Property &p, PropertyAttributes attributes);
|
||||
void insertMember(String *s, const Property *p, PropertyAttributes attributes);
|
||||
|
||||
inline ExecutionEngine *engine() const { return internalClass()->engine; }
|
||||
|
||||
|
|
@ -152,7 +154,7 @@ public:
|
|||
bool setArrayLength(uint newLen);
|
||||
void setArrayLengthUnchecked(uint l);
|
||||
|
||||
void arraySet(uint index, const Property &p, PropertyAttributes attributes = Attr_Data);
|
||||
void arraySet(uint index, const Property *p, PropertyAttributes attributes = Attr_Data);
|
||||
void arraySet(uint index, ValueRef value);
|
||||
|
||||
bool arrayPut(uint index, ValueRef value) {
|
||||
|
|
@ -361,7 +363,7 @@ inline void Object::push_back(const ValueRef v)
|
|||
setArrayLengthUnchecked(idx + 1);
|
||||
}
|
||||
|
||||
inline void Object::arraySet(uint index, const Property &p, PropertyAttributes attributes)
|
||||
inline void Object::arraySet(uint index, const Property *p, PropertyAttributes attributes)
|
||||
{
|
||||
// ### Clean up
|
||||
arrayCreate();
|
||||
|
|
@ -375,9 +377,9 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a
|
|||
}
|
||||
setArrayAttributes(index, attributes);
|
||||
Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
|
||||
pd->value = p.value;
|
||||
pd->value = p->value;
|
||||
if (attributes.isAccessor())
|
||||
pd->set = p.set;
|
||||
pd->set = p->set;
|
||||
if (isArrayObject() && index >= getLength())
|
||||
setArrayLengthUnchecked(index + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,15 +135,15 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
|
|||
return Encode::null();
|
||||
|
||||
PropertyAttributes attrs;
|
||||
Property p;
|
||||
uint index;
|
||||
Scope scope(object->engine());
|
||||
ScopedProperty p(scope);
|
||||
ScopedString name(scope);
|
||||
next(name.getRef(), &index, &p, &attrs);
|
||||
next(name.getRef(), &index, p, &attrs);
|
||||
if (attrs.isEmpty())
|
||||
return Encode::null();
|
||||
|
||||
value = object->objectValue()->getValue(&p, attrs);
|
||||
value = object->objectValue()->getValue(p, attrs);
|
||||
|
||||
if (!!name)
|
||||
return name->asReturnedValue();
|
||||
|
|
@ -157,15 +157,15 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
|
|||
return Encode::null();
|
||||
|
||||
PropertyAttributes attrs;
|
||||
Property p;
|
||||
uint index;
|
||||
Scope scope(object->engine());
|
||||
ScopedProperty p(scope);
|
||||
ScopedString name(scope);
|
||||
next(name.getRef(), &index, &p, &attrs);
|
||||
next(name.getRef(), &index, p, &attrs);
|
||||
if (attrs.isEmpty())
|
||||
return Encode::null();
|
||||
|
||||
value = object->objectValue()->getValue(&p, attrs);
|
||||
value = object->objectValue()->getValue(p, attrs);
|
||||
|
||||
if (!!name)
|
||||
return name->asReturnedValue();
|
||||
|
|
@ -179,12 +179,11 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
|
|||
return Encode::null();
|
||||
|
||||
PropertyAttributes attrs;
|
||||
// ### GC
|
||||
Property p;
|
||||
uint index;
|
||||
Scope scope(object->engine());
|
||||
ScopedProperty p(scope);
|
||||
ScopedString name(scope);
|
||||
next(name.getRef(), &index, &p, &attrs);
|
||||
next(name.getRef(), &index, p, &attrs);
|
||||
if (attrs.isEmpty())
|
||||
return Encode::null();
|
||||
|
||||
|
|
|
|||
|
|
@ -109,8 +109,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
|
|||
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
|
||||
|
||||
ScopedContext global(scope, scope.engine->rootContext());
|
||||
Property p(ScopedFunctionObject(scope, BuiltinFunction::create(global, v4->id___proto__, method_get_proto)),
|
||||
ScopedFunctionObject(scope, BuiltinFunction::create(global, v4->id___proto__, method_set_proto)));
|
||||
ScopedProperty p(scope);
|
||||
p->value = BuiltinFunction::create(global, v4->id___proto__, method_get_proto);
|
||||
p->set = BuiltinFunction::create(global, v4->id___proto__, method_set_proto);
|
||||
insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
|
||||
}
|
||||
|
||||
|
|
@ -185,9 +186,9 @@ ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx)
|
|||
return Encode::undefined();
|
||||
|
||||
ScopedValue attributes(scope, ctx->argument(2));
|
||||
Property pd;
|
||||
ScopedProperty pd(scope);
|
||||
PropertyAttributes attrs;
|
||||
toPropertyDescriptor(scope.engine, attributes, &pd, &attrs);
|
||||
toPropertyDescriptor(scope.engine, attributes, pd, &attrs);
|
||||
if (scope.engine->hasException)
|
||||
return Encode::undefined();
|
||||
|
||||
|
|
@ -211,17 +212,17 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
|
|||
|
||||
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
|
||||
ScopedString name(scope);
|
||||
ScopedProperty pd(scope);
|
||||
ScopedProperty n(scope);
|
||||
while (1) {
|
||||
uint index;
|
||||
PropertyAttributes attrs;
|
||||
Property pd;
|
||||
it.next(name.getRef(), &index, &pd, &attrs);
|
||||
it.next(name.getRef(), &index, pd, &attrs);
|
||||
if (attrs.isEmpty())
|
||||
break;
|
||||
Property n;
|
||||
PropertyAttributes nattrs;
|
||||
val = o->getValue(&pd, attrs);
|
||||
toPropertyDescriptor(scope.engine, val, &n, &nattrs);
|
||||
val = o->getValue(pd, attrs);
|
||||
toPropertyDescriptor(scope.engine, val, n, &nattrs);
|
||||
if (scope.engine->hasException)
|
||||
return Encode::undefined();
|
||||
bool ok;
|
||||
|
|
@ -491,9 +492,9 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
|
|||
o = ctx->d()->engine->globalObject();
|
||||
}
|
||||
|
||||
Property pd;
|
||||
pd.value = f;
|
||||
pd.set = Primitive::emptyValue();
|
||||
ScopedProperty pd(scope);
|
||||
pd->value = f;
|
||||
pd->set = Primitive::emptyValue();
|
||||
o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
|
@ -519,9 +520,9 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
|
|||
o = ctx->d()->engine->globalObject();
|
||||
}
|
||||
|
||||
Property pd;
|
||||
pd.value = Primitive::emptyValue();
|
||||
pd.set = f;
|
||||
ScopedProperty pd(scope);
|
||||
pd->value = Primitive::emptyValue();
|
||||
pd->set = f;
|
||||
o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
|
@ -641,26 +642,26 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, c
|
|||
ScopedObject o(scope, engine->newObject());
|
||||
ScopedString s(scope);
|
||||
|
||||
Property pd;
|
||||
ScopedProperty pd(scope);
|
||||
if (attrs.isData()) {
|
||||
pd.value = desc->value;
|
||||
pd->value = desc->value;
|
||||
s = engine->newString(QStringLiteral("value"));
|
||||
o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
|
||||
pd.value = Primitive::fromBoolean(attrs.isWritable());
|
||||
pd->value = Primitive::fromBoolean(attrs.isWritable());
|
||||
s = engine->newString(QStringLiteral("writable"));
|
||||
o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
|
||||
} else {
|
||||
pd.value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
|
||||
pd->value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
|
||||
s = engine->newString(QStringLiteral("get"));
|
||||
o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
|
||||
pd.value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
|
||||
pd->value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
|
||||
s = engine->newString(QStringLiteral("set"));
|
||||
o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
|
||||
}
|
||||
pd.value = Primitive::fromBoolean(attrs.isEnumerable());
|
||||
pd->value = Primitive::fromBoolean(attrs.isEnumerable());
|
||||
s = engine->newString(QStringLiteral("enumerable"));
|
||||
o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
|
||||
pd.value = Primitive::fromBoolean(attrs.isConfigurable());
|
||||
pd->value = Primitive::fromBoolean(attrs.isConfigurable());
|
||||
s = engine->newString(QStringLiteral("configurable"));
|
||||
o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
|
||||
|
||||
|
|
|
|||
|
|
@ -68,18 +68,18 @@ struct Property {
|
|||
return pd;
|
||||
}
|
||||
|
||||
inline bool isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const;
|
||||
inline void merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs);
|
||||
inline bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const;
|
||||
inline void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs);
|
||||
|
||||
inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; }
|
||||
inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
|
||||
inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
|
||||
inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); }
|
||||
|
||||
void copy(const Property &other, PropertyAttributes attrs) {
|
||||
value = other.value;
|
||||
void copy(const Property *other, PropertyAttributes attrs) {
|
||||
value = other->value;
|
||||
if (attrs.isAccessor())
|
||||
set = other.set;
|
||||
set = other->set;
|
||||
}
|
||||
|
||||
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
|
||||
|
|
@ -98,7 +98,7 @@ private:
|
|||
Property &operator=(const Property &);
|
||||
};
|
||||
|
||||
inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const
|
||||
inline bool Property::isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
|
||||
{
|
||||
if (attrs.type() != PropertyAttributes::Generic && attrs.type() != otherAttrs.type())
|
||||
return false;
|
||||
|
|
@ -108,18 +108,18 @@ inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &
|
|||
return false;
|
||||
if (attrs.hasWritable() && attrs.isWritable() != otherAttrs.isWritable())
|
||||
return false;
|
||||
if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other.value))
|
||||
if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other->value))
|
||||
return false;
|
||||
if (attrs.type() == PropertyAttributes::Accessor) {
|
||||
if (value.heapObject() != other.value.heapObject())
|
||||
if (value.heapObject() != other->value.heapObject())
|
||||
return false;
|
||||
if (set.heapObject() != other.set.heapObject())
|
||||
if (set.heapObject() != other->set.heapObject())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Property::merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs)
|
||||
inline void Property::merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs)
|
||||
{
|
||||
if (otherAttrs.hasEnumerable())
|
||||
attrs.setEnumerable(otherAttrs.isEnumerable());
|
||||
|
|
@ -129,13 +129,13 @@ inline void Property::merge(PropertyAttributes &attrs, const Property &other, Pr
|
|||
attrs.setWritable(otherAttrs.isWritable());
|
||||
if (otherAttrs.type() == PropertyAttributes::Accessor) {
|
||||
attrs.setType(PropertyAttributes::Accessor);
|
||||
if (!other.value.isEmpty())
|
||||
value = other.value;
|
||||
if (!other.set.isEmpty())
|
||||
set = other.set;
|
||||
if (!other->value.isEmpty())
|
||||
value = other->value;
|
||||
if (!other->set.isEmpty())
|
||||
set = other->set;
|
||||
} else if (otherAttrs.type() == PropertyAttributes::Data){
|
||||
attrs.setType(PropertyAttributes::Data);
|
||||
value = other.value;
|
||||
value = other->value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -501,10 +501,13 @@ struct ScopedProperty
|
|||
ScopedProperty(Scope &scope)
|
||||
{
|
||||
property = reinterpret_cast<Property*>(scope.alloc(sizeof(Property) / sizeof(Value)));
|
||||
property->value = Encode::undefined();
|
||||
property->set = Encode::undefined();
|
||||
}
|
||||
|
||||
Property *operator->() { return property; }
|
||||
operator const Property &() { return *property; }
|
||||
operator const Property *() const { return property; }
|
||||
operator Property *() { return property; }
|
||||
|
||||
Property *property;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String
|
|||
Property *pd = s->__getOwnProperty__(*index, &a);
|
||||
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
|
||||
*attrs = a;
|
||||
p->copy(*pd, a);
|
||||
p->copy(pd, a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue