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

Last change on this file since 573 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 16.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
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
56 the script location with the functions fileName(), lineNumber() and
57 columnNumber().
58
59 You can obtain the starting line number and ending line number of a
60 Qt Script function definition with functionStartLineNumber() and
61 functionEndLineNumber(), respectively.
62
63 For Qt Script functions and Qt methods (e.g. slots), you can call
64 functionParameterNames() to get the names of the formal parameters of the
65 function.
66
67 For Qt methods and Qt property accessors, you can obtain the index
68 of the underlying QMetaMethod or QMetaProperty by calling
69 functionMetaIndex().
70
71 \sa QScriptContext, QScriptEngineAgent
72*/
73
74/*!
75 \enum QScriptContextInfo::FunctionType
76
77 This enum specifies the type of function being called.
78
79 \value ScriptFunction The function is a Qt Script function, i.e. it was defined through a call to QScriptEngine::evaluate().
80 \value QtFunction The function is a Qt function (a signal, slot or method).
81 \value QtPropertyFunction The function is a Qt property getter or setter.
82 \value NativeFunction The function is a built-in Qt Script function, or it was defined through a call to QScriptEngine::newFunction().
83*/
84
85class QScriptContextInfoPrivate
86{
87 Q_DECLARE_PUBLIC(QScriptContextInfo)
88public:
89 QScriptContextInfoPrivate();
90 QScriptContextInfoPrivate(const QScriptContext *context);
91 ~QScriptContextInfoPrivate();
92
93 qint64 scriptId;
94 int lineNumber;
95 int columnNumber;
96 QString fileName;
97
98 QString functionName;
99 QScriptContextInfo::FunctionType functionType;
100
101 int functionStartLineNumber;
102 int functionEndLineNumber;
103 int functionMetaIndex;
104
105 QStringList parameterNames;
106
107 QBasicAtomicInt ref;
108
109 QScriptContextInfo *q_ptr;
110};
111
112/*!
113 \internal
114*/
115QScriptContextInfoPrivate::QScriptContextInfoPrivate()
116{
117 ref = 0;
118 functionType = QScriptContextInfo::NativeFunction;
119 functionMetaIndex = -1;
120 functionStartLineNumber = -1;
121 functionEndLineNumber = -1;
122 scriptId = -1;
123 lineNumber = -1;
124 columnNumber = -1;
125}
126
127/*!
128 \internal
129*/
130QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context)
131{
132 Q_ASSERT(context);
133 ref = 0;
134 functionType = QScriptContextInfo::NativeFunction;
135 functionMetaIndex = -1;
136 functionStartLineNumber = -1;
137 functionEndLineNumber = -1;
138 scriptId = -1;
139 lineNumber = -1;
140 columnNumber = -1;
141
142 JSC::CallFrame *frame = const_cast<JSC::CallFrame *>(QScriptEnginePrivate::frameForContext(context));
143
144 // Get the line number:
145
146 //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
147 JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame;
148 if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) { //top context
149 frame = rewindContext; //for retreiving the global context's "fake" frame
150 // An agent might have provided the line number.
151 lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
152 } else {
153 // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
154 while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context)
155 rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag();
156 if (rewindContext) {
157 frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame
158
159 JSC::Instruction *returnPC = rewindContext->returnPC();
160 JSC::CodeBlock *codeBlock = frame->codeBlock();
161 if (returnPC && codeBlock) {
162#if ENABLE(JIT)
163 unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC));
164#else
165 unsigned bytecodeOffset = returnPC - codeBlock->instructions().begin();
166#endif
167 bytecodeOffset--; //because returnPC is on the next instruction. We want the current one
168 lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset);
169 }
170 }
171 }
172
173 // Get the filename and the scriptId:
174 JSC::CodeBlock *codeBlock = frame->codeBlock();
175 if (codeBlock) {
176 JSC::SourceProvider *source = codeBlock->source();
177 scriptId = source->asID();
178 fileName = source->url();
179 }
180
181 // Get the others informations:
182 JSC::JSObject *callee = frame->callee();
183 if (callee && callee->inherits(&JSC::InternalFunction::info))
184 functionName = JSC::asInternalFunction(callee)->name(&frame->globalData());
185 if (callee && callee->inherits(&JSC::JSFunction::info)) {
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/*!
320 Returns the column number corresponding to the statement being
321 executed, or -1 if the column number is not available.
322
323 The column number is only available if Qt Script code is being
324 executed.
325
326 \sa lineNumber(), fileName()
327*/
328int QScriptContextInfo::columnNumber() const
329{
330 Q_D(const QScriptContextInfo);
331 if (!d)
332 return -1;
333 return d->columnNumber;
334}
335
336/*!
337 Returns the name of the called function, or an empty string if
338 the name is not available.
339
340 For script functions of type QtPropertyFunction, this function
341 always returns the name of the property; you can use
342 QScriptContext::argumentCount() to differentiate between reads and
343 writes.
344
345 \sa fileName(), functionType()
346*/
347QString QScriptContextInfo::functionName() const
348{
349 Q_D(const QScriptContextInfo);
350 if (!d)
351 return QString();
352 return d->functionName;
353}
354
355/*!
356 Returns the type of the called function.
357
358 \sa functionName(), QScriptContext::callee()
359*/
360QScriptContextInfo::FunctionType QScriptContextInfo::functionType() const
361{
362 Q_D(const QScriptContextInfo);
363 if (!d)
364 return NativeFunction;
365 return d->functionType;
366}
367
368/*!
369 Returns the line number where the definition of the called function
370 starts, or -1 if the line number is not available.
371
372 The starting line number is only available if the functionType() is
373 ScriptFunction.
374
375 \sa functionEndLineNumber(), fileName()
376*/
377int QScriptContextInfo::functionStartLineNumber() const
378{
379 Q_D(const QScriptContextInfo);
380 if (!d)
381 return -1;
382 return d->functionStartLineNumber;
383}
384
385/*!
386 Returns the line number where the definition of the called function
387 ends, or -1 if the line number is not available.
388
389 The ending line number is only available if the functionType() is
390 ScriptFunction.
391
392 \sa functionStartLineNumber()
393*/
394int QScriptContextInfo::functionEndLineNumber() const
395{
396 Q_D(const QScriptContextInfo);
397 if (!d)
398 return -1;
399 return d->functionEndLineNumber;
400}
401
402/*!
403 Returns the names of the formal parameters of the called function,
404 or an empty QStringList if the parameter names are not available.
405
406 \sa QScriptContext::argument()
407*/
408QStringList QScriptContextInfo::functionParameterNames() const
409{
410 Q_D(const QScriptContextInfo);
411 if (!d)
412 return QStringList();
413 return d->parameterNames;
414}
415
416/*!
417 Returns the meta index of the called function, or -1 if the meta
418 index is not available.
419
420 The meta index is only available if the functionType() is QtFunction
421 or QtPropertyFunction. For QtFunction, the meta index can be passed
422 to QMetaObject::method() to obtain the corresponding method
423 definition; for QtPropertyFunction, the meta index can be passed to
424 QMetaObject::property() to obtain the corresponding property
425 definition.
426
427 \sa QScriptContext::thisObject()
428*/
429int QScriptContextInfo::functionMetaIndex() const
430{
431 Q_D(const QScriptContextInfo);
432 if (!d)
433 return -1;
434 return d->functionMetaIndex;
435}
436
437/*!
438 Returns true if this QScriptContextInfo is null, i.e. does not
439 contain any information.
440*/
441bool QScriptContextInfo::isNull() const
442{
443 Q_D(const QScriptContextInfo);
444 return (d == 0);
445}
446
447/*!
448 Returns true if this QScriptContextInfo is equal to the \a other
449 info, otherwise returns false.
450*/
451bool QScriptContextInfo::operator==(const QScriptContextInfo &other) const
452{
453 Q_D(const QScriptContextInfo);
454 const QScriptContextInfoPrivate *od = other.d_func();
455 if (d == od)
456 return true;
457 if (!d || !od)
458 return false;
459 return ((d->scriptId == od->scriptId)
460 && (d->lineNumber == od->lineNumber)
461 && (d->columnNumber == od->columnNumber)
462 && (d->fileName == od->fileName)
463 && (d->functionName == od->functionName)
464 && (d->functionType == od->functionType)
465 && (d->functionStartLineNumber == od->functionStartLineNumber)
466 && (d->functionEndLineNumber == od->functionEndLineNumber)
467 && (d->functionMetaIndex == od->functionMetaIndex)
468 && (d->parameterNames == od->parameterNames));
469}
470
471/*!
472 Returns true if this QScriptContextInfo is not equal to the \a other
473 info, otherwise returns false.
474*/
475bool QScriptContextInfo::operator!=(const QScriptContextInfo &other) const
476{
477 return !(*this == other);
478}
479
480#ifndef QT_NO_DATASTREAM
481/*!
482 \fn QDataStream &operator<<(QDataStream &stream, const QScriptContextInfo &info)
483 \since 4.4
484 \relates QScriptContextInfo
485
486 Writes the given \a info to the specified \a stream.
487*/
488QDataStream &operator<<(QDataStream &out, const QScriptContextInfo &info)
489{
490 out << info.scriptId();
491 out << (qint32)info.lineNumber();
492 out << (qint32)info.columnNumber();
493
494 out << (quint32)info.functionType();
495 out << (qint32)info.functionStartLineNumber();
496 out << (qint32)info.functionEndLineNumber();
497 out << (qint32)info.functionMetaIndex();
498
499 out << info.fileName();
500 out << info.functionName();
501 out << info.functionParameterNames();
502
503 return out;
504}
505
506/*!
507 \fn QDataStream &operator>>(QDataStream &stream, QScriptContextInfo &info)
508 \since 4.4
509 \relates QScriptContextInfo
510
511 Reads a QScriptContextInfo from the specified \a stream into the
512 given \a info.
513*/
514Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &in, QScriptContextInfo &info)
515{
516 if (!info.d_ptr) {
517 info.d_ptr = new QScriptContextInfoPrivate();
518 }
519
520 in >> info.d_ptr->scriptId;
521
522 qint32 line;
523 in >> line;
524 info.d_ptr->lineNumber = line;
525
526 qint32 column;
527 in >> column;
528 info.d_ptr->columnNumber = column;
529
530 quint32 ftype;
531 in >> ftype;
532 info.d_ptr->functionType = QScriptContextInfo::FunctionType(ftype);
533
534 qint32 startLine;
535 in >> startLine;
536 info.d_ptr->functionStartLineNumber = startLine;
537
538 qint32 endLine;
539 in >> endLine;
540 info.d_ptr->functionEndLineNumber = endLine;
541
542 qint32 metaIndex;
543 in >> metaIndex;
544 info.d_ptr->functionMetaIndex = metaIndex;
545
546 in >> info.d_ptr->fileName;
547 in >> info.d_ptr->functionName;
548 in >> info.d_ptr->parameterNames;
549
550 return in;
551}
552#endif
553
554QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.