diff options
author | Robin Burchell <robin.burchell@crimson.no> | 2017-01-18 14:12:51 +0100 |
---|---|---|
committer | Robin Burchell <robin.burchell@crimson.no> | 2017-01-26 15:26:28 +0000 |
commit | 040a70ea209eb8dcd980c077b625dc0b353db89a (patch) | |
tree | 48aaedb3bc7e235eba1bb4c56cf84fb096ab2107 /src/qml/jsruntime | |
parent | 92834d5631cd2ca2a6031f129429da9f34a54fbc (diff) |
jsruntime: Add a vtable hook on Object for instanceof
This will hopefully allow us to customize the behavior of
QmlTypeWrapper to allow comparison QMetaObject comparison against a
QObjectWrapper lhs (i.e. foo instanceof Item will hopefully be possible)
Task-number: QTBUG-24799
Change-Id: I780c8b424ec14d6ed6f93eeac46390e2fc920000
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 43 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 34 |
3 files changed, 56 insertions, 28 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index eb9cb80cee..2f664c6398 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1155,6 +1155,49 @@ uint Object::getLength(const Managed *m) return v->toUInt32(); } +// 'var' is 'V' in 15.3.5.3. +ReturnedValue Object::instanceOf(const Object *typeObject, const Value &var) +{ + QV4::ExecutionEngine *engine = typeObject->internalClass()->engine; + + // 15.3.5.3, Assume F is a Function object. + const FunctionObject *function = typeObject->as<FunctionObject>(); + if (!function) + return engine->throwTypeError(); + + Heap::FunctionObject *f = function->d(); + if (function->isBoundFunction()) + f = function->cast<BoundFunction>()->target(); + + // 15.3.5.3, 1: HasInstance can only be used on an object + const Object *lhs = var.as<Object>(); + if (!lhs) + return Encode(false); + + // 15.3.5.3, 2 + const Object *o = f->protoProperty(); + if (!o) // 15.3.5.3, 3 + return engine->throwTypeError(); + + Heap::Object *v = lhs->d(); + + // 15.3.5.3, 4 + while (v) { + // 15.3.5.3, 4, a + v = v->prototype; + + // 15.3.5.3, 4, b + if (!v) + break; // will return false + + // 15.3.5.3, 4, c + else if (o->d() == v) + return Encode(true); + } + + return Encode(false); +} + bool Object::setArrayLength(uint newLen) { Q_ASSERT(isArrayObject()); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 4a78690f47..6a543ae1a8 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -140,6 +140,7 @@ struct ObjectVTable void (*setLookup)(Managed *m, Lookup *l, const Value &v); uint (*getLength)(const Managed *m); void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); + ReturnedValue (*instanceOf)(const Object *typeObject, const Value &var); }; #define DEFINE_OBJECT_VTABLE_BASE(classname) \ @@ -159,7 +160,8 @@ const QV4::ObjectVTable classname::static_vtbl = \ getLookup, \ setLookup, \ getLength, \ - advanceIterator \ + advanceIterator, \ + instanceOf \ } #define DEFINE_OBJECT_VTABLE(classname) \ @@ -351,6 +353,8 @@ public: void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes) { vtable()->advanceIterator(this, it, name, index, p, attributes); } uint getLength() const { return vtable()->getLength(this); } + ReturnedValue instanceOf(const Value &var) const + { return vtable()->instanceOf(this, var); } inline void construct(Scope &scope, CallData *d) const { return vtable()->construct(this, scope, d); } @@ -372,6 +376,7 @@ protected: static void setLookup(Managed *m, Lookup *l, const Value &v); static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); static uint getLength(const Managed *m); + static ReturnedValue instanceOf(const Object *typeObject, const Value &var); private: ReturnedValue internalGet(String *name, bool *hasProperty) const; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 023a739e33..7f184f8221 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -343,35 +343,15 @@ ReturnedValue Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex) return Encode(engine->currentContext->deleteProperty(name)); } -QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &lval, const Value &rval) { - const FunctionObject *function = right.as<FunctionObject>(); - if (!function) - return engine->throwTypeError(); - - Heap::FunctionObject *f = function->d(); - if (function->isBoundFunction()) - f = function->cast<BoundFunction>()->target(); - - const Object *o = left.as<Object>(); - if (!o) - return Encode(false); - Heap::Object *v = o->d(); - - o = f->protoProperty(); - if (!o) - return engine->throwTypeError(); - - while (v) { - v = v->prototype; - - if (!v) - break; - else if (o->d() == v) - return Encode(true); - } + // 11.8.6, 5: rval must be an Object + const Object *rhs = rval.as<Object>(); + if (!rhs) + return engine->throwTypeError(); - return Encode(false); + // 11.8.6, 7: call "HasInstance", which we term instanceOf, and return the result. + return rhs->instanceOf(lval); } QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right) |