aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-15 22:33:11 +0100
committerLars Knoll <lars.knoll@qt.io>2018-04-26 20:27:05 +0000
commita1e5364b492610adf0636fefa3fc400558e211b6 (patch)
tree3c4fa3d591e1f5254b52dbe2f3e215417205e803 /src
parent783088c3a49e3c344dbd4566cc6ed5dd30c27f31 (diff)
Fix length property of Function objects
According to ES6, the length property is the number of required arguments, ie. the number of arguments until the first arg that has adefault parameter. Also fix a crash when parsing a parameterlist with a trailing comma. Change-Id: I4f6b2be4feae7b513388be66b43b160bb3cc77f1 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4codegen.cpp3
-rw-r--r--src/qml/compiler/qv4compileddata.cpp1
-rw-r--r--src/qml/compiler/qv4compileddata_p.h3
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp2
-rw-r--r--src/qml/parser/qqmljsast_p.h20
6 files changed, 26 insertions, 4 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 99811c3779..2b6bda1de3 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2363,6 +2363,9 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
Reference arg = referenceForName(e->name, true);
initializeAndDestructureBindingElement(e, arg);
} else {
+ if (!formals->next)
+ // trailing comma
+ break;
Q_UNREACHABLE();
}
formals = formals->next;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 8f8514535a..59c37fb6c7 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -520,6 +520,7 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
signalParameterNameTable.append(stringTable.getStringId(arg));
function->nFormals = formals.size();
+ function->length = function->nFormals;
// Hack to ensure an activation is created.
function->flags |= QV4::CompiledData::Function::HasCatchOrWith | QV4::CompiledData::Function::HasDirectEval;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 41c27ffcd4..48bef10c6d 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -219,6 +219,7 @@ struct Function
quint32_le codeSize;
quint32_le nameIndex;
+ quint32_le length;
quint32_le nFormals;
quint32_le formalsOffset;
quint32_le nLocals;
@@ -276,7 +277,7 @@ struct Function
return (a + 7) & ~size_t(7);
}
};
-static_assert(sizeof(Function) == 76, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Function) == 80, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
// Qml data structures
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index bfb450d408..4bc3940a02 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -313,6 +313,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
function->nestedFunctionIndex =
irFunction->returnsClosure ? quint32(module->functions.indexOf(irFunction->nestedContexts.first()))
: std::numeric_limits<uint32_t>::max();
+ function->length = irFunction->formals ? irFunction->formals->length() : 0;
function->nFormals = irFunction->arguments.size();
function->formalsOffset = currentOffset;
currentOffset += function->nFormals * sizeof(quint32);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 1a26fc857c..327a15361f 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -422,7 +422,7 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function
ScopedString name(s, function->name());
f->init(name, true);
Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
- setProperty(s.engine, Index_Length, Primitive::fromInt32(f->formalParameterCount()));
+ setProperty(s.engine, Index_Length, Primitive::fromInt32(int(function->compiledFunction->length)));
}
Heap::InternalClass *ScriptFunction::classForConstructor() const
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index db41528a02..30f6011924 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -2307,14 +2307,30 @@ public:
if (formals->bindingRestElement())
return false;
BindingElement *e = formals->bindingElement();
- Q_ASSERT(e);
- if (e->initializer || e->binding)
+ if (e && (e->initializer || e->binding))
return false;
formals = formals->next;
}
return true;
}
+ int length()
+ {
+ // the length property of Function objects
+ int l = 0;
+ AST::FormalParameterList *formals = this;
+ while (formals) {
+ if (formals->bindingRestElement())
+ break;
+ BindingElement *e = formals->bindingElement();
+ if (!e || e->initializer)
+ break;
+ ++l;
+ formals = formals->next;
+ }
+ return l;
+ }
+
bool containsName(const QString &name) const {
for (const FormalParameterList *it = this; it; it = it->next) {
if (QQmlJS::AST::BindingElement *b = it->bindingElement()) {