diff options
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 146 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup_p.h | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 37 | ||||
-rw-r--r-- | tests/manual/v4/TestExpectations | 3 |
4 files changed, 169 insertions, 33 deletions
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 94df9685e3..e66055653e 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -93,16 +93,58 @@ void Lookup::getterGeneric(QV4::Lookup *l, QV4::Value *result, const QV4::Value return; } - Value res; - if (Managed *m = object.asManaged()) { - res = m->get(l->name); - } else { - ExecutionContext *ctx = l->name->engine()->current; - Object *o = __qmljs_convert_to_object(ctx, object); - res = o->get(l->name); + ExecutionEngine *engine = l->name->engine(); + Object *proto; + switch (object.type()) { + case Value::Undefined_Type: + case Value::Null_Type: + engine->current->throwTypeError(); + case Value::Boolean_Type: + proto = engine->booleanClass->prototype; + break; + case Value::String_Type: + proto = engine->stringClass->prototype; + if (l->name == engine->id_length) { + // special case, as the property is on the object itself + l->getter = stringLengthGetter; + stringLengthGetter(l, result, object); + return; + } + break; + case Value::Integer_Type: + default: // Number + proto = engine->numberClass->prototype; } + + PropertyAttributes attrs; + Property *p = l->lookup(proto, &attrs); + if (p) { + l->type = object.type(); + l->proto = proto; + if (attrs.isData()) { + if (l->level == 0) + l->getter = Lookup::primitiveGetter0; + else if (l->level == 1) + l->getter = Lookup::primitiveGetter1; + if (result) + *result = p->value; + return; + } else { + if (l->level == 0) + l->getter = Lookup::primitiveGetterAccessor0; + else if (l->level == 1) + l->getter = Lookup::primitiveGetterAccessor1; + if (result) + *result = p->value; + Value res = proto->getValue(object, p, attrs); + if (result) + *result = res; + return; + } + } + if (result) - *result = res; + *result = Value::undefinedValue(); } void Lookup::getter0(Lookup *l, Value *result, const Value &object) @@ -225,6 +267,94 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object) } +void Lookup::primitiveGetter0(Lookup *l, Value *result, const Value &object) +{ + if (object.type() == l->type) { + Object *o = l->proto; + if (l->classList[0] == o->internalClass) { + if (result) + *result = o->memberData[l->index].value; + return; + } + } + l->getter = getterGeneric; + getterGeneric(l, result, object); +} + +void Lookup::primitiveGetter1(Lookup *l, Value *result, const Value &object) +{ + if (object.type() == l->type) { + Object *o = l->proto; + if (l->classList[0] == o->internalClass && + l->classList[1] == o->prototype()->internalClass) { + if (result) + *result = o->prototype()->memberData[l->index].value; + return; + } + } + l->getter = getterGeneric; + getterGeneric(l, result, object); +} + +void Lookup::primitiveGetterAccessor0(Lookup *l, Value *result, const Value &object) +{ + if (object.type() == l->type) { + Object *o = l->proto; + if (l->classList[0] == o->internalClass) { + Value res; + FunctionObject *getter = o->memberData[l->index].getter(); + if (!getter) { + res = Value::undefinedValue(); + } else { + CALLDATA(0); + d.thisObject = object; + res = getter->call(d); + } + if (result) + *result = res; + return; + } + } + l->getter = getterGeneric; + getterGeneric(l, result, object); +} + +void Lookup::primitiveGetterAccessor1(Lookup *l, Value *result, const Value &object) +{ + if (object.type() == l->type) { + Object *o = l->proto; + if (l->classList[0] == o->internalClass && + l->classList[1] == o->prototype()->internalClass) { + Value res; + FunctionObject *getter = o->prototype()->memberData[l->index].getter(); + if (!getter) { + res = Value::undefinedValue(); + } else { + CALLDATA(0); + d.thisObject = object; + res = getter->call(d); + } + if (result) + *result = res; + return; + } + } + l->getter = getterGeneric; + getterGeneric(l, result, object); +} + +void Lookup::stringLengthGetter(Lookup *l, Value *result, const Value &object) +{ + if (String *s = object.asString()) { + if (result) + *result = Value::fromUInt32(s->length()); + return; + } + l->getter = getterGeneric; + getterGeneric(l, result, object); +} + + void Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx, Value *result) { Object *o = ctx->engine->globalObject; diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 3763182e84..b37738dd92 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -59,7 +59,15 @@ struct Lookup { void (*globalGetter)(Lookup *l, ExecutionContext *ctx, Value *result); void (*setter)(Lookup *l, const Value &object, const Value &v); }; - InternalClass *classList[Size]; + union { + InternalClass *classList[Size]; + struct { + void *dummy0; + void *dummy1; + Object *proto; + unsigned type; + }; + }; int level; uint index; String *name; @@ -72,6 +80,12 @@ struct Lookup { static void getterAccessor1(Lookup *l, Value *result, const Value &object); static void getterAccessor2(Lookup *l, Value *result, const Value &object); + static void primitiveGetter0(Lookup *l, Value *result, const Value &object); + static void primitiveGetter1(Lookup *l, Value *result, const Value &object); + static void primitiveGetterAccessor0(Lookup *l, Value *result, const Value &object); + static void primitiveGetterAccessor1(Lookup *l, Value *result, const Value &object); + static void stringLengthGetter(Lookup *l, Value *result, const Value &object); + static void globalGetterGeneric(Lookup *l, ExecutionContext *ctx, Value *result); static void globalGetter0(Lookup *l, ExecutionContext *ctx, Value *result); static void globalGetter1(Lookup *l, ExecutionContext *ctx, Value *result); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 4f195670b2..33521efb02 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -808,19 +808,12 @@ void __qmljs_call_property(ExecutionContext *context, Value *result, const Value void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, const Value &thisObject, uint index, Value *args, int argc) { - Lookup *l = context->lookups + index; + Value func; - Object *baseObject; - if (thisObject.isObject()) - baseObject = thisObject.objectValue(); - else if (thisObject.isString()) - baseObject = context->engine->stringClass->prototype; - else - baseObject = __qmljs_convert_to_object(context, thisObject); + Lookup *l = context->lookups + index; + l->getter(l, &func, thisObject); - Value func; - l->getter(l, &func, Value::fromObject(baseObject)); - FunctionObject *o = func.asFunctionObject(); + Object *o = func.asObject(); if (!o) context->throwTypeError(); @@ -869,21 +862,21 @@ void __qmljs_call_value(ExecutionContext *context, Value *result, const Value *t void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc) { - Lookup *l = context->lookups + index; Value func; + + Lookup *l = context->lookups + index; l->globalGetter(l, context, &func); - if (Object *f = func.asObject()) { - CallData d; - d.args = args; - d.argc = argc; - Value res = f->construct(d); - if (result) - *result = res; - return; - } + Object *f = func.asObject(); + if (!f) + context->throwTypeError(); - context->throwTypeError(); + CallData d; + d.args = args; + d.argc = argc; + Value res = f->construct(d); + if (result) + *result = res; } diff --git a/tests/manual/v4/TestExpectations b/tests/manual/v4/TestExpectations index e1c228db8e..a5270c369f 100644 --- a/tests/manual/v4/TestExpectations +++ b/tests/manual/v4/TestExpectations @@ -3,7 +3,6 @@ 15.2.3.6-2-17-1 failing -10.4.3-1-104 failing 10.4.3-1-106 failing 11.2.3-3_3 failing S13_A15_T4 failing @@ -18,4 +17,4 @@ S15.2.4.4_A14 failing Sbp_12.5_A9_T3 failing Sbp_12.6.1_A13_T3 failing Sbp_12.6.2_A13_T3 failing -Sbp_12.6.4_A13_T3 failing +Sbp_12.6.4_A13_T3 failing
\ No newline at end of file |