Add source file and line number to QV4::Exception
authorLars Knoll <lars.knoll@digia.com>
Mon, 20 May 2013 18:24:42 +0000 (20:24 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 21 May 2013 08:03:03 +0000 (10:03 +0200)
This will allow us to replace v8::Message properly and give
us proper error reporting for uncaught exceptions.

Change-Id: I1c03b6c21456dea06931a874bb2aa5a0b00aff62
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
18 files changed:
src/qml/qml/v4/llvm_runtime.cpp
src/qml/qml/v4/moth/qv4instr_moth_p.h
src/qml/qml/v4/moth/qv4isel_moth.cpp
src/qml/qml/v4/moth/qv4isel_moth_p.h
src/qml/qml/v4/moth/qv4vme_moth.cpp
src/qml/qml/v4/qv4codegen.cpp
src/qml/qml/v4/qv4context.cpp
src/qml/qml/v4/qv4function_p.h
src/qml/qml/v4/qv4isel_llvm.cpp
src/qml/qml/v4/qv4isel_llvm_p.h
src/qml/qml/v4/qv4isel_masm.cpp
src/qml/qml/v4/qv4isel_masm_p.h
src/qml/qml/v4/qv4isel_p.cpp
src/qml/qml/v4/qv4isel_p.h
src/qml/qml/v4/qv4jsir_p.h
src/qml/qml/v4/qv4runtime.cpp
src/qml/qml/v4/qv4runtime_p.h
src/qml/qml/v4/qv4v8.cpp

index 89d057d..615b303 100644 (file)
@@ -472,7 +472,7 @@ void __qmljs_llvm_typeof(ExecutionContext *ctx, Value *result, const Value *valu
 
 void __qmljs_llvm_throw(ExecutionContext *context, Value *value)
 {
-    __qmljs_throw(context, *value);
+    __qmljs_throw(context, *value, -1);
 }
 
 void __qmljs_llvm_delete_exception_handler(ExecutionContext *context)
index ed762af..96043b4 100644 (file)
@@ -249,6 +249,7 @@ union Instr
     struct instr_callBuiltinThrow {
         MOTH_INSTR_HEADER
         Param arg;
+        int line;
     };
     struct instr_callBuiltinFinishTry {
         MOTH_INSTR_HEADER
index 7e55a4e..1b16ea4 100644 (file)
@@ -674,10 +674,11 @@ void InstructionSelection::callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR
     addInstruction(call);
 }
 
-void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg)
+void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg, int line)
 {
     Instruction::CallBuiltinThrow call;
     call.arg = getParam(arg);
+    call.line = line;
     addInstruction(call);
 }
 
index 58f8eec..c499b5d 100644 (file)
@@ -44,7 +44,7 @@ protected:
     virtual void callBuiltinPostIncrementSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result);
     virtual void callBuiltinPostIncrementName(const QString &name, V4IR::Temp *result);
     virtual void callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR::Temp *result);
-    virtual void callBuiltinThrow(V4IR::Temp *arg);
+    virtual void callBuiltinThrow(V4IR::Temp *arg, int line);
     virtual void callBuiltinFinishTry();
     virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result);
     virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result);
index 4a7e189..69b239d 100644 (file)
@@ -308,7 +308,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
     MOTH_END_INSTR(CallActivationProperty)
 
     MOTH_BEGIN_INSTR(CallBuiltinThrow)
-        __qmljs_builtin_throw(context, VALUE(instr.arg));
+        __qmljs_throw(context, VALUE(instr.arg), instr.line);
     MOTH_END_INSTR(CallBuiltinThrow)
 
     MOTH_BEGIN_INSTR(EnterTry)
index e5459c9..41fbba1 100644 (file)
@@ -2584,6 +2584,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
 
     enterEnvironment(ast);
     V4IR::Function *function = _module->newFunction(name, _function);
+    function->sourceFile = QUrl::fromLocalFile(_fileName);
 
     if (_debugger)
         _debugger->addFunction(function);
index 5119677..5a4752a 100644 (file)
@@ -522,7 +522,8 @@ void ExecutionContext::inplaceBitOp(String *name, const Value &value, BinOp op)
 
 void ExecutionContext::throwError(const Value &value)
 {
-    __qmljs_builtin_throw(this, value);
+    // ### line number???
+    __qmljs_throw(this, value, -1);
 }
 
 void ExecutionContext::throwError(const QString &message)
index d73dc8d..e4a9cd9 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <QtCore/QVector>
 #include <QtCore/QByteArray>
+#include <QtCore/qurl.h>
 
 #include <config.h>
 #include <assembler/MacroAssemblerCodeRef.h>
@@ -102,6 +103,8 @@ struct Function {
     bool isStrict;
     bool isNamedExpression;
 
+    QUrl sourceFile;
+
     Function(String *name)
         : name(name)
         , code(0)
index f40eb56..5f06700 100644 (file)
@@ -420,7 +420,7 @@ void InstructionSelection::callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR
     Q_UNREACHABLE();
 }
 
-void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg)
+void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg, int line)
 {
     // TODO
     assert(!"TODO!");
index e96d0b9..aeccde0 100644 (file)
@@ -87,7 +87,7 @@ public: // methods from InstructionSelection:
     virtual void callBuiltinPostIncrementSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result);
     virtual void callBuiltinPostIncrementName(const QString &name, V4IR::Temp *result);
     virtual void callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR::Temp *result);
-    virtual void callBuiltinThrow(V4IR::Temp *arg);
+    virtual void callBuiltinThrow(V4IR::Temp *arg, int line);
     virtual void callBuiltinCreateExceptionHandler(V4IR::Temp *result);
     virtual void callBuiltinFinishTry();
     virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result);
index 43757d0..5c660e6 100644 (file)
@@ -720,9 +720,9 @@ void InstructionSelection::callBuiltinPostDecrementValue(V4IR::Temp *value, V4IR
                          Assembler::PointerToValue(result), Assembler::PointerToValue(value));
 }
 
-void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg)
+void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg, int line)
 {
-    generateFunctionCall(Assembler::Void, __qmljs_builtin_throw, Assembler::ContextRegister, Assembler::Reference(arg));
+    generateFunctionCall(Assembler::Void, __qmljs_throw, Assembler::ContextRegister, Assembler::Reference(arg), Assembler::TrustedImm32(line));
 }
 
 typedef void *(*MiddleOfFunctionEntryPoint(ExecutionContext *, void *localsPtr));
index 437c250..bdd05e3 100644 (file)
@@ -771,7 +771,7 @@ protected:
     virtual void callBuiltinPostIncrementSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result);
     virtual void callBuiltinPostIncrementName(const QString &name, V4IR::Temp *result);
     virtual void callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR::Temp *result);
-    virtual void callBuiltinThrow(V4IR::Temp *arg);
+    virtual void callBuiltinThrow(V4IR::Temp *arg, int line);
     virtual void callBuiltinFinishTry();
     virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result);
     virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result);
index f31ad18..3c83c68 100644 (file)
@@ -47,6 +47,7 @@ QV4::Function *EvalInstructionSelection::createFunctionMapping(QV4::Function *ou
     vmFunction->isStrict = irFunction->isStrict;
     vmFunction->outer = outer;
     vmFunction->isNamedExpression = irFunction->isNamedExpression;
+    vmFunction->sourceFile = irFunction->sourceFile;
 
     if (outer)
         outer->nestedFunctions.append(vmFunction);
@@ -309,7 +310,7 @@ void InstructionSelection::callBuiltin(V4IR::Call *call, V4IR::Temp *result)
     case V4IR::Name::builtin_throw: {
         V4IR::Temp *arg = call->args->expr->asTemp();
         assert(arg != 0);
-        callBuiltinThrow(arg);
+        callBuiltinThrow(arg, baseName->line);
     } return;
 
     case V4IR::Name::builtin_finish_try:
index 6739ff1..d4f38d3 100644 (file)
@@ -115,7 +115,7 @@ public: // to implement by subclasses:
     virtual void callBuiltinPostIncrementSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result) = 0;
     virtual void callBuiltinPostIncrementName(const QString &name, V4IR::Temp *result) = 0;
     virtual void callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR::Temp *result) = 0;
-    virtual void callBuiltinThrow(V4IR::Temp *arg) = 0;
+    virtual void callBuiltinThrow(V4IR::Temp *arg, int line) = 0;
     virtual void callBuiltinFinishTry() = 0;
     virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result) = 0;
     virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result) = 0;
index f056d72..abe24da 100644 (file)
@@ -58,6 +58,7 @@
 #include <QtCore/QVector>
 #include <QtCore/QString>
 #include <QtCore/QBitArray>
+#include <QtCore/qurl.h>
 
 #ifdef CONST
 #undef CONST
@@ -652,6 +653,8 @@ struct Function {
     QVector<Function *> nestedFunctions;
     Function *outer;
 
+    QUrl sourceFile;
+
     int insideWithOrCatch;
 
     uint hasDirectEval: 1;
index f0df925..eec8f80 100644 (file)
 using namespace QV4;
 
 
-Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionValue)
+Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionValue, int line)
     : exception(exceptionValue)
-{
+    , m_line(line)
+{
+    ExecutionContext *c = throwingContext;
+    while (c) {
+        if (c->type == ExecutionContext::Type_CallContext ||
+            c->type == ExecutionContext::Type_SimpleCallContext) {
+            FunctionObject *f = static_cast<SimpleCallContext *>(c)->function;
+            if (f && f->function)
+                m_file = f->function->sourceFile;
+            break;
+        }
+        c = c->outer;
+    }
     this->throwingContext = throwingContext->engine->current;
     accepted = false;
 }
@@ -947,7 +959,7 @@ void __qmljs_construct_property(ExecutionContext *context, Value *result, const
     context->throwTypeError();
 }
 
-void __qmljs_throw(ExecutionContext *context, const Value &value)
+void __qmljs_throw(ExecutionContext *context, const Value &value, int line)
 {
     if (context->engine->debugger)
         context->engine->debugger->aboutToThrow(value);
@@ -985,7 +997,7 @@ void __qmljs_throw(ExecutionContext *context, const Value &value)
     printf("stack walked. throwing exception now...\n");
 #endif
 
-    throw Exception(context, value);
+    throw Exception(context, value, line);
 }
 
 void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &value)
@@ -1206,11 +1218,6 @@ void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *re
     o->putIndexed(context, idx, v);
 }
 
-void __qmljs_builtin_throw(ExecutionContext *context, const Value &val)
-{
-    __qmljs_throw(context, val);
-}
-
 ExecutionContext *__qmljs_builtin_push_with_scope(const Value &o, ExecutionContext *ctx)
 {
     Object *obj = o.toObject(ctx);
index e5c276a..4890859 100644 (file)
@@ -49,6 +49,7 @@
 #include <QtCore/QString>
 #include <QtCore/qnumeric.h>
 #include <QtCore/QDebug>
+#include <QtCore/qurl.h>
 
 #include <cmath>
 #include <cassert>
@@ -90,7 +91,7 @@ struct ExecutionEngine;
 struct InternalClass;
 
 struct Q_QML_EXPORT Exception {
-    explicit Exception(ExecutionContext *throwingContext, const Value &exceptionValue);
+    explicit Exception(ExecutionContext *throwingContext, const Value &exceptionValue, int line);
     ~Exception();
 
     void accept(ExecutionContext *catchingContext);
@@ -98,11 +99,15 @@ struct Q_QML_EXPORT Exception {
     void partiallyUnwindContext(ExecutionContext *catchingContext);
 
     Value value() const { return exception; }
+    QUrl file() const { return m_file; }
+    int lineNumber() const { return m_line; }
 
 private:
     ExecutionContext *throwingContext;
     bool accepted;
     PersistentValue exception;
+    QUrl m_file;
+    int m_line;
 };
 
 }
@@ -137,7 +142,6 @@ void __qmljs_builtin_post_decrement_name(QV4::ExecutionContext *context, QV4::Va
 void __qmljs_builtin_post_decrement_member(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name);
 void __qmljs_builtin_post_decrement_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
 
-void Q_NORETURN __qmljs_builtin_throw(QV4::ExecutionContext *context, const QV4::Value &val);
 void Q_NORETURN __qmljs_builtin_rethrow(QV4::ExecutionContext *context);
 QV4::ExecutionContext *__qmljs_builtin_push_with_scope(const QV4::Value &o, QV4::ExecutionContext *ctx);
 QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::String *exceptionVarName, const QV4::Value &exceptionValue, QV4::ExecutionContext *ctx);
@@ -206,7 +210,7 @@ void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::Value *result, co
 void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, QV4::String *name);
 void __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::String *name);
 
-void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::Value &value);
+void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::Value &value, int line);
 
 // binary operators
 typedef void (*BinOp)(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
index ea02065..b54419e 100644 (file)
@@ -247,7 +247,8 @@ Handle<Value> Script::Run()
         QV4::Function *f = QV4::EvalFunction::parseSource(engine->rootContext, m_origin.m_fileName, m_script, QQmlJS::Codegen::EvalCode,
                                                                         /*strictMode =*/ false, /*inheritContext =*/ false);
         if (!f)
-            __qmljs_throw(engine->current, QV4::Value::fromObject(engine->newSyntaxErrorObject(engine->current, 0)));
+            // ### FIX file/line number
+            __qmljs_throw(engine->current, QV4::Value::fromObject(engine->newSyntaxErrorObject(engine->current, 0)), -1);
 
         result = engine->run(f);
     } catch (QV4::Exception &e) {
@@ -1912,7 +1913,7 @@ ObjectTemplate::ObjectTemplate()
 
 Handle<Value> ThrowException(Handle<Value> exception)
 {
-    __qmljs_throw(currentEngine()->current, exception->v4Value());
+    __qmljs_throw(currentEngine()->current, exception->v4Value(), -1);
     return Handle<Value>();
 }