📄 qscriptcontext_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 <QtCore/QtDebug>#ifndef QT_NO_SCRIPT#include "qscriptcontext_p.h"#include "qscriptengine_p.h"#include "qscriptvalueimpl_p.h"#include "qscriptmember_p.h"#include "qscriptobject_p.h"#include "qscriptprettypretty_p.h"#include "qscriptast_p.h"#include "qscriptnodepool_p.h"#include "qscriptcompiler_p.h"#include "qscriptextenumeration_p.h"#include <math.h> // floor & friends...#define Q_SCRIPT_NO_PRINT_GENERATED_CODE#define Q_SCRIPT_NO_JOINED_FUNCTION#define CHECK_TEMPSTACK(needed) do { \ if (stackPtr + needed >= eng->tempStackEnd) { \ throwError(QLatin1String("out of memory")); \ HandleException(); \ } \} while (0)#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODEstatic QTextStream qout(stderr, QIODevice::WriteOnly);#endifstatic inline void qscript_uint_to_string_helper(uint i, QString &s){ switch (i) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: s += QLatin1Char('0' + i); break; default: qscript_uint_to_string_helper(i / 10, s); s += QLatin1Char('0' + (i % 10)); }}static inline void qscript_uint_to_string(qsreal i, QString &s){ if (i < 0) return; // nothing to do qsreal x = ::fmod(i, 10); if (x != 0.0 && x != 1.0 && x != 2.0 && x != 3.0 && x != 4.0 && x != 5.0 && x != 6.0 && x != 7.0 && x != 8.0 && x != 9.0) return; // nothing to do qscript_uint_to_string_helper(uint(i), s);}static inline qint32 toArrayIndex(const QScriptValueImpl &v){ if (v.isNumber()) { if (floor(v.m_number_value) == v.m_number_value) return v.toUInt32(); } else if (v.isString()) { QByteArray bytes = v.m_string_value->s.toUtf8(); char *eptr; quint32 pos = strtoul(bytes.constData(), &eptr, 10); if ((eptr == bytes.constData() + bytes.size()) && (QByteArray::number(pos) == bytes)) { return pos; } } return -1;}#define CREATE_MEMBER(__obj__, __name__, __member__, __flags__) do { \ (__obj__).createMember(__name__, __member__, __flags__); \ eng->adjustBytesAllocated(sizeof(QScript::Member) + sizeof(QScriptValueImpl)); \} while (0)#define BEGIN_PREFIX_OPERATOR \ QScriptValue::ResolveFlags mode; \ mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value) \ | QScriptValue::ResolvePrototype; \ --stackPtr; \ const QScriptValueImpl &object = stackPtr[-1]; \ QScriptNameIdImpl *memberName = 0; \ if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique) \ memberName = stackPtr[0].m_string_value; \ else \ memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false); \ QScript::Member member; \ QScriptValueImpl base; \ QScriptValueImpl value; \ QScriptValueImpl getter; \ QScriptValueImpl setter; \ const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); \ if (object.resolve(memberName, &member, &base, mode)) { \ base.get(member, &value); \ if (hasUncaughtException()) { \ stackPtr -= 2; \ HandleException(); \ } else if (member.isGetterOrSetter()) { \ if (member.isGetter()) { \ getter = value; \ if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \ stackPtr -= 2; \ throwError(QLatin1String("No setter defined")); \ HandleException(); \ } \ base.get(member, &setter); \ } else { \ setter = value; \ QScript::Member tmp = member; \ if (!base.m_object_value->findGetter(&member)) { \ stackPtr -= 2; \ throwError(QLatin1String("No getter defined")); \ HandleException(); \ } \ base.get(member, &getter); \ member = tmp; \ } \ value = getter.call(object); \ if (hasUncaughtException()) { \ stackPtr -= 2; \ Done(); \ } \ } \ } else if (!isMemberAssignment) { \ stackPtr -= 2; \ throwNotDefined(memberName); \ HandleException(); \ } else { \ base = object; \ CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ eng->newUndefined(&value); \ }#define END_PREFIX_OPERATOR \ if (member.isSetter()) { \ setter.call(object, QScriptValueImplList() << value); \ if (hasUncaughtException()) { \ stackPtr -= 2; \ Done(); \ } \ } else { \ if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \ base = object; \ CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ } \ if (member.isWritable()) { \ base.put(member, value); \ if (hasUncaughtException()) { \ stackPtr -= 2; \ HandleException(); \ } \ } \ } \ *--stackPtr = value; \ ++iPtr;#define BEGIN_INPLACE_OPERATOR \ if (! stackPtr[-1].isReference()) { \ stackPtr -= 2; \ throwSyntaxError(QLatin1String("invalid assignment lvalue")); \ HandleException(); \ } \ QScriptValue::ResolveFlags mode; \ mode = QScriptValue::ResolveFlags(stackPtr[-1].m_int_value) \ | QScriptValue::ResolvePrototype; \ QScriptValueImpl object = eng->toObject(stackPtr[-3]); \ if (! object.isValid()) { \ stackPtr -= 4; \ throwTypeError(QLatin1String("not an object")); \ HandleException(); \ } \ QScriptNameIdImpl *memberName = 0; \ if (stackPtr[-2].isString() && stackPtr[-2].m_string_value->unique) \ memberName = stackPtr[-2].m_string_value; \ else \ memberName = eng->nameId(stackPtr[-2].toString(), /*persistent=*/false); \ QScriptValueImpl lhs; \ QScriptValueImpl base; \ QScript::Member member; \ QScriptValueImpl getter; \ QScriptValueImpl setter; \ const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); \ if (object.resolve(memberName, &member, &base, mode)) { \ base.get(member, &lhs); \ if (hasUncaughtException()) { \ stackPtr -= 4; \ HandleException(); \ } else if (member.isGetterOrSetter()) { \ if (member.isGetter()) { \ getter = lhs; \ if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \ stackPtr -= 4; \ throwError(QLatin1String("No setter defined")); \ HandleException(); \ } \ base.get(member, &setter); \ } else { \ setter = lhs; \ QScript::Member tmp = member; \ if (!base.m_object_value->findGetter(&member)) { \ stackPtr -= 4; \ throwError(QLatin1String("No getter defined")); \ HandleException(); \ } \ base.get(member, &getter); \ member = tmp; \ } \ lhs = getter.call(object); \ if (hasUncaughtException()) { \ stackPtr -= 4; \ Done(); \ } \ } \ } else if (!isMemberAssignment) { \ stackPtr -= 4; \ throwNotDefined(memberName); \ HandleException(); \ } else { \ base = object; \ CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ eng->newUndefined(&lhs); \ } \ const QScriptValueImpl &rhs = stackPtr[0];#define END_INPLACE_OPERATOR \ if (member.isSetter()) { \ setter.call(object, QScriptValueImplList() << *stackPtr); \ if (hasUncaughtException()) { \ stackPtr -= 1; \ Done(); \ } \ } else { \ if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \ base = object; \ CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ } \ if (member.isWritable()) { \ base.put(member, *stackPtr); \ if (hasUncaughtException()) { \ stackPtr -= 1; \ HandleException(); \ } \ } \ } \ ++iPtr;namespace QScript {void ScriptFunction::execute(QScriptContextPrivate *context){ if (! m_compiledCode) { QScriptEngine *eng = context->engine(); Compiler compiler(eng); CompilationUnit unit = compiler.compile(m_definition->body, formals); if (! unit.isValid()) { context->throwError(unit.errorMessage()); return; } m_compiledCode = m_astPool->createCompiledCode(m_definition->body, unit); } context->execute(m_compiledCode);}QString ScriptFunction::toString(QScriptContextPrivate *context) const{ QScriptEngine *eng = context->engine(); QString str; QTextStream out(&str, QIODevice::WriteOnly); PrettyPretty pp(eng, out); pp(m_definition, /*indent=*/ 1); return str;}QString ScriptFunction::fileName() const{ return m_astPool->fileName();}QString ScriptFunction::functionName() const{ if (!m_definition->name) return QLatin1String("<anonymous>"); return m_definition->name->s;}} // namespace QScript/*! \internal Resolves and gets the value specified by \a stackPtr. stackPtr[0] contains the member specifier, stackPtr[-1] contains the object. If the member can be resolved, sets \a value to the value of that member, otherwise returns false.*/bool QScriptContextPrivate::resolveField(QScriptEnginePrivate *eng, QScriptValueImpl *stackPtr, QScriptValueImpl *value){ const QScriptValueImpl &m = stackPtr[0]; QScriptValueImpl &object = stackPtr[-1]; if (! object.isObject()) object = eng->toObject(object); if (! object.isValid()) return false; if (QScript::Ecma::Array::Instance *arrayInstance = eng->arrayConstructor->get(object)) { qint32 pos = toArrayIndex(m); if (pos != -1) { *value = arrayInstance->value.at(pos); if (! value->isValid()) eng->newUndefined(value); return true; } } QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0; if (! nameId || ! nameId->unique) nameId = eng->nameId(eng->convertToNativeString(m), /*persistent=*/false); // ### slow! QScript::Member member; QScriptValueImpl base; if (! object.resolve(nameId, &member, &base, QScriptValue::ResolveFull)) // ### ... return false; if (base.m_class == eng->m_globalObject.m_class) stackPtr[-1] = base; else if (object.m_class == eng->m_class_with) stackPtr[-1] = object.prototype(); base.get(member, value); return true;}void QScriptContextPrivate::execute(QScript::Code *code){ QScript::Code *oldCode = m_code; m_code = code;#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODE qout << QLatin1String("function:") << endl; for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) { qout << int(current - code->firstInstruction) << QLatin1String(":\t"); current->print(qout); qout << endl; } qout << endl;#endif QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); if (!parentContext()) eng->setupProcessEvents(); // set up the temp stack if (! tempStack) stackPtr = tempStack = eng->tempStackBegin; QScriptValueImpl undefined; eng->newUndefined(&undefined); catching = false; m_state = QScriptContext::NormalState; m_result = undefined; firstInstruction = code->firstInstruction; lastInstruction = code->lastInstruction; iPtr = code->firstInstruction; // ### kill iPtr m_scopeChain = m_activation;#ifndef Q_SCRIPT_DIRECT_CODE# define I(opc) case QScriptInstruction::OP_##opc# define Next() goto Lfetch# define Done() goto Ldone# define HandleException() goto Lhandle_exceptionLfetch:#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -