summaryrefslogtreecommitdiffstats
path: root/src/script/api/qscriptcontextinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/api/qscriptcontextinfo.cpp')
-rw-r--r--src/script/api/qscriptcontextinfo.cpp565
1 files changed, 565 insertions, 0 deletions
diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp
new file mode 100644
index 0000000..e59b773
--- /dev/null
+++ b/src/script/api/qscriptcontextinfo.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptcontextinfo.h"
+
+#include "qscriptcontext_p.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+#include "../bridge/qscriptqobject_p.h"
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmetaobject.h>
+#include "CodeBlock.h"
+#include "JSFunction.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.4
+ \class QScriptContextInfo
+
+ \brief The QScriptContextInfo class provides additional information about a QScriptContext.
+
+ \ingroup script
+
+
+ QScriptContextInfo is typically used for debugging purposes. It can
+ provide information about the code being executed, such as the type
+ of the called function, and the original source code location of the
+ current statement.
+
+ If the called function is executing Qt Script code, you can obtain
+ the script location with the functions fileName(), lineNumber() and
+ columnNumber().
+
+ You can obtain the starting line number and ending line number of a
+ Qt Script function definition with functionStartLineNumber() and
+ functionEndLineNumber(), respectively.
+
+ For Qt Script functions and Qt methods (e.g. slots), you can call
+ functionParameterNames() to get the names of the formal parameters of the
+ function.
+
+ For Qt methods and Qt property accessors, you can obtain the index
+ of the underlying QMetaMethod or QMetaProperty by calling
+ functionMetaIndex().
+
+ \sa QScriptContext, QScriptEngineAgent
+*/
+
+/*!
+ \enum QScriptContextInfo::FunctionType
+
+ This enum specifies the type of function being called.
+
+ \value ScriptFunction The function is a Qt Script function, i.e. it was defined through a call to QScriptEngine::evaluate().
+ \value QtFunction The function is a Qt function (a signal, slot or method).
+ \value QtPropertyFunction The function is a Qt property getter or setter.
+ \value NativeFunction The function is a built-in Qt Script function, or it was defined through a call to QScriptEngine::newFunction().
+*/
+
+class QScriptContextInfoPrivate
+{
+ Q_DECLARE_PUBLIC(QScriptContextInfo)
+public:
+ QScriptContextInfoPrivate();
+ QScriptContextInfoPrivate(const QScriptContext *context);
+ ~QScriptContextInfoPrivate();
+
+ qint64 scriptId;
+ int lineNumber;
+ int columnNumber;
+ QString fileName;
+
+ QString functionName;
+ QScriptContextInfo::FunctionType functionType;
+
+ int functionStartLineNumber;
+ int functionEndLineNumber;
+ int functionMetaIndex;
+
+ QStringList parameterNames;
+
+ QBasicAtomicInt ref;
+
+ QScriptContextInfo *q_ptr;
+};
+
+/*!
+ \internal
+*/
+QScriptContextInfoPrivate::QScriptContextInfoPrivate()
+{
+ ref = 0;
+ functionType = QScriptContextInfo::NativeFunction;
+ functionMetaIndex = -1;
+ functionStartLineNumber = -1;
+ functionEndLineNumber = -1;
+ scriptId = -1;
+ lineNumber = -1;
+ columnNumber = -1;
+}
+
+/*!
+ \internal
+*/
+QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context)
+{
+ Q_ASSERT(context);
+ ref = 0;
+ functionType = QScriptContextInfo::NativeFunction;
+ functionMetaIndex = -1;
+ functionStartLineNumber = -1;
+ functionEndLineNumber = -1;
+ scriptId = -1;
+ lineNumber = -1;
+ columnNumber = -1;
+
+ const JSC::ExecState *frame = QScriptEnginePrivate::frameForContext(context);
+
+ // Get the line number:
+
+ //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
+ QScriptContext *rewindContext = context->engine()->currentContext();
+ if (rewindContext != context) { //ignore top context (native function)
+ // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
+ while (rewindContext && rewindContext->parentContext() != context)
+ rewindContext = rewindContext->parentContext();
+ if (rewindContext) {
+ JSC::ExecState *aboveFrame = QScriptEnginePrivate::frameForContext(rewindContext);
+ frame = aboveFrame->callerFrame()->removeHostCallFrameFlag(); //it will be different for the global context.
+
+ JSC::Instruction *returnPC = aboveFrame->returnPC();
+ JSC::CodeBlock *codeBlock = frame->codeBlock();
+ if (returnPC && codeBlock) {
+ lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame),
+ returnPC - codeBlock->instructions().begin() -1);
+ }
+ }
+ } else {
+ // An agent might have provided the line number.
+ lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
+ }
+
+ // Get the filename and the scriptId:
+ JSC::CodeBlock *codeBlock = frame->codeBlock();
+ if (codeBlock) {
+ JSC::SourceProvider *source = codeBlock->source();
+ scriptId = source->asID();
+ fileName = source->url();
+ }
+
+ // Get the others informations:
+ JSC::JSObject *callee = frame->callee();
+ if (callee && callee->isObject(&JSC::InternalFunction::info))
+ functionName = JSC::asInternalFunction(callee)->name(&frame->globalData());
+ if (callee && callee->isObject(&JSC::JSFunction::info)) {
+ functionType = QScriptContextInfo::ScriptFunction;
+ JSC::FunctionBodyNode *body = JSC::asFunction(callee)->body();
+ functionStartLineNumber = body->firstLine();
+ functionEndLineNumber = body->lastLine();
+ const JSC::Identifier* params = body->parameters();
+ for (size_t i = 0; i < body->parameterCount(); ++i)
+ parameterNames.append(params[i].ustring());
+ // ### get the function name from the AST
+ } else if (callee && callee->isObject(&QScript::QtFunction::info)) {
+ functionType = QScriptContextInfo::QtFunction;
+ // ### the slot can be overloaded -- need to get the particular overload from the context
+ functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->initialIndex();
+ const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject();
+ if (meta != 0) {
+ QMetaMethod method = meta->method(functionMetaIndex);
+ QList<QByteArray> formals = method.parameterNames();
+ for (int i = 0; i < formals.count(); ++i)
+ parameterNames.append(QLatin1String(formals.at(i)));
+ }
+ }
+ else if (callee && callee->isObject(&QScript::QtPropertyFunction::info)) {
+ functionType = QScriptContextInfo::QtPropertyFunction;
+ functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex();
+ }
+}
+
+/*!
+ \internal
+*/
+QScriptContextInfoPrivate::~QScriptContextInfoPrivate()
+{
+}
+
+/*!
+ Constructs a new QScriptContextInfo from the given \a context.
+
+ The relevant information is extracted from the \a context at
+ construction time; i.e. if you continue script execution in the \a
+ context, the new state of the context will not be reflected in a
+ previously created QScriptContextInfo.
+*/
+QScriptContextInfo::QScriptContextInfo(const QScriptContext *context)
+ : d_ptr(0)
+{
+ if (context) {
+ d_ptr = new QScriptContextInfoPrivate(context);
+ d_ptr->q_ptr = this;
+ }
+}
+
+/*!
+ Constructs a new QScriptContextInfo from the \a other info.
+*/
+QScriptContextInfo::QScriptContextInfo(const QScriptContextInfo &other)
+ : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+ Constructs a null QScriptContextInfo.
+
+ \sa isNull()
+*/
+QScriptContextInfo::QScriptContextInfo()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Destroys the QScriptContextInfo.
+*/
+QScriptContextInfo::~QScriptContextInfo()
+{
+}
+
+/*!
+ Assigns the \a other info to this QScriptContextInfo,
+ and returns a reference to this QScriptContextInfo.
+*/
+QScriptContextInfo &QScriptContextInfo::operator=(const QScriptContextInfo &other)
+{
+ d_ptr = other.d_ptr;
+ return *this;
+}
+
+/*!
+ Returns the ID of the script where the code being executed was
+ defined, or -1 if the ID is not available (i.e. a native function is
+ being executed).
+
+ \sa QScriptEngineAgent::scriptLoad()
+*/
+qint64 QScriptContextInfo::scriptId() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->scriptId;
+}
+
+/*!
+ Returns the name of the file where the code being executed was
+ defined, if available; otherwise returns an empty string.
+
+ For Qt Script code, this function returns the fileName argument
+ that was passed to QScriptEngine::evaluate().
+
+ \sa lineNumber(), functionName()
+*/
+QString QScriptContextInfo::fileName() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return QString();
+ return d->fileName;
+}
+
+/*!
+ Returns the line number corresponding to the statement being
+ executed, or -1 if the line number is not available.
+
+ The line number is only available if Qt Script code is being
+ executed.
+
+ \sa columnNumber(), fileName()
+*/
+int QScriptContextInfo::lineNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->lineNumber;
+}
+
+/*!
+ Returns the column number corresponding to the statement being
+ executed, or -1 if the column number is not available.
+
+ The column number is only available if Qt Script code is being
+ executed.
+
+ \sa lineNumber(), fileName()
+*/
+int QScriptContextInfo::columnNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->columnNumber;
+}
+
+/*!
+ Returns the name of the called function, or an empty string if
+ the name is not available.
+
+ For script functions of type QtPropertyFunction, this function
+ always returns the name of the property; you can use
+ QScriptContext::argumentCount() to differentiate between reads and
+ writes.
+
+ \sa fileName(), functionType()
+*/
+QString QScriptContextInfo::functionName() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return QString();
+ return d->functionName;
+}
+
+/*!
+ Returns the type of the called function.
+
+ \sa functionName(), QScriptContext::callee()
+*/
+QScriptContextInfo::FunctionType QScriptContextInfo::functionType() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return NativeFunction;
+ return d->functionType;
+}
+
+/*!
+ Returns the line number where the definition of the called function
+ starts, or -1 if the line number is not available.
+
+ The starting line number is only available if the functionType() is
+ ScriptFunction.
+
+ \sa functionEndLineNumber(), fileName()
+*/
+int QScriptContextInfo::functionStartLineNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->functionStartLineNumber;
+}
+
+/*!
+ Returns the line number where the definition of the called function
+ ends, or -1 if the line number is not available.
+
+ The ending line number is only available if the functionType() is
+ ScriptFunction.
+
+ \sa functionStartLineNumber()
+*/
+int QScriptContextInfo::functionEndLineNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->functionEndLineNumber;
+}
+
+/*!
+ Returns the names of the formal parameters of the called function,
+ or an empty QStringList if the parameter names are not available.
+
+ \sa QScriptContext::argument()
+*/
+QStringList QScriptContextInfo::functionParameterNames() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return QStringList();
+ return d->parameterNames;
+}
+
+/*!
+ Returns the meta index of the called function, or -1 if the meta
+ index is not available.
+
+ The meta index is only available if the functionType() is QtFunction
+ or QtPropertyFunction. For QtFunction, the meta index can be passed
+ to QMetaObject::method() to obtain the corresponding method
+ definition; for QtPropertyFunction, the meta index can be passed to
+ QMetaObject::property() to obtain the corresponding property
+ definition.
+
+ \sa QScriptContext::thisObject()
+*/
+int QScriptContextInfo::functionMetaIndex() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->functionMetaIndex;
+}
+
+/*!
+ Returns true if this QScriptContextInfo is null, i.e. does not
+ contain any information.
+*/
+bool QScriptContextInfo::isNull() const
+{
+ Q_D(const QScriptContextInfo);
+ return (d == 0);
+}
+
+/*!
+ Returns true if this QScriptContextInfo is equal to the \a other
+ info, otherwise returns false.
+*/
+bool QScriptContextInfo::operator==(const QScriptContextInfo &other) const
+{
+ Q_D(const QScriptContextInfo);
+ const QScriptContextInfoPrivate *od = other.d_func();
+ if (d == od)
+ return true;
+ if (!d || !od)
+ return false;
+ return ((d->scriptId == od->scriptId)
+ && (d->lineNumber == od->lineNumber)
+ && (d->columnNumber == od->columnNumber)
+ && (d->fileName == od->fileName)
+ && (d->functionName == od->functionName)
+ && (d->functionType == od->functionType)
+ && (d->functionStartLineNumber == od->functionStartLineNumber)
+ && (d->functionEndLineNumber == od->functionEndLineNumber)
+ && (d->functionMetaIndex == od->functionMetaIndex)
+ && (d->parameterNames == od->parameterNames));
+}
+
+/*!
+ Returns true if this QScriptContextInfo is not equal to the \a other
+ info, otherwise returns false.
+*/
+bool QScriptContextInfo::operator!=(const QScriptContextInfo &other) const
+{
+ return !(*this == other);
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QScriptContextInfo &info)
+ \since 4.4
+ \relates QScriptContextInfo
+
+ Writes the given \a info to the specified \a stream.
+*/
+QDataStream &operator<<(QDataStream &out, const QScriptContextInfo &info)
+{
+ out << info.scriptId();
+ out << (qint32)info.lineNumber();
+ out << (qint32)info.columnNumber();
+
+ out << (quint32)info.functionType();
+ out << (qint32)info.functionStartLineNumber();
+ out << (qint32)info.functionEndLineNumber();
+ out << (qint32)info.functionMetaIndex();
+
+ out << info.fileName();
+ out << info.functionName();
+ out << info.functionParameterNames();
+
+ return out;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QScriptContextInfo &info)
+ \since 4.4
+ \relates QScriptContextInfo
+
+ Reads a QScriptContextInfo from the specified \a stream into the
+ given \a info.
+*/
+Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &in, QScriptContextInfo &info)
+{
+ if (!info.d_ptr) {
+ info.d_ptr = new QScriptContextInfoPrivate();
+ }
+
+ in >> info.d_ptr->scriptId;
+
+ qint32 line;
+ in >> line;
+ info.d_ptr->lineNumber = line;
+
+ qint32 column;
+ in >> column;
+ info.d_ptr->columnNumber = column;
+
+ quint32 ftype;
+ in >> ftype;
+ info.d_ptr->functionType = QScriptContextInfo::FunctionType(ftype);
+
+ qint32 startLine;
+ in >> startLine;
+ info.d_ptr->functionStartLineNumber = startLine;
+
+ qint32 endLine;
+ in >> endLine;
+ info.d_ptr->functionEndLineNumber = endLine;
+
+ qint32 metaIndex;
+ in >> metaIndex;
+ info.d_ptr->functionMetaIndex = metaIndex;
+
+ in >> info.d_ptr->fileName;
+ in >> info.d_ptr->functionName;
+ in >> info.d_ptr->parameterNames;
+
+ return in;
+}
+#endif
+
+QT_END_NAMESPACE