source: trunk/src/script/api/qscriptcontextinfo.cpp@ 1036

Last change on this file since 1036 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 16.0 KB
RevLine 
[556]1/****************************************************************************
2**
[846]3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
[556]4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtScript module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL-ONLY$
10** GNU Lesser General Public License Usage
11** This file may be used under the terms of the GNU Lesser
12** General Public License version 2.1 as published by the Free Software
13** Foundation and appearing in the file LICENSE.LGPL included in the
14** packaging of this file. Please review the following information to
15** ensure the GNU Lesser General Public License version 2.1 requirements
16** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17**
18** If you have questions regarding the use of this file, please contact
19** Nokia at [email protected].
20** $QT_END_LICENSE$
21**
22****************************************************************************/
23
24#include "config.h"
25#include "qscriptcontextinfo.h"
26
27#include "qscriptcontext_p.h"
28#include "qscriptengine.h"
29#include "qscriptengine_p.h"
30#include "../bridge/qscriptqobject_p.h"
31#include <QtCore/qdatastream.h>
32#include <QtCore/qmetaobject.h>
33#include "CodeBlock.h"
34#include "JSFunction.h"
35#if ENABLE(JIT)
36#include "MacroAssemblerCodeRef.h"
37#endif
38
39QT_BEGIN_NAMESPACE
40
41/*!
42 \since 4.4
43 \class QScriptContextInfo
44
45 \brief The QScriptContextInfo class provides additional information about a QScriptContext.
46
47 \ingroup script
48
49
50 QScriptContextInfo is typically used for debugging purposes. It can
51 provide information about the code being executed, such as the type
52 of the called function, and the original source code location of the
53 current statement.
54
55 If the called function is executing Qt Script code, you can obtain
[846]56 the script location with the functions fileName() and lineNumber().
[556]57
58 You can obtain the starting line number and ending line number of a
59 Qt Script function definition with functionStartLineNumber() and
60 functionEndLineNumber(), respectively.
61
62 For Qt Script functions and Qt methods (e.g. slots), you can call
63 functionParameterNames() to get the names of the formal parameters of the
64 function.
65
66 For Qt methods and Qt property accessors, you can obtain the index
67 of the underlying QMetaMethod or QMetaProperty by calling
68 functionMetaIndex().
69
70 \sa QScriptContext, QScriptEngineAgent
71*/
72
73/*!
74 \enum QScriptContextInfo::FunctionType
75
76 This enum specifies the type of function being called.
77
78 \value ScriptFunction The function is a Qt Script function, i.e. it was defined through a call to QScriptEngine::evaluate().
79 \value QtFunction The function is a Qt function (a signal, slot or method).
80 \value QtPropertyFunction The function is a Qt property getter or setter.
81 \value NativeFunction The function is a built-in Qt Script function, or it was defined through a call to QScriptEngine::newFunction().
82*/
83
84class QScriptContextInfoPrivate
85{
86 Q_DECLARE_PUBLIC(QScriptContextInfo)
87public:
88 QScriptContextInfoPrivate();
89 QScriptContextInfoPrivate(const QScriptContext *context);
90 ~QScriptContextInfoPrivate();
91
92 qint64 scriptId;
93 int lineNumber;
94 int columnNumber;
95 QString fileName;
96
97 QString functionName;
98 QScriptContextInfo::FunctionType functionType;
99
100 int functionStartLineNumber;
101 int functionEndLineNumber;
102 int functionMetaIndex;
103
104 QStringList parameterNames;
105
106 QBasicAtomicInt ref;
107
108 QScriptContextInfo *q_ptr;
109};
110
111/*!
112 \internal
113*/
114QScriptContextInfoPrivate::QScriptContextInfoPrivate()
115{
116 ref = 0;
117 functionType = QScriptContextInfo::NativeFunction;
118 functionMetaIndex = -1;
119 functionStartLineNumber = -1;
120 functionEndLineNumber = -1;
121 scriptId = -1;
122 lineNumber = -1;
123 columnNumber = -1;
124}
125
126/*!
127 \internal
128*/
129QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context)
130{
131 Q_ASSERT(context);
132 ref = 0;
133 functionType = QScriptContextInfo::NativeFunction;
134 functionMetaIndex = -1;
135 functionStartLineNumber = -1;
136 functionEndLineNumber = -1;
137 scriptId = -1;
138 lineNumber = -1;
139 columnNumber = -1;
140
141 JSC::CallFrame *frame = const_cast<JSC::CallFrame *>(QScriptEnginePrivate::frameForContext(context));
142
143 // Get the line number:
144
145 //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
146 JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame;
147 if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) { //top context
148 frame = rewindContext; //for retreiving the global context's "fake" frame
149 // An agent might have provided the line number.
150 lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
151 } else {
152 // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
153 while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context)
154 rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag();
155 if (rewindContext) {
156 frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame
157
158 JSC::Instruction *returnPC = rewindContext->returnPC();
159 JSC::CodeBlock *codeBlock = frame->codeBlock();
[846]160 if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
[556]161#if ENABLE(JIT)
162 unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC));
163#else
164 unsigned bytecodeOffset = returnPC - codeBlock->instructions().begin();
165#endif
166 bytecodeOffset--; //because returnPC is on the next instruction. We want the current one
167 lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset);
168 }
169 }
170 }
171
172 // Get the filename and the scriptId:
173 JSC::CodeBlock *codeBlock = frame->codeBlock();
[846]174 if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
[556]175 JSC::SourceProvider *source = codeBlock->source();
176 scriptId = source->asID();
177 fileName = source->url();
178 }
179
[846]180 // Get the others information:
[556]181 JSC::JSObject *callee = frame->callee();
182 if (callee && callee->inherits(&JSC::InternalFunction::info))
[846]183 functionName = JSC::asInternalFunction(callee)->name(frame);
184 if (callee && callee->inherits(&JSC::JSFunction::info)
185 && !JSC::asFunction(callee)->isHostFunction()) {
[556]186 functionType = QScriptContextInfo::ScriptFunction;
187 JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable();
188 functionStartLineNumber = body->lineNo();
189 functionEndLineNumber = body->lastLine();
190 for (size_t i = 0; i < body->parameterCount(); ++i)
191 parameterNames.append(body->parameterName(i));
192 // ### get the function name from the AST
193 } else if (callee && callee->inherits(&QScript::QtFunction::info)) {
194 functionType = QScriptContextInfo::QtFunction;
195 // ### the slot can be overloaded -- need to get the particular overload from the context
196 functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->initialIndex();
197 const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject();
198 if (meta != 0) {
199 QMetaMethod method = meta->method(functionMetaIndex);
200 QList<QByteArray> formals = method.parameterNames();
201 for (int i = 0; i < formals.count(); ++i)
202 parameterNames.append(QLatin1String(formals.at(i)));
203 }
204 }
205 else if (callee && callee->inherits(&QScript::QtPropertyFunction::info)) {
206 functionType = QScriptContextInfo::QtPropertyFunction;
207 functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex();
208 }
209}
210
211/*!
212 \internal
213*/
214QScriptContextInfoPrivate::~QScriptContextInfoPrivate()
215{
216}
217
218/*!
219 Constructs a new QScriptContextInfo from the given \a context.
220
221 The relevant information is extracted from the \a context at
222 construction time; i.e. if you continue script execution in the \a
223 context, the new state of the context will not be reflected in a
224 previously created QScriptContextInfo.
225*/
226QScriptContextInfo::QScriptContextInfo(const QScriptContext *context)
227 : d_ptr(0)
228{
229 if (context) {
230 d_ptr = new QScriptContextInfoPrivate(context);
231 d_ptr->q_ptr = this;
232 }
233}
234
235/*!
236 Constructs a new QScriptContextInfo from the \a other info.
237*/
238QScriptContextInfo::QScriptContextInfo(const QScriptContextInfo &other)
239 : d_ptr(other.d_ptr)
240{
241}
242
243/*!
244 Constructs a null QScriptContextInfo.
245
246 \sa isNull()
247*/
248QScriptContextInfo::QScriptContextInfo()
249 : d_ptr(0)
250{
251}
252
253/*!
254 Destroys the QScriptContextInfo.
255*/
256QScriptContextInfo::~QScriptContextInfo()
257{
258}
259
260/*!
261 Assigns the \a other info to this QScriptContextInfo,
262 and returns a reference to this QScriptContextInfo.
263*/
264QScriptContextInfo &QScriptContextInfo::operator=(const QScriptContextInfo &other)
265{
266 d_ptr = other.d_ptr;
267 return *this;
268}
269
270/*!
271 Returns the ID of the script where the code being executed was
272 defined, or -1 if the ID is not available (i.e. a native function is
273 being executed).
274
275 \sa QScriptEngineAgent::scriptLoad()
276*/
277qint64 QScriptContextInfo::scriptId() const
278{
279 Q_D(const QScriptContextInfo);
280 if (!d)
281 return -1;
282 return d->scriptId;
283}
284
285/*!
286 Returns the name of the file where the code being executed was
287 defined, if available; otherwise returns an empty string.
288
289 For Qt Script code, this function returns the fileName argument
290 that was passed to QScriptEngine::evaluate().
291
292 \sa lineNumber(), functionName()
293*/
294QString QScriptContextInfo::fileName() const
295{
296 Q_D(const QScriptContextInfo);
297 if (!d)
298 return QString();
299 return d->fileName;
300}
301
302/*!
303 Returns the line number corresponding to the statement being
304 executed, or -1 if the line number is not available.
305
306 The line number is only available if Qt Script code is being
307 executed.
308
309 \sa columnNumber(), fileName()
310*/
311int QScriptContextInfo::lineNumber() const
312{
313 Q_D(const QScriptContextInfo);
314 if (!d)
315 return -1;
316 return d->lineNumber;
317}
318
319/*!
[846]320 \obsolete
[556]321*/
322int QScriptContextInfo::columnNumber() const
323{
324 Q_D(const QScriptContextInfo);
325 if (!d)
326 return -1;
327 return d->columnNumber;
328}
329
330/*!
331 Returns the name of the called function, or an empty string if
332 the name is not available.
333
334 For script functions of type QtPropertyFunction, this function
335 always returns the name of the property; you can use
336 QScriptContext::argumentCount() to differentiate between reads and
337 writes.
338
339 \sa fileName(), functionType()
340*/
341QString QScriptContextInfo::functionName() const
342{
343 Q_D(const QScriptContextInfo);
344 if (!d)
345 return QString();
346 return d->functionName;
347}
348
349/*!
350 Returns the type of the called function.
351
352 \sa functionName(), QScriptContext::callee()
353*/
354QScriptContextInfo::FunctionType QScriptContextInfo::functionType() const
355{
356 Q_D(const QScriptContextInfo);
357 if (!d)
358 return NativeFunction;
359 return d->functionType;
360}
361
362/*!
363 Returns the line number where the definition of the called function
364 starts, or -1 if the line number is not available.
365
366 The starting line number is only available if the functionType() is
367 ScriptFunction.
368
369 \sa functionEndLineNumber(), fileName()
370*/
371int QScriptContextInfo::functionStartLineNumber() const
372{
373 Q_D(const QScriptContextInfo);
374 if (!d)
375 return -1;
376 return d->functionStartLineNumber;
377}
378
379/*!
380 Returns the line number where the definition of the called function
381 ends, or -1 if the line number is not available.
382
383 The ending line number is only available if the functionType() is
384 ScriptFunction.
385
386 \sa functionStartLineNumber()
387*/
388int QScriptContextInfo::functionEndLineNumber() const
389{
390 Q_D(const QScriptContextInfo);
391 if (!d)
392 return -1;
393 return d->functionEndLineNumber;
394}
395
396/*!
397 Returns the names of the formal parameters of the called function,
398 or an empty QStringList if the parameter names are not available.
399
400 \sa QScriptContext::argument()
401*/
402QStringList QScriptContextInfo::functionParameterNames() const
403{
404 Q_D(const QScriptContextInfo);
405 if (!d)
406 return QStringList();
407 return d->parameterNames;
408}
409
410/*!
411 Returns the meta index of the called function, or -1 if the meta
412 index is not available.
413
414 The meta index is only available if the functionType() is QtFunction
415 or QtPropertyFunction. For QtFunction, the meta index can be passed
416 to QMetaObject::method() to obtain the corresponding method
417 definition; for QtPropertyFunction, the meta index can be passed to
418 QMetaObject::property() to obtain the corresponding property
419 definition.
420
421 \sa QScriptContext::thisObject()
422*/
423int QScriptContextInfo::functionMetaIndex() const
424{
425 Q_D(const QScriptContextInfo);
426 if (!d)
427 return -1;
428 return d->functionMetaIndex;
429}
430
431/*!
432 Returns true if this QScriptContextInfo is null, i.e. does not
433 contain any information.
434*/
435bool QScriptContextInfo::isNull() const
436{
437 Q_D(const QScriptContextInfo);
438 return (d == 0);
439}
440
441/*!
442 Returns true if this QScriptContextInfo is equal to the \a other
443 info, otherwise returns false.
444*/
445bool QScriptContextInfo::operator==(const QScriptContextInfo &other) const
446{
447 Q_D(const QScriptContextInfo);
448 const QScriptContextInfoPrivate *od = other.d_func();
449 if (d == od)
450 return true;
451 if (!d || !od)
452 return false;
453 return ((d->scriptId == od->scriptId)
454 && (d->lineNumber == od->lineNumber)
455 && (d->columnNumber == od->columnNumber)
456 && (d->fileName == od->fileName)
457 && (d->functionName == od->functionName)
458 && (d->functionType == od->functionType)
459 && (d->functionStartLineNumber == od->functionStartLineNumber)
460 && (d->functionEndLineNumber == od->functionEndLineNumber)
461 && (d->functionMetaIndex == od->functionMetaIndex)
462 && (d->parameterNames == od->parameterNames));
463}
464
465/*!
466 Returns true if this QScriptContextInfo is not equal to the \a other
467 info, otherwise returns false.
468*/
469bool QScriptContextInfo::operator!=(const QScriptContextInfo &other) const
470{
471 return !(*this == other);
472}
473
474#ifndef QT_NO_DATASTREAM
475/*!
476 \fn QDataStream &operator<<(QDataStream &stream, const QScriptContextInfo &info)
477 \since 4.4
478 \relates QScriptContextInfo
479
480 Writes the given \a info to the specified \a stream.
481*/
482QDataStream &operator<<(QDataStream &out, const QScriptContextInfo &info)
483{
484 out << info.scriptId();
485 out << (qint32)info.lineNumber();
486 out << (qint32)info.columnNumber();
487
488 out << (quint32)info.functionType();
489 out << (qint32)info.functionStartLineNumber();
490 out << (qint32)info.functionEndLineNumber();
491 out << (qint32)info.functionMetaIndex();
492
493 out << info.fileName();
494 out << info.functionName();
495 out << info.functionParameterNames();
496
497 return out;
498}
499
500/*!
501 \fn QDataStream &operator>>(QDataStream &stream, QScriptContextInfo &info)
502 \since 4.4
503 \relates QScriptContextInfo
504
505 Reads a QScriptContextInfo from the specified \a stream into the
506 given \a info.
507*/
508Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &in, QScriptContextInfo &info)
509{
510 if (!info.d_ptr) {
511 info.d_ptr = new QScriptContextInfoPrivate();
512 }
513
514 in >> info.d_ptr->scriptId;
515
516 qint32 line;
517 in >> line;
518 info.d_ptr->lineNumber = line;
519
520 qint32 column;
521 in >> column;
522 info.d_ptr->columnNumber = column;
523
524 quint32 ftype;
525 in >> ftype;
526 info.d_ptr->functionType = QScriptContextInfo::FunctionType(ftype);
527
528 qint32 startLine;
529 in >> startLine;
530 info.d_ptr->functionStartLineNumber = startLine;
531
532 qint32 endLine;
533 in >> endLine;
534 info.d_ptr->functionEndLineNumber = endLine;
535
536 qint32 metaIndex;
537 in >> metaIndex;
538 info.d_ptr->functionMetaIndex = metaIndex;
539
540 in >> info.d_ptr->fileName;
541 in >> info.d_ptr->functionName;
542 in >> info.d_ptr->parameterNames;
543
544 return in;
545}
546#endif
547
548QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.