From 0c9d347089ec3c0813b5a09eb7911ed1b1d752e2 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 14 Jun 2013 13:08:13 +0200 Subject: [PATCH] Implement error.fileName and error.lineNumber Useful extensions to the error object. This also helped track down a few places in the parser where we wouldn't give correct error information. Change-Id: Id03653e096216e097c13a7a6e698ca142d92da13 Reviewed-by: Simon Hausmann --- src/qml/qml/v4/qv4codegen.cpp | 2 +- src/qml/qml/v4/qv4context.cpp | 7 +++++++ src/qml/qml/v4/qv4context_p.h | 1 + src/qml/qml/v4/qv4engine.cpp | 6 ++++++ src/qml/qml/v4/qv4engine_p.h | 1 + src/qml/qml/v4/qv4errorobject.cpp | 16 ++++++++++++++++ src/qml/qml/v4/qv4errorobject_p.h | 1 + tests/auto/qml/qjsengine/tst_qjsengine.cpp | 3 --- 8 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/qml/qml/v4/qv4codegen.cpp b/src/qml/qml/v4/qv4codegen.cpp index 77c4610..310272c 100644 --- a/src/qml/qml/v4/qv4codegen.cpp +++ b/src/qml/qml/v4/qv4codegen.cpp @@ -2616,7 +2616,7 @@ void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail) void Codegen::throwReferenceError(const SourceLocation &loc, const QString &detail) { if (_context) - _context->throwReferenceError(QV4::Value::fromString(_context, detail)); + _context->throwReferenceError(QV4::Value::fromString(_context, detail), _fileName, loc.startLine); else if (_errorHandler) throwSyntaxError(loc, detail); else diff --git a/src/qml/qml/v4/qv4context.cpp b/src/qml/qml/v4/qv4context.cpp index 79553b9..4838a15 100644 --- a/src/qml/qml/v4/qv4context.cpp +++ b/src/qml/qml/v4/qv4context.cpp @@ -582,6 +582,13 @@ void ExecutionContext::throwReferenceError(Value value) throwError(Value::fromObject(engine->newReferenceErrorObject(msg))); } +void ExecutionContext::throwReferenceError(Value value, const QString &fileName, int line) +{ + String *s = value.toString(this); + QString msg = s->toQString() + QStringLiteral(" is not defined"); + throwError(Value::fromObject(engine->newReferenceErrorObject(msg, fileName, line))); +} + void ExecutionContext::throwRangeError(Value value) { String *s = value.toString(this); diff --git a/src/qml/qml/v4/qv4context_p.h b/src/qml/qml/v4/qv4context_p.h index 1f59d27..4e1aebf 100644 --- a/src/qml/qml/v4/qv4context_p.h +++ b/src/qml/qml/v4/qv4context_p.h @@ -133,6 +133,7 @@ struct Q_QML_EXPORT ExecutionContext void Q_NORETURN throwTypeError(); void Q_NORETURN throwTypeError(const QString &message); void Q_NORETURN throwReferenceError(Value value); + void Q_NORETURN throwReferenceError(Value value, const QString &fileName, int line); void Q_NORETURN throwRangeError(Value value); void Q_NORETURN throwURIError(Value msg); void Q_NORETURN throwUnimplemented(const QString &message); diff --git a/src/qml/qml/v4/qv4engine.cpp b/src/qml/qml/v4/qv4engine.cpp index f0ceaf7..ad5bcaf 100644 --- a/src/qml/qml/v4/qv4engine.cpp +++ b/src/qml/qml/v4/qv4engine.cpp @@ -532,6 +532,12 @@ Object *ExecutionEngine::newReferenceErrorObject(const QString &message) return new (memoryManager) ReferenceErrorObject(this, message); } +Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber) +{ + return new (memoryManager) ReferenceErrorObject(this, message, fileName, lineNumber); +} + + Object *ExecutionEngine::newTypeErrorObject(const QString &message) { return new (memoryManager) TypeErrorObject(this, message); diff --git a/src/qml/qml/v4/qv4engine_p.h b/src/qml/qml/v4/qv4engine_p.h index c137534..09f76ec 100644 --- a/src/qml/qml/v4/qv4engine_p.h +++ b/src/qml/qml/v4/qv4engine_p.h @@ -266,6 +266,7 @@ struct Q_QML_EXPORT ExecutionEngine Object *newSyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *message); Object *newSyntaxErrorObject(const QString &message); Object *newReferenceErrorObject(const QString &message); + Object *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber); Object *newTypeErrorObject(const QString &message); Object *newRangeErrorObject(const QString &message); Object *newURIErrorObject(Value message); diff --git a/src/qml/qml/v4/qv4errorobject.cpp b/src/qml/qml/v4/qv4errorobject.cpp index b8939a9..0f77b54 100644 --- a/src/qml/qml/v4/qv4errorobject.cpp +++ b/src/qml/qml/v4/qv4errorobject.cpp @@ -85,6 +85,10 @@ ErrorObject::ErrorObject(ExecutionEngine *engine, const Value &message, ErrorTyp defineDefaultProperty(engine, QStringLiteral("name"), Value::fromString(engine, className())); stackTrace = engine->stackTrace(); + if (!stackTrace.isEmpty()) { + defineDefaultProperty(engine, QStringLiteral("fileName"), Value::fromString(engine, stackTrace.at(0).source)); + defineDefaultProperty(engine, QStringLiteral("lineNumber"), Value::fromInt32(stackTrace.at(0).line)); + } stack = Value::emptyValue(); } @@ -137,6 +141,10 @@ SyntaxErrorObject::SyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *m { vtbl = &static_vtbl; prototype = ctx->engine->syntaxErrorPrototype; + if (message) { + defineDefaultProperty(ctx->engine, QStringLiteral("fileName"), Value::fromString(ctx, message->fileName)); + defineDefaultProperty(ctx->engine, QStringLiteral("lineNumber"), Value::fromInt32(message->startLine)); + } } @@ -171,6 +179,14 @@ ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QStrin prototype = engine->referenceErrorPrototype; } +ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber) + : ErrorObject(engine, Value::fromString(engine, msg), ReferenceError) +{ + prototype = engine->referenceErrorPrototype; + defineDefaultProperty(engine, QStringLiteral("fileName"), Value::fromString(engine->rootContext, fileName)); + defineDefaultProperty(engine, QStringLiteral("lineNumber"), Value::fromInt32(lineNumber)); +} + TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message) : ErrorObject(engine, message, TypeError) { diff --git a/src/qml/qml/v4/qv4errorobject_p.h b/src/qml/qml/v4/qv4errorobject_p.h index 41e3aba..7cc8804 100644 --- a/src/qml/qml/v4/qv4errorobject_p.h +++ b/src/qml/qml/v4/qv4errorobject_p.h @@ -83,6 +83,7 @@ struct RangeErrorObject: ErrorObject { struct ReferenceErrorObject: ErrorObject { ReferenceErrorObject(ExecutionEngine *engine, const Value &message); ReferenceErrorObject(ExecutionEngine *engine, const QString &msg); + ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber); }; struct SyntaxErrorObject: ErrorObject { diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index e0e08d9..9f4756b 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -923,7 +923,6 @@ void tst_QJSEngine::evaluate() ret = eng.evaluate(code); QCOMPARE(ret.isError(), expectHadError); if (ret.isError()) { - QEXPECT_FAIL("", "we have no more lineNumber property ", Continue); QVERIFY(ret.property("lineNumber").strictlyEquals(eng.toScriptValue(expectErrorLineNumber))); } } @@ -1605,8 +1604,6 @@ void tst_QJSEngine::errorConstructors() QJSValue ret = eng.evaluate(code); QVERIFY(ret.isError()); QVERIFY(ret.toString().startsWith(name)); - //QTBUG-6138: JSC doesn't assign lineNumber when errors are not thrown - QEXPECT_FAIL("", "we have no more lineNumber property ", Continue); QCOMPARE(ret.property("lineNumber").toInt(), i+2); } } -- 2.7.4