summaryrefslogtreecommitdiffstats
path: root/src/script/qscriptengine_p.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/qscriptengine_p.cpp')
-rw-r--r--src/script/qscriptengine_p.cpp2729
1 files changed, 0 insertions, 2729 deletions
diff --git a/src/script/qscriptengine_p.cpp b/src/script/qscriptengine_p.cpp
deleted file mode 100644
index 84a420d..0000000
--- a/src/script/qscriptengine_p.cpp
+++ /dev/null
@@ -1,2729 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtScript module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** 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, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, 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.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qscriptengine_p.h"
-
-#ifndef QT_NO_SCRIPT
-
-#include "qscriptvalueimpl_p.h"
-#include "qscriptcontext_p.h"
-#include "qscriptmember_p.h"
-#include "qscriptobject_p.h"
-#include "qscriptlexer_p.h"
-#include "qscriptnodepool_p.h"
-#include "qscriptparser_p.h"
-#include "qscriptcompiler_p.h"
-#include "qscriptvalueiteratorimpl_p.h"
-#include "qscriptecmaglobal_p.h"
-#include "qscriptecmamath_p.h"
-#include "qscriptecmaarray_p.h"
-#include "qscriptextenumeration_p.h"
-#include "qscriptsyntaxchecker_p.h"
-#include "qscriptsyntaxcheckresult_p.h"
-#include "qscriptclass.h"
-#include "qscriptclass_p.h"
-#include "qscriptengineagent.h"
-
-#include <QtCore/QDate>
-#include <QtCore/QDateTime>
-#include <QtCore/QRegExp>
-#include <QtCore/QStringList>
-#include <QtCore/QVariant>
-
-#ifndef QT_NO_QOBJECT
-#include "qscriptextensioninterface.h"
-#include <QtCore/QDir>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QTextStream>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QPluginLoader>
-#endif
-
-Q_DECLARE_METATYPE(QScriptValue)
-#ifndef QT_NO_QOBJECT
-Q_DECLARE_METATYPE(QObjectList)
-#endif
-Q_DECLARE_METATYPE(QList<int>)
-
-QT_BEGIN_NAMESPACE
-
-extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
-extern double qstrtod(const char *s00, char const **se, bool *ok);
-
-namespace QScript {
-
-QString numberToString(qsreal value)
-{
- if (qIsNaN(value))
- return QLatin1String("NaN");
-
- else if (qIsInf(value))
- return QLatin1String(value < 0 ? "-Infinity" : "Infinity");
-
- else if (value == 0)
- return QLatin1String("0");
-
- QByteArray buf;
- buf.reserve(80);
-
- int decpt;
- int sign;
- char *result = 0;
- (void) qdtoa(value, 0, 0, &decpt, &sign, 0, &result);
-
- if (! result)
- return QString();
-
- else if (decpt <= 0 && decpt > -6) {
-
- buf.fill('0', -decpt + 2 + sign);
-
- if (sign) // fix the sign.
- buf[0] = '-';
-
- buf[sign + 1] = '.';
- buf += result;
- }
-
- else {
- if (sign)
- buf += '-';
-
- buf += result;
- int length = buf.length() - sign;
-
- if (decpt <= 21 && decpt > 0) {
- if (length <= decpt)
- buf += QByteArray().fill('0', decpt - length);
- else
- buf.insert(decpt + sign, '.');
- }
-
- else if (result[0] >= '0' && result[0] <= '9') {
- if (length > 1)
- buf.insert(1 + sign, '.');
-
- buf += 'e';
- buf += (decpt >= 0) ? '+' : '-';
-
- int e = decpt - 1;
-
- if (e < 0)
- e = -e;
-
- if (e >= 100)
- buf += '0' + e / 100;
-
- if (e >= 10)
- buf += '0' + (e % 100) / 10;
-
- buf += '0' + e % 10;
- }
- }
-
- free(result);
-
- return QString::fromLatin1(buf);
-}
-
-static int toDigit(char c)
-{
- if ((c >= '0') && (c <= '9'))
- return c - '0';
- else if ((c >= 'a') && (c <= 'z'))
- return 10 + c - 'a';
- else if ((c >= 'A') && (c <= 'Z'))
- return 10 + c - 'A';
- return -1;
-}
-
-qsreal integerFromString(const char *buf, int size, int radix)
-{
- if (size == 0)
- return qSNaN();
-
- qsreal sign = 1.0;
- int i = 0;
- if (buf[0] == '+') {
- ++i;
- } else if (buf[0] == '-') {
- sign = -1.0;
- ++i;
- }
-
- if (((size-i) >= 2) && (buf[i] == '0')) {
- if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
- && (radix < 34)) {
- if ((radix != 0) && (radix != 16))
- return 0;
- radix = 16;
- i += 2;
- } else {
- if (radix == 0) {
- radix = 8;
- ++i;
- }
- }
- } else if (radix == 0) {
- radix = 10;
- }
-
- int j = i;
- for ( ; i < size; ++i) {
- int d = toDigit(buf[i]);
- if ((d == -1) || (d >= radix))
- break;
- }
- qsreal result;
- if (j == i) {
- if (!qstrcmp(buf, "Infinity"))
- result = qInf();
- else
- result = qSNaN();
- } else {
- result = 0;
- qsreal multiplier = 1;
- for (--i ; i >= j; --i, multiplier *= radix)
- result += toDigit(buf[i]) * multiplier;
- }
- result *= sign;
- return result;
-}
-
-qsreal integerFromString(const QString &str, int radix)
-{
- QByteArray ba = str.trimmed().toUtf8();
- return integerFromString(ba.constData(), ba.size(), radix);
-}
-
-qsreal numberFromString(const QString &repr)
-{
- QString str = repr.trimmed();
- if ((str.length() > 2) && (str.at(0) == QLatin1Char('0')) && (str.at(1).toUpper() == QLatin1Char('X')))
- return integerFromString(str.mid(2), 16);
- QByteArray latin1 = str.toLatin1();
- const char *data = latin1.constData();
- const char *eptr = 0;
- qsreal result = qstrtod(data, &eptr, 0);
- if (eptr == data) {
- if (str == QLatin1String("Infinity"))
- result = +qInf();
- else if (str == QLatin1String("+Infinity"))
- result = +qInf();
- else if (str == QLatin1String("-Infinity"))
- result = -qInf();
- else if (str.isEmpty())
- result = 0;
- else
- result = qSNaN();
- } else if (eptr != (data + latin1.length())) {
- result = qSNaN();
- }
- return result;
-}
-
-NodePool::NodePool(const QString &fileName, QScriptEnginePrivate *engine)
- : m_fileName(fileName), m_engine(engine)
-{
-#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
- m_id = engine->nextScriptId();
-#endif
-}
-
-NodePool::~NodePool()
-{
- qDeleteAll(m_codeCache);
- m_codeCache.clear();
-
-#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
- m_engine->notifyScriptUnload(id());
-#endif
-}
-
-Code *NodePool::createCompiledCode(AST::Node *node, CompilationUnit &compilation)
-{
- QHash<AST::Node*, Code*>::const_iterator it = m_codeCache.constFind(node);
- if (it != m_codeCache.constEnd())
- return it.value();
-
- Code *code = new Code();
- code->init(compilation, this);
-
- m_codeCache.insert(node, code);
- return code;
-}
-
-class EvalFunction : public QScriptFunction
-{
-public:
- EvalFunction(QScriptEnginePrivate *)
- { length = 1; }
-
- virtual ~EvalFunction() {}
-
- void evaluate(QScriptContextPrivate *context, const QString &contents,
- int lineNo, const QString &fileName, bool calledFromScript)
- {
- QScriptEnginePrivate *eng_p = context->engine();
-
- QExplicitlySharedDataPointer<NodePool> pool;
- pool = new NodePool(fileName, eng_p);
- eng_p->setNodePool(pool.data());
-
- QString errorMessage;
- int errorLineNumber;
- AST::Node *program = eng_p->createAbstractSyntaxTree(
- contents, lineNo, &errorMessage, &errorLineNumber);
-
- eng_p->setNodePool(0);
-
-#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
- eng_p->notifyScriptLoad(pool->id(), contents, fileName, lineNo);
-#endif
-
- Code *code = 0;
- if (program) {
- Compiler compiler(eng_p);
- compiler.setTopLevelCompiler(true);
- CompilationUnit compilation = compiler.compile(program);
- if (!compilation.isValid()) {
- errorMessage = compilation.errorMessage();
- errorLineNumber = compilation.errorLineNumber();
- } else {
- code = pool->createCompiledCode(program, compilation);
- }
- }
-
- if (!code) {
- context->errorLineNumber = errorLineNumber;
- context->currentLine = errorLineNumber;
-#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
- Code *oldCode = context->m_code;
- Code dummy;
- dummy.astPool = pool.data();
- context->m_code = &dummy; // so agents get the script ID
- bool wasEvaluating = eng_p->m_evaluating;
- eng_p->m_evaluating = true;
- eng_p->notifyFunctionEntry(context);
-#endif
- context->throwError(QScriptContext::SyntaxError, errorMessage);
-#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
- eng_p->notifyFunctionExit(context);
- eng_p->m_evaluating = wasEvaluating;
- context->m_code = oldCode;
-#endif
- return;
- }
-
- if (calledFromScript) {
- if (QScriptContextPrivate *pc = context->parentContext()) {
- context->setActivationObject(pc->activationObject());
- context->setThisObject(pc->thisObject());
- context->m_scopeChain = pc->m_scopeChain;
- }
- }
-
- const QScriptInstruction *iPtr = context->instructionPointer();
- context->execute(code);
- context->setInstructionPointer(iPtr);
- }
-
- virtual void execute(QScriptContextPrivate *context)
- {
- QScriptEnginePrivate *eng = context->engine();
- int lineNo = context->currentLine;
- if (lineNo == -1) {
- QScriptContextPrivate *pc = context->parentContext();
- if (pc)
- lineNo = pc->currentLine;
- else
- lineNo = 1;
- }
- QString fileName; // don't set this for now, we don't want to change the official eval() for now.
-
- if (context->argumentCount() == 0) {
- context->setReturnValue(eng->undefinedValue());
- } else {
- QScriptValueImpl arg = context->argument(0);
- if (arg.isString()) {
- QString contents = arg.toString();
- evaluate(context, contents, lineNo, fileName, /*calledFromScript=*/true);
- } else {
- context->setReturnValue(arg);
- }
- }
- }
-
- QString functionName() const
- {
- return QLatin1String("eval");
- }
-};
-
-class ArgumentsClassData: public QScriptClassData
-{
-
-public:
-
- static inline QScript::ArgumentsObjectData *get(const QScriptValueImpl &object)
- { return static_cast<QScript::ArgumentsObjectData*>(object.objectData()); }
-
- virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId,
- QScript::Member *member, QScriptValueImpl *base,
- QScript::AccessMode access);
- virtual bool get(const QScriptValueImpl &object, const QScript::Member &member,
- QScriptValueImpl *out_value);
- virtual bool put(QScriptValueImpl *object, const QScript::Member &member,
- const QScriptValueImpl &value);
- virtual void mark(const QScriptValueImpl &object, int generation);
- virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object);
-};
-
-class ArgumentsClassDataIterator: public QScriptClassDataIterator
-{
-public:
- ArgumentsClassDataIterator(ArgumentsObjectData *data);
- virtual ~ArgumentsClassDataIterator();
-
- virtual bool hasNext() const;
- virtual void next(QScript::Member *member);
-
- virtual bool hasPrevious() const;
- virtual void previous(QScript::Member *member);
-
- virtual void toFront();
- virtual void toBack();
-
-private:
- ArgumentsObjectData *m_data;
- uint m_pos;
-};
-
-bool ArgumentsClassData::resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId,
- QScript::Member *member, QScriptValueImpl *base,
- QScript::AccessMode /*access*/)
-{
- QString propertyName = object.engine()->toString(nameId);
- bool isNumber;
- quint32 index = propertyName.toUInt(&isNumber);
- if (isNumber) {
- QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object);
- if (index < data->length) {
- member->native(/*nameId=*/0, index, QScriptValue::SkipInEnumeration);
- *base = object;
- return true;
- }
- }
-
- return false;
-}
-
-bool ArgumentsClassData::get(const QScriptValueImpl &object, const QScript::Member &member,
- QScriptValueImpl *out_value)
-{
- QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object);
- if (member.nameId() == 0) {
- QScriptObject *activation_data = data->activation.objectValue();
- *out_value = activation_data->m_values[member.id()];
- return true;
- }
- return false;
-}
-
-bool ArgumentsClassData::put(QScriptValueImpl *object, const QScript::Member &member,
- const QScriptValueImpl &value)
-{
- Q_ASSERT(member.nameId() == 0);
- QScript::ArgumentsObjectData *data = ArgumentsClassData::get(*object);
- QScriptObject *activation_data = data->activation.objectValue();
- activation_data->m_values[member.id()] = value;
- return true;
-}
-
-void ArgumentsClassData::mark(const QScriptValueImpl &object, int generation)
-{
- QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object);
- data->activation.mark(generation);
-}
-
-QScriptClassDataIterator *ArgumentsClassData::newIterator(const QScriptValueImpl &object)
-{
- QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object);
- return new ArgumentsClassDataIterator(data);
-}
-
-ArgumentsClassDataIterator::ArgumentsClassDataIterator(ArgumentsObjectData *data)
- : m_data(data), m_pos(0)
-{
-}
-
-ArgumentsClassDataIterator::~ArgumentsClassDataIterator()
-{
-}
-
-bool ArgumentsClassDataIterator::hasNext() const
-{
- return m_pos < m_data->length;
-}
-
-void ArgumentsClassDataIterator::next(QScript::Member *member)
-{
- if (m_pos == m_data->length) {
- member->invalidate();
- } else {
- member->native(/*nameId=*/0, m_pos, QScriptValue::SkipInEnumeration);
- ++m_pos;
- }
-}
-
-bool ArgumentsClassDataIterator::hasPrevious() const
-{
- return (m_pos != 0);
-}
-
-void ArgumentsClassDataIterator::previous(QScript::Member *member)
-{
- if (m_pos == 0) {
- member->invalidate();
- } else {
- --m_pos;
- member->native(/*nameId=*/0, m_pos, QScriptValue::SkipInEnumeration);
- }
-}
-
-void ArgumentsClassDataIterator::toFront()
-{
- m_pos = 0;
-}
-
-void ArgumentsClassDataIterator::toBack()
-{
- m_pos = m_data->length;
-}
-
-} // namespace QScript
-
-const qsreal QScriptEnginePrivate::D16 = 65536.0;
-const qsreal QScriptEnginePrivate::D32 = 4294967296.0;
-
-QScriptEnginePrivate::~QScriptEnginePrivate()
-{
- while (!m_agents.isEmpty())
- delete m_agents.takeFirst();
-
- // invalidate values that we have references to
- {
- QHash<QScriptObject*, QScriptValuePrivate*>::const_iterator it;
- for (it = m_objectHandles.constBegin(); it != m_objectHandles.constEnd(); ++it)
- (*it)->invalidate();
- }
- {
- QHash<QScriptNameIdImpl*, QScriptValuePrivate*>::const_iterator it;
- for (it = m_stringHandles.constBegin(); it != m_stringHandles.constEnd(); ++it)
- (*it)->invalidate();
- }
- {
- QVector<QScriptValuePrivate*>::const_iterator it;
- for (it = m_otherHandles.constBegin(); it != m_otherHandles.constEnd(); ++it)
- (*it)->invalidate();
- }
-
- // invalidate interned strings that are known to the outside world
- {
- QHash<QScriptNameIdImpl*, QScriptStringPrivate*>::const_iterator it;
- for (it = m_internedStrings.constBegin(); it != m_internedStrings.constEnd(); ++it)
- it.value()->nameId = 0;
- }
-
- delete[] m_string_hash_base;
- qDeleteAll(m_stringRepository);
- qDeleteAll(m_tempStringRepository);
-
- if (tempStackBegin)
- delete[] tempStackBegin;
-
-#ifndef QT_NO_QOBJECT
- deletePendingQObjects();
- qDeleteAll(m_qobjectData);
-# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE
- qDeleteAll(m_cachedMetaObjects);
-# endif
-#endif
-
- qDeleteAll(m_allocated_classes);
-}
-
-QScript::AST::Node *QScriptEnginePrivate::changeAbstractSyntaxTree(QScript::AST::Node *prg)
-{
- QScript::AST::Node *was = m_abstractSyntaxTree;
- m_abstractSyntaxTree = prg;
- return was;
-}
-
-QScript::AST::Node *QScriptEnginePrivate::createAbstractSyntaxTree(
- const QString &source, int lineNumber, QString *errorMessage, int *errorLineNumber)
-{
- QScript::Lexer lex(this);
- setLexer(&lex);
- lex.setCode(source, lineNumber);
-
- QScriptParser parser;
-
- if (! parser.parse(this)) {
- if (errorMessage)
- *errorMessage = parser.errorMessage();
- if (errorLineNumber)
- *errorLineNumber = parser.errorLineNumber();
- return 0;
- }
-
- return abstractSyntaxTree();
-}
-
-void QScriptEnginePrivate::markObject(const QScriptValueImpl &object, int generation)
-{
- QScriptObject *instance = object.objectValue();
- QScript::GCBlock *block = QScript::GCBlock::get(instance);
-
- enum { MAX_GC_DEPTH = 32 };
-
- if (block->generation + 1 != generation)
- return;
-
- if (m_gc_depth >= MAX_GC_DEPTH) {
- // do the marking later
- m_markStack.append(object);
- return;
- }
-
- ++block->generation;
- ++m_gc_depth;
-
- if (QScriptClassData *data = object.classInfo()->data())
- data->mark(object, generation);
-
- if (instance->m_prototype.isObject())
- markObject(instance->m_prototype, generation);
-
- if (instance->m_scope.isObject())
- markObject(instance->m_scope, generation);
-
- const QScriptValueImpl &internalValue = instance->m_internalValue;
-
- if (internalValue.isValid()) {
- if (internalValue.isObject())
- markObject(internalValue, generation);
-
- else if (internalValue.isString())
- markString(internalValue.m_string_value, generation);
- }
-
- int garbage = 0;
-
- for (int i = 0; i < instance->memberCount(); ++i) {
- QScript::Member m;
- instance->member(i, &m);
-
- if (! m.isValid()) {
- ++garbage;
- continue;
- }
-
- Q_ASSERT(m.isObjectProperty());
-
- QScriptValueImpl child;
- instance->get(m, &child);
-
- if (m.nameId())
- markString(m.nameId(), generation);
-
- if (! child.isValid())
- continue;
-
- else if (child.isObject())
- markObject(child, generation);
-
- else if (child.isString())
- markString(child.m_string_value, generation);
- }
-
- --m_gc_depth;
-
- if (garbage < 128) // ###
- return;
-
- int j = 0;
- for (int i = 0; i < instance->memberCount(); ++i) {
- QScript::Member m;
- instance->member(i, &m);
-
- if (! m.isValid())
- continue;
-
- if (i != j) {
- instance->m_members[j].object(m.nameId(), j, m.flags());
- instance->m_values[j] = instance->m_values[i];
- }
- ++j;
- }
- //qDebug() << "==> old:" << instance->m_members.size() << "new:" << j;
- instance->m_members.resize(j);
- instance->m_values.resize(j);
-}
-
-void QScriptEnginePrivate::markFrame(QScriptContextPrivate *context, int generation)
-{
- QScriptValueImpl activation = context->activationObject();
- QScriptValueImpl thisObject = context->thisObject();
- QScriptValueImpl scopeChain = context->m_scopeChain;
- QScriptValueImpl callee = context->m_callee;
- QScriptValueImpl arguments = context->m_arguments;
-
- if (activation.isObject())
- markObject(activation, generation);
-
- if (scopeChain.isObject())
- markObject(scopeChain, generation);
-
- if (thisObject.isObject())
- markObject(thisObject, generation);
-
- if (callee.isObject())
- markObject(callee, generation);
-
- if (arguments.isObject())
- markObject(arguments, generation);
-
- if (context->returnValue().isValid()) {
- if (context->returnValue().isObject())
- markObject(context->returnValue(), generation);
-
- else if (context->returnValue().isString())
- markString(context->returnValue().m_string_value, generation);
- }
-
- if (context->baseStackPointer() != context->currentStackPointer()) {
- // mark the temp stack
-
- for (const QScriptValueImpl *it = context->baseStackPointer(); it != (context->currentStackPointer() + 1); ++it) {
- if (! it) {
- qWarning() << "no temp stack!!!";
- break;
- }
-
- else if (! it->isValid()) // ### assert?
- continue;
-
- else if (it->isObject())
- markObject(*it, generation);
-
- else if (it->isString())
- markString(it->m_string_value, generation);
- }
- }
-}
-
-bool QScriptEnginePrivate::isCollecting() const
-{
- return (m_gc_depth != -1) || objectAllocator.sweeping();
-}
-
-void QScriptEnginePrivate::maybeGC_helper(bool do_string_gc)
-{
- // qDebug() << "==>" << objectAllocator.newAllocatedBlocks() << "free:" << objectAllocator.freeBlocks();
- Q_ASSERT(m_gc_depth == -1);
- ++m_gc_depth;
-
- int generation = m_objectGeneration + 1;
-
- markObject(m_globalObject, generation);
-
- objectConstructor->mark(this, generation);
- numberConstructor->mark(this, generation);
- booleanConstructor->mark(this, generation);
- stringConstructor->mark(this, generation);
- dateConstructor->mark(this, generation);
- functionConstructor->mark(this, generation);
- arrayConstructor->mark(this, generation);
- regexpConstructor->mark(this, generation);
- errorConstructor->mark(this, generation);
- enumerationConstructor->mark(this, generation);
- variantConstructor->mark(this, generation);
-#ifndef QT_NO_QOBJECT
- qobjectConstructor->mark(this, generation);
- qmetaObjectConstructor->mark(this, generation);
-#endif
-
- {
- QScriptContextPrivate *current = currentContext();
- while (current != 0) {
- markFrame (current, generation);
- current = current->parentContext();
- }
- }
-
- {
- QHash<QScriptObject*, QScriptValuePrivate*>::const_iterator it;
- for (it = m_objectHandles.constBegin(); it != m_objectHandles.constEnd(); ++it)
- markObject((*it)->value, generation);
- }
-
- {
- QHash<QScriptNameIdImpl*, QScriptValuePrivate*>::const_iterator it;
- for (it = m_stringHandles.constBegin(); it != m_stringHandles.constEnd(); ++it)
- markString((*it)->value.stringValue(), generation);
- }
-
- {
- QHash<int, QScriptCustomTypeInfo>::const_iterator it;
- for (it = m_customTypes.constBegin(); it != m_customTypes.constEnd(); ++it)
- (*it).prototype.mark(generation);
- }
-
-#ifndef QT_NO_QOBJECT
-# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE
- {
- QHash<const QMetaObject*, QScriptMetaObject*>::const_iterator it;
- for (it = m_cachedMetaObjects.constBegin(); it != m_cachedMetaObjects.constEnd(); ++it) {
- {
- QList<QScriptNameIdImpl*> memberNames = (*it)->registeredMemberNames();
- QList<QScriptNameIdImpl*>::const_iterator it2;
- for (it2 = memberNames.constBegin(); it2 != memberNames.constEnd(); ++it2)
- markString(*it2, generation);
- }
- {
- QList<QScriptValueImpl> propertyAccessors = (*it)->registeredPropertyAccessors();
- QList<QScriptValueImpl>::const_iterator it2;
- for (it2 = propertyAccessors.constBegin(); it2 != propertyAccessors.constEnd(); ++it2)
- markObject(*it2, generation);
- }
- }
- }
-# endif
- processMarkStack(generation); // make sure everything is marked before marking qobject data
- {
- QHash<QObject*, QScriptQObjectData*>::const_iterator it;
- for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) {
- QScriptQObjectData *qdata = it.value();
- qdata->mark(generation);
- }
- }
-#endif
- processMarkStack(generation);
-
- Q_ASSERT(m_gc_depth == 0);
- --m_gc_depth;
-
- objectAllocator.sweep(generation);
-
- m_objectGeneration = generation;
-
- //qDebug() << "free blocks:" << objectAllocator.freeBlocks();
-
-#ifndef QT_NO_QOBJECT
- deletePendingQObjects();
-#endif
-
- if (! do_string_gc)
- return;
-
- {
- QHash<QScriptNameIdImpl*, QScriptStringPrivate*>::const_iterator it;
- for (it = m_internedStrings.constBegin(); it != m_internedStrings.constEnd(); ++it) {
- it.value()->nameId->used = true;
- }
- }
-
-#if 0
- qDebug() << "do_string_gc:" << do_string_gc
- << ((m_stringRepository.size() - m_oldStringRepositorySize) > 256)
- << ((m_tempStringRepository.size() - m_oldTempStringRepositorySize) > 2048);
-#endif
-
- QVector<QScriptNameIdImpl*> compressed;
- compressed.reserve(m_stringRepository.size());
-
- for (int i = 0; i < m_stringRepository.size(); ++i) {
- QScriptNameIdImpl *entry = m_stringRepository.at(i);
-
- if (entry->used || entry->persistent) {
- compressed.append(entry);
- entry->used = false;
- }
-
- else {
- //qDebug() << "deleted unique:" << entry->s;
- delete entry;
- }
- }
-
- // qDebug() << "before:" << m_stringRepository.size() << "after:" << compressed.size() << globalObject.objectValue()->m_members.size();
- m_stringRepository = compressed;
- rehashStringRepository(/*resize=*/ false);
- m_oldStringRepositorySize = m_stringRepository.size();
- m_newAllocatedStringRepositoryChars = 0;
-
- compressed.clear();
- for (int i = 0; i < m_tempStringRepository.size(); ++i) {
- QScriptNameIdImpl *entry = m_tempStringRepository.at(i);
-
- if (entry->used || entry->persistent) {
- compressed.append(entry);
- entry->used = false;
- }
-
- else {
- //qDebug() << "deleted:" << entry->s;
- delete entry;
- }
- }
-
- //qDebug() << "before:" << m_tempStringRepository.size() << "after:" << compressed.size();
-
- m_tempStringRepository = compressed;
- m_oldTempStringRepositorySize = m_tempStringRepository.size();
- m_newAllocatedTempStringRepositoryChars = 0;
-}
-
-void QScriptEnginePrivate::processMarkStack(int generation)
-{
- // mark the objects we couldn't process due to recursion depth
- while (!m_markStack.isEmpty())
- markObject(m_markStack.takeLast(), generation);
-}
-
-void QScriptEnginePrivate::evaluate(QScriptContextPrivate *context, const QString &contents, int lineNumber, const QString &fileName)
-{
- // ### try to remove cast
- QScript::EvalFunction *evalFunction = static_cast<QScript::EvalFunction*>(m_evalFunction);
- evalFunction->evaluate(context, contents, lineNumber, fileName, /*calledFromScript=*/ false);
-}
-
-qsreal QScriptEnginePrivate::convertToNativeDouble_helper(const QScriptValueImpl &value)
-{
- switch (value.type()) {
- case QScript::InvalidType:
- Q_ASSERT(value.isValid());
- break;
-
- case QScript::UndefinedType:
- case QScript::PointerType:
- break;
-
- case QScript::NullType:
- return 0;
-
- case QScript::BooleanType:
- return value.m_bool_value;
-
- case QScript::IntegerType:
- case QScript::ReferenceType:
- return value.m_int_value;
-
- case QScript::NumberType:
- return value.m_number_value;
-
- case QScript::StringType:
- return QScript::numberFromString(toString(value.m_string_value));
-
- case QScript::ObjectType: {
- QScriptValueImpl p = value.engine()->toPrimitive(value, QScriptValueImpl::NumberTypeHint);
- if (! p.isValid() || p.isObject())
- break;
-
- return convertToNativeDouble(p);
- }
-
- case QScript::LazyStringType:
- return QScript::numberFromString(*value.m_lazy_string_value);
-
- } // switch
-
- return qSNaN();
-}
-
-bool QScriptEnginePrivate::convertToNativeBoolean_helper(const QScriptValueImpl &value)
-{
- switch (value.type()) {
- case QScript::InvalidType:
- Q_ASSERT(value.isValid());
- return false;
-
- case QScript::UndefinedType:
- case QScript::PointerType:
- case QScript::NullType:
- case QScript::ReferenceType:
- return false;
-
- case QScript::BooleanType:
- return value.m_bool_value;
-
- case QScript::IntegerType:
- return value.m_int_value != 0;
-
- case QScript::NumberType:
- return value.m_number_value != 0 && !qIsNaN(value.m_number_value);
-
- case QScript::StringType:
- return toString(value.m_string_value).length() != 0;
-
- case QScript::ObjectType:
- return true;
-
- case QScript::LazyStringType:
- return value.m_lazy_string_value->length() != 0;
-
- } // switch
-
- return false;
-}
-
-QString QScriptEnginePrivate::convertToNativeString_helper(const QScriptValueImpl &value)
-{
- static QStringList predefined;
- if (predefined.isEmpty()) {
- predefined.append(QString::fromLatin1("undefined"));
- predefined.append(QString::fromLatin1("null"));
- predefined.append(QString::fromLatin1("true"));
- predefined.append(QString::fromLatin1("false"));
- predefined.append(QString::fromLatin1("pointer"));
- }
-
- switch (value.type()) {
- case QScript::InvalidType:
- Q_ASSERT(value.isValid());
- return QString();
-
- case QScript::UndefinedType:
- return predefined.at(0);
-
- case QScript::NullType:
- return predefined.at(1);
-
- case QScript::BooleanType:
- return value.m_bool_value ? predefined.at(2) : predefined.at(3);
-
- case QScript::IntegerType:
- return QString::number(value.m_int_value);
-
- case QScript::NumberType:
- return QScript::numberToString(value.m_number_value);
-
- case QScript::PointerType:
- return predefined.at(4);
-
- case QScript::StringType:
- return toString(value.m_string_value);
-
- case QScript::ReferenceType:
- return QString();
-
- case QScript::ObjectType: {
- QScriptValueImpl p = value.engine()->toPrimitive(value, QScriptValueImpl::StringTypeHint);
-
- if (!p.isValid() || strictlyEquals(p, value))
- return p.classInfo()->name();
-
- return convertToNativeString(p);
- }
-
- case QScript::LazyStringType:
- return *value.m_lazy_string_value;
-
- } // switch
-
- return QString();
-}
-
-QScriptValueImpl QScriptEnginePrivate::toObject_helper(const QScriptValueImpl &value)
-{
- QScriptValueImpl result;
- switch (value.type()) {
- case QScript::BooleanType:
- booleanConstructor->newBoolean(&result, value.m_bool_value);
- break;
-
- case QScript::NumberType:
- numberConstructor->newNumber(&result, value.m_number_value);
- break;
-
- case QScript::StringType:
- stringConstructor->newString(&result, value.m_string_value->s);
- break;
-
- case QScript::LazyStringType:
- stringConstructor->newString(&result, *value.m_lazy_string_value);
- break;
-
- case QScript::InvalidType:
- case QScript::UndefinedType:
- case QScript::NullType:
- case QScript::IntegerType:
- case QScript::ReferenceType:
- case QScript::PointerType:
- case QScript::ObjectType:
- break;
- } // switch
-
- return result;
-}
-
-// [[defaultValue]]
-QScriptValueImpl QScriptEnginePrivate::toPrimitive_helper(const QScriptValueImpl &object,
- QScriptValueImpl::TypeHint hint)
-{
- QScriptNameIdImpl *functionIds[2];
-
- if ((hint == QScriptValueImpl::NumberTypeHint)
- || (hint == QScriptValueImpl::NoTypeHint
- && object.classInfo() != dateConstructor->classInfo())) {
- functionIds[0] = idTable()->id_valueOf;
- functionIds[1] = idTable()->id_toString;
- } else {
- functionIds[0] = idTable()->id_toString;
- functionIds[1] = idTable()->id_valueOf;
- }
-
- for (int i = 0; i < 2; ++i) {
- QScriptValueImpl base;
- QScript::Member member;
-
- if (! object.resolve(functionIds[i], &member, &base, QScriptValue::ResolvePrototype, QScript::Read))
- return object;
-
- QScriptValueImpl f_valueOf;
- base.get(member, &f_valueOf);
-
- if (QScriptFunction *foo = convertToNativeFunction(f_valueOf)) {
- QScriptContextPrivate *me = pushContext();
- QScriptValueImpl activation;
- newActivation(&activation);
- if (f_valueOf.scope().isValid())
- activation.setScope(f_valueOf.scope());
- else
- activation.setScope(m_globalObject);
- me->setActivationObject(activation);
- me->setThisObject(object);
- me->m_callee = f_valueOf;
- foo->execute(me);
- QScriptValueImpl result = me->returnValue();
- bool exception = (me->state() == QScriptContext::ExceptionState);
- popContext();
- if (exception || (result.isValid() && !result.isObject()))
- return result;
- }
- }
-
- return object;
-}
-
-void QScriptEnginePrivate::rehashStringRepository(bool resize)
-{
- if (resize) {
- delete[] m_string_hash_base;
- m_string_hash_size <<= 1; // ### use primes
-
- m_string_hash_base = new QScriptNameIdImpl* [m_string_hash_size];
- }
-
- memset(m_string_hash_base, 0, sizeof(QScriptNameIdImpl*) * m_string_hash_size);
-
- for (int index = 0; index < m_stringRepository.size(); ++index) {
- QScriptNameIdImpl *entry = m_stringRepository.at(index);
- uint h = _q_scriptHash(entry->s) % m_string_hash_size;
- entry->h = h;
- entry->next = m_string_hash_base[h];
- m_string_hash_base[h] = entry;
- }
-}
-
-QScriptNameIdImpl *QScriptEnginePrivate::insertStringEntry(const QString &s)
-{
- QScriptNameIdImpl *entry = new QScriptNameIdImpl(s);
- entry->unique = true;
- m_stringRepository.append(entry);
- m_newAllocatedStringRepositoryChars += s.length();
-
- uint h = _q_scriptHash(s) % m_string_hash_size;
- entry->h = h;
- entry->next = m_string_hash_base[h];
- m_string_hash_base[h] = entry;
-
- if (m_stringRepository.count() == m_string_hash_size)
- rehashStringRepository();
-
- return entry;
-}
-
-QScriptValueImpl QScriptEnginePrivate::call(const QScriptValueImpl &callee,
- const QScriptValueImpl &thisObject,
- const QScriptValueImplList &args,
- bool asConstructor)
-{
- QScriptFunction *function = callee.toFunction();
- Q_ASSERT(function);
-
- if (++m_callDepth == m_maxCallDepth) {
- QScriptContextPrivate *ctx_p = currentContext();
- return ctx_p->throwError(QLatin1String("call stack overflow"));
- }
-
- QScriptContextPrivate *nested = pushContext();
- // set up the temp stack
- if (! nested->tempStack)
- nested->stackPtr = nested->tempStack = tempStackBegin;
-
- newActivation(&nested->m_activation);
- if (callee.m_object_value->m_scope.isValid())
- nested->m_activation.m_object_value->m_scope = callee.m_object_value->m_scope;
- else
- nested->m_activation.m_object_value->m_scope = m_globalObject;
-
- QScriptObject *activation_data = nested->m_activation.m_object_value;
-
- int formalCount = function->formals.count();
- int argc = args.count();
- int mx = qMax(formalCount, argc);
- activation_data->m_members.resize(mx);
- activation_data->m_values.resize(mx);
- for (int i = 0; i < mx; ++i) {
- QScriptNameIdImpl *nameId = 0;
- if (i < formalCount)
- nameId = function->formals.at(i);
-
- activation_data->m_members[i].object(nameId, i, QScriptValue::SkipInEnumeration);
- QScriptValueImpl arg = (i < argc) ? args.at(i) : m_undefinedValue;
- if (arg.isValid() && arg.engine() && (arg.engine() != this)) {
- qWarning("QScriptValue::call() failed: "
- "cannot call function with argument created in "
- "a different engine");
- popContext();
- return QScriptValueImpl();
- }
- activation_data->m_values[i] = arg.isValid() ? arg : m_undefinedValue;
- }
-
- nested->argc = argc;
- QVector<QScriptValueImpl> argsv = args.toVector();
- nested->args = const_cast<QScriptValueImpl*> (argsv.constData());
-
- if (thisObject.isObject())
- nested->m_thisObject = thisObject;
- else
- nested->m_thisObject = m_globalObject;
- nested->m_callee = callee;
- nested->m_calledAsConstructor = asConstructor;
-
- nested->m_result = m_undefinedValue;
- function->execute(nested);
- --m_callDepth;
- QScriptValueImpl result = nested->m_result;
- nested->args = 0;
- popContext();
-
- return result;
-}
-
-QScriptValueImpl QScriptEnginePrivate::call(const QScriptValueImpl &callee,
- const QScriptValueImpl &thisObject,
- const QScriptValueImpl &args,
- bool asConstructor)
-{
- QScriptValueImplList argsList;
- if (QScript::Ecma::Array::Instance *arr = arrayConstructor->get(args)) {
- QScript::Array actuals = arr->value;
- for (quint32 i = 0; i < actuals.count(); ++i) {
- QScriptValueImpl a = actuals.at(i);
- if (! a.isValid())
- argsList << undefinedValue();
- else
- argsList << a;
- }
- } else if (args.classInfo() == m_class_arguments) {
- QScript::ArgumentsObjectData *arguments;
- arguments = static_cast<QScript::ArgumentsObjectData*> (args.objectData());
- QScriptObject *activation = arguments->activation.objectValue();
- for (uint i = 0; i < arguments->length; ++i)
- argsList << activation->m_values[i];
- } else if (!(args.isUndefined() || args.isNull())) {
- return currentContext()->throwError(
- QScriptContext::TypeError,
- QLatin1String("QScriptValue::call(): arguments must be an array"));
- }
- return call(callee, thisObject, argsList, asConstructor);
-}
-
-QScriptValueImpl QScriptEnginePrivate::arrayFromStringList(const QStringList &lst)
-{
- QScriptValueImpl arr = newArray(lst.size());
- for (int i = 0; i < lst.size(); ++i)
- arr.setProperty(i, QScriptValueImpl(this, lst.at(i)));
- return arr;
-}
-
-QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValueImpl &arr)
-{
- QStringList lst;
- uint len = arr.property(QLatin1String("length")).toUInt32();
- for (uint i = 0; i < len; ++i)
- lst.append(arr.property(i).toString());
- return lst;
-}
-
-QScriptValueImpl QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst)
-{
- QScriptValueImpl arr = newArray(lst.size());
- for (int i = 0; i < lst.size(); ++i)
- arr.setProperty(i, valueFromVariant(lst.at(i)));
- return arr;
-}
-
-QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValueImpl &arr)
-{
- QVariantList lst;
- uint len = arr.property(QLatin1String("length")).toUInt32();
- for (uint i = 0; i < len; ++i)
- lst.append(arr.property(i).toVariant());
- return lst;
-}
-
-QScriptValueImpl QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap)
-{
- QScriptValueImpl obj = newObject();
- QVariantMap::const_iterator it;
- for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
- obj.setProperty(it.key(), valueFromVariant(it.value()));
- return obj;
-}
-
-QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValueImpl &obj)
-{
- QVariantMap vmap;
- QScriptValueIteratorImpl it(obj);
- while (it.hasNext()) {
- it.next();
- vmap.insert(it.name(), it.value().toVariant());
- }
- return vmap;
-}
-
-QScriptValueImpl QScriptEnginePrivate::create(int type, const void *ptr)
-{
- Q_Q(QScriptEngine);
- Q_ASSERT(ptr);
- QScriptValueImpl result;
- QScriptCustomTypeInfo info = m_customTypes.value(type);
- if (info.marshal) {
- result = toImpl(info.marshal(q, ptr));
- } else {
- // check if it's one of the types we know
- switch (QMetaType::Type(type)) {
- case QMetaType::Void:
- result = m_undefinedValue;
- break;
- case QMetaType::Bool:
- result = QScriptValueImpl(*reinterpret_cast<const bool*>(ptr));
- break;
- case QMetaType::Int:
- result = QScriptValueImpl(*reinterpret_cast<const int*>(ptr));
- break;
- case QMetaType::UInt:
- result = QScriptValueImpl(*reinterpret_cast<const uint*>(ptr));
- break;
- case QMetaType::LongLong:
- result = QScriptValueImpl(qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
- break;
- case QMetaType::ULongLong:
-#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
-#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
- result = QScriptValueImpl(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
- result = QScriptValueImpl(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
-#else
- result = QScriptValueImpl(qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
-#endif
- break;
- case QMetaType::Double:
- result = QScriptValueImpl(*reinterpret_cast<const double*>(ptr));
- break;
- case QMetaType::QString:
- result = QScriptValueImpl(this, *reinterpret_cast<const QString*>(ptr));
- break;
- case QMetaType::Float:
- result = QScriptValueImpl(*reinterpret_cast<const float*>(ptr));
- break;
- case QMetaType::Short:
- result = QScriptValueImpl(*reinterpret_cast<const short*>(ptr));
- break;
- case QMetaType::UShort:
- result = QScriptValueImpl(*reinterpret_cast<const unsigned short*>(ptr));
- break;
- case QMetaType::Char:
- result = QScriptValueImpl(*reinterpret_cast<const char*>(ptr));
- break;
- case QMetaType::UChar:
- result = QScriptValueImpl(*reinterpret_cast<const unsigned char*>(ptr));
- break;
- case QMetaType::QChar:
- result = QScriptValueImpl((*reinterpret_cast<const QChar*>(ptr)).unicode());
- break;
- case QMetaType::QStringList:
- result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr));
- break;
- case QMetaType::QVariantList:
- result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr));
- break;
- case QMetaType::QVariantMap:
- result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr));
- break;
- case QMetaType::QDateTime: {
- QDateTime dateTime = *reinterpret_cast<const QDateTime *>(ptr);
- dateConstructor->newDate(&result, dateTime);
- } break;
- case QMetaType::QDate: {
- QDate date = *reinterpret_cast<const QDate *>(ptr);
- dateConstructor->newDate(&result, date);
- } break;
-#ifndef QT_NO_REGEXP
- case QMetaType::QRegExp: {
- QRegExp rx = *reinterpret_cast<const QRegExp *>(ptr);
- regexpConstructor->newRegExp(&result, rx);
- } break;
-#endif
-#ifndef QT_NO_QOBJECT
- case QMetaType::QObjectStar:
- case QMetaType::QWidgetStar:
- newQObject(&result, *reinterpret_cast<QObject* const *>(ptr));
- break;
-#endif
- default:
- if (type == qMetaTypeId<QScriptValue>()) {
- result = toImpl(*reinterpret_cast<const QScriptValue*>(ptr));
- if (!result.isValid())
- result = m_undefinedValue;
- }
-
-#ifndef QT_NO_QOBJECT
- // lazy registration of some common list types
- else if (type == qMetaTypeId<QObjectList>()) {
- qScriptRegisterSequenceMetaType<QObjectList>(q);
- return create(type, ptr);
- }
-#endif
- else if (type == qMetaTypeId<QList<int> >()) {
- qScriptRegisterSequenceMetaType<QList<int> >(q);
- return create(type, ptr);
- }
-
- else {
- QByteArray typeName = QMetaType::typeName(type);
- if (typeName == "QVariant")
- result = valueFromVariant(*reinterpret_cast<const QVariant*>(ptr));
- else if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
- result = nullValue();
- else
- newVariant(&result, QVariant(type, ptr));
- }
- }
- }
- if (result.isObject() && info.prototype.isValid()
- && strictlyEquals(result.prototype(), objectConstructor->publicPrototype)) {
- result.setPrototype(info.prototype);
- }
- return result;
-}
-
-bool QScriptEnginePrivate::convert(const QScriptValueImpl &value,
- int type, void *ptr,
- QScriptEnginePrivate *eng)
-{
- if (!eng)
- eng = value.engine();
- if (eng) {
- QScriptCustomTypeInfo info = eng->m_customTypes.value(type);
- if (info.demarshal) {
- info.demarshal(eng->toPublic(value), ptr);
- return true;
- }
- }
-
- // check if it's one of the types we know
- switch (QMetaType::Type(type)) {
- case QMetaType::Bool:
- *reinterpret_cast<bool*>(ptr) = value.toBoolean();
- return true;
- case QMetaType::Int:
- *reinterpret_cast<int*>(ptr) = value.toInt32();
- return true;
- case QMetaType::UInt:
- *reinterpret_cast<uint*>(ptr) = value.toUInt32();
- return true;
- case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger());
- return true;
- case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger());
- return true;
- case QMetaType::Double:
- *reinterpret_cast<double*>(ptr) = value.toNumber();
- return true;
- case QMetaType::QString:
- if (value.isUndefined() || value.isNull())
- *reinterpret_cast<QString*>(ptr) = QString();
- else
- *reinterpret_cast<QString*>(ptr) = value.toString();
- return true;
- case QMetaType::Float:
- *reinterpret_cast<float*>(ptr) = value.toNumber();
- return true;
- case QMetaType::Short:
- *reinterpret_cast<short*>(ptr) = short(value.toInt32());
- return true;
- case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16();
- return true;
- case QMetaType::Char:
- *reinterpret_cast<char*>(ptr) = char(value.toInt32());
- return true;
- case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32());
- return true;
- case QMetaType::QChar:
- if (value.isString()) {
- QString str = value.toString();
- *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0);
- } else {
- *reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16());
- }
- return true;
- case QMetaType::QDateTime:
- if (value.isDate()) {
- *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime();
- return true;
- } break;
- case QMetaType::QDate:
- if (value.isDate()) {
- *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date();
- return true;
- } break;
-#ifndef QT_NO_REGEXP
- case QMetaType::QRegExp:
- if (value.isRegExp()) {
- *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp();
- return true;
- } break;
-#endif
-#ifndef QT_NO_QOBJECT
- case QMetaType::QObjectStar:
- if (value.isQObject() || value.isNull()) {
- *reinterpret_cast<QObject* *>(ptr) = value.toQObject();
- return true;
- } break;
- case QMetaType::QWidgetStar:
- if (value.isQObject() || value.isNull()) {
- QObject *qo = value.toQObject();
- if (!qo || qo->isWidgetType()) {
- *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo);
- return true;
- }
- } break;
-#endif
- case QMetaType::QStringList:
- if (value.isArray()) {
- *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value);
- return true;
- } break;
- case QMetaType::QVariantList:
- if (value.isArray()) {
- *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value);
- return true;
- } break;
- case QMetaType::QVariantMap:
- if (value.isObject()) {
- *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value);
- return true;
- } break;
- default:
- ;
- }
-
- QByteArray name = QMetaType::typeName(type);
-#ifndef QT_NO_QOBJECT
- if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr)))
- return true;
-#endif
- if (value.isVariant() && name.endsWith('*')) {
- int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value.variantValue();
- if (valueType == var.userType()) {
- *reinterpret_cast<void* *>(ptr) = var.data();
- return true;
- } else {
- // look in the prototype chain
- QScriptValueImpl proto = value.prototype();
- while (proto.isObject()) {
- bool canCast = false;
- if (proto.isVariant()) {
- canCast = (type == proto.variantValue().userType())
- || (valueType && (valueType == proto.variantValue().userType()));
- }
-#ifndef QT_NO_QOBJECT
- else if (proto.isQObject()) {
- QByteArray className = name.left(name.size()-1);
- if (QObject *qobject = proto.toQObject())
- canCast = qobject->qt_metacast(className) != 0;
- }
-#endif
- if (canCast) {
- QByteArray varTypeName = QMetaType::typeName(var.userType());
- if (varTypeName.endsWith('*'))
- *reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data());
- else
- *reinterpret_cast<void* *>(ptr) = var.data();
- return true;
- }
- proto = proto.prototype();
- }
- }
- } else if (value.isNull() && name.endsWith('*')) {
- *reinterpret_cast<void* *>(ptr) = 0;
- return true;
- } else if (type == qMetaTypeId<QScriptValue>()) {
- if (!eng)
- return false;
- *reinterpret_cast<QScriptValue*>(ptr) = eng->toPublic(value);
- return true;
- } else if (name == "QVariant") {
- *reinterpret_cast<QVariant*>(ptr) = value.toVariant();
- return true;
- }
-
- // lazy registration of some common list types
-#ifndef QT_NO_QOBJECT
- else if (type == qMetaTypeId<QObjectList>()) {
- if (!eng)
- return false;
- qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
- return convert(value, type, ptr, eng);
- }
-#endif
- else if (type == qMetaTypeId<QList<int> >()) {
- if (!eng)
- return false;
- qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
- return convert(value, type, ptr, eng);
- }
-
-#if 0
- if (!name.isEmpty()) {
- qWarning("QScriptEngine::convert: unable to convert value to type `%s'",
- name.constData());
- }
-#endif
- return false;
-}
-
-QScriptEngine::DemarshalFunction QScriptEnginePrivate::demarshalFunction(int type) const
-{
- return m_customTypes.value(type).demarshal;
-}
-
-QScriptValuePrivate *QScriptEnginePrivate::registerValue(const QScriptValueImpl &value)
-{
- if (value.isString()) {
- QScriptNameIdImpl *id = value.stringValue();
- QScriptValuePrivate *p = m_stringHandles.value(id);
- if (p)
- return p;
- p = m_handleRepository.get();
- p->engine = q_func();
- p->value = value;
- m_stringHandles.insert(id, p);
- return p;
- } else if (value.isObject()) {
- QScriptObject *instance = value.objectValue();
- QScriptValuePrivate *p = m_objectHandles.value(instance);
- if (p)
- return p;
- p = m_handleRepository.get();
- p->engine = q_func();
- p->value = value;
- m_objectHandles.insert(instance, p);
- return p;
- }
- QScriptValuePrivate *p = m_handleRepository.get();
- p->engine = q_func();
- p->value = value;
- m_otherHandles.append(p);
- return p;
-}
-
-QScriptEnginePrivate::QScriptEnginePrivate()
-{
- m_undefinedValue = QScriptValueImpl(QScriptValue::UndefinedValue);
- m_nullValue = QScriptValueImpl(QScriptValue::NullValue);
-
- m_evaluating = false;
- m_abort = false;
- m_callDepth = 0;
-#if defined(Q_OS_WIN)
- m_maxCallDepth = 88;
-#elif defined(Q_OS_MAC)
- m_maxCallDepth = 640;
-#elif defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6)
- m_maxCallDepth = 360;
-#else
- m_maxCallDepth = 512;
-#endif
- m_oldStringRepositorySize = 0;
- m_oldTempStringRepositorySize = 0;
- m_newAllocatedStringRepositoryChars = 0;
- m_newAllocatedTempStringRepositoryChars = 0;
- m_context = 0;
- m_abstractSyntaxTree = 0;
- m_lexer = 0;
- m_scriptCounter = 0;
- m_agent = 0;
- m_objectGeneration = 0;
- m_class_prev_id = QScriptClassInfo::CustomType;
- m_next_object_id = 0;
- m_gc_depth = -1;
-
- objectConstructor = 0;
- numberConstructor = 0;
- booleanConstructor = 0;
- stringConstructor = 0;
- dateConstructor = 0;
- functionConstructor = 0;
- arrayConstructor = 0;
- regexpConstructor = 0;
- errorConstructor = 0;
- enumerationConstructor = 0;
- variantConstructor = 0;
- qobjectConstructor = 0;
- qmetaObjectConstructor = 0;
-
- m_processEventsInterval = -1;
- m_nextProcessEvents = 0;
- m_processEventIncr = 0;
-
- m_stringRepository.reserve(DefaultHashSize);
- m_string_hash_size = DefaultHashSize;
- m_string_hash_base = new QScriptNameIdImpl* [m_string_hash_size];
- memset(m_string_hash_base, 0, sizeof(QScriptNameIdImpl*) * m_string_hash_size);
-
- tempStackBegin = 0;
-}
-
-void QScriptEnginePrivate::init()
-{
- qMetaTypeId<QScriptValue>();
- qMetaTypeId<QList<int> >();
-#ifndef QT_NO_QOBJECT
- qMetaTypeId<QObjectList>();
-#endif
-
- m_class_prev_id = QScriptClassInfo::CustomType;
- m_class_object = registerClass(QLatin1String("Object"), QScriptClassInfo::ObjectType);
- m_class_function = registerClass(QLatin1String("Function"), QScriptClassInfo::FunctionType);
- m_class_activation = registerClass(QLatin1String("activation"), QScriptClassInfo::ActivationType);
-
- m_class_arguments = registerClass(QLatin1String("arguments"), QScript::ObjectType);
- m_class_arguments->setData(new QScript::ArgumentsClassData());
-
- m_class_with = registerClass(QLatin1String("__qscript_internal_with"), QScript::ObjectType);
-
- // public name ids
- m_id_table.id_constructor = nameId(QLatin1String("constructor"), true);
- m_id_table.id_false = nameId(QLatin1String("false"), true);
- m_id_table.id_null = nameId(QLatin1String("null"), true);
- m_id_table.id_object = nameId(QLatin1String("object"), true);
- m_id_table.id_pointer = nameId(QLatin1String("pointer"), true);
- m_id_table.id_prototype = nameId(QLatin1String("prototype"), true);
- m_id_table.id_arguments = nameId(QLatin1String("arguments"), true);
- m_id_table.id_this = nameId(QLatin1String("this"), true);
- m_id_table.id_toString = nameId(QLatin1String("toString"), true);
- m_id_table.id_true = nameId(QLatin1String("true"), true);
- m_id_table.id_undefined = nameId(QLatin1String("undefined"), true);
- m_id_table.id_valueOf = nameId(QLatin1String("valueOf"), true);
- m_id_table.id_length = nameId(QLatin1String("length"), true);
- m_id_table.id_callee = nameId(QLatin1String("callee"), true);
- m_id_table.id___proto__ = nameId(QLatin1String("__proto__"), true);
- m_id_table.id___qt_sender__ = nameId(QLatin1String("__qt_sender__"), true);
-
- const int TEMP_STACK_SIZE = 10 * 1024;
- tempStackBegin = new QScriptValueImpl[TEMP_STACK_SIZE];
- tempStackEnd = tempStackBegin + TEMP_STACK_SIZE;
- tempStackBegin[0] = m_undefinedValue;
-
- objectAllocator.blockGC(true);
-
- QScript::Ecma::Global::construct(&m_globalObject, this);
-
- // create the prototypes first...
- objectConstructor = new QScript::Ecma::Object(this, m_class_object);
- functionConstructor = new QScript::Ecma::Function(this, m_class_function);
- // ... then we can initialize
- functionConstructor->initialize();
- objectConstructor->initialize();
-
- numberConstructor = new QScript::Ecma::Number(this);
- booleanConstructor = new QScript::Ecma::Boolean(this);
- stringConstructor = new QScript::Ecma::String(this);
- dateConstructor = new QScript::Ecma::Date(this);
- arrayConstructor = new QScript::Ecma::Array(this);
- regexpConstructor = new QScript::Ecma::RegExp(this);
- errorConstructor = new QScript::Ecma::Error(this);
-
- QScript::Ecma::Global::initialize(&m_globalObject, this);
-
- const QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration;
-
- m_globalObject.setProperty(QLatin1String("Object"),
- objectConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("Function"),
- functionConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("Number"),
- numberConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("Boolean"),
- booleanConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("String"),
- stringConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("Date"),
- dateConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("Array"),
- arrayConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("RegExp"),
- regexpConstructor->ctor, flags);
- m_globalObject.setProperty(QLatin1String("Error"),
- errorConstructor->ctor, flags);
-
- m_globalObject.setProperty(QLatin1String("EvalError"),
- errorConstructor->evalErrorCtor, flags);
- m_globalObject.setProperty(QLatin1String("RangeError"),
- errorConstructor->rangeErrorCtor, flags);
- m_globalObject.setProperty(QLatin1String("ReferenceError"),
- errorConstructor->referenceErrorCtor, flags);
- m_globalObject.setProperty(QLatin1String("SyntaxError"),
- errorConstructor->syntaxErrorCtor, flags);
- m_globalObject.setProperty(QLatin1String("TypeError"),
- errorConstructor->typeErrorCtor, flags);
- m_globalObject.setProperty(QLatin1String("URIError"),
- errorConstructor->uriErrorCtor, flags);
-
- QScriptValueImpl tmp; // ### fixme
- m_evalFunction = new QScript::EvalFunction(this);
- functionConstructor->newFunction(&tmp, m_evalFunction);
- m_globalObject.setProperty(QLatin1String("eval"), tmp, flags);
-
- QScriptValueImpl mathObject;
- QScript::Ecma::Math::construct(&mathObject, this);
- m_globalObject.setProperty(QLatin1String("Math"), mathObject, flags);
-
- enumerationConstructor = new QScript::Ext::Enumeration(this);
-
- variantConstructor = new QScript::Ext::Variant(this);
-
-#ifndef QT_NO_QOBJECT
- qobjectConstructor = new QScript::ExtQObject(this);
- qmetaObjectConstructor = new QScript::ExtQMetaObject(this);
-#endif
-
- objectAllocator.blockGC(false);
-
- QScriptContextPrivate *context_p = pushContext();
- context_p->setActivationObject(m_globalObject);
- context_p->setThisObject(m_globalObject);
-}
-
-#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY)
-static QScriptValueImpl __setupPackage__(QScriptContextPrivate *ctx,
- QScriptEnginePrivate *eng,
- QScriptClassInfo *)
-{
- QString path = ctx->argument(0).toString();
- QStringList components = path.split(QLatin1Char('.'));
- QScriptValueImpl o = eng->globalObject();
- for (int i = 0; i < components.count(); ++i) {
- QString name = components.at(i);
- QScriptValueImpl oo = o.property(name);
- if (!oo.isValid()) {
- oo = eng->newObject();
- o.setProperty(name, oo);
- }
- o = oo;
- }
- return o;
-}
-#endif
-
-QScriptValueImpl QScriptEnginePrivate::importExtension(const QString &extension)
-{
-#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
- Q_UNUSED(extension);
-#else
- Q_Q(QScriptEngine);
- if (m_importedExtensions.contains(extension))
- return undefinedValue(); // already imported
-
- QScriptContextPrivate *context = currentContext();
- QCoreApplication *app = QCoreApplication::instance();
- if (!app)
- return context->throwError(QLatin1String("No application object"));
-
- QObjectList staticPlugins = QPluginLoader::staticInstances();
- QStringList libraryPaths = app->libraryPaths();
- QString dot = QLatin1String(".");
- QStringList pathComponents = extension.split(dot);
- QString initDotJs = QLatin1String("__init__.js");
-
- QString ext;
- for (int i = 0; i < pathComponents.count(); ++i) {
- if (!ext.isEmpty())
- ext.append(dot);
- ext.append(pathComponents.at(i));
- if (m_importedExtensions.contains(ext))
- continue; // already imported
-
- if (m_extensionsBeingImported.contains(ext)) {
- return context->throwError(QString::fromLatin1("recursive import of %0")
- .arg(extension));
- }
- m_extensionsBeingImported.insert(ext);
-
- QScriptExtensionInterface *iface = 0;
- QString initjsContents;
- QString initjsFileName;
-
- // look for the extension in static plugins
- for (int j = 0; j < staticPlugins.size(); ++j) {
- iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j));
- if (!iface)
- continue;
- if (iface->keys().contains(ext))
- break; // use this one
- else
- iface = 0; // keep looking
- }
-
- {
- // look for __init__.js resource
- QString path = QString::fromLatin1(":/qtscriptextension");
- for (int j = 0; j <= i; ++j) {
- path.append(QLatin1Char('/'));
- path.append(pathComponents.at(j));
- }
- path.append(QLatin1Char('/'));
- path.append(initDotJs);
- QFile file(path);
- if (file.open(QIODevice::ReadOnly)) {
- QTextStream ts(&file);
- initjsContents = ts.readAll();
- initjsFileName = path;
- file.close();
- }
- }
-
- if (!iface && initjsContents.isEmpty()) {
- // look for the extension in library paths
- for (int j = 0; j < libraryPaths.count(); ++j) {
- QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script");
- QDir dir(libPath);
- if (!dir.exists(dot))
- continue;
-
- // look for C++ plugin
- QFileInfoList files = dir.entryInfoList(QDir::Files);
- for (int k = 0; k < files.count(); ++k) {
- QFileInfo entry = files.at(k);
- QString filePath = entry.canonicalFilePath();
- QPluginLoader loader(filePath);
- iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
- if (iface) {
- if (iface->keys().contains(ext))
- break; // use this one
- else
- iface = 0; // keep looking
- }
- }
-
- // look for __init__.js in the corresponding dir
- QDir dirdir(libPath);
- bool dirExists = dirdir.exists();
- for (int k = 0; dirExists && (k <= i); ++k)
- dirExists = dirdir.cd(pathComponents.at(k));
- if (dirExists && dirdir.exists(initDotJs)) {
- QFile file(dirdir.canonicalPath()
- + QDir::separator() + initDotJs);
- if (file.open(QIODevice::ReadOnly)) {
- QTextStream ts(&file);
- initjsContents = ts.readAll();
- initjsFileName = file.fileName();
- file.close();
- }
- }
-
- if (iface || !initjsContents.isEmpty())
- break;
- }
- }
-
- if (!iface && initjsContents.isEmpty()) {
- m_extensionsBeingImported.remove(ext);
- return context->throwError(
- QString::fromLatin1("Unable to import %0: no such extension")
- .arg(extension));
- }
-
- // initialize the extension in a new context
- QScriptContextPrivate *ctx_p = pushContext();
- ctx_p->setThisObject(globalObject());
- newActivation(&ctx_p->m_activation);
- QScriptObject *activation_data = ctx_p->m_activation.m_object_value;
- activation_data->m_scope = globalObject();
-
- activation_data->m_members.resize(4);
- activation_data->m_values.resize(4);
- activation_data->m_members[0].object(
- nameId(QLatin1String("__extension__")), 0,
- QScriptValue::ReadOnly | QScriptValue::Undeletable);
- activation_data->m_values[0] = QScriptValueImpl(this, ext);
- activation_data->m_members[1].object(
- nameId(QLatin1String("__setupPackage__")), 1, 0);
- activation_data->m_values[1] = createFunction(__setupPackage__, 0, 0);
- activation_data->m_members[2].object(
- nameId(QLatin1String("__all__")), 2, 0);
- activation_data->m_values[2] = undefinedValue();
- activation_data->m_members[3].object(
- nameId(QLatin1String("__postInit__")), 3, 0);
- activation_data->m_values[3] = undefinedValue();
-
- // the script is evaluated first
- if (!initjsContents.isEmpty()) {
- evaluate(ctx_p, initjsContents, /*lineNumber=*/1, initjsFileName);
- if (hasUncaughtException()) {
- QScriptValueImpl r = ctx_p->returnValue();
- popContext();
- m_extensionsBeingImported.remove(ext);
- return r;
- }
- }
-
- // next, the C++ plugin is called
- if (iface) {
- iface->initialize(ext, q);
- if (hasUncaughtException()) {
- QScriptValueImpl r = ctx_p->returnValue();
- popContext();
- m_extensionsBeingImported.remove(ext);
- return r;
- }
- }
-
- // if the __postInit__ function has been set, we call it
- QScriptValueImpl postInit = ctx_p->m_activation.property(QLatin1String("__postInit__"));
- if (postInit.isFunction()) {
- postInit.call(globalObject());
- if (hasUncaughtException()) {
- QScriptValueImpl r = ctx_p->returnValue();
- popContext();
- m_extensionsBeingImported.remove(ext);
- return r;
- }
- }
-
- popContext();
-
- m_importedExtensions.insert(ext);
- m_extensionsBeingImported.remove(ext);
- } // for (i)
-#endif // QT_NO_QOBJECT
- return undefinedValue();
-}
-
-QStringList QScriptEnginePrivate::availableExtensions() const
-{
-#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
- return QStringList();
-#else
- QCoreApplication *app = QCoreApplication::instance();
- if (!app)
- return QStringList();
-
- QSet<QString> result;
-
- QObjectList staticPlugins = QPluginLoader::staticInstances();
- for (int i = 0; i < staticPlugins.size(); ++i) {
- QScriptExtensionInterface *iface;
- iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i));
- if (iface) {
- QStringList keys = iface->keys();
- for (int j = 0; j < keys.count(); ++j)
- result << keys.at(j);
- }
- }
-
- QStringList libraryPaths = app->libraryPaths();
- for (int i = 0; i < libraryPaths.count(); ++i) {
- QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script");
- QDir dir(libPath);
- if (!dir.exists())
- continue;
-
- // look for C++ plugins
- QFileInfoList files = dir.entryInfoList(QDir::Files);
- for (int j = 0; j < files.count(); ++j) {
- QFileInfo entry = files.at(j);
- QString filePath = entry.canonicalFilePath();
- QPluginLoader loader(filePath);
- QScriptExtensionInterface *iface;
- iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
- if (iface) {
- QStringList keys = iface->keys();
- for (int k = 0; k < keys.count(); ++k)
- result << keys.at(k);
- }
- }
-
- // look for scripts
- QString initDotJs = QLatin1String("__init__.js");
- QList<QFileInfo> stack;
- stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
- while (!stack.isEmpty()) {
- QFileInfo entry = stack.takeLast();
- QDir dd(entry.canonicalFilePath());
- if (dd.exists(initDotJs)) {
- QString rpath = dir.relativeFilePath(dd.canonicalPath());
- QStringList components = rpath.split(QLatin1Char('/'));
- result << components.join(QLatin1String("."));
- stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
- }
- }
- }
-
- QStringList lst = result.toList();
- qSort(lst);
- return lst;
-#endif
-}
-
-QStringList QScriptEnginePrivate::importedExtensions() const
-{
- QStringList lst = m_importedExtensions.toList();
- qSort(lst);
- return lst;
-}
-
-void QScriptEnginePrivate::gc()
-{
- if (!objectAllocator.blocked()) {
- // do the GC now
- maybeGC_helper(/*do_string_gc=*/true);
- } else {
- // GC will be performed the next time maybeGC()
- // is called and the allocator is not blocked
- objectAllocator.requestGC();
- }
-}
-
-QStringList QScriptEnginePrivate::uncaughtExceptionBacktrace() const
-{
- QScriptValueImpl value = uncaughtException();
- if (!value.isError())
- return m_exceptionBacktrace;
- return QScript::Ecma::Error::backtrace(value);
-}
-
-void QScriptEnginePrivate::clearExceptions()
-{
- m_exceptionBacktrace = QStringList();
- QScriptContextPrivate *ctx_p = currentContext();
- while (ctx_p) {
- ctx_p->m_state = QScriptContext::NormalState;
- ctx_p = ctx_p->parentContext();
- }
-}
-
-#ifndef QT_NO_QOBJECT
-void QScriptEnginePrivate::emitSignalHandlerException()
-{
- Q_Q(QScriptEngine);
- emit q->signalHandlerException(toPublic(uncaughtException()));
-}
-#endif
-
-void QScriptEnginePrivate::processEvents()
-{
-#ifndef QT_NO_QOBJECT
- Q_ASSERT(m_processEventTracker.isValid());
- int elapsed = m_processEventTracker.elapsed();
- if (m_nextProcessEvents < elapsed) {
- do {
- m_nextProcessEvents = m_nextProcessEvents + m_processEventsInterval;
- } while (m_nextProcessEvents < elapsed);
- QCoreApplication::processEvents();
- }
-#endif
-}
-
-void QScriptEnginePrivate::setupProcessEvents()
-{
- if (m_processEventsInterval > 0) {
- m_nextProcessEvents = m_processEventsInterval;
- m_processEventIncr = 0;
- m_processEventTracker.restart();
- }
-}
-
-void QScriptEnginePrivate::abortEvaluation(const QScriptValueImpl &result)
-{
- m_abort = true;
- currentContext()->setReturnValue(result);
-}
-
-#ifndef QT_NO_QOBJECT
-
-void QScriptEnginePrivate::newQObject(QScriptValueImpl *out, QObject *object,
- QScriptEngine::ValueOwnership ownership,
- const QScriptEngine::QObjectWrapOptions &options,
- bool setDefaultPrototype)
-{
- if (!object) {
- *out = m_nullValue;
- return;
- }
- Q_ASSERT(qobjectConstructor != 0);
- QScriptQObjectData *data = qobjectData(object);
- bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0;
- QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject;
- QScriptValueImpl existingWrapper;
- bool hasExisting = data->findWrapper(ownership, opt, &existingWrapper);
- if (preferExisting) {
- if (hasExisting) {
- *out = existingWrapper;
- } else {
- qobjectConstructor->newQObject(out, object, ownership, opt);
- data->registerWrapper(*out, ownership, opt);
- }
- } else {
- qobjectConstructor->newQObject(out, object, ownership, opt);
- if (!hasExisting)
- data->registerWrapper(*out, ownership, opt);
- }
-
- if (setDefaultPrototype) {
- const QMetaObject *meta = object->metaObject();
- while (meta) {
- QByteArray typeString = meta->className();
- typeString.append('*');
- int typeId = QMetaType::type(typeString);
- if (typeId != 0) {
- QScriptValueImpl proto = defaultPrototype(typeId);
- if (proto.isValid()) {
- out->setPrototype(proto);
- break;
- }
- }
- meta = meta->superClass();
- }
- }
-}
-
-QScriptQObjectData *QScriptEnginePrivate::qobjectData(QObject *object)
-{
- QHash<QObject*, QScriptQObjectData*>::const_iterator it;
- it = m_qobjectData.constFind(object);
- if (it != m_qobjectData.constEnd())
- return it.value();
-
- QScriptQObjectData *data = new QScriptQObjectData();
- m_qobjectData.insert(object, data);
- QObject::connect(object, SIGNAL(destroyed(QObject*)),
- q_func(), SLOT(_q_objectDestroyed(QObject *)));
- return data;
-}
-
-void QScriptEnginePrivate::_q_objectDestroyed(QObject *object)
-{
- QHash<QObject*, QScriptQObjectData*>::iterator it;
- it = m_qobjectData.find(object);
- Q_ASSERT(it != m_qobjectData.end());
- QScriptQObjectData *data = it.value();
- m_qobjectData.erase(it);
- delete data;
-}
-
-void QScriptEnginePrivate::disposeQObject(QObject *object)
-{
- if (isCollecting()) {
- // wait until we're done with GC before deleting it
- int index = m_qobjectsToBeDeleted.indexOf(object);
- if (index == -1)
- m_qobjectsToBeDeleted.append(object);
- } else {
- delete object;
- }
-}
-
-void QScriptEnginePrivate::deletePendingQObjects()
-{
- while (!m_qobjectsToBeDeleted.isEmpty())
- delete m_qobjectsToBeDeleted.takeFirst();
-}
-
-bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal,
- const QScriptValueImpl &receiver,
- const QScriptValueImpl &function)
-{
- Q_ASSERT(sender);
- Q_ASSERT(signal);
- const QMetaObject *meta = sender->metaObject();
- int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
- if (index == -1)
- return false;
- return scriptConnect(sender, index, receiver, function);
-}
-
-bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal,
- const QScriptValueImpl &receiver,
- const QScriptValueImpl &function)
-{
- Q_ASSERT(sender);
- Q_ASSERT(signal);
- const QMetaObject *meta = sender->metaObject();
- int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
- if (index == -1)
- return false;
- return scriptDisconnect(sender, index, receiver, function);
-}
-
-bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex,
- const QScriptValueImpl &receiver,
- const QScriptValueImpl &function,
- const QScriptValueImpl &senderWrapper)
-{
- QScriptQObjectData *data = qobjectData(sender);
- return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper);
-}
-
-bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex,
- const QScriptValueImpl &receiver,
- const QScriptValueImpl &function)
-{
- QScriptQObjectData *data = qobjectData(sender);
- if (!data)
- return false;
- return data->removeSignalHandler(sender, signalIndex, receiver, function);
-}
-
-bool QScriptEnginePrivate::scriptConnect(const QScriptValueImpl &signal,
- const QScriptValueImpl &receiver,
- const QScriptValueImpl &function)
-{
- QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(signal.toFunction());
- int index = fun->mostGeneralMethod();
- return scriptConnect(fun->qobject(), index, receiver, function, fun->object());
-}
-
-bool QScriptEnginePrivate::scriptDisconnect(const QScriptValueImpl &signal,
- const QScriptValueImpl &receiver,
- const QScriptValueImpl &function)
-{
- QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(signal.toFunction());
- int index = fun->mostGeneralMethod();
- return scriptDisconnect(fun->qobject(), index, receiver, function);
-}
-
-bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValueImpl &value,
- const QByteArray &targetType,
- void **result)
-{
- if (!targetType.endsWith('*'))
- return false;
- if (QObject *qobject = value.toQObject()) {
- int start = targetType.startsWith("const ") ? 6 : 0;
- QByteArray className = targetType.mid(start, targetType.size()-start-1);
- if (void *instance = qobject->qt_metacast(className)) {
- *result = instance;
- return true;
- }
- }
- return false;
-}
-
-#endif // QT_NO_QOBJECT
-
-void QScriptEnginePrivate::setAgent(QScriptEngineAgent *agent)
-{
- Q_Q(QScriptEngine);
- if (agent && (agent->engine() != q)) {
- qWarning("QScriptEngine::setAgent(): "
- "cannot set agent belonging to different engine");
- return;
- }
- if (agent) {
- int index = m_agents.indexOf(agent);
- if (index == -1)
- m_agents.append(agent);
- }
- m_agent = agent;
-}
-
-QScriptEngineAgent *QScriptEnginePrivate::agent() const
-{
- return m_agent;
-}
-
-void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent)
-{
- m_agents.removeOne(agent);
- if (m_agent == agent)
- m_agent = 0;
-}
-
-#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
-qint64 QScriptEnginePrivate::nextScriptId()
-{
- // ### reuse IDs by using a pool
- return m_scriptCounter++;
-}
-
-void QScriptEnginePrivate::notifyScriptLoad_helper(qint64 id, const QString &program,
- const QString &fileName, int lineNumber)
-{
- m_agent->scriptLoad(id, program, fileName, lineNumber);
-}
-
-void QScriptEnginePrivate::notifyScriptUnload_helper(qint64 id)
-{
- m_agent->scriptUnload(id);
-}
-
-void QScriptEnginePrivate::notifyPositionChange_helper(QScriptContextPrivate *ctx)
-{
- m_agent->positionChange(ctx->scriptId(), ctx->currentLine, ctx->currentColumn);
-}
-
-void QScriptEnginePrivate::notifyContextPush_helper()
-{
- m_agent->contextPush();
-}
-
-void QScriptEnginePrivate::notifyContextPop_helper()
-{
- m_agent->contextPop();
-}
-
-void QScriptEnginePrivate::notifyFunctionEntry_helper(QScriptContextPrivate *ctx)
-{
- m_agent->functionEntry(ctx->scriptId());
-}
-
-void QScriptEnginePrivate::notifyFunctionExit_helper(QScriptContextPrivate *ctx)
-{
- m_agent->functionExit(ctx->scriptId(), toPublic(ctx->returnValue()));
-}
-
-void QScriptEnginePrivate::notifyException_helper(QScriptContextPrivate *ctx)
-{
- bool hasHandler = (ctx->exceptionHandlerContext() != 0);
- m_agent->exceptionThrow(ctx->scriptId(), toPublic(ctx->returnValue()), hasHandler);
-}
-
-void QScriptEnginePrivate::notifyExceptionCatch_helper(QScriptContextPrivate *ctx)
-{
- m_agent->exceptionCatch(ctx->scriptId(), toPublic(ctx->returnValue()));
-}
-
-void QScriptEnginePrivate::notifyDebugger(QScriptContextPrivate *ctx)
-{
- if (m_agent && m_agent->supportsExtension(QScriptEngineAgent::DebuggerInvocationRequest)) {
- QVariantList args;
- args.append(ctx->scriptId());
- args.append(ctx->currentLine);
- args.append(ctx->currentColumn);
- QVariant ret = m_agent->extension(QScriptEngineAgent::DebuggerInvocationRequest, args);
- QScriptValueImpl val = valueFromVariant(ret);
- if (val.isValid())
- ctx->m_result = val;
- }
-}
-
-#endif // Q_SCRIPT_NO_EVENT_NOTIFY
-
-QScriptString QScriptEnginePrivate::internedString(const QString &str)
-{
- return internedString(nameId(str, /*persistent=*/false));
-}
-
-QScriptString QScriptEnginePrivate::internedString(QScriptNameIdImpl *nid)
-{
- if (!nid)
- return QScriptString();
- QScriptStringPrivate *d = m_internedStrings.value(nid);
- if (!d) {
- d = m_internedStringRepository.get();
- d->nameId = nid;
- d->engine = this;
- m_internedStrings.insert(d->nameId, d);
- }
- QScriptString result;
- QScriptStringPrivate::init(result, d);
- return result;
-}
-
-void QScriptEnginePrivate::uninternString(QScriptStringPrivate *d)
-{
- Q_ASSERT(d->nameId);
- QHash<QScriptNameIdImpl*, QScriptStringPrivate*>::iterator it;
- it = m_internedStrings.find(d->nameId);
- Q_ASSERT(it != m_internedStrings.end());
- m_internedStrings.erase(it);
- m_internedStringRepository.release(d);
-}
-
-QScriptValueImpl QScriptEnginePrivate::toImpl_helper(const QScriptValue &value)
-{
- QScriptValuePrivate *p = QScriptValuePrivate::get(value);
- Q_ASSERT(p != 0);
- Q_ASSERT(p->value.type() == QScript::LazyStringType);
- QString str = *p->value.m_lazy_string_value;
- if (!p->ref.deref())
- delete p;
- QScriptValueImpl v;
- newString(&v, str);
- p = registerValue(v);
- QScriptValuePrivate::init(const_cast<QScriptValue&>(value), p);
- return v;
-}
-
-QScriptValueImpl QScriptEnginePrivate::newObject(QScriptClass *scriptClass,
- const QScriptValueImpl &data)
-{
- if (!scriptClass)
- return QScriptValueImpl();
- QScriptValueImpl v;
- QScriptValueImpl proto = toImpl(scriptClass->prototype());
- if (!proto.isObject())
- proto = objectConstructor->publicPrototype;
- newObject(&v, proto);
- QScriptClassPrivate *cls_p = QScriptClassPrivate::get(scriptClass);
- QScriptClassInfo *info = cls_p->classInfo();
- v.setClassInfo(info);
- if (info->type() & QScriptClassInfo::FunctionBased) {
- QScriptFunction *fun = cls_p->newFunction();
- v.setObjectData(fun);
- }
- v.setInternalValue(data);
- return v;
-}
-
-int QScriptEnginePrivate::registerCustomClassType()
-{
- return ++m_class_prev_id;
-}
-
-QScriptValueImpl QScriptEnginePrivate::objectById(qint64 id) const
-{
- QScript::GCAlloc<QScriptObject>::const_iterator it;
- for (it = objectAllocator.constBegin(); it != objectAllocator.constEnd(); ++it) {
- const QScriptObject *obj = it.data();
- if (obj->m_id == id) {
- QScriptValueImpl ret;
- ret.m_type = QScript::ObjectType;
- ret.m_object_value = const_cast<QScriptObject*>(obj);
- return ret;
- }
- }
- return QScriptValueImpl();
-}
-
-namespace QScript {
-
-static QScriptValueImpl qsTranslate(QScriptContextPrivate *ctx, QScriptEnginePrivate *eng, QScriptClassInfo *)
-{
- if (ctx->argumentCount() < 2)
- return ctx->throwError(QString::fromLatin1("qsTranslate() requires at least two arguments"));
- if (!ctx->argument(0).isString())
- return ctx->throwError(QString::fromLatin1("qsTranslate(): first argument (context) must be a string"));
- if (!ctx->argument(1).isString())
- return ctx->throwError(QString::fromLatin1("qsTranslate(): second argument (text) must be a string"));
- if ((ctx->argumentCount() > 2) && !ctx->argument(2).isString())
- return ctx->throwError(QString::fromLatin1("qsTranslate(): third argument (comment) must be a string"));
- if ((ctx->argumentCount() > 3) && !ctx->argument(3).isString())
- return ctx->throwError(QString::fromLatin1("qsTranslate(): fourth argument (encoding) must be a string"));
- if ((ctx->argumentCount() > 4) && !ctx->argument(4).isNumber())
- return ctx->throwError(QString::fromLatin1("qsTranslate(): fifth argument (n) must be a number"));
-#ifndef QT_NO_QOBJECT
- QString context = ctx->argument(0).toString();
-#endif
- QString text = ctx->argument(1).toString();
-#ifndef QT_NO_QOBJECT
- QString comment;
- if (ctx->argumentCount() > 2)
- comment = ctx->argument(2).toString();
- QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr;
- if (ctx->argumentCount() > 3) {
- QString encStr = ctx->argument(3).toString();
- if (encStr == QLatin1String("CodecForTr"))
- encoding = QCoreApplication::CodecForTr;
- else if (encStr == QLatin1String("UnicodeUTF8"))
- encoding = QCoreApplication::UnicodeUTF8;
- else
- return ctx->throwError(QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr));
- }
- int n = -1;
- if (ctx->argumentCount() > 4)
- n = ctx->argument(4).toInt32();
-#endif
- QString result;
-#ifndef QT_NO_QOBJECT
- result = QCoreApplication::translate(context.toLatin1().constData(),
- text.toLatin1().constData(),
- comment.toLatin1().constData(),
- encoding, n);
-#else
- result = text;
-#endif
- return QScriptValueImpl(eng, result);
-}
-
-static QScriptValueImpl qTranslateNoOp(QScriptContextPrivate *ctx, QScriptEnginePrivate *, QScriptClassInfo *)
-{
- return ctx->argument(1);
-}
-
-static QScriptValueImpl qsTr(QScriptContextPrivate *ctx, QScriptEnginePrivate *eng, QScriptClassInfo *)
-{
- if (ctx->argumentCount() < 1)
- return ctx->throwError(QString::fromLatin1("qsTr() requires at least one argument"));
- if (!ctx->argument(0).isString())
- return ctx->throwError(QString::fromLatin1("qsTr(): first argument (text) must be a string"));
- if ((ctx->argumentCount() > 1) && !ctx->argument(1).isString())
- return ctx->throwError(QString::fromLatin1("qsTr(): second argument (comment) must be a string"));
- if ((ctx->argumentCount() > 2) && !ctx->argument(2).isNumber())
- return ctx->throwError(QString::fromLatin1("qsTranslate(): third argument (n) must be a number"));
-#ifndef QT_NO_QOBJECT
- QString context;
- if (ctx->parentContext())
- context = QFileInfo(ctx->parentContext()->fileName()).baseName();
-#endif
- QString text = ctx->argument(0).toString();
-#ifndef QT_NO_QOBJECT
- QString comment;
- if (ctx->argumentCount() > 1)
- comment = ctx->argument(1).toString();
- int n = -1;
- if (ctx->argumentCount() > 2)
- n = ctx->argument(2).toInt32();
-#endif
- QString result;
-#ifndef QT_NO_QOBJECT
- result = QCoreApplication::translate(context.toLatin1().constData(),
- text.toLatin1().constData(),
- comment.toLatin1().constData(),
- QCoreApplication::CodecForTr, n);
-#else
- result = text;
-#endif
- return QScriptValueImpl(eng, result);
-}
-
-static QScriptValueImpl qTrNoOp(QScriptContextPrivate *ctx, QScriptEnginePrivate *, QScriptClassInfo *)
-{
- return ctx->argument(0);
-}
-
-} // namespace QScript
-
-void QScriptEnginePrivate::installTranslatorFunctions(QScriptValueImpl &object)
-{
- Q_ASSERT(object.isObject());
- const QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration;
- object.setProperty(QLatin1String("qsTranslate"),
- createFunction(QScript::qsTranslate, /*length=*/5, /*classInfo=*/0),
- flags);
- object.setProperty(QLatin1String("QT_TRANSLATE_NOOP"),
- createFunction(QScript::qTranslateNoOp, /*length=*/2, /*classInfo=*/0),
- flags);
- object.setProperty(QLatin1String("qsTr"),
- createFunction(QScript::qsTr, /*length=*/3, /*classInfo=*/0),
- flags);
- object.setProperty(QLatin1String("QT_TR_NOOP"),
- createFunction(QScript::qTrNoOp, /*length=*/1, /*classInfo=*/0),
- flags);
-
- stringConstructor->addPrototypeFunction(QLatin1String("arg"), QScript::Ecma::String::method_ext_arg, 1);
-}
-
-bool QScriptEnginePrivate::canEvaluate(const QString &program)
-{
- QScript::SyntaxChecker checker;
- QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
- return (result.state != QScript::SyntaxChecker::Intermediate);
-}
-
-QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program)
-{
- QScript::SyntaxChecker checker;
- QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
- QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate();
- switch (result.state) {
- case QScript::SyntaxChecker::Error:
- p->state = QScriptSyntaxCheckResult::Error;
- break;
- case QScript::SyntaxChecker::Intermediate:
- p->state = QScriptSyntaxCheckResult::Intermediate;
- break;
- case QScript::SyntaxChecker::Valid:
- p->state = QScriptSyntaxCheckResult::Valid;
- break;
- }
- p->errorLineNumber = result.errorLineNumber;
- p->errorColumnNumber = result.errorColumnNumber;
- p->errorMessage = result.errorMessage;
- return QScriptSyntaxCheckResult(p);
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SCRIPT