diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-05-22 13:49:27 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2013-05-22 15:47:40 +0200 |
commit | 54d8facf66d668d8cea1184f7f24928e97497ae1 (patch) | |
tree | c28b591ea8b632234107c6650585b4f4bc7bca28 | |
parent | e57285b323b0c669841e9be7b2af427958a8c9b6 (diff) |
Add a QV4::Script class
The class is a replacement for v8::Script. Start using it
in various places.
Change-Id: Ie5537639e44fa1ee23aea8605eae3c736819ef52
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r-- | src/qml/qml/v4/qv4context.cpp | 25 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4context_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4engine.cpp | 31 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4engine_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4globalobject.cpp | 114 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4globalobject_p.h | 11 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4script.cpp | 187 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4script_p.h | 78 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4v8.cpp | 30 | ||||
-rw-r--r-- | src/qml/qml/v4/v4.pri | 2 | ||||
-rw-r--r-- | src/qml/qml/v8/qjsengine.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/v8/qv8engine.cpp | 10 |
12 files changed, 340 insertions, 165 deletions
diff --git a/src/qml/qml/v4/qv4context.cpp b/src/qml/qml/v4/qv4context.cpp index 928a57877f..0535f86275 100644 --- a/src/qml/qml/v4/qv4context.cpp +++ b/src/qml/qml/v4/qv4context.cpp @@ -201,6 +201,31 @@ void CallContext::initCallContext(ExecutionEngine *engine, FunctionObject *funct } } +void CallContext::initQmlContext(ExecutionEngine *engine, Object *qml, FunctionObject *function) +{ + initBaseContext(Type_QmlContext, engine); + + this->function = function; + this->arguments = 0; + this->argumentCount = 0; + this->thisObject = Value::undefinedValue(); + + strictMode = true; + marked = false; + this->outer = function->scope; +#ifndef QT_NO_DEBUG + assert(outer->next != (ExecutionContext *)0x1); +#endif + + activation = qml; + + lookups = function->function->lookups; + + locals = (Value *)(this + 1); + if (function->varCount) + std::fill(locals, locals + function->varCount, Value::undefinedValue()); +} + bool ExecutionContext::deleteProperty(String *name) { diff --git a/src/qml/qml/v4/qv4context_p.h b/src/qml/qml/v4/qv4context_p.h index 0cd4a21baa..a96db3433b 100644 --- a/src/qml/qml/v4/qv4context_p.h +++ b/src/qml/qml/v4/qv4context_p.h @@ -169,6 +169,7 @@ struct CallContext : public SimpleCallContext { void initCallContext(QV4::ExecutionEngine *engine, FunctionObject *function, Value *args, int argc, const Value &thisObject); + void initQmlContext(QV4::ExecutionEngine *engine, Object *qml, QV4::FunctionObject *function); bool needsOwnArguments() const; Value *locals; @@ -220,6 +221,8 @@ inline const CallContext *ExecutionContext::asCallContext() const /* Function *f, int argc */ #define requiredMemoryForExecutionContect(f, argc) \ sizeof(CallContext) + sizeof(Value) * (f->varCount + qMax((uint)argc, f->formalParameterCount)) +#define requiredMemoryForQmlExecutionContect(f) \ + sizeof(CallContext) + sizeof(Value) * (f->locals.size()) #define stackContextSize (sizeof(CallContext) + 32*sizeof(Value)) } // namespace QV4 diff --git a/src/qml/qml/v4/qv4engine.cpp b/src/qml/qml/v4/qv4engine.cpp index 8fafddf182..cdcb12f88c 100644 --- a/src/qml/qml/v4/qv4engine.cpp +++ b/src/qml/qml/v4/qv4engine.cpp @@ -315,6 +315,17 @@ CallContext *ExecutionEngine::newCallContext(FunctionObject *f, const Value &thi return c; } +CallContext *ExecutionEngine::newQmlContext(FunctionObject *f, Object *qml) +{ + CallContext *c = static_cast<CallContext *>(memoryManager->allocContext(requiredMemoryForExecutionContect(f, 0))); + + c->initQmlContext(this, qml, f); + c->parent = current; + current = c; + + return c; +} + CallContext *ExecutionEngine::newCallContext(void *stackSpace, FunctionObject *f, const Value &thisObject, Value *args, int argc) { CallContext *c; @@ -671,23 +682,3 @@ void ExecutionEngine::markObjects() variantPrototype->mark(); sequencePrototype->mark(); } - -Value ExecutionEngine::run(Function *function, ExecutionContext *ctx) -{ - if (!ctx) - ctx = rootContext; - - TemporaryAssignment<Function*> savedGlobalCode(globalCode, function); - - // ### Would be better to have a SavedExecutionState object that - // saves this and restores it in the destructor (to survive an exception). - ctx->strictMode = function->isStrict; - ctx->lookups = function->lookups; - - if (debugger) - debugger->aboutToCall(0, ctx); - QV4::Value result = function->code(ctx, function->codeData); - if (debugger) - debugger->justLeft(ctx); - return result; -} diff --git a/src/qml/qml/v4/qv4engine_p.h b/src/qml/qml/v4/qv4engine_p.h index 6d1ae60da2..96188d44a2 100644 --- a/src/qml/qml/v4/qv4engine_p.h +++ b/src/qml/qml/v4/qv4engine_p.h @@ -227,6 +227,7 @@ struct Q_QML_EXPORT ExecutionEngine CatchContext *newCatchContext(String* exceptionVarName, const QV4::Value &exceptionValue); CallContext *newCallContext(FunctionObject *f, const QV4::Value &thisObject, QV4::Value *args, int argc); CallContext *newCallContext(void *stackSpace, FunctionObject *f, const QV4::Value &thisObject, QV4::Value *args, int argc); + CallContext *newQmlContext(FunctionObject *f, Object *qml); ExecutionContext *pushGlobalContext(); void pushContext(SimpleCallContext *context); ExecutionContext *popContext(); @@ -284,8 +285,6 @@ struct Q_QML_EXPORT ExecutionEngine void markObjects(); - Value run(Function *function, ExecutionContext *ctx = 0); - void initRootContext(); InternalClass *newClass(const InternalClass &other); diff --git a/src/qml/qml/v4/qv4globalobject.cpp b/src/qml/qml/v4/qv4globalobject.cpp index cae1d715e7..e56b396b6b 100644 --- a/src/qml/qml/v4/qv4globalobject.cpp +++ b/src/qml/qml/v4/qv4globalobject.cpp @@ -44,6 +44,8 @@ #include "qv4value_p.h" #include "qv4context_p.h" #include "qv4function_p.h" +#include "qv4debugging_p.h" +#include "qv4script_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -62,6 +64,7 @@ using namespace QV4; + static inline char toHex(char c) { static const char hexnumbers[] = "0123456789ABCDEF"; @@ -344,18 +347,9 @@ DEFINE_MANAGED_VTABLE(EvalFunction); EvalFunction::EvalFunction(ExecutionContext *scope) : FunctionObject(scope, scope->engine->id_eval) - , qmlActivation(0) -{ - vtbl = &static_vtbl; - defineReadonlyProperty(scope->engine->id_length, Value::fromInt32(1)); -} - -EvalFunction::EvalFunction(ExecutionContext *scope, Object *qmlActivation) - : FunctionObject(scope, scope->engine->id_eval) { vtbl = &static_vtbl; defineReadonlyProperty(scope->engine->id_length, Value::fromInt32(1)); - this->qmlActivation = qmlActivation; } Value EvalFunction::evalCall(ExecutionContext *parentContext, Value /*thisObject*/, Value *args, int argc, bool directCall) @@ -378,31 +372,26 @@ Value EvalFunction::evalCall(ExecutionContext *parentContext, Value /*thisObject const QString code = args[0].stringValue()->toQString(); bool inheritContext = !ctx->strictMode; - QV4::Function *f = parseSource(ctx, QStringLiteral("eval code"), - code, QQmlJS::Codegen::EvalCode, - (directCall && parentContext->strictMode), inheritContext); + Script script(ctx, code, QString("eval code")); + script.strictMode = (directCall && parentContext->strictMode); + script.inheritContext = inheritContext; + script.parse(); - if (!f) + if (!script.function) return Value::undefinedValue(); - strictMode = f->isStrict || (ctx->strictMode); - if (qmlActivation) - strictMode = true; + strictMode = script.function->isStrict || (ctx->strictMode); - usesArgumentsObject = f->usesArgumentsObject; - needsActivation = f->needsActivation(); + usesArgumentsObject = script.function->usesArgumentsObject; + needsActivation = script.function->needsActivation(); if (strictMode) { CallContext *k = ctx->engine->newCallContext(this, ctx->thisObject, 0, 0); - if (qmlActivation) { - k->activation = qmlActivation; - k->type = ExecutionContext::Type_QmlContext; - } ctx = k; } ExecutionContext::EvalCode evalCode; - evalCode.function = f; + evalCode.function = script.function; evalCode.next = ctx->currentEvalCode; ctx->currentEvalCode = &evalCode; @@ -412,7 +401,7 @@ Value EvalFunction::evalCall(ExecutionContext *parentContext, Value /*thisObject Value result = Value::undefinedValue(); try { - result = f->code(ctx, f->codeData); + result = script.function->code(ctx, script.function->codeData); } catch (Exception &ex) { ctx->strictMode = cstrict; ctx->currentEvalCode = evalCode.next; @@ -437,83 +426,6 @@ Value EvalFunction::call(Managed *that, ExecutionContext *context, const Value & return static_cast<EvalFunction *>(that)->evalCall(context, thisObject, args, argc, false); } -//Value EvalFunction::construct(ExecutionContext *ctx, Value *, int) -//{ -// ctx->throwTypeError(); -// return Value::undefinedValue(); -//} - -QV4::Function *EvalFunction::parseSource(QV4::ExecutionContext *ctx, - const QString &fileName, const QString &source, - QQmlJS::Codegen::Mode mode, - bool strictMode, bool inheritContext) -{ - using namespace QQmlJS; - - MemoryManager::GCBlocker gcBlocker(ctx->engine->memoryManager); - - ExecutionEngine *vm = ctx->engine; - V4IR::Module module; - Function *globalCode = 0; - - { - QQmlJS::Engine ee, *engine = ⅇ - Lexer lexer(engine); - lexer.setCode(source, 1, false); - Parser parser(engine); - - const bool parsed = parser.parseProgram(); - - DiagnosticMessage *error = 0, **errIt = &error; - foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) { - if (m.isError()) { - *errIt = new DiagnosticMessage; - (*errIt)->fileName = fileName; - (*errIt)->offset = m.loc.offset; - (*errIt)->length = m.loc.length; - (*errIt)->startLine = m.loc.startLine; - (*errIt)->startColumn = m.loc.startColumn; - (*errIt)->type = DiagnosticMessage::Error; - (*errIt)->message = m.message; - errIt = &(*errIt)->next; - } else { - std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn - << ": warning: " << qPrintable(m.message) << std::endl; - } - } - if (error) - ctx->throwSyntaxError(error); - - if (parsed) { - using namespace AST; - Program *program = AST::cast<Program *>(parser.rootNode()); - if (!program) { - // if parsing was successful, and we have no program, then - // we're done...: - return 0; - } - - QStringList inheritedLocals; - if (inheritContext) - for (String * const *i = ctx->variables(), * const *ei = i + ctx->variableCount(); i < ei; ++i) - inheritedLocals.append(*i ? (*i)->toQString() : QString()); - - Codegen cg(ctx, strictMode); - V4IR::Function *globalIRCode = cg(fileName, source, program, &module, mode, inheritedLocals); - QScopedPointer<EvalInstructionSelection> isel(ctx->engine->iselFactory->create(vm, &module)); - if (inheritContext) - isel->setUseFastLookups(false); - if (globalIRCode) - globalCode = isel->vmFunction(globalIRCode); - } - - if (! globalCode) - // ### should be a syntax error - ctx->throwTypeError(); - } - - return globalCode; -} static inline int toInt(const QChar &qc, int R) { diff --git a/src/qml/qml/v4/qv4globalobject_p.h b/src/qml/qml/v4/qv4globalobject_p.h index 97a8b705f5..b1abc212e6 100644 --- a/src/qml/qml/v4/qv4globalobject_p.h +++ b/src/qml/qml/v4/qv4globalobject_p.h @@ -44,28 +44,19 @@ #include "qv4global_p.h" #include "qv4functionobject_p.h" -QT_END_NAMESPACE +QT_BEGIN_NAMESPACE namespace QV4 { struct Q_QML_EXPORT EvalFunction : FunctionObject { EvalFunction(ExecutionContext *scope); - EvalFunction(ExecutionContext *scope, Object *qmlActivation); - - static QV4::Function *parseSource(QV4::ExecutionContext *ctx, - const QString &fileName, - const QString &source, - QQmlJS::Codegen::Mode mode, bool strictMode, - bool inheritContext); Value evalCall(ExecutionContext *context, Value thisObject, Value *args, int argc, bool directCall); using Managed::construct; static Value call(Managed *that, ExecutionContext *, const Value &, Value *, int); - Object *qmlActivation; - protected: static const ManagedVTable static_vtbl; }; diff --git a/src/qml/qml/v4/qv4script.cpp b/src/qml/qml/v4/qv4script.cpp new file mode 100644 index 0000000000..3b4456055c --- /dev/null +++ b/src/qml/qml/v4/qv4script.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4script_p.h" +#include "qv4mm_p.h" +#include "qv4functionobject_p.h" +#include "qv4function_p.h" +#include "qv4context_p.h" +#include "qv4debugging_p.h" + +#include <private/qqmljsengine_p.h> +#include <private/qqmljslexer_p.h> +#include <private/qqmljsparser_p.h> +#include <private/qqmljsast_p.h> +#include <qv4jsir_p.h> +#include <qv4codegen_p.h> + +#include <QtCore/QDebug> +#include <QtCore/QString> + +using namespace QV4; + + +void Script::parse() +{ + using namespace QQmlJS; + + MemoryManager::GCBlocker gcBlocker(scope->engine->memoryManager); + + ExecutionEngine *vm = scope->engine; + V4IR::Module module; + Function *globalCode = 0; + + { + QQmlJS::Engine ee, *engine = ⅇ + Lexer lexer(engine); + lexer.setCode(sourceCode, 1, false); + Parser parser(engine); + + const bool parsed = parser.parseProgram(); + + DiagnosticMessage *error = 0, **errIt = &error; + foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) { + if (m.isError()) { + *errIt = new DiagnosticMessage; + (*errIt)->fileName = sourceFile; + (*errIt)->offset = m.loc.offset; + (*errIt)->length = m.loc.length; + (*errIt)->startLine = m.loc.startLine; + (*errIt)->startColumn = m.loc.startColumn; + (*errIt)->type = DiagnosticMessage::Error; + (*errIt)->message = m.message; + errIt = &(*errIt)->next; + } else { + qWarning() << sourceFile << ':' << m.loc.startLine << ':' << m.loc.startColumn + << ": warning: " << m.message; + } + } + if (error) + scope->throwSyntaxError(error); + + if (parsed) { + using namespace AST; + Program *program = AST::cast<Program *>(parser.rootNode()); + if (!program) { + // if parsing was successful, and we have no program, then + // we're done...: + return; + } + + QStringList inheritedLocals; + if (inheritContext) + for (String * const *i = scope->variables(), * const *ei = i + scope->variableCount(); i < ei; ++i) + inheritedLocals.append(*i ? (*i)->toQString() : QString()); + + Codegen cg(scope, strictMode); + V4IR::Function *globalIRCode = cg(sourceFile, sourceCode, program, &module, QQmlJS::Codegen::EvalCode, inheritedLocals); + QScopedPointer<EvalInstructionSelection> isel(scope->engine->iselFactory->create(vm, &module)); + if (inheritContext) + isel->setUseFastLookups(false); + if (globalIRCode) + globalCode = isel->vmFunction(globalIRCode); + } + + if (! globalCode) + // ### should be a syntax error + scope->throwTypeError(); + } + + function = globalCode; +} + +struct QmlFunction : FunctionObject +{ + QmlFunction(ExecutionContext *scope) + : FunctionObject(scope, scope->engine->id_eval) + { + defineReadonlyProperty(scope->engine->id_length, Value::fromInt32(1)); + } +}; + +Value Script::run() +{ + QV4::ExecutionEngine *engine = scope->engine; + + if (!function) + // ### FIX file/line number + __qmljs_throw(engine->current, QV4::Value::fromObject(engine->newSyntaxErrorObject(engine->current, 0)), -1); + + if (!qml) { + TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, function); + + bool strict = scope->strictMode; + Lookup *lookups = scope->lookups; + + scope->strictMode = function->isStrict; + scope->lookups = function->lookups; + + if (engine->debugger) + engine->debugger->aboutToCall(0, scope); + + QV4::Value result; + try { + result = function->code(scope, function->codeData); + } catch (Exception &e) { + scope->strictMode = strict; + scope->lookups = lookups; + throw; + } + + if (engine->debugger) + engine->debugger->justLeft(scope); + return result; + } else { + QmlFunction *f = new (engine->memoryManager) QmlFunction(scope); + f->function = function; + f->usesArgumentsObject = function->usesArgumentsObject; + f->needsActivation = function->needsActivation(); + + CallContext *ctx = engine->newQmlContext(f, qml); + + Value result = function->code(ctx, function->codeData); + + engine->popContext(); + + return result; + } +} + diff --git a/src/qml/qml/v4/qv4script_p.h b/src/qml/qml/v4/qv4script_p.h new file mode 100644 index 0000000000..442b4fd071 --- /dev/null +++ b/src/qml/qml/v4/qv4script_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QV4SCRIPT_H +#define QV4SCRIPT_H + +#include "qv4global_p.h" +#include "qv4engine_p.h" + +QT_BEGIN_NAMESPACE + +namespace QV4 { + +struct ExecutionContext; + +struct Script { + Script(ExecutionContext *scope, const QString &sourceCode, const QString &source, int line = 0, int column = 0) + : sourceFile(source), line(line), column(column), sourceCode(sourceCode) + , scope(scope), strictMode(false), inheritContext(false), qml(0), function(0) {} + Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source, int line = 0, int column = 0) + : sourceFile(source), line(line), column(column), sourceCode(sourceCode) + , scope(engine->rootContext), strictMode(true), inheritContext(true), qml(qml), function(0) {} + QString sourceFile; + int line; + int column; + QString sourceCode; + ExecutionContext *scope; + bool strictMode; + bool inheritContext; + Object *qml; + Function *function; + + void parse(); + Value run(); +}; + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/qml/qml/v4/qv4v8.cpp b/src/qml/qml/v4/qv4v8.cpp index e730eb1a17..e0ca7ee5a8 100644 --- a/src/qml/qml/v4/qv4v8.cpp +++ b/src/qml/qml/v4/qv4v8.cpp @@ -55,6 +55,7 @@ #include "qv4booleanobject_p.h" #include "qv4stringobject_p.h" #include "qv4objectproto_p.h" +#include "qv4script_p.h" #include <QThreadStorage> using namespace QQmlJS; @@ -240,34 +241,17 @@ Handle<Value> Script::Run() QV4::ExecutionEngine *engine = Isolate::GetCurrent()->GetEngine(); QV4::ExecutionContext *ctx = engine->current; - QV4::Function *f = QV4::EvalFunction::parseSource(engine->rootContext, m_origin.m_fileName, m_script, QQmlJS::Codegen::EvalCode, - /*strictMode =*/ false, /*inheritContext =*/ false); - if (!f) - // ### FIX file/line number - __qmljs_throw(engine->current, QV4::Value::fromObject(engine->newSyntaxErrorObject(engine->current, 0)), -1); - - return engine->run(f); + QV4::Script script(ctx, m_script, m_origin.m_fileName, m_origin.m_lineNumber, m_origin.m_columnNumber); + script.parse(); + return script.run(); } Handle<Value> Script::Run(Handle<Object> qml) { QV4::ExecutionEngine *engine = Isolate::GetCurrent()->GetEngine(); - QV4::ExecutionContext *ctx = engine->current; - - QV4::Value result = QV4::Value::undefinedValue(); - - try { - - QV4::EvalFunction *eval = new (engine->memoryManager) QV4::EvalFunction(engine->rootContext, qml->v4Value().asObject()); - - QV4::Value arg = QV4::Value::fromString(engine->current, m_script); - - result = eval->evalCall(engine->current, QV4::Value::undefinedValue(), &arg, 1, /*directCall*/ false); - } catch (QV4::Exception &e) { - e.accept(ctx); - return Handle<Value>(); - } - return result; + QV4::Script script(engine, qml->v4Value().asObject(), m_script, m_origin.m_fileName, m_origin.m_lineNumber, m_origin.m_columnNumber); + script.parse(); + return script.run(); } Handle<Value> Script::Id() diff --git a/src/qml/qml/v4/v4.pri b/src/qml/qml/v4/v4.pri index ccfb723f8f..b6f27c540f 100644 --- a/src/qml/qml/v4/v4.pri +++ b/src/qml/qml/v4/v4.pri @@ -48,6 +48,7 @@ SOURCES += \ $$PWD/qv4regexp.cpp \ $$PWD/qv4unwindhelper.cpp \ $$PWD/qv4serialize.cpp \ + $$PWD/qv4script.cpp \ $$PWD/qv4v8.cpp \ $$PWD/qv4executableallocator.cpp \ $$PWD/qv4sequenceobject.cpp @@ -96,6 +97,7 @@ HEADERS += \ $$PWD/qv4unwindhelper_p-dw2.h \ $$PWD/qv4unwindhelper_p-arm.h \ $$PWD/qv4serialize_p.h \ + $$PWD/qv4script_p.h \ $$PWD/qv4v8_p.h \ $$PWD/qv4util_p.h \ $$PWD/qv4executableallocator_p.h \ diff --git a/src/qml/qml/v8/qjsengine.cpp b/src/qml/qml/v8/qjsengine.cpp index 754a67ebe0..1e3713e5e0 100644 --- a/src/qml/qml/v8/qjsengine.cpp +++ b/src/qml/qml/v8/qjsengine.cpp @@ -48,6 +48,7 @@ #include "private/qv4engine_p.h" #include "private/qv4mm_p.h" #include "private/qv4globalobject_p.h" +#include "private/qv4script_p.h" #include <QtCore/qdatetime.h> #include <QtCore/qmetaobject.h> @@ -256,12 +257,14 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in { QV4::ExecutionContext *ctx = d->m_v4Engine->current; try { - QV4::Function *f = QV4::EvalFunction::parseSource(ctx, fileName, program, QQmlJS::Codegen::EvalCode, - d->m_v4Engine->current->strictMode, true); - if (!f) + QV4::Script script(ctx, program, fileName, lineNumber); + script.strictMode = ctx->strictMode; + script.inheritContext = true; + script.parse(); + if (!script.function) return QJSValue(); - QV4::Value result = d->m_v4Engine->run(f); + QV4::Value result = script.run(); return new QJSValuePrivate(d->m_v4Engine, result); } catch (QV4::Exception& ex) { ex.accept(ctx); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index b6431b7fad..267dea58ce 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -73,6 +73,7 @@ #include <private/qv4globalobject_p.h> #include <private/qv4regexpobject_p.h> #include <private/qv4variantobject_p.h> +#include <private/qv4script_p.h> Q_DECLARE_METATYPE(QList<int>) @@ -1479,14 +1480,13 @@ QV4::Value QV8Engine::toString(const QString &string) QV4::Value QV8Engine::evaluateScript(const QString &script, QV4::Object *scopeObject) { - QV4::ExecutionContext *ctx = m_v4Engine->current; + QV4::Script qmlScript(m_v4Engine, scopeObject, script, QString()); + QV4::ExecutionContext *ctx = m_v4Engine->current; QV4::Value result = QV4::Value::undefinedValue(); - try { - QV4::EvalFunction *eval = new (m_v4Engine->memoryManager) QV4::EvalFunction(m_v4Engine->rootContext, scopeObject); - QV4::Value arg = QV4::Value::fromString(m_v4Engine->current, script); - result = eval->evalCall(m_v4Engine->current, QV4::Value::undefinedValue(), &arg, 1, /*directCall*/ false); + qmlScript.parse(); + result = qmlScript.run(); } catch (QV4::Exception &e) { e.accept(ctx); } |