Move the engine and context classes into their own files
Change-Id: Ie20138990908a921ca3d7475618275ed82d9cb5c Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
parent
d7416a80fa
commit
65724ce3e7
|
@ -40,6 +40,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include "qmljs_runtime.h"
|
||||
#include "qmljs_environment.h"
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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 <qmljs_engine.h>
|
||||
#include <qmljs_objects.h>
|
||||
#include <qv4ecmaobjects_p.h>
|
||||
|
||||
namespace QQmlJS {
|
||||
namespace VM {
|
||||
|
||||
ExecutionEngine::ExecutionEngine()
|
||||
{
|
||||
rootContext = newContext();
|
||||
rootContext->init(this);
|
||||
|
||||
id_length = identifier(QStringLiteral("length"));
|
||||
id_prototype = identifier(QStringLiteral("prototype"));
|
||||
id_constructor = identifier(QStringLiteral("constructor"));
|
||||
id_arguments = identifier(QStringLiteral("arguments"));
|
||||
id___proto__ = identifier(QStringLiteral("__proto__"));
|
||||
|
||||
objectPrototype = new ObjectPrototype();
|
||||
stringPrototype = new StringPrototype(rootContext);
|
||||
numberPrototype = new NumberPrototype();
|
||||
booleanPrototype = new BooleanPrototype();
|
||||
arrayPrototype = new ArrayPrototype();
|
||||
datePrototype = new DatePrototype();
|
||||
functionPrototype = new FunctionPrototype(rootContext);
|
||||
regExpPrototype = new RegExpPrototype();
|
||||
errorPrototype = new ErrorPrototype();
|
||||
evalErrorPrototype = new EvalErrorPrototype(rootContext);
|
||||
rangeErrorPrototype = new RangeErrorPrototype(rootContext);
|
||||
referenceErrorPrototype = new ReferenceErrorPrototype(rootContext);
|
||||
syntaxErrorPrototype = new SyntaxErrorPrototype(rootContext);
|
||||
typeErrorPrototype = new TypeErrorPrototype(rootContext);
|
||||
uRIErrorPrototype = new URIErrorPrototype(rootContext);
|
||||
|
||||
stringPrototype->prototype = objectPrototype;
|
||||
numberPrototype->prototype = objectPrototype;
|
||||
booleanPrototype->prototype = objectPrototype;
|
||||
arrayPrototype->prototype = objectPrototype;
|
||||
datePrototype->prototype = objectPrototype;
|
||||
functionPrototype->prototype = objectPrototype;
|
||||
regExpPrototype->prototype = objectPrototype;
|
||||
errorPrototype->prototype = objectPrototype;
|
||||
evalErrorPrototype->prototype = errorPrototype;
|
||||
rangeErrorPrototype->prototype = errorPrototype;
|
||||
referenceErrorPrototype->prototype = errorPrototype;
|
||||
syntaxErrorPrototype->prototype = errorPrototype;
|
||||
typeErrorPrototype->prototype = errorPrototype;
|
||||
uRIErrorPrototype->prototype = errorPrototype;
|
||||
|
||||
objectCtor = Value::fromObject(new ObjectCtor(rootContext));
|
||||
stringCtor = Value::fromObject(new StringCtor(rootContext));
|
||||
numberCtor = Value::fromObject(new NumberCtor(rootContext));
|
||||
booleanCtor = Value::fromObject(new BooleanCtor(rootContext));
|
||||
arrayCtor = Value::fromObject(new ArrayCtor(rootContext));
|
||||
functionCtor = Value::fromObject(new FunctionCtor(rootContext));
|
||||
dateCtor = Value::fromObject(new DateCtor(rootContext));
|
||||
regExpCtor = Value::fromObject(new RegExpCtor(rootContext));
|
||||
errorCtor = Value::fromObject(new ErrorCtor(rootContext));
|
||||
evalErrorCtor = Value::fromObject(new EvalErrorCtor(rootContext));
|
||||
rangeErrorCtor = Value::fromObject(new RangeErrorCtor(rootContext));
|
||||
referenceErrorCtor = Value::fromObject(new ReferenceErrorCtor(rootContext));
|
||||
syntaxErrorCtor = Value::fromObject(new SyntaxErrorCtor(rootContext));
|
||||
typeErrorCtor = Value::fromObject(new TypeErrorCtor(rootContext));
|
||||
uRIErrorCtor = Value::fromObject(new URIErrorCtor(rootContext));
|
||||
|
||||
stringCtor.objectValue()->prototype = functionPrototype;
|
||||
numberCtor.objectValue()->prototype = functionPrototype;
|
||||
booleanCtor.objectValue()->prototype = functionPrototype;
|
||||
arrayCtor.objectValue()->prototype = functionPrototype;
|
||||
functionCtor.objectValue()->prototype = functionPrototype;
|
||||
dateCtor.objectValue()->prototype = functionPrototype;
|
||||
regExpCtor.objectValue()->prototype = functionPrototype;
|
||||
errorCtor.objectValue()->prototype = functionPrototype;
|
||||
evalErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
rangeErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
referenceErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
syntaxErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
typeErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
uRIErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
|
||||
objectPrototype->init(rootContext, objectCtor);
|
||||
stringPrototype->init(rootContext, stringCtor);
|
||||
numberPrototype->init(rootContext, numberCtor);
|
||||
booleanPrototype->init(rootContext, booleanCtor);
|
||||
arrayPrototype->init(rootContext, arrayCtor);
|
||||
datePrototype->init(rootContext, dateCtor);
|
||||
functionPrototype->init(rootContext, functionCtor);
|
||||
regExpPrototype->init(rootContext, regExpCtor);
|
||||
errorPrototype->init(rootContext, errorCtor);
|
||||
evalErrorPrototype->init(rootContext, evalErrorCtor);
|
||||
rangeErrorPrototype->init(rootContext, rangeErrorCtor);
|
||||
referenceErrorPrototype->init(rootContext, referenceErrorCtor);
|
||||
syntaxErrorPrototype->init(rootContext, syntaxErrorCtor);
|
||||
typeErrorPrototype->init(rootContext, typeErrorCtor);
|
||||
uRIErrorPrototype->init(rootContext, uRIErrorCtor);
|
||||
|
||||
//
|
||||
// set up the global object
|
||||
//
|
||||
VM::Object *glo = newObject(/*rootContext*/);
|
||||
globalObject = Value::fromObject(glo);
|
||||
rootContext->activation = glo;
|
||||
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Number")), numberCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Boolean")), booleanCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Array")), arrayCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Function")), functionCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Date")), dateCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("RegExp")), regExpCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Error")), errorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("EvalError")), evalErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("RangeError")), rangeErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("ReferenceError")), referenceErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("SyntaxError")), syntaxErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("TypeError")), typeErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("URIError")), uRIErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Math")), Value::fromObject(newMathObject(rootContext)));
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("undefined")), Value::undefinedValue());
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("NaN")), Value::fromDouble(nan("")));
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Infinity")), Value::fromDouble(INFINITY));
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("eval")), Value::fromObject(new EvalFunction(rootContext)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
ExecutionContext *ExecutionEngine::newContext()
|
||||
{
|
||||
return new ExecutionContext();
|
||||
}
|
||||
|
||||
String *ExecutionEngine::identifier(const QString &s)
|
||||
{
|
||||
String *&id = identifiers[s];
|
||||
if (! id)
|
||||
id = newString(s);
|
||||
return id;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *))
|
||||
{
|
||||
NativeFunction *f = new NativeFunction(scope, code);
|
||||
f->prototype = scope->engine->functionPrototype;
|
||||
return f;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, IR::Function *function)
|
||||
{
|
||||
ScriptFunction *f = new ScriptFunction(scope, function);
|
||||
Object *proto = scope->engine->newObject();
|
||||
proto->__put__(scope, scope->engine->id_constructor, Value::fromObject(f));
|
||||
f->__put__(scope, scope->engine->id_prototype, Value::fromObject(proto));
|
||||
f->prototype = scope->engine->functionPrototype;
|
||||
return f;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newObject()
|
||||
{
|
||||
Object *object = new Object();
|
||||
object->prototype = objectPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newObjectCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new ObjectCtor(ctx);
|
||||
}
|
||||
|
||||
String *ExecutionEngine::newString(const QString &s)
|
||||
{
|
||||
return new String(s);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newStringObject(const Value &value)
|
||||
{
|
||||
StringObject *object = new StringObject(value);
|
||||
object->prototype = stringPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newStringCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new StringCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newNumberObject(const Value &value)
|
||||
{
|
||||
NumberObject *object = new NumberObject(value);
|
||||
object->prototype = numberPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newNumberCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new NumberCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newBooleanObject(const Value &value)
|
||||
{
|
||||
Object *object = new BooleanObject(value);
|
||||
object->prototype = booleanPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newBooleanCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new BooleanCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newFunctionObject(ExecutionContext *ctx)
|
||||
{
|
||||
Object *object = new FunctionObject(ctx);
|
||||
object->prototype = functionPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newFunctionCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new FunctionCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newArrayObject()
|
||||
{
|
||||
ArrayObject *object = new ArrayObject();
|
||||
object->prototype = arrayPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newArrayObject(const Array &value)
|
||||
{
|
||||
ArrayObject *object = new ArrayObject(value);
|
||||
object->prototype = arrayPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newArrayCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new ArrayCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newDateObject(const Value &value)
|
||||
{
|
||||
Object *object = new DateObject(value);
|
||||
object->prototype = datePrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newDateCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new DateCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
|
||||
{
|
||||
bool global = (flags & IR::RegExp::RegExp_Global);
|
||||
QRegularExpression::PatternOptions options = 0;
|
||||
if (flags & IR::RegExp::RegExp_IgnoreCase)
|
||||
options |= QRegularExpression::CaseInsensitiveOption;
|
||||
if (flags & IR::RegExp::RegExp_Multiline)
|
||||
options |= QRegularExpression::MultilineOption;
|
||||
|
||||
Object *object = new RegExpObject(QRegularExpression(pattern, options), global);
|
||||
object->prototype = regExpPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newRegExpCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new RegExpCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newErrorObject(const Value &value)
|
||||
{
|
||||
ErrorObject *object = new ErrorObject(value);
|
||||
object->prototype = errorPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newMathObject(ExecutionContext *ctx)
|
||||
{
|
||||
MathObject *object = new MathObject(ctx);
|
||||
object->prototype = objectPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newActivationObject(ExecutionContext *ctx)
|
||||
{
|
||||
return new ActivationObject(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newForEachIteratorObject(Object *o)
|
||||
{
|
||||
return new ForEachIteratorObject(o);
|
||||
}
|
||||
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
|
@ -0,0 +1,182 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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 QMLJS_ENGINE_H
|
||||
#define QMLJS_ENGINE_H
|
||||
|
||||
#include <qmljs_objects.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
namespace QQmlJS {
|
||||
namespace VM {
|
||||
|
||||
struct Value;
|
||||
struct Array;
|
||||
struct Object;
|
||||
struct BooleanObject;
|
||||
struct NumberObject;
|
||||
struct StringObject;
|
||||
struct ArrayObject;
|
||||
struct DateObject;
|
||||
struct FunctionObject;
|
||||
struct RegExpObject;
|
||||
struct ErrorObject;
|
||||
struct ActivationObject;
|
||||
struct ArgumentsObject;
|
||||
struct ExecutionContext;
|
||||
struct ExecutionEngine;
|
||||
|
||||
struct ObjectPrototype;
|
||||
struct StringPrototype;
|
||||
struct NumberPrototype;
|
||||
struct BooleanPrototype;
|
||||
struct ArrayPrototype;
|
||||
struct FunctionPrototype;
|
||||
struct DatePrototype;
|
||||
struct RegExpPrototype;
|
||||
struct ErrorPrototype;
|
||||
struct EvalErrorPrototype;
|
||||
struct RangeErrorPrototype;
|
||||
struct ReferenceErrorPrototype;
|
||||
struct SyntaxErrorPrototype;
|
||||
struct TypeErrorPrototype;
|
||||
struct URIErrorPrototype;
|
||||
|
||||
struct ExecutionEngine
|
||||
{
|
||||
ExecutionContext *rootContext;
|
||||
Value globalObject;
|
||||
|
||||
Value objectCtor;
|
||||
Value stringCtor;
|
||||
Value numberCtor;
|
||||
Value booleanCtor;
|
||||
Value arrayCtor;
|
||||
Value functionCtor;
|
||||
Value dateCtor;
|
||||
Value regExpCtor;
|
||||
Value errorCtor;
|
||||
Value evalErrorCtor;
|
||||
Value rangeErrorCtor;
|
||||
Value referenceErrorCtor;
|
||||
Value syntaxErrorCtor;
|
||||
Value typeErrorCtor;
|
||||
Value uRIErrorCtor;
|
||||
|
||||
ObjectPrototype *objectPrototype;
|
||||
StringPrototype *stringPrototype;
|
||||
NumberPrototype *numberPrototype;
|
||||
BooleanPrototype *booleanPrototype;
|
||||
ArrayPrototype *arrayPrototype;
|
||||
FunctionPrototype *functionPrototype;
|
||||
DatePrototype *datePrototype;
|
||||
RegExpPrototype *regExpPrototype;
|
||||
ErrorPrototype *errorPrototype;
|
||||
EvalErrorPrototype *evalErrorPrototype;
|
||||
RangeErrorPrototype *rangeErrorPrototype;
|
||||
ReferenceErrorPrototype *referenceErrorPrototype;
|
||||
SyntaxErrorPrototype *syntaxErrorPrototype;
|
||||
TypeErrorPrototype *typeErrorPrototype;
|
||||
URIErrorPrototype *uRIErrorPrototype;
|
||||
|
||||
QHash<QString, String *> identifiers;
|
||||
|
||||
String *id_length;
|
||||
String *id_prototype;
|
||||
String *id_constructor;
|
||||
String *id_arguments;
|
||||
String *id___proto__;
|
||||
|
||||
struct ExceptionHandler {
|
||||
ExecutionContext *context;
|
||||
const uchar *code; // Interpreter state
|
||||
int targetTempIndex; // Interpreter state
|
||||
jmp_buf stackFrame;
|
||||
};
|
||||
|
||||
QVector<ExceptionHandler> unwindStack;
|
||||
|
||||
ExecutionEngine();
|
||||
|
||||
ExecutionContext *newContext();
|
||||
|
||||
String *identifier(const QString &s);
|
||||
|
||||
FunctionObject *newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *));
|
||||
FunctionObject *newScriptFunction(ExecutionContext *scope, IR::Function *function);
|
||||
|
||||
Object *newObject();
|
||||
FunctionObject *newObjectCtor(ExecutionContext *ctx);
|
||||
|
||||
String *newString(const QString &s);
|
||||
Object *newStringObject(const Value &value);
|
||||
FunctionObject *newStringCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newNumberObject(const Value &value);
|
||||
FunctionObject *newNumberCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newBooleanObject(const Value &value);
|
||||
FunctionObject *newBooleanCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newFunctionObject(ExecutionContext *ctx);
|
||||
FunctionObject *newFunctionCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newArrayObject();
|
||||
Object *newArrayObject(const Array &value);
|
||||
FunctionObject *newArrayCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newDateObject(const Value &value);
|
||||
FunctionObject *newDateCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newRegExpObject(const QString &pattern, int flags);
|
||||
FunctionObject *newRegExpCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newErrorObject(const Value &value);
|
||||
Object *newMathObject(ExecutionContext *ctx);
|
||||
Object *newActivationObject(ExecutionContext *ctx);
|
||||
|
||||
Object *newForEachIteratorObject(Object *o);
|
||||
};
|
||||
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
||||
|
||||
#endif
|
|
@ -0,0 +1,181 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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 <qmljs_environment.h>
|
||||
#include <qmljs_objects.h>
|
||||
#include <qv4ecmaobjects_p.h>
|
||||
|
||||
namespace QQmlJS {
|
||||
namespace VM {
|
||||
|
||||
void ExecutionContext::init(ExecutionEngine *eng)
|
||||
{
|
||||
engine = eng;
|
||||
parent = 0;
|
||||
arguments = 0;
|
||||
argumentCount = 0;
|
||||
locals = 0;
|
||||
activation = 0;
|
||||
thisObject = Value::nullValue();
|
||||
result = Value::undefinedValue();
|
||||
formals = 0;
|
||||
formalCount = 0;
|
||||
vars = 0;
|
||||
varCount = 0;
|
||||
}
|
||||
|
||||
PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp)
|
||||
{
|
||||
for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
|
||||
if (ctx->activation) {
|
||||
if (PropertyDescriptor *pd = ctx->activation->__getPropertyDescriptor__(this, name, tmp))
|
||||
return pd;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op)
|
||||
{
|
||||
for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
|
||||
if (ctx->activation) {
|
||||
if (ctx->activation->inplaceBinOp(value, name, op, this))
|
||||
return;
|
||||
}
|
||||
}
|
||||
throwReferenceError(Value::fromString(name));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwError(Value value)
|
||||
{
|
||||
result = value;
|
||||
__qmljs_builtin_throw(value, this);
|
||||
}
|
||||
|
||||
void ExecutionContext::throwError(const QString &message)
|
||||
{
|
||||
Value v = Value::fromString(this, message);
|
||||
throwError(Value::fromObject(engine->newErrorObject(v)));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwTypeError()
|
||||
{
|
||||
Value v = Value::fromString(this, QStringLiteral("Type error"));
|
||||
throwError(Value::fromObject(engine->newErrorObject(v)));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwUnimplemented(const QString &message)
|
||||
{
|
||||
Value v = Value::fromString(this, QStringLiteral("Unimplemented ") + message);
|
||||
throwError(Value::fromObject(engine->newErrorObject(v)));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwReferenceError(Value value)
|
||||
{
|
||||
String *s = value.toString(this);
|
||||
QString msg = s->toQString() + QStringLiteral(" is not defined");
|
||||
throwError(Value::fromObject(engine->newErrorObject(Value::fromString(this, msg))));
|
||||
}
|
||||
|
||||
void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc)
|
||||
{
|
||||
engine = parent->engine;
|
||||
this->parent = f->scope;
|
||||
assert(this->parent == f->scope);
|
||||
result = Value::undefinedValue();
|
||||
|
||||
if (f->needsActivation)
|
||||
activation = engine->newActivationObject(this);
|
||||
else
|
||||
activation = 0;
|
||||
|
||||
thisObject = that;
|
||||
|
||||
formals = f->formalParameterList;
|
||||
formalCount = f->formalParameterCount;
|
||||
arguments = args;
|
||||
argumentCount = argc;
|
||||
if (f->needsActivation || argc < formalCount){
|
||||
arguments = new Value[qMax(argc, formalCount)];
|
||||
if (argc)
|
||||
std::copy(args, args + argc, arguments);
|
||||
if (argc < formalCount)
|
||||
std::fill(arguments + argc, arguments + formalCount, Value::undefinedValue());
|
||||
}
|
||||
vars = f->varList;
|
||||
varCount = f->varCount;
|
||||
locals = varCount ? new Value[varCount] : 0;
|
||||
if (varCount)
|
||||
std::fill(locals, locals + varCount, Value::undefinedValue());
|
||||
}
|
||||
|
||||
void ExecutionContext::leaveCallContext()
|
||||
{
|
||||
if (activation) {
|
||||
delete[] locals;
|
||||
locals = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutionContext::initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc)
|
||||
{
|
||||
initCallContext(parent, that, f, args, argc);
|
||||
}
|
||||
|
||||
void ExecutionContext::leaveConstructorContext(FunctionObject *f)
|
||||
{
|
||||
wireUpPrototype(f);
|
||||
leaveCallContext();
|
||||
}
|
||||
|
||||
void ExecutionContext::wireUpPrototype(FunctionObject *f)
|
||||
{
|
||||
assert(thisObject.isObject());
|
||||
result = thisObject;
|
||||
|
||||
Value proto = f->__get__(this, engine->id_prototype);
|
||||
thisObject.objectValue()->prototype = proto.objectValue();
|
||||
if (! thisObject.isObject())
|
||||
thisObject.objectValue()->prototype = engine->objectPrototype;
|
||||
|
||||
}
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
|
@ -0,0 +1,98 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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 QMLJS_ENVIRONMENT_H
|
||||
#define QMLJS_ENVIRONMENT_H
|
||||
|
||||
#include <qmljs_runtime.h>
|
||||
|
||||
namespace QQmlJS {
|
||||
namespace VM {
|
||||
|
||||
struct Value;
|
||||
struct Object;
|
||||
struct ExecutionEngine;
|
||||
struct ExecutionContext;
|
||||
|
||||
struct ExecutionContext {
|
||||
ExecutionEngine *engine;
|
||||
ExecutionContext *parent;
|
||||
Object *activation;
|
||||
Value thisObject;
|
||||
Value *arguments;
|
||||
unsigned int argumentCount;
|
||||
Value *locals;
|
||||
Value result;
|
||||
String **formals;
|
||||
unsigned int formalCount;
|
||||
String **vars;
|
||||
unsigned int varCount;
|
||||
|
||||
PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp);
|
||||
void inplaceBitOp(Value value, String *name, BinOp op);
|
||||
|
||||
inline Value argument(unsigned int index = 0)
|
||||
{
|
||||
if (index < argumentCount)
|
||||
return arguments[index];
|
||||
return Value::undefinedValue();
|
||||
}
|
||||
|
||||
void init(ExecutionEngine *eng);
|
||||
|
||||
void initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc);
|
||||
void leaveCallContext();
|
||||
|
||||
void initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc);
|
||||
void leaveConstructorContext(FunctionObject *f);
|
||||
void wireUpPrototype(FunctionObject *f);
|
||||
|
||||
void throwError(Value value);
|
||||
void throwError(const QString &message);
|
||||
void throwTypeError();
|
||||
void throwReferenceError(Value value);
|
||||
void throwUnimplemented(const QString &message);
|
||||
};
|
||||
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
||||
|
||||
#endif
|
|
@ -686,292 +686,3 @@ PropertyDescriptor *ArgumentsObject::__getPropertyDescriptor__(ExecutionContext
|
|||
|
||||
return Object::__getPropertyDescriptor__(ctx, name, to_fill);
|
||||
}
|
||||
|
||||
ExecutionEngine::ExecutionEngine()
|
||||
{
|
||||
rootContext = newContext();
|
||||
rootContext->init(this);
|
||||
|
||||
id_length = identifier(QStringLiteral("length"));
|
||||
id_prototype = identifier(QStringLiteral("prototype"));
|
||||
id_constructor = identifier(QStringLiteral("constructor"));
|
||||
id_arguments = identifier(QStringLiteral("arguments"));
|
||||
id___proto__ = identifier(QStringLiteral("__proto__"));
|
||||
|
||||
objectPrototype = new ObjectPrototype();
|
||||
stringPrototype = new StringPrototype(rootContext);
|
||||
numberPrototype = new NumberPrototype();
|
||||
booleanPrototype = new BooleanPrototype();
|
||||
arrayPrototype = new ArrayPrototype();
|
||||
datePrototype = new DatePrototype();
|
||||
functionPrototype = new FunctionPrototype(rootContext);
|
||||
regExpPrototype = new RegExpPrototype();
|
||||
errorPrototype = new ErrorPrototype();
|
||||
evalErrorPrototype = new EvalErrorPrototype(rootContext);
|
||||
rangeErrorPrototype = new RangeErrorPrototype(rootContext);
|
||||
referenceErrorPrototype = new ReferenceErrorPrototype(rootContext);
|
||||
syntaxErrorPrototype = new SyntaxErrorPrototype(rootContext);
|
||||
typeErrorPrototype = new TypeErrorPrototype(rootContext);
|
||||
uRIErrorPrototype = new URIErrorPrototype(rootContext);
|
||||
|
||||
stringPrototype->prototype = objectPrototype;
|
||||
numberPrototype->prototype = objectPrototype;
|
||||
booleanPrototype->prototype = objectPrototype;
|
||||
arrayPrototype->prototype = objectPrototype;
|
||||
datePrototype->prototype = objectPrototype;
|
||||
functionPrototype->prototype = objectPrototype;
|
||||
regExpPrototype->prototype = objectPrototype;
|
||||
errorPrototype->prototype = objectPrototype;
|
||||
evalErrorPrototype->prototype = errorPrototype;
|
||||
rangeErrorPrototype->prototype = errorPrototype;
|
||||
referenceErrorPrototype->prototype = errorPrototype;
|
||||
syntaxErrorPrototype->prototype = errorPrototype;
|
||||
typeErrorPrototype->prototype = errorPrototype;
|
||||
uRIErrorPrototype->prototype = errorPrototype;
|
||||
|
||||
objectCtor = Value::fromObject(new ObjectCtor(rootContext));
|
||||
stringCtor = Value::fromObject(new StringCtor(rootContext));
|
||||
numberCtor = Value::fromObject(new NumberCtor(rootContext));
|
||||
booleanCtor = Value::fromObject(new BooleanCtor(rootContext));
|
||||
arrayCtor = Value::fromObject(new ArrayCtor(rootContext));
|
||||
functionCtor = Value::fromObject(new FunctionCtor(rootContext));
|
||||
dateCtor = Value::fromObject(new DateCtor(rootContext));
|
||||
regExpCtor = Value::fromObject(new RegExpCtor(rootContext));
|
||||
errorCtor = Value::fromObject(new ErrorCtor(rootContext));
|
||||
evalErrorCtor = Value::fromObject(new EvalErrorCtor(rootContext));
|
||||
rangeErrorCtor = Value::fromObject(new RangeErrorCtor(rootContext));
|
||||
referenceErrorCtor = Value::fromObject(new ReferenceErrorCtor(rootContext));
|
||||
syntaxErrorCtor = Value::fromObject(new SyntaxErrorCtor(rootContext));
|
||||
typeErrorCtor = Value::fromObject(new TypeErrorCtor(rootContext));
|
||||
uRIErrorCtor = Value::fromObject(new URIErrorCtor(rootContext));
|
||||
|
||||
stringCtor.objectValue()->prototype = functionPrototype;
|
||||
numberCtor.objectValue()->prototype = functionPrototype;
|
||||
booleanCtor.objectValue()->prototype = functionPrototype;
|
||||
arrayCtor.objectValue()->prototype = functionPrototype;
|
||||
functionCtor.objectValue()->prototype = functionPrototype;
|
||||
dateCtor.objectValue()->prototype = functionPrototype;
|
||||
regExpCtor.objectValue()->prototype = functionPrototype;
|
||||
errorCtor.objectValue()->prototype = functionPrototype;
|
||||
evalErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
rangeErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
referenceErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
syntaxErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
typeErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
uRIErrorCtor.objectValue()->prototype = errorPrototype;
|
||||
|
||||
objectPrototype->init(rootContext, objectCtor);
|
||||
stringPrototype->init(rootContext, stringCtor);
|
||||
numberPrototype->init(rootContext, numberCtor);
|
||||
booleanPrototype->init(rootContext, booleanCtor);
|
||||
arrayPrototype->init(rootContext, arrayCtor);
|
||||
datePrototype->init(rootContext, dateCtor);
|
||||
functionPrototype->init(rootContext, functionCtor);
|
||||
regExpPrototype->init(rootContext, regExpCtor);
|
||||
errorPrototype->init(rootContext, errorCtor);
|
||||
evalErrorPrototype->init(rootContext, evalErrorCtor);
|
||||
rangeErrorPrototype->init(rootContext, rangeErrorCtor);
|
||||
referenceErrorPrototype->init(rootContext, referenceErrorCtor);
|
||||
syntaxErrorPrototype->init(rootContext, syntaxErrorCtor);
|
||||
typeErrorPrototype->init(rootContext, typeErrorCtor);
|
||||
uRIErrorPrototype->init(rootContext, uRIErrorCtor);
|
||||
|
||||
//
|
||||
// set up the global object
|
||||
//
|
||||
VM::Object *glo = newObject(/*rootContext*/);
|
||||
globalObject = Value::fromObject(glo);
|
||||
rootContext->activation = glo;
|
||||
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Number")), numberCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Boolean")), booleanCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Array")), arrayCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Function")), functionCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Date")), dateCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("RegExp")), regExpCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Error")), errorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("EvalError")), evalErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("RangeError")), rangeErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("ReferenceError")), referenceErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("SyntaxError")), syntaxErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("TypeError")), typeErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("URIError")), uRIErrorCtor);
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Math")), Value::fromObject(newMathObject(rootContext)));
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("undefined")), Value::undefinedValue());
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("NaN")), Value::fromDouble(nan("")));
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("Infinity")), Value::fromDouble(INFINITY));
|
||||
glo->__put__(rootContext, identifier(QStringLiteral("eval")), Value::fromObject(new EvalFunction(rootContext)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
ExecutionContext *ExecutionEngine::newContext()
|
||||
{
|
||||
return new ExecutionContext();
|
||||
}
|
||||
|
||||
String *ExecutionEngine::identifier(const QString &s)
|
||||
{
|
||||
String *&id = identifiers[s];
|
||||
if (! id)
|
||||
id = newString(s);
|
||||
return id;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *))
|
||||
{
|
||||
NativeFunction *f = new NativeFunction(scope, code);
|
||||
f->prototype = scope->engine->functionPrototype;
|
||||
return f;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, IR::Function *function)
|
||||
{
|
||||
ScriptFunction *f = new ScriptFunction(scope, function);
|
||||
Object *proto = scope->engine->newObject();
|
||||
proto->__put__(scope, scope->engine->id_constructor, Value::fromObject(f));
|
||||
f->__put__(scope, scope->engine->id_prototype, Value::fromObject(proto));
|
||||
f->prototype = scope->engine->functionPrototype;
|
||||
return f;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newObject()
|
||||
{
|
||||
Object *object = new Object();
|
||||
object->prototype = objectPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newObjectCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new ObjectCtor(ctx);
|
||||
}
|
||||
|
||||
String *ExecutionEngine::newString(const QString &s)
|
||||
{
|
||||
return new String(s);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newStringObject(const Value &value)
|
||||
{
|
||||
StringObject *object = new StringObject(value);
|
||||
object->prototype = stringPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newStringCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new StringCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newNumberObject(const Value &value)
|
||||
{
|
||||
NumberObject *object = new NumberObject(value);
|
||||
object->prototype = numberPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newNumberCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new NumberCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newBooleanObject(const Value &value)
|
||||
{
|
||||
Object *object = new BooleanObject(value);
|
||||
object->prototype = booleanPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newBooleanCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new BooleanCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newFunctionObject(ExecutionContext *ctx)
|
||||
{
|
||||
Object *object = new FunctionObject(ctx);
|
||||
object->prototype = functionPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newFunctionCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new FunctionCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newArrayObject()
|
||||
{
|
||||
ArrayObject *object = new ArrayObject();
|
||||
object->prototype = arrayPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newArrayObject(const Array &value)
|
||||
{
|
||||
ArrayObject *object = new ArrayObject(value);
|
||||
object->prototype = arrayPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newArrayCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new ArrayCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newDateObject(const Value &value)
|
||||
{
|
||||
Object *object = new DateObject(value);
|
||||
object->prototype = datePrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newDateCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new DateCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
|
||||
{
|
||||
bool global = (flags & IR::RegExp::RegExp_Global);
|
||||
QRegularExpression::PatternOptions options = 0;
|
||||
if (flags & IR::RegExp::RegExp_IgnoreCase)
|
||||
options |= QRegularExpression::CaseInsensitiveOption;
|
||||
if (flags & IR::RegExp::RegExp_Multiline)
|
||||
options |= QRegularExpression::MultilineOption;
|
||||
|
||||
Object *object = new RegExpObject(QRegularExpression(pattern, options), global);
|
||||
object->prototype = regExpPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
FunctionObject *ExecutionEngine::newRegExpCtor(ExecutionContext *ctx)
|
||||
{
|
||||
return new RegExpCtor(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newErrorObject(const Value &value)
|
||||
{
|
||||
ErrorObject *object = new ErrorObject(value);
|
||||
object->prototype = errorPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newMathObject(ExecutionContext *ctx)
|
||||
{
|
||||
MathObject *object = new MathObject(ctx);
|
||||
object->prototype = objectPrototype;
|
||||
return object;
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newActivationObject(ExecutionContext *ctx)
|
||||
{
|
||||
return new ActivationObject(ctx);
|
||||
}
|
||||
|
||||
Object *ExecutionEngine::newForEachIteratorObject(Object *o)
|
||||
{
|
||||
return new ForEachIteratorObject(o);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#define QMLJS_OBJECTS_H
|
||||
|
||||
#include "qmljs_runtime.h"
|
||||
#include "qmljs_engine.h"
|
||||
#include "qmljs_environment.h"
|
||||
#include "qv4array_p.h"
|
||||
#include "qv4codegen_p.h"
|
||||
|
||||
|
@ -50,7 +52,6 @@
|
|||
#include <QtCore/QRegularExpression>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <setjmp.h>
|
||||
|
||||
namespace QQmlJS {
|
||||
|
||||
|
@ -600,102 +601,6 @@ struct ArgumentsObject: Object {
|
|||
virtual PropertyDescriptor *__getPropertyDescriptor__(ExecutionContext *ctx, String *name, PropertyDescriptor *to_fill);
|
||||
};
|
||||
|
||||
struct ExecutionEngine
|
||||
{
|
||||
ExecutionContext *rootContext;
|
||||
Value globalObject;
|
||||
|
||||
Value objectCtor;
|
||||
Value stringCtor;
|
||||
Value numberCtor;
|
||||
Value booleanCtor;
|
||||
Value arrayCtor;
|
||||
Value functionCtor;
|
||||
Value dateCtor;
|
||||
Value regExpCtor;
|
||||
Value errorCtor;
|
||||
Value evalErrorCtor;
|
||||
Value rangeErrorCtor;
|
||||
Value referenceErrorCtor;
|
||||
Value syntaxErrorCtor;
|
||||
Value typeErrorCtor;
|
||||
Value uRIErrorCtor;
|
||||
|
||||
ObjectPrototype *objectPrototype;
|
||||
StringPrototype *stringPrototype;
|
||||
NumberPrototype *numberPrototype;
|
||||
BooleanPrototype *booleanPrototype;
|
||||
ArrayPrototype *arrayPrototype;
|
||||
FunctionPrototype *functionPrototype;
|
||||
DatePrototype *datePrototype;
|
||||
RegExpPrototype *regExpPrototype;
|
||||
ErrorPrototype *errorPrototype;
|
||||
EvalErrorPrototype *evalErrorPrototype;
|
||||
RangeErrorPrototype *rangeErrorPrototype;
|
||||
ReferenceErrorPrototype *referenceErrorPrototype;
|
||||
SyntaxErrorPrototype *syntaxErrorPrototype;
|
||||
TypeErrorPrototype *typeErrorPrototype;
|
||||
URIErrorPrototype *uRIErrorPrototype;
|
||||
|
||||
QHash<QString, String *> identifiers;
|
||||
|
||||
String *id_length;
|
||||
String *id_prototype;
|
||||
String *id_constructor;
|
||||
String *id_arguments;
|
||||
String *id___proto__;
|
||||
|
||||
struct ExceptionHandler {
|
||||
ExecutionContext *context;
|
||||
const uchar *code; // Interpreter state
|
||||
int targetTempIndex; // Interpreter state
|
||||
jmp_buf stackFrame;
|
||||
};
|
||||
|
||||
QVector<ExceptionHandler> unwindStack;
|
||||
|
||||
ExecutionEngine();
|
||||
|
||||
ExecutionContext *newContext();
|
||||
|
||||
String *identifier(const QString &s);
|
||||
|
||||
FunctionObject *newNativeFunction(ExecutionContext *scope, void (*code)(ExecutionContext *));
|
||||
FunctionObject *newScriptFunction(ExecutionContext *scope, IR::Function *function);
|
||||
|
||||
Object *newObject();
|
||||
FunctionObject *newObjectCtor(ExecutionContext *ctx);
|
||||
|
||||
String *newString(const QString &s);
|
||||
Object *newStringObject(const Value &value);
|
||||
FunctionObject *newStringCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newNumberObject(const Value &value);
|
||||
FunctionObject *newNumberCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newBooleanObject(const Value &value);
|
||||
FunctionObject *newBooleanCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newFunctionObject(ExecutionContext *ctx);
|
||||
FunctionObject *newFunctionCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newArrayObject();
|
||||
Object *newArrayObject(const Array &value);
|
||||
FunctionObject *newArrayCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newDateObject(const Value &value);
|
||||
FunctionObject *newDateCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newRegExpObject(const QString &pattern, int flags);
|
||||
FunctionObject *newRegExpCtor(ExecutionContext *ctx);
|
||||
|
||||
Object *newErrorObject(const Value &value);
|
||||
Object *newMathObject(ExecutionContext *ctx);
|
||||
Object *newActivationObject(ExecutionContext *ctx);
|
||||
|
||||
Object *newForEachIteratorObject(Object *o);
|
||||
};
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
||||
|
||||
|
|
|
@ -230,138 +230,6 @@ Value Value::property(ExecutionContext *ctx, String *name) const
|
|||
return isObject() ? objectValue()->__get__(ctx, name) : undefinedValue();
|
||||
}
|
||||
|
||||
void ExecutionContext::init(ExecutionEngine *eng)
|
||||
{
|
||||
engine = eng;
|
||||
parent = 0;
|
||||
arguments = 0;
|
||||
argumentCount = 0;
|
||||
locals = 0;
|
||||
activation = 0;
|
||||
thisObject = Value::nullValue();
|
||||
result = Value::undefinedValue();
|
||||
formals = 0;
|
||||
formalCount = 0;
|
||||
vars = 0;
|
||||
varCount = 0;
|
||||
}
|
||||
|
||||
PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp)
|
||||
{
|
||||
for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
|
||||
if (ctx->activation) {
|
||||
if (PropertyDescriptor *pd = ctx->activation->__getPropertyDescriptor__(this, name, tmp))
|
||||
return pd;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op)
|
||||
{
|
||||
for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) {
|
||||
if (ctx->activation) {
|
||||
if (ctx->activation->inplaceBinOp(value, name, op, this))
|
||||
return;
|
||||
}
|
||||
}
|
||||
throwReferenceError(Value::fromString(name));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwError(Value value)
|
||||
{
|
||||
result = value;
|
||||
__qmljs_builtin_throw(value, this);
|
||||
}
|
||||
|
||||
void ExecutionContext::throwError(const QString &message)
|
||||
{
|
||||
Value v = Value::fromString(this, message);
|
||||
throwError(Value::fromObject(engine->newErrorObject(v)));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwTypeError()
|
||||
{
|
||||
Value v = Value::fromString(this, QStringLiteral("Type error"));
|
||||
throwError(Value::fromObject(engine->newErrorObject(v)));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwUnimplemented(const QString &message)
|
||||
{
|
||||
Value v = Value::fromString(this, QStringLiteral("Unimplemented ") + message);
|
||||
throwError(Value::fromObject(engine->newErrorObject(v)));
|
||||
}
|
||||
|
||||
void ExecutionContext::throwReferenceError(Value value)
|
||||
{
|
||||
String *s = value.toString(this);
|
||||
QString msg = s->toQString() + QStringLiteral(" is not defined");
|
||||
throwError(Value::fromObject(engine->newErrorObject(Value::fromString(this, msg))));
|
||||
}
|
||||
|
||||
void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc)
|
||||
{
|
||||
engine = parent->engine;
|
||||
this->parent = f->scope;
|
||||
assert(this->parent == f->scope);
|
||||
result = Value::undefinedValue();
|
||||
|
||||
if (f->needsActivation)
|
||||
activation = engine->newActivationObject(this);
|
||||
else
|
||||
activation = 0;
|
||||
|
||||
thisObject = that;
|
||||
|
||||
formals = f->formalParameterList;
|
||||
formalCount = f->formalParameterCount;
|
||||
arguments = args;
|
||||
argumentCount = argc;
|
||||
if (f->needsActivation || argc < formalCount){
|
||||
arguments = new Value[qMax(argc, formalCount)];
|
||||
if (argc)
|
||||
std::copy(args, args + argc, arguments);
|
||||
if (argc < formalCount)
|
||||
std::fill(arguments + argc, arguments + formalCount, Value::undefinedValue());
|
||||
}
|
||||
vars = f->varList;
|
||||
varCount = f->varCount;
|
||||
locals = varCount ? new Value[varCount] : 0;
|
||||
if (varCount)
|
||||
std::fill(locals, locals + varCount, Value::undefinedValue());
|
||||
}
|
||||
|
||||
void ExecutionContext::leaveCallContext()
|
||||
{
|
||||
if (activation) {
|
||||
delete[] locals;
|
||||
locals = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutionContext::initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc)
|
||||
{
|
||||
initCallContext(parent, that, f, args, argc);
|
||||
}
|
||||
|
||||
void ExecutionContext::leaveConstructorContext(FunctionObject *f)
|
||||
{
|
||||
wireUpPrototype(f);
|
||||
leaveCallContext();
|
||||
}
|
||||
|
||||
void ExecutionContext::wireUpPrototype(FunctionObject *f)
|
||||
{
|
||||
assert(thisObject.isObject());
|
||||
result = thisObject;
|
||||
|
||||
Value proto = f->__get__(this, engine->id_prototype);
|
||||
thisObject.objectValue()->prototype = proto.objectValue();
|
||||
if (! thisObject.isObject())
|
||||
thisObject.objectValue()->prototype = engine->objectPrototype;
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Value __qmljs_init_closure(IR::Function *clos, ExecutionContext *ctx)
|
||||
|
|
|
@ -570,47 +570,6 @@ inline bool Value::sameValue(Value other) {
|
|||
|
||||
#include <qmljs_math.h>
|
||||
|
||||
struct ExecutionContext {
|
||||
ExecutionEngine *engine;
|
||||
ExecutionContext *parent;
|
||||
Object *activation;
|
||||
Value thisObject;
|
||||
Value *arguments;
|
||||
unsigned int argumentCount;
|
||||
Value *locals;
|
||||
Value result;
|
||||
String **formals;
|
||||
unsigned int formalCount;
|
||||
String **vars;
|
||||
unsigned int varCount;
|
||||
|
||||
PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp);
|
||||
void inplaceBitOp(Value value, String *name, BinOp op);
|
||||
|
||||
inline Value argument(unsigned int index = 0)
|
||||
{
|
||||
if (index < argumentCount)
|
||||
return arguments[index];
|
||||
return Value::undefinedValue();
|
||||
}
|
||||
|
||||
void init(ExecutionEngine *eng);
|
||||
|
||||
void initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc);
|
||||
void leaveCallContext();
|
||||
|
||||
void initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc);
|
||||
void leaveConstructorContext(FunctionObject *f);
|
||||
void wireUpPrototype(FunctionObject *f);
|
||||
|
||||
void throwError(Value value);
|
||||
void throwError(const QString &message);
|
||||
void throwTypeError();
|
||||
void throwReferenceError(Value value);
|
||||
void throwUnimplemented(const QString &message);
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
|
4
v4.pro
4
v4.pro
|
@ -13,6 +13,8 @@ LIBS += -rdynamic
|
|||
SOURCES += main.cpp \
|
||||
qv4codegen.cpp \
|
||||
qv4ir.cpp \
|
||||
qmljs_engine.cpp \
|
||||
qmljs_environment.cpp \
|
||||
qmljs_runtime.cpp \
|
||||
qmljs_objects.cpp \
|
||||
qv4syntaxchecker.cpp \
|
||||
|
@ -24,6 +26,8 @@ SOURCES += main.cpp \
|
|||
HEADERS += \
|
||||
qv4codegen_p.h \
|
||||
qv4ir_p.h \
|
||||
qmljs_engine.h \
|
||||
qmljs_environment.h \
|
||||
qmljs_runtime.h \
|
||||
qmljs_objects.h \
|
||||
qmljs_math.h \
|
||||
|
|
Loading…
Reference in New Issue