diff options
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 60 | ||||
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator_p.h | 12 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 2 | ||||
-rw-r--r-- | src/qml/parser/qqmljsengine_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/ftw/qfinitestack_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompileddata.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 52 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlinstruction.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlinstruction_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlscript.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlscript_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 31 | ||||
-rw-r--r-- | tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp | 3 | ||||
-rw-r--r-- | tests/auto/qml/parserstress/tst_parserstress.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp | 2 |
18 files changed, 164 insertions, 45 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 83f3dfe84a..41aa17fff3 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -140,9 +140,6 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co return false; } - // Reserve space for pseudo context-scope function - _functions << program; - AST::UiObjectDefinition *rootObject = AST::cast<AST::UiObjectDefinition*>(program->members->member); Q_ASSERT(rootObject); output->indexOfRootObject = defineQMLObject(rootObject); @@ -1028,7 +1025,7 @@ bool QQmlCodeGenerator::isStatementNodeScript(AST::Statement *statement) return true; } -QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output) +QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const QVector<int> &runtimeFunctionIndices) { jsUnitGenerator = &output.jsGenerator; const QmlObject *rootObject = output.objects.at(output.indexOfRootObject); @@ -1107,7 +1104,7 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output) quint32 *functionsTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToFunctions); for (Function *f = o->functions->first; f; f = f->next) - *functionsTable++ = f->index; + *functionsTable++ = runtimeFunctionIndices[f->index]; char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties; for (QmlProperty *p = o->properties->first; p; p = p->next) { @@ -1120,6 +1117,8 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output) for (Binding *b = o->bindings->first; b; b = b->next) { QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr); *bindingToWrite = *b; + if (b->type == QV4::CompiledData::Binding::Type_Script) + bindingToWrite->value.compiledScriptIndex = runtimeFunctionIndices[b->value.compiledScriptIndex]; bindingPtr += sizeof(QV4::CompiledData::Binding); } @@ -1155,16 +1154,23 @@ int QmlUnitGenerator::getStringId(const QString &str) const return jsUnitGenerator->getStringId(str); } -void JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, ParsedQML *output) +QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, ParsedQML *output) { - _module = &output->jsModule; + return generateJSCodeForFunctionsAndBindings(fileName, output->code, &output->jsModule, &output->jsParserEngine, + output->program, output->functions); +} + +QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, const QString &sourceCode, V4IR::Module *jsModule, + QQmlJS::Engine *jsEngine, AST::UiProgram *qmlRoot, const QList<AST::Node*> &functions) +{ + QVector<int> runtimeFunctionIndices(functions.size()); + _module = jsModule; _module->setFileName(fileName); - QmlScanner scan(this, output->code); - scan.begin(output->program, QmlBinding); - foreach (AST::Node *node, output->functions) { - if (node == output->program) - continue; + QmlScanner scan(this, sourceCode); + scan.begin(qmlRoot, QmlBinding); + foreach (AST::Node *node, functions) { + Q_ASSERT(node != qmlRoot); AST::FunctionDeclaration *function = AST::cast<AST::FunctionDeclaration*>(node); scan.enterEnvironment(node, function ? FunctionCode : QmlBinding); @@ -1174,11 +1180,11 @@ void JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, P scan.end(); _env = 0; - _function = defineFunction(QString("context scope"), output->program, 0, 0); + _function = defineFunction(QString("context scope"), qmlRoot, 0, 0); - foreach (AST::Node *node, output->functions) { - if (node == output->program) - continue; + for (int i = 0; i < functions.count(); ++i) { + AST::Node *node = functions.at(i); + Q_ASSERT(node != qmlRoot); AST::FunctionDeclaration *function = AST::cast<AST::FunctionDeclaration*>(node); @@ -1193,20 +1199,28 @@ void JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, P body = function->body ? function->body->elements : 0; else { // Synthesize source elements. - QQmlJS::MemoryPool *pool = output->jsParserEngine.pool(); - AST::SourceElement *element = new (pool) AST::StatementSourceElement(static_cast<AST::Statement*>(node)); - body = new (output->jsParserEngine.pool()) AST::SourceElements(element); + QQmlJS::MemoryPool *pool = jsEngine->pool(); + + AST::Statement *stmt = node->statementCast(); + if (!stmt) { + Q_ASSERT(node->expressionCast()); + AST::ExpressionNode *expr = node->expressionCast(); + stmt = new (pool) AST::ExpressionStatement(expr); + } + AST::SourceElement *element = new (pool) AST::StatementSourceElement(stmt); + body = new (pool) AST::SourceElements(element); body = body->finish(); } - defineFunction(name, node, - function ? function->formals : 0, - body); - + V4IR::Function *irFunc = defineFunction(name, node, + function ? function->formals : 0, + body); + runtimeFunctionIndices[i] = _module->functions.indexOf(irFunc); // ### } qDeleteAll(_envMap); _envMap.clear(); + return runtimeFunctionIndices; } diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h index 09faec2374..b6749516d3 100644 --- a/src/qml/compiler/qqmlcodegenerator_p.h +++ b/src/qml/compiler/qqmlcodegenerator_p.h @@ -127,12 +127,13 @@ struct QmlProperty : public QV4::CompiledData::Property struct Binding : public QV4::CompiledData::Binding { + // Binding's compiledScriptIndex is index in parsedQML::functions Binding *next; }; struct Function { - int index; + int index; // index in parsedQML::functions Function *next; }; @@ -276,7 +277,7 @@ struct Q_QML_EXPORT QmlUnitGenerator { } - QV4::CompiledData::QmlUnit *generate(ParsedQML &output); + QV4::CompiledData::QmlUnit *generate(ParsedQML &output, const QVector<int> &runtimeFunctionIndices); private: int getStringId(const QString &str) const; @@ -335,7 +336,10 @@ struct Q_QML_EXPORT JSCodeGen : public QQmlJS::Codegen : QQmlJS::Codegen(/*strict mode*/false) {} - void generateJSCodeForFunctionsAndBindings(const QString &fileName, ParsedQML *output); + // Returns mapping from input functions to index in V4IR::Module::functions / compiledData->runtimeFunctions + QVector<int> generateJSCodeForFunctionsAndBindings(const QString &fileName, ParsedQML *output); + QVector<int> generateJSCodeForFunctionsAndBindings(const QString &fileName, const QString &sourceCode, V4IR::Module *jsModule, + QQmlJS::Engine *jsEngine, AST::UiProgram *qmlRoot, const QList<AST::Node*> &functions); private: struct QmlScanner : public ScanFunctions @@ -350,8 +354,6 @@ private: JSCodeGen *codeGen; }; - - V4IR::Module jsModule; }; } // namespace QtQml diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index c5f841b52f..e3f835be9c 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1842,7 +1842,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, if (member.function) { V4IR::Function *function = defineFunction(member.function->name.toString(), member.function, member.function->formals, member.function->body ? member.function->body->elements : 0); - if (! _env->parent) { + if (! _env->parent || _env->compilationMode == QmlBinding) { move(_block->NAME(member.function->name.toString(), member.function->identifierToken.startLine, member.function->identifierToken.startColumn), _block->CLOSURE(function)); } else { diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h index 4f58e7f8ea..195b98bfd7 100644 --- a/src/qml/parser/qqmljsengine_p.h +++ b/src/qml/parser/qqmljsengine_p.h @@ -102,6 +102,7 @@ public: ~Engine(); void setCode(const QString &code); + const QString &code() const { return _code; } void addComment(int pos, int len, int line, int col); QList<AST::SourceLocation> comments() const; diff --git a/src/qml/qml/ftw/qfinitestack_p.h b/src/qml/qml/ftw/qfinitestack_p.h index 1b25ed2e55..8b499d9b6d 100644 --- a/src/qml/qml/ftw/qfinitestack_p.h +++ b/src/qml/qml/ftw/qfinitestack_p.h @@ -65,6 +65,8 @@ struct QFiniteStack { inline void deallocate(); inline void allocate(int size); + inline int capacity() const { return _alloc; } + inline bool isEmpty() const; inline const T &top() const; inline T &top(); diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp index 35de0ac358..9fcef176ad 100644 --- a/src/qml/qml/qqmlcompileddata.cpp +++ b/src/qml/qml/qqmlcompileddata.cpp @@ -243,6 +243,9 @@ void QQmlCompiledData::initialize(QQmlEngine *engine) { Q_ASSERT(!hasEngine()); QQmlCleanup::addToEngine(engine); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); + if (compilationUnit && !compilationUnit->engine) + compilationUnit->linkToEngine(v4); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index a17080f559..afbec31cb5 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -62,6 +62,7 @@ #include "qqmlglobal_p.h" #include "qqmlbinding_p.h" #include "qqmlabstracturlinterceptor.h" +#include "qqmlcodegenerator_p.h" #include <QDebug> #include <QPointF> @@ -809,6 +810,7 @@ bool QQmlCompiler::compile(QQmlEngine *engine, this->unit = unit; this->unitRoot = root; this->output = out; + this->functionsToCompile.clear(); // Compile types const QList<QQmlTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); @@ -915,6 +917,53 @@ void QQmlCompiler::compileTree(QQmlScript::Object *tree) if (!buildObject(tree, BindingContext()) || !completeComponentBuild()) return; + const QQmlScript::Parser &parser = unit->parser(); + QQmlJS::Engine *jsEngine = parser.jsEngine(); + QQmlJS::MemoryPool *pool = jsEngine->pool(); + + foreach (JSBindingReference *root, allBindingReferenceRoots) { + for (JSBindingReference *b = root; b; b = b->nextReference) { + JSBindingReference &binding = *b; + + QQmlJS::AST::Node *node = binding.expression.asAST(); + // Always wrap this in an ExpressionStatement, to make sure that + // property var foo: function() { ... } results in a closure initialization. + if (!node->statementCast()) { + AST::ExpressionNode *expr = node->expressionCast(); + node = new (pool) AST::ExpressionStatement(expr); + } + + functionsToCompile.append(node); + binding.compiledIndex = functionsToCompile.count() - 1; + } + } + + if (!functionsToCompile.isEmpty()) { + JSCodeGen jsCodeGen; + + V4IR::Module jsModule; + const QString &sourceCode = jsEngine->code(); + AST::UiProgram *qmlRoot = parser.qmlRoot(); + + const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(unit->finalUrlString(), sourceCode, &jsModule, jsEngine, qmlRoot, functionsToCompile); + + foreach (JSBindingReference *root, allBindingReferenceRoots) { + for (JSBindingReference *b = root; b; b = b->nextReference) { + JSBindingReference &binding = *b; + functionsToCompile.append(binding.expression.asAST()); + binding.compiledIndex = runtimeFunctionIndices[binding.compiledIndex]; + } + } + + QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); + QV4::Compiler::JSUnitGenerator jsUnitGenerator(&jsModule); + QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(v4->executableAllocator, &jsModule, &jsUnitGenerator)); + isel->setUseFastLookups(false); + QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/true); + output->compilationUnit = jsUnit; + output->compilationUnit->ref(); + } + Instruction::Init init; init.bindingsSize = compileState->totalBindingsCount; init.parserStatusSize = compileState->parserStatusCount; @@ -3519,7 +3568,7 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding, const JSBindingReference &js = static_cast<const JSBindingReference &>(ref); Instruction::StoreBinding store; - store.value = output->indexForString(js.expression.asScript()); + store.functionIndex = js.compiledIndex; store.context = js.bindingContext.stack; store.owner = js.bindingContext.owner; store.line = binding->location.start.line; @@ -3587,6 +3636,7 @@ bool QQmlCompiler::completeComponentBuild() if (componentStats) componentStats->componentStat.scriptBindings.append(b->value->location); } + allBindingReferenceRoots.append(compileState->bindings.first()); // Check pop()'s matched push()'s Q_ASSERT(compileState->objectDepth.depth() == 0); diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index b0fad4708b..9ad0b7f0f9 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -63,6 +63,7 @@ #include "qqmltypenamecache_p.h" #include "qqmltypeloader_p.h" #include "private/qv4identifier_p.h" +#include <private/qqmljsastfwd_p.h> #include <QtCore/qbytearray.h> #include <QtCore/qset.h> @@ -460,6 +461,9 @@ private: int cachedComponentTypeRef; int cachedTranslationContextIndex; + QList<QQmlJS::AST::Node*> functionsToCompile; + QList<QQmlCompilerTypes::JSBindingReference*> allBindingReferenceRoots; + // Compiler component statistics. Only collected if QML_COMPILER_STATS=1 struct ComponentStat { diff --git a/src/qml/qml/qqmlinstruction.cpp b/src/qml/qml/qqmlinstruction.cpp index 626140d99d..33ea3bb7d9 100644 --- a/src/qml/qml/qqmlinstruction.cpp +++ b/src/qml/qml/qqmlinstruction.cpp @@ -222,7 +222,7 @@ void QQmlCompiledData::dump(QQmlInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.primitive << "\t" << instr->assignCustomType.type; break; case QQmlInstruction::StoreBinding: - qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.functionIndex << "\t" << instr->assignBinding.context; break; case QQmlInstruction::StoreValueSource: qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property.coreIndex << "\t" << instr->assignValueSource.castValue; diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h index be27f9069c..14a038783d 100644 --- a/src/qml/qml/qqmlinstruction_p.h +++ b/src/qml/qml/qqmlinstruction_p.h @@ -237,7 +237,7 @@ union QQmlInstruction struct instr_assignBinding { QML_INSTR_HEADER QQmlPropertyRawData property; - int value; + int functionIndex; // index in CompiledData::runtimeFunctions short context; short owner; bool isRoot:1; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index e41248b4ca..42ec886bae 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -488,10 +488,8 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledD , _vmeMetaObject(0) , _qmlContext(0) { - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - if (compiledData->compilationUnit && !compiledData->compilationUnit->engine) - compiledData->compilationUnit->linkToEngine(v4); - + if (!compiledData->isInitialized()) + compiledData->initialize(engine); } QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent) diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp index 7996f9f48c..88603ac2a8 100644 --- a/src/qml/qml/qqmlscript.cpp +++ b/src/qml/qml/qqmlscript.cpp @@ -1303,7 +1303,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node) QQmlScript::Parser::Parser() -: root(0), data(0) +: root(0), _qmlRoot(0), data(0) { } @@ -1380,6 +1380,8 @@ bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray & /* pre _errors[ii].setUrl(url); } + _qmlRoot = parser.ast(); + return _errors.isEmpty(); } @@ -1759,6 +1761,7 @@ void QQmlScript::Parser::clear() } _pool.clear(); + _qmlRoot = 0; } int QQmlScript::Parser::findOrCreateTypeId(const QString &name, Object *object) @@ -1782,4 +1785,9 @@ void QQmlScript::Parser::setTree(QQmlScript::Object *tree) root = tree; } +Engine *QQmlScript::Parser::jsEngine() const +{ + return data ? &data->engine : 0; +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h index 790f1b2b81..f8786b0a2d 100644 --- a/src/qml/qml/qqmlscript_p.h +++ b/src/qml/qml/qqmlscript_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE class QByteArray; class QQmlPropertyCache; -namespace QQmlJS { namespace AST { class Node; class StringLiteral; } } +namespace QQmlJS { class Engine; namespace AST { class Node; class StringLiteral; class UiProgram; } } namespace QQmlCompilerTypes { struct BindingReference; struct ComponentCompileState; } namespace QQmlScript { @@ -511,6 +511,9 @@ public: void setScriptFile(const QString &filename) {_scriptFile = filename; } QString scriptFile() const { return _scriptFile; } + QQmlJS::AST::UiProgram *qmlRoot() const { return _qmlRoot; } + QQmlJS::Engine *jsEngine() const; + // ### private: QList<QQmlError> _errors; @@ -520,6 +523,7 @@ public: QList<Pragma> _pragmas; QList<TypeReference*> _refTypes; QString _scriptFile; + QQmlJS::AST::UiProgram *_qmlRoot; ParserJsASTData *data; }; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 76cb0ce38f..5f733caf51 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2335,7 +2335,7 @@ void QQmlTypeData::compile() // Compile JS binding expressions and signal handlers JSCodeGen jsCodeGen; - jsCodeGen.generateJSCodeForFunctionsAndBindings(finalUrlString(), parsedQML.data()); + const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(finalUrlString(), parsedQML.data()); QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); @@ -2346,7 +2346,7 @@ void QQmlTypeData::compile() // Generate QML compiled type data structures QmlUnitGenerator qmlGenerator; - QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML.data()); + QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML.data(), runtimeFunctionIndices); if (jsUnit) { Q_ASSERT(!jsUnit->data); diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 9583fa1d68..c5dfeb2956 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -226,6 +226,18 @@ static QVariant variantFromString(const QString &string) return QQmlStringConverters::variantFromString(string); } +static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::ExecutionEngine *v4, QV4::SafeValue *qmlBindingWrappers, QQmlContextData *context, QObject *scope, int objIdx) +{ + QV4::Scope valueScope(v4); + QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, qmlBindingWrappers[objIdx]); + if (!wrapper) { + QV4::ScopedObject scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, scope)); + wrapper = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, scopeObject); + qmlBindingWrappers[objIdx] = wrapper; + } + return wrapper->context(); +} + // XXX we probably need some form of "work count" here to prevent us checking this // for every instruction. #define QML_BEGIN_INSTR_COMMON(I) { \ @@ -343,6 +355,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, QV4::ExecutionEngine *v4 = ep->v4engine(); QV4::Scope valueScope(v4); QV4::ScopedValue tmpValue(valueScope); + QV4::SafeValue *qmlBindingWrappers = valueScope.alloc(objects.capacity()); + std::fill(qmlBindingWrappers, qmlBindingWrappers + objects.capacity(), QV4::Primitive::undefinedValue()); int status = -1; // needed for dbus QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::BypassInterceptor | @@ -546,6 +560,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, ddata->outerContext = CTXT; ddata->lineNumber = instr.line; ddata->columnNumber = instr.column; + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); QML_END_INSTR(CompleteQMLObject) QML_BEGIN_INSTR(CreateCppObject) @@ -618,6 +633,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, ddata->parentFrozen = true; } objects.push(o); + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); QML_END_INSTR(CreateCppObject) QML_BEGIN_INSTR(CreateSimpleObject) @@ -647,6 +663,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, ddata->parentFrozen = true; objects.push(o); + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); QML_END_INSTR(CreateSimpleObject) QML_BEGIN_INSTR(SetId) @@ -685,6 +702,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, QQmlComponentPrivate::get(qcomp)->creationContext = CTXT; objects.push(qcomp); + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); INSTRUCTIONSTREAM += instr.count; QML_END_INSTR(CreateComponent) @@ -810,9 +828,13 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex)) QML_NEXT_INSTR(StoreBinding); - QQmlBinding *bind = new QQmlBinding(PRIMITIVES.at(instr.value), - context, CTXT, COMP->name, instr.line, - instr.column); + QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, context, objects.count() - 1 - instr.context); + + QV4::Function *runtimeFunction = COMP->compilationUnit->runtimeFunctions[instr.functionIndex]; + + tmpValue = QV4::FunctionObject::creatScriptFunction(qmlContext, runtimeFunction); + + QQmlBinding *bind = new QQmlBinding(tmpValue, context, CTXT, COMP->name, instr.line, instr.column); bindValues.push(bind); bind->m_mePtr = &bindValues.top(); bind->setTarget(target, instr.property, CTXT); @@ -919,6 +941,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, VME_EXCEPTION(tr("Unable to create attached object"), instr.line); objects.push(qmlObject); + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); QML_END_INSTR(FetchAttached) QML_BEGIN_INSTR(FetchQList) @@ -947,6 +970,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, VME_EXCEPTION(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line); objects.push(obj); + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); QML_END_INSTR(FetchObject) QML_BEGIN_INSTR(PopQList) @@ -1003,6 +1027,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, Q_ASSERT(valueHandler); valueHandler->read(target, instr.property); objects.push(valueHandler); + qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue(); QML_END_INSTR(FetchValueType) QML_BEGIN_INSTR(PopValueType) diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index 11afc9ea22..8024df99b6 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -969,7 +969,8 @@ void tst_QQmlEngineDebugService::setBindingForObject() QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered"); QCOMPARE(onEnteredRef.name, QString("onEntered")); - QCOMPARE(onEnteredRef.value, QVariant("{ console.log('hello') }")); + // Sorry, can't do that anymore: QCOMPARE(onEnteredRef.value, QVariant("{ console.log('hello') }")); + QCOMPARE(onEnteredRef.value, QVariant("function() { [code] }")); m_dbg->setBindingForObject(mouseAreaObject.debugId, "onEntered", "{console.log('hello, world') }", false, diff --git a/tests/auto/qml/parserstress/tst_parserstress.cpp b/tests/auto/qml/parserstress/tst_parserstress.cpp index afa58f4437..15b3ff56b6 100644 --- a/tests/auto/qml/parserstress/tst_parserstress.cpp +++ b/tests/auto/qml/parserstress/tst_parserstress.cpp @@ -94,6 +94,13 @@ void tst_parserstress::ecmascript_data() QTest::addColumn<QString>("file"); foreach (const QString &file, files) { + // Skip, QTBUG-34047 + if (file.endsWith(QStringLiteral("tests/ecma_3/Statements/regress-324650.js"))) + continue; + if (file.endsWith(QStringLiteral("tests/ecma_3/Statements/regress-74474-002.js"))) + continue; + if (file.endsWith(QStringLiteral("tests/ecma_3/Statements/regress-74474-003.js"))) + continue; QTest::newRow(qPrintable(file)) << file; } } diff --git a/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp b/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp index 44ab690f68..a119607769 100644 --- a/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp +++ b/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp @@ -316,7 +316,7 @@ void tst_qqmlinstruction::dump() { QQmlCompiledData::Instruction::StoreBinding i; i.property.coreIndex = 26; - i.value = 3; + i.functionIndex = 3; i.context = 2; i.owner = 0; data->addInstruction(i); |