id_eval = newIdentifier(QStringLiteral("eval"));
emptyClass = new InternalClass(this);
- arrayClass = emptyClass->addMember(id_length);
+ arrayClass = emptyClass->addMember(id_length, Attr_ReadOnly);
initRootContext();
objectPrototype = new (memoryManager) ObjectPrototype(this);
Object *proto = scope->engine->newObject();
proto->defineDefaultProperty(scope->engine->id_constructor, Value::fromObject(this));
- PropertyDescriptor *pd = insertMember(scope->engine->id_prototype);
+ PropertyDescriptor *pd = insertMember(scope->engine->id_prototype, Attr_NotEnumerable|Attr_NotConfigurable);
pd->type = PropertyDescriptor::Data;
pd->writable = PropertyDescriptor::Enabled;
pd->enumerable = PropertyDescriptor::Disabled;
PropertyDescriptor pd = PropertyDescriptor::fromAccessor(thrower, thrower);
pd.configurable = PropertyDescriptor::Disabled;
pd.enumerable = PropertyDescriptor::Disabled;
- *insertMember(scope->engine->id_arguments) = pd;
- *insertMember(scope->engine->id_caller) = pd;
+ *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
+ *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
}
void BoundFunction::destroy(Managed *that)
namespace QQmlJS {
namespace VM {
-enum PropertyFlags {
- Writable = 0x1,
- Enumerable = 0x2,
- Configurable = 0x4
+enum {
+ Attr_Default = 0,
+ Attr_Accessor = 0x1,
+ Attr_NotWritable = 0x2,
+ Attr_NotEnumerable = 0x4,
+ Attr_NotConfigurable = 0x8,
+ Attr_ReadOnly = Attr_NotWritable|Attr_NotEnumerable|Attr_NotConfigurable,
+ Attr_Invalid = 0xff
};
+typedef uchar PropertyAttributes;
+
}
}
: engine(other.engine)
, propertyTable(other.propertyTable)
, nameMap(other.nameMap)
+ , propertyData(other.propertyData)
, transitions()
, size(other.size)
{
}
-InternalClass *InternalClass::addMember(String *string, uint *index)
+InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index)
{
engine->identifierCache->toIdentifier(string);
- uint id = string->identifier;
+ uint id = string->identifier | ((uint)data << 24);
assert(propertyTable.constFind(id) == propertyTable.constEnd());
} else {
// create a new class and add it to the tree
InternalClass *newClass = new InternalClass(*this);
- newClass->propertyTable.insert(id, size);
+ newClass->propertyTable.insert(string->identifier, size);
newClass->nameMap.append(string);
+ newClass->propertyData.append(data);
++newClass->size;
transitions.insert(id, newClass);
return newClass;
for (int i = 0; i < nameMap.size(); ++i) {
if (i == propIdx)
continue;
- object->internalClass = object->internalClass->addMember(nameMap.at(i));
+ object->internalClass = object->internalClass->addMember(nameMap.at(i), propertyData.at(i));
}
transitions.insert(toRemove, object->internalClass);
#include <QHash>
#include <QVector>
+#include <qv4global.h>
QT_BEGIN_NAMESPACE
ExecutionEngine *engine;
QHash<uint, uint> propertyTable; // id to valueIndex
QVector<String *> nameMap;
+
+ QVector<PropertyAttributes> propertyData;
+
QHash<int, InternalClass *> transitions; // id to next class, positive means add, negative delete
uint size;
InternalClass(ExecutionEngine *engine) : engine(engine), size(0) {}
- InternalClass *addMember(String *string, uint *index = 0);
+ InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0);
void removeMember(Object *object, uint id);
uint find(String *s);
if (!parseValue(&val))
return false;
- PropertyDescriptor *p = o->insertMember(context->engine->newIdentifier(key));
+ PropertyDescriptor *p = o->insertMember(context->engine->newIdentifier(key), Attr_Default);
p->type = PropertyDescriptor::Data;
p->writable = PropertyDescriptor::Enabled;
p->enumerable = PropertyDescriptor::Enabled;
Value (*getIndexed)(Managed *, ExecutionContext *ctx, uint index, bool *hasProperty);
void (*put)(Managed *, ExecutionContext *ctx, String *name, const Value &value);
void (*putIndexed)(Managed *, ExecutionContext *ctx, uint index, const Value &value);
- PropertyFlags (*query)(Managed *, ExecutionContext *ctx, String *name);
- PropertyFlags (*queryIndexed)(Managed *, ExecutionContext *ctx, uint index);
+ PropertyAttributes (*query)(Managed *, ExecutionContext *ctx, String *name);
+ PropertyAttributes (*queryIndexed)(Managed *, ExecutionContext *ctx, uint index);
bool (*deleteProperty)(Managed *m, ExecutionContext *ctx, String *name);
bool (*deleteIndexedProperty)(Managed *m, ExecutionContext *ctx, uint index);
const char *className;
void Object::defineDefaultProperty(String *name, Value value)
{
- PropertyDescriptor *pd = insertMember(name);
+ PropertyDescriptor *pd = insertMember(name, Attr_Default);
pd->type = PropertyDescriptor::Data;
pd->writable = PropertyDescriptor::Enabled;
pd->enumerable = PropertyDescriptor::Disabled;
void Object::defineReadonlyProperty(String *name, Value value)
{
- PropertyDescriptor *pd = insertMember(name);
+ PropertyDescriptor *pd = insertMember(name, Attr_ReadOnly);
pd->type = PropertyDescriptor::Data;
pd->writable = PropertyDescriptor::Disabled;
pd->enumerable = PropertyDescriptor::Disabled;
o->markArrayObjects();
}
-PropertyDescriptor *Object::insertMember(String *s)
+PropertyDescriptor *Object::insertMember(String *s, PropertyAttributes attributes)
{
uint idx;
- internalClass = internalClass->addMember(s, &idx);
+ internalClass = internalClass->addMember(s, attributes, &idx);
if (idx >= memberDataAlloc) {
memberDataAlloc = qMax((uint)8, 2*memberDataAlloc);
static_cast<Object *>(m)->internalPutIndexed(ctx, index, value);
}
-PropertyFlags Object::query(Managed *m, ExecutionContext *ctx, String *name)
+PropertyAttributes Object::query(Managed *m, ExecutionContext *ctx, String *name)
{
Object *that = static_cast<Object *>(m);
PropertyDescriptor *pd = that->__getPropertyDescriptor__(ctx, name);
if (!pd || pd->type == PropertyDescriptor::Generic)
- return PropertyFlags(0);
- return pd->propertyFlags();
+ return Attr_Invalid;
+ return pd->toPropertyAttributes();
}
-PropertyFlags Object::queryIndexed(Managed *m, ExecutionContext *ctx, uint index)
+PropertyAttributes Object::queryIndexed(Managed *m, ExecutionContext *ctx, uint index)
{
Object *that = static_cast<Object *>(m);
PropertyDescriptor *pd = that->__getPropertyDescriptor__(ctx, index);
if (!pd || pd->type == PropertyDescriptor::Generic)
- return PropertyFlags(0);
- return pd->propertyFlags();
+ return Attr_Invalid;
+ return pd->toPropertyAttributes();
}
bool Object::deleteProperty(Managed *m, ExecutionContext *ctx, String *name)
}
{
- PropertyDescriptor *p = insertMember(name);
+ PropertyDescriptor *p = insertMember(name, Attr_Default);
p->type = PropertyDescriptor::Data;
p->value = value;
p->configurable = PropertyDescriptor::Enabled;
if (!extensible)
goto reject;
// clause 4
- PropertyDescriptor *pd = insertMember(name);
+ PropertyDescriptor *pd = insertMember(name, desc->toPropertyAttributes());
*pd = *desc;
pd->fullyPopulated();
return true;
void defineReadonlyProperty(ExecutionEngine *engine, const QString &name, Value value);
void defineReadonlyProperty(String *name, Value value);
- PropertyDescriptor *insertMember(String *s);
+ PropertyDescriptor *insertMember(String *s, PropertyAttributes attributes);
// Array handling
static Value getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty);
static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value);
static void putIndexed(Managed *m, ExecutionContext *ctx, uint index, const Value &value);
- static PropertyFlags query(Managed *m, ExecutionContext *ctx, String *name);
- static PropertyFlags queryIndexed(Managed *m, ExecutionContext *ctx, uint index);
+ static PropertyAttributes query(Managed *m, ExecutionContext *ctx, String *name);
+ static PropertyAttributes queryIndexed(Managed *m, ExecutionContext *ctx, uint index);
static bool deleteProperty(Managed *m, ExecutionContext *ctx, String *name);
static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index);
#include "qv4global.h"
#include "qv4value.h"
+#include "qv4internalclass.h"
QT_BEGIN_NAMESPACE
struct FunctionObject;
-struct PropertyDescriptor {
+struct Property {
+ union {
+ Value value;
+ struct {
+ FunctionObject *get;
+ FunctionObject *set;
+ };
+ };
+};
+
+struct PropertyDescriptor : public Property
+{
enum Type {
Generic,
Data,
Disabled,
Enabled
};
- union {
- Value value;
- struct {
- FunctionObject *get;
- FunctionObject *set;
- };
- };
uint type : 8;
uint writable : 8;
uint enumerable : 8;
uint configurable : 8;
- PropertyFlags propertyFlags() {
- int f = 0;
- if (writable == Enabled)
- f |= Writable;
- if (configurable == Enabled)
- f |= Configurable;
- if (enumerable == Enabled)
- f |= Enumerable;
- return PropertyFlags(f);
- }
-
static inline PropertyDescriptor fromValue(Value v) {
PropertyDescriptor pd;
pd.value = v;
return pd;
}
+ PropertyAttributes toPropertyAttributes() const {
+ PropertyAttributes attrs = 0;
+ if (type == Accessor)
+ attrs |= Attr_Accessor;
+ else if (writable != Enabled)
+ attrs |= Attr_NotWritable;
+ if (enumerable != Enabled)
+ attrs |= Attr_NotEnumerable;
+ if (configurable != Enabled)
+ attrs |= Attr_NotConfigurable;
+ return attrs;
+ }
+
// Section 8.10
inline void fullyPopulated() {
if (type == Generic) {
{
}
-PropertyFlags RegExp::query(Managed *m, ExecutionContext *ctx, String *name)
+PropertyAttributes RegExp::query(Managed *m, ExecutionContext *ctx, String *name)
{
- return PropertyFlags(0);
+ return Attr_Invalid;
}
-PropertyFlags RegExp::queryIndexed(Managed *m, ExecutionContext *ctx, uint index)
+PropertyAttributes RegExp::queryIndexed(Managed *m, ExecutionContext *ctx, uint index)
{
- return PropertyFlags(0);
+ return Attr_Invalid;
}
bool RegExp::deleteProperty(Managed *m, ExecutionContext *ctx, String *name)
static Value getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty);
static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value);
static void putIndexed(Managed *m, ExecutionContext *ctx, uint index, const Value &value);
- static PropertyFlags query(Managed *m, ExecutionContext *ctx, String *name);
- static PropertyFlags queryIndexed(Managed *m, ExecutionContext *ctx, uint index);
+ static PropertyAttributes query(Managed *m, ExecutionContext *ctx, String *name);
+ static PropertyAttributes queryIndexed(Managed *m, ExecutionContext *ctx, uint index);
static bool deleteProperty(Managed *m, ExecutionContext *ctx, String *name);
static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index);
vtbl = &static_vtbl;
type = Type_RegExpObject;
- PropertyDescriptor *lastIndexProperty = insertMember(engine->newIdentifier(QStringLiteral("lastIndex")));
+ PropertyDescriptor *lastIndexProperty = insertMember(engine->newIdentifier(QStringLiteral("lastIndex")),
+ Attr_NotEnumerable|Attr_NotConfigurable);
lastIndexProperty->type = PropertyDescriptor::Data;
lastIndexProperty->writable = PropertyDescriptor::Enabled;
lastIndexProperty->enumerable = PropertyDescriptor::Disabled;
assert(o);
uint idx = name->asArrayIndex();
- PropertyDescriptor *pd = (idx != UINT_MAX) ? o->arrayInsert(idx) : o->insertMember(name);
+ PropertyDescriptor *pd = (idx != UINT_MAX) ? o->arrayInsert(idx) : o->insertMember(name, Attr_Default);
pd->value = val ? *val : Value::undefinedValue();
pd->type = PropertyDescriptor::Data;
pd->writable = PropertyDescriptor::Enabled;
assert(o);
uint idx = name->asArrayIndex();
- PropertyDescriptor *pd = (idx != UINT_MAX) ? o->arrayInsert(idx) : o->insertMember(name);
+ PropertyDescriptor *pd = (idx != UINT_MAX) ? o->arrayInsert(idx) : o->insertMember(name, Attr_Accessor);
pd->get = getter ? getter->asFunctionObject() : 0;
pd->set = setter ? setter->asFunctionObject() : 0;
pd->type = PropertyDescriptor::Accessor;
o->putIndexed(ctx, index, value);
}
-PropertyFlags String::query(Managed *m, ExecutionContext *ctx, String *name)
+PropertyAttributes String::query(Managed *m, ExecutionContext *ctx, String *name)
{
- return PropertyFlags(0);
+ return Attr_Invalid;
}
-PropertyFlags String::queryIndexed(Managed *m, ExecutionContext *ctx, uint index)
+PropertyAttributes String::queryIndexed(Managed *m, ExecutionContext *ctx, uint index)
{
String *that = static_cast<String *>(m);
- return (index < that->_text.length()) ? PropertyFlags(Enumerable) : PropertyFlags(0);
+ return (index < that->_text.length()) ? Attr_NotConfigurable|Attr_NotWritable : Attr_Invalid;
}
bool String::deleteProperty(Managed *m, ExecutionContext *ctx, String *name)
static Value getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty);
static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value);
static void putIndexed(Managed *m, ExecutionContext *ctx, uint index, const Value &value);
- static PropertyFlags query(Managed *m, ExecutionContext *ctx, String *name);
- static PropertyFlags queryIndexed(Managed *m, ExecutionContext *ctx, uint index);
+ static PropertyAttributes query(Managed *m, ExecutionContext *ctx, String *name);
+ static PropertyAttributes queryIndexed(Managed *m, ExecutionContext *ctx, uint index);
static bool deleteProperty(Managed *m, ExecutionContext *ctx, String *name);
static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index);
QQmlJS::VM::Object *o = ConstValuePtr(this)->asObject();
assert(o);
- VM::PropertyDescriptor *pd = o->insertMember(name->asVMString());
+ PropertyAttributes attrs = Attr_Accessor;
+ if (attribute & DontDelete)
+ attrs |= Attr_NotConfigurable;
+ if (attribute & DontEnum)
+ attrs |= Attr_NotEnumerable;
+ VM::PropertyDescriptor *pd = o->insertMember(name->asVMString(), attrs);
*pd = VM::PropertyDescriptor::fromAccessor(wrappedGetter, wrappedSetter);
pd->writable = VM::PropertyDescriptor::Undefined;
pd->configurable = attribute & DontDelete ? VM::PropertyDescriptor::Disabled : VM::PropertyDescriptor::Enabled;
m_template = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
foreach (const ObjectTemplate::Accessor &acc, m_template->m_accessors) {
- VM::PropertyDescriptor *pd = this->insertMember(acc.name->asVMString());
+ PropertyAttributes attrs = Attr_Accessor;
+ if (acc.attribute & DontDelete)
+ attrs |= Attr_NotConfigurable;
+ if (acc.attribute & DontEnum)
+ attrs |= Attr_NotEnumerable;
+ VM::PropertyDescriptor *pd = this->insertMember(acc.name->asVMString(), attrs);
*pd = VM::PropertyDescriptor::fromAccessor(acc.getter->vmValue().asFunctionObject(),
acc.setter->vmValue().asFunctionObject());
pd->writable = VM::PropertyDescriptor::Undefined;
void initProperties(Template *tmpl)
{
foreach (const Template::Property &p, tmpl->m_properties) {
- VM::PropertyDescriptor *pd = this->insertMember(p.name->asVMString());
+ PropertyAttributes attrs = Attr_Default;
+ if (p.attributes & DontDelete)
+ attrs |= Attr_NotConfigurable;
+ if (p.attributes & DontEnum)
+ attrs |= Attr_NotEnumerable;
+ if (p.attributes & ReadOnly)
+ attrs |= Attr_NotWritable;
+ VM::PropertyDescriptor *pd = this->insertMember(p.name->asVMString(), attrs);
*pd = VM::PropertyDescriptor::fromValue(p.value->vmValue());
pd->writable = p.attributes & ReadOnly ? VM::PropertyDescriptor::Disabled : VM::PropertyDescriptor::Enabled;
pd->configurable = p.attributes & DontDelete ? VM::PropertyDescriptor::Disabled : VM::PropertyDescriptor::Enabled;
BaseClass::putIndexed(m, ctx, index, value);
}
- static PropertyFlags propertyAttributesToFlags(const Handle<Value> &attr)
+ static PropertyAttributes propertyAttributesToFlags(const Handle<Value> &attr)
{
- int flags = 0;
+ PropertyAttributes flags = 0;
int intAttr = attr->ToInt32()->Value();
- if (!(intAttr & ReadOnly))
- flags |= VM::Writable;
- if (!(intAttr & DontDelete))
- flags |= VM::Configurable;
- if (!(intAttr & DontEnum))
- flags |= VM::Enumerable;
- return PropertyFlags(flags);
+ if (intAttr & ReadOnly)
+ flags |= VM::Attr_NotWritable;
+ if (intAttr & DontDelete)
+ flags |= VM::Attr_NotConfigurable;
+ if (intAttr & DontEnum)
+ flags |= VM::Attr_NotEnumerable;
+ return flags;
}
- static PropertyFlags query(VM::Managed *m, ExecutionContext *ctx, VM::String *name)
+ static PropertyAttributes query(VM::Managed *m, ExecutionContext *ctx, VM::String *name)
{
V4V8Object *that = static_cast<V4V8Object*>(m);
if (that->m_template->m_namedPropertyQuery) {
if (!result.IsEmpty())
return propertyAttributesToFlags(result);
}
- PropertyFlags flags = BaseClass::query(m, ctx, name);
+ PropertyAttributes flags = BaseClass::query(m, ctx, name);
if (flags == 0 && that->m_template->m_fallbackPropertySetter) {
Handle<Value> result = that->m_template->m_fallbackPropertyQuery(String::New(name), that->fallbackAccessorInfo());
if (!result.IsEmpty())
return flags;
}
- static PropertyFlags queryIndexed(VM::Managed *m, ExecutionContext *ctx, uint index)
+ static PropertyAttributes queryIndexed(VM::Managed *m, ExecutionContext *ctx, uint index)
{
V4V8Object *that = static_cast<V4V8Object*>(m);
if (that->m_template->m_indexedPropertyQuery) {