diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-03-15 22:33:11 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-04-26 20:27:05 +0000 |
commit | a1e5364b492610adf0636fefa3fc400558e211b6 (patch) | |
tree | 3c4fa3d591e1f5254b52dbe2f3e215417205e803 | |
parent | 783088c3a49e3c344dbd4566cc6ed5dd30c27f31 (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>
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 20 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 4 |
7 files changed, 26 insertions, 8 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()) { diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index fd30f36c13..5673f3f8a3 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -4128,7 +4128,6 @@ language/expressions/array/spread-sngl-literal language/expressions/arrow-function/cannot-override-this-with-thisArg language/expressions/arrow-function/dflt-params-ref-later language/expressions/arrow-function/dflt-params-ref-self -language/expressions/arrow-function/dflt-params-trailing-comma language/expressions/arrow-function/dstr-ary-init-iter-close language/expressions/arrow-function/dstr-ary-init-iter-get-err language/expressions/arrow-function/dstr-ary-init-iter-no-close @@ -4300,8 +4299,6 @@ language/expressions/arrow-function/lexical-super-call-from-within-constructor language/expressions/arrow-function/lexical-super-property language/expressions/arrow-function/lexical-super-property-from-within-constructor language/expressions/arrow-function/lexical-this -language/expressions/arrow-function/params-trailing-comma-multiple -language/expressions/arrow-function/params-trailing-comma-single language/expressions/arrow-function/prototype-rules language/expressions/arrow-function/scope-body-lex-distinct language/expressions/arrow-function/scope-param-elem-var-close @@ -6802,7 +6799,6 @@ language/module-code/namespace/Symbol.iterator language/module-code/namespace/Symbol.toStringTag language/module-code/parse-export-empty language/rest-parameters/array-pattern -language/rest-parameters/expected-argument-count language/rest-parameters/object-pattern language/rest-parameters/with-new-target language/statements/async-function/cptn-decl |