diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-06-22 12:32:13 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-26 10:04:18 +0000 |
commit | eae4756f74d70de46d9345ece54345f597bc1929 (patch) | |
tree | 3bd9de778a4a035a79595ed160c7b474a03695ec | |
parent | e9b3bdb96e008060a0e78815a3995015e5e4598d (diff) |
Add a MemberFunction function object
Member functions in ES7 can not be called as constructors and
will throw a type error when trying.
Some more fixes are needed here, as they also do not have a
prototype property.
Change-Id: Ieb920163acaa68d4ff0ff73ae4c1015e883b406f
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4enginebase_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 35 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 |
5 files changed, 46 insertions, 10 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 657c267f7c..bdf1c93d0c 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -343,6 +343,10 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) classes[Class_ScriptFunction] = ic->d(); ic = ic->changeVTable(ConstructorFunction::staticVTable()); classes[Class_ConstructorFunction] = ic->d(); + ic = ic->changeVTable(MemberFunction::staticVTable()); + classes[Class_MemberFunction] = ic->d(); + ic = ic->changeVTable(GeneratorFunction::staticVTable()); + classes[Class_MemberFunction] = ic->d(); ic = ic->changeVTable(GeneratorFunction::staticVTable()); classes[Class_GeneratorFunction] = ic->d(); classes[Class_ObjectProto] = classes[Class_Object]->addMember(id_constructor()->identifier(), Attr_NotEnumerable, &index); diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h index 3e7aaca6a7..645f8e375f 100644 --- a/src/qml/jsruntime/qv4enginebase_p.h +++ b/src/qml/jsruntime/qv4enginebase_p.h @@ -106,6 +106,7 @@ struct Q_QML_EXPORT EngineBase { Class_SymbolObject, Class_ScriptFunction, Class_ConstructorFunction, + Class_MemberFunction, Class_ObjectProto, Class_RegExp, Class_RegExpObject, diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 589ed8fded..f73d6eef43 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -145,20 +145,25 @@ void FunctionObject::init(String *n, bool createProto) Scope s(internalClass()->engine); ScopedValue protectThis(s, this); - Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()->identifier()) == Heap::FunctionObject::Index_Prototype); - if (createProto) { - ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto))); - Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->find(s.engine->id_constructor()->identifier()) == Heap::FunctionObject::Index_ProtoConstructor); - proto->setProperty(Heap::FunctionObject::Index_ProtoConstructor, d()); - setProperty(Heap::FunctionObject::Index_Prototype, proto); - } else { - setProperty(Heap::FunctionObject::Index_Prototype, Primitive::undefinedValue()); - } + if (createProto) + createDefaultPrototypeProperty(); if (n) defineReadonlyConfigurableProperty(s.engine->id_name(), *n); } +void FunctionObject::createDefaultPrototypeProperty() +{ + Scope s(this); + + Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()->identifier()) == Heap::FunctionObject::Index_Prototype); + Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->find(s.engine->id_constructor()->identifier()) == Heap::FunctionObject::Index_ProtoConstructor); + + ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto))); + proto->setProperty(Heap::FunctionObject::Index_ProtoConstructor, d()); + setProperty(Heap::FunctionObject::Index_Prototype, proto); +} + ReturnedValue FunctionObject::name() const { return get(scope()->internalClass->engine->id_name()); @@ -184,6 +189,11 @@ Heap::FunctionObject *FunctionObject::createConstructorFunction(ExecutionContext return scope->engine()->memoryManager->allocate<ConstructorFunction>(scope, function); } +Heap::FunctionObject *FunctionObject::createMemberFunction(ExecutionContext *scope, Function *function) +{ + return scope->engine()->memoryManager->allocate<MemberFunction>(scope, function); +} + Heap::FunctionObject *FunctionObject::createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, jsCallFunction code, int argumentCount) { Scope scope(engine); @@ -502,6 +512,13 @@ ReturnedValue ConstructorFunction::call(const FunctionObject *f, const Value *, return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|")); } +DEFINE_OBJECT_VTABLE(MemberFunction); + +ReturnedValue MemberFunction::callAsConstructor(const FunctionObject *f, const Value *, int) +{ + return f->engine()->throwTypeError(QStringLiteral("Function is not a constructor.")); +} + DEFINE_OBJECT_VTABLE(DefaultClassConstructorFunction); ReturnedValue DefaultClassConstructorFunction::callAsConstructor(const FunctionObject *f, const Value *, int) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 7a7c86a6c3..3245137ac9 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -124,6 +124,10 @@ struct ConstructorFunction : ScriptFunction { }; +struct MemberFunction : ScriptFunction +{ +}; + struct DefaultClassConstructorFunction : FunctionObject { }; @@ -161,6 +165,8 @@ struct Q_QML_EXPORT FunctionObject: Object { void init(String *name, bool createProto); + void createDefaultPrototypeProperty(); + inline ReturnedValue callAsConstructor(const JSCallData &data) const; ReturnedValue callAsConstructor(const Value *argv, int argc) const { return d()->jsConstruct(this, argv, argc); @@ -174,6 +180,7 @@ struct Q_QML_EXPORT FunctionObject: Object { static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function); static Heap::FunctionObject *createConstructorFunction(ExecutionContext *scope, Function *function); + static Heap::FunctionObject *createMemberFunction(ExecutionContext *scope, Function *function); static Heap::FunctionObject *createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, jsCallFunction code, int argumentCount); bool strictMode() const { return d()->function ? d()->function->isStrict() : false; } @@ -247,6 +254,13 @@ struct ConstructorFunction : ScriptFunction { static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); }; +struct MemberFunction : ScriptFunction { + V4_OBJECT2(MemberFunction, ScriptFunction) + V4_INTERNALCLASS(MemberFunction) + static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc); +}; + + struct DefaultClassConstructorFunction : FunctionObject { V4_OBJECT2(DefaultClassConstructorFunction, FunctionObject) static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index d7555ae6cc..48b5657c7f 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1536,7 +1536,7 @@ ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classInde Identifier id = propertyName->toPropertyKey(); QV4::Function *f = unit->runtimeFunctions[methods[i].function]; Q_ASSERT(f); - function = FunctionObject::createScriptFunction(current, f); + function = FunctionObject::createMemberFunction(current, f); Q_ASSERT(function); PropertyAttributes attributes; switch (methods[i].type) { |