📄 qscriptengine_p.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtScript module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#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 "qscriptvalueiterator.h"#include "qscriptecmaglobal_p.h"#include "qscriptecmamath_p.h"#include "qscriptecmaarray_p.h"#include "qscriptextenumeration_p.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>#endifQ_DECLARE_METATYPE(QScriptValue)Q_DECLARE_METATYPE(QVariant)#ifndef QT_NO_QOBJECTQ_DECLARE_METATYPE(QObjectList)#endifQ_DECLARE_METATYPE(QList<int>)namespace QScript {NodePool::~NodePool(){ qDeleteAll(m_codeCache); m_codeCache.clear();}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) { QScriptEngine *engine = context->engine(); QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); QExplicitlySharedDataPointer<NodePool> pool; pool = new NodePool(fileName); eng_p->setNodePool(pool); AST::Node *program = eng_p->createAbstractSyntaxTree(contents, lineNo); eng_p->setNodePool(0); if (! program) { context->errorLineNumber = lineNo; context->currentLine = lineNo; context->throwError(QScriptContext::SyntaxError, eng_p->errorMessage()); return; } Compiler compiler(engine); compiler.setTopLevelCompiler(true); CompilationUnit compilation = compiler.compile(program); if (! compilation.isValid()) { context->throwError(compilation.errorMessage()); return; } Code *code = pool->createCompiledCode(program, compilation); if (calledFromScript) { if (QScriptContext *parentContext = context->parentContext()) { QScriptContextPrivate *pc_p = QScriptContextPrivate::get(parentContext); context->setActivationObject(pc_p->activationObject()); context->setThisObject(pc_p->thisObject()); } } const QScriptInstruction *iPtr = context->instructionPointer(); context->execute(code); context->setInstructionPointer(iPtr); } virtual void execute(QScriptContextPrivate *context) { QScriptEnginePrivate *eng = QScriptEnginePrivate::get(context->engine()); int lineNo = context->currentLine; 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); } } }};class WithClassData: public QScriptClassData{public: virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, QScript::Member *member, QScriptValueImpl *base);};bool WithClassData::resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, QScript::Member *member, QScriptValueImpl *base){ QScriptValueImpl proto = object.prototype(); Q_ASSERT(proto.isValid()); Q_ASSERT(proto.isObject()); return proto.resolve(nameId, member, base, QScriptValue::ResolveScope);}class ArgumentsClassData: public QScriptClassData{public: static inline QScript::ArgumentsObjectData *get(const QScriptValueImpl &object) { return static_cast<QScript::ArgumentsObjectData*>(object.objectData().data()); } virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, QScript::Member *member, QScriptValueImpl *base); 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);};bool ArgumentsClassData::resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, QScript::Member *member, QScriptValueImpl *base){ QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(object.engine()); if (nameId == eng_p->idTable()->id_length) { member->native(nameId, /*id=*/ 0, QScriptValue::Undeletable | QScriptValue::ReadOnly); *base = object; return true; } else if (nameId == eng_p->idTable()->id_callee) { member->native(nameId, /*id=*/ 0, QScriptValue::Undeletable | QScriptValue::ReadOnly); *base = object; return true; } QString propertyName = eng_p->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, 0); *base = object; return true; } } return false;}bool ArgumentsClassData::get(const QScriptValueImpl &object, const QScript::Member &member, QScriptValueImpl *out_value){ QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(object.engine()); QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object); if (member.nameId() == 0) { QScriptObject *activation_data = data->activation.objectValue(); *out_value = activation_data->m_objects[member.id()]; return true; } else if (member.nameId() == eng_p->idTable()->id_length) { eng_p->newNumber(out_value, data->length); return true; } else if (member.nameId() == eng_p->idTable()->id_callee) { *out_value = data->callee; 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_objects[member.id()] = value; return true;}void ArgumentsClassData::mark(const QScriptValueImpl &object, int generation){ QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object); data->activation.mark(generation); data->callee.mark(generation);}} // namespace QScriptconst qsreal QScriptEnginePrivate::D16 = 65536.0;const qsreal QScriptEnginePrivate::D32 = 4294967296.0;QScriptEnginePrivate::~QScriptEnginePrivate(){ // invalidate values that we have references to { QHash<QScriptObject*, QScriptValuePrivate*>::const_iterator it; for (it = m_objectHandles.constBegin(); it != m_objectHandles.constEnd(); ++it) (*it)->value.invalidate(); } { QHash<QScriptNameIdImpl*, QScriptValuePrivate*>::const_iterator it; for (it = m_stringHandles.constBegin(); it != m_stringHandles.constEnd(); ++it) (*it)->value.invalidate(); } { QVector<QScriptValuePrivate*>::const_iterator it; for (it = m_otherHandles.constBegin(); it != m_otherHandles.constEnd(); ++it) (*it)->value.invalidate(); } delete[] m_string_hash_base; qDeleteAll(m_stringRepository); qDeleteAll(m_tempStringRepository); delete[] tempStackBegin;#ifndef QT_NO_QOBJECT# 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){ m_errorMessage.clear(); QScript::Lexer lex(q_func()); setLexer(&lex); lex.setCode(source, lineNumber); QScriptParser parser; if (! parser.parse(this)) { m_errorMessage = parser.errorMessage(); lineNumber = 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -