Annotate stack traces when frames are elided through tail calls
Task-number: QTBUG-72407 Change-Id: I98b96852309fc783a945797185f666196513d24b Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
8396dc86f2
commit
8fd3cfe7d0
|
@ -1011,6 +1011,11 @@ StackTrace ExecutionEngine::stackTrace(int frameLimit) const
|
||||||
frame.line = qAbs(f->lineNumber());
|
frame.line = qAbs(f->lineNumber());
|
||||||
frame.column = -1;
|
frame.column = -1;
|
||||||
stack.append(frame);
|
stack.append(frame);
|
||||||
|
if (f->isTailCalling) {
|
||||||
|
QV4::StackFrame frame;
|
||||||
|
frame.function = QStringLiteral("[elided tail calls]");
|
||||||
|
stack.append(frame);
|
||||||
|
}
|
||||||
--frameLimit;
|
--frameLimit;
|
||||||
f = f->parent;
|
f = f->parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -518,6 +518,7 @@ ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value *
|
||||||
do {
|
do {
|
||||||
frame.pendingTailCall = false;
|
frame.pendingTailCall = false;
|
||||||
result = Moth::VME::exec(&frame, engine);
|
result = Moth::VME::exec(&frame, engine);
|
||||||
|
frame.isTailCalling = true;
|
||||||
} while (frame.pendingTailCall);
|
} while (frame.pendingTailCall);
|
||||||
|
|
||||||
frame.pop();
|
frame.pop();
|
||||||
|
|
|
@ -125,6 +125,7 @@ struct Q_QML_EXPORT CppStackFrame {
|
||||||
bool yieldIsIterator;
|
bool yieldIsIterator;
|
||||||
bool callerCanHandleTailCall;
|
bool callerCanHandleTailCall;
|
||||||
bool pendingTailCall;
|
bool pendingTailCall;
|
||||||
|
bool isTailCalling;
|
||||||
|
|
||||||
void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc, bool callerCanHandleTailCall = false) {
|
void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc, bool callerCanHandleTailCall = false) {
|
||||||
this->engine = engine;
|
this->engine = engine;
|
||||||
|
@ -140,6 +141,7 @@ struct Q_QML_EXPORT CppStackFrame {
|
||||||
yieldIsIterator = false;
|
yieldIsIterator = false;
|
||||||
this->callerCanHandleTailCall = callerCanHandleTailCall;
|
this->callerCanHandleTailCall = callerCanHandleTailCall;
|
||||||
pendingTailCall = false;
|
pendingTailCall = false;
|
||||||
|
isTailCalling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push() {
|
void push() {
|
||||||
|
|
|
@ -1759,6 +1759,22 @@ void tst_QJSEngine::stacktrace()
|
||||||
QJSValue result2 = eng.evaluate(script2, fileName);
|
QJSValue result2 = eng.evaluate(script2, fileName);
|
||||||
QVERIFY(!result2.isError());
|
QVERIFY(!result2.isError());
|
||||||
QVERIFY(result2.isString());
|
QVERIFY(result2.isString());
|
||||||
|
|
||||||
|
{
|
||||||
|
QString script3 = QString::fromLatin1(
|
||||||
|
"'use strict'\n"
|
||||||
|
"function throwUp() { throw new Error('up') }\n"
|
||||||
|
"function indirectlyThrow() { return throwUp() }\n"
|
||||||
|
"indirectlyThrow()\n"
|
||||||
|
);
|
||||||
|
QJSValue result3 = eng.evaluate(script3);
|
||||||
|
QVERIFY(result3.isError());
|
||||||
|
QJSValue stack = result3.property("stack");
|
||||||
|
QVERIFY(stack.isString());
|
||||||
|
QString stackTrace = stack.toString();
|
||||||
|
QVERIFY(!stackTrace.contains(QStringLiteral("indirectlyThrow")));
|
||||||
|
QVERIFY(stackTrace.contains(QStringLiteral("elide")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QJSEngine::numberParsing_data()
|
void tst_QJSEngine::numberParsing_data()
|
||||||
|
|
Loading…
Reference in New Issue