aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-22 12:32:13 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-26 10:04:18 +0000
commiteae4756f74d70de46d9345ece54345f597bc1929 (patch)
tree3bd9de778a4a035a79595ed160c7b474a03695ec
parente9b3bdb96e008060a0e78815a3995015e5e4598d (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.cpp4
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp35
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp2
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) {