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)
struct instr_callBuiltinThrow {
MOTH_INSTR_HEADER
Param arg;
+ int line;
};
struct instr_callBuiltinFinishTry {
MOTH_INSTR_HEADER
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);
}
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);
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)
enterEnvironment(ast);
V4IR::Function *function = _module->newFunction(name, _function);
+ function->sourceFile = QUrl::fromLocalFile(_fileName);
if (_debugger)
_debugger->addFunction(function);
void ExecutionContext::throwError(const Value &value)
{
- __qmljs_builtin_throw(this, value);
+ // ### line number???
+ __qmljs_throw(this, value, -1);
}
void ExecutionContext::throwError(const QString &message)
#include <QtCore/QVector>
#include <QtCore/QByteArray>
+#include <QtCore/qurl.h>
#include <config.h>
#include <assembler/MacroAssemblerCodeRef.h>
bool isStrict;
bool isNamedExpression;
+ QUrl sourceFile;
+
Function(String *name)
: name(name)
, code(0)
Q_UNREACHABLE();
}
-void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg)
+void InstructionSelection::callBuiltinThrow(V4IR::Temp *arg, int line)
{
// TODO
assert(!"TODO!");
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);
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));
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);
vmFunction->isStrict = irFunction->isStrict;
vmFunction->outer = outer;
vmFunction->isNamedExpression = irFunction->isNamedExpression;
+ vmFunction->sourceFile = irFunction->sourceFile;
if (outer)
outer->nestedFunctions.append(vmFunction);
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:
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;
#include <QtCore/QVector>
#include <QtCore/QString>
#include <QtCore/QBitArray>
+#include <QtCore/qurl.h>
#ifdef CONST
#undef CONST
QVector<Function *> nestedFunctions;
Function *outer;
+ QUrl sourceFile;
+
int insideWithOrCatch;
uint hasDirectEval: 1;
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;
}
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);
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)
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);
#include <QtCore/QString>
#include <QtCore/qnumeric.h>
#include <QtCore/QDebug>
+#include <QtCore/qurl.h>
#include <cmath>
#include <cassert>
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);
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;
};
}
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);
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);
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) {
Handle<Value> ThrowException(Handle<Value> exception)
{
- __qmljs_throw(currentEngine()->current, exception->v4Value());
+ __qmljs_throw(currentEngine()->current, exception->v4Value(), -1);
return Handle<Value>();
}