diff options
Diffstat (limited to 'src/qml/jsruntime/qv4object.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 9d6cb730a9..7dd0a247d6 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -736,6 +736,88 @@ ReturnedValue Object::virtualInstanceOf(const Object *typeObject, const Value &v return checkedInstanceOf(engine, function, var); } +ReturnedValue Object::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup) +{ + Heap::Object *obj = object->d(); + PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]); + if (name.isArrayIndex()) { + lookup->indexedLookup.index = name.asArrayIndex(); + lookup->getter = Lookup::getterIndexed; + return lookup->getter(lookup, engine, *object); + } + + auto index = obj->internalClass->findValueOrGetter(name); + if (index.isValid()) { + PropertyAttributes attrs = index.attrs; + uint nInline = obj->vtable()->nInlineProperties; + if (attrs.isData()) { + if (index.index < obj->vtable()->nInlineProperties) { + index.index += obj->vtable()->inlinePropertyOffset; + lookup->getter = Lookup::getter0Inline; + } else { + index.index -= nInline; + lookup->getter = Lookup::getter0MemberData; + } + } else { + lookup->getter = Lookup::getterAccessor; + } + lookup->objectLookup.ic = obj->internalClass; + lookup->objectLookup.offset = index.index; + return lookup->getter(lookup, engine, *object); + } + + lookup->protoLookup.protoId = obj->internalClass->protoId; + lookup->resolveProtoGetter(name, obj->prototype()); + return lookup->getter(lookup, engine, *object); +} + +bool Object::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value) +{ + Scope scope(engine); + ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]); + + Heap::InternalClass *c = object->internalClass(); + PropertyKey key = name->toPropertyKey(); + auto idx = c->findValueOrSetter(key); + if (idx.isValid()) { + if (object->isArrayObject() && idx.index == Heap::ArrayObject::LengthPropertyIndex) { + Q_ASSERT(!idx.attrs.isAccessor()); + lookup->setter = Lookup::arrayLengthSetter; + return lookup->setter(lookup, engine, *object, value); + } else if (idx.attrs.isData() && idx.attrs.isWritable()) { + lookup->objectLookup.ic = object->internalClass(); + lookup->objectLookup.offset = idx.index; + lookup->setter = idx.index < object->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0; + return lookup->setter(lookup, engine, *object, value); + } else { + // ### handle setter + lookup->setter = Lookup::setterFallback; + } + return lookup->setter(lookup, engine, *object, value); + } + + lookup->insertionLookup.protoId = c->protoId; + if (!object->put(key, value)) { + lookup->setter = Lookup::setterFallback; + return false; + } + + if (object->internalClass() == c) { + // ### setter in the prototype, should handle this + lookup->setter = Lookup::setterFallback; + return true; + } + idx = object->internalClass()->findValueOrSetter(key); + if (!idx.isValid() || idx.attrs.isAccessor()) { // ### can this even happen? + lookup->setter = Lookup::setterFallback; + return false; + } + lookup->insertionLookup.newClass = object->internalClass(); + lookup->insertionLookup.offset = idx.index; + lookup->setter = Lookup::setterInsert; + return true; +} + ReturnedValue Object::checkedInstanceOf(ExecutionEngine *engine, const FunctionObject *f, const Value &var) { Scope scope(engine); |