static void showException(QQmlJS::VM::ExecutionContext *ctx)
{
- if (QQmlJS::VM::ErrorObject *e = ctx->engine->exception.asErrorObject())
- std::cerr << "Uncaught exception: " << qPrintable(e->value.toString(ctx)->toQString()) << std::endl;
- else
+ QQmlJS::VM::ErrorObject *e = ctx->engine->exception.asErrorObject();
+ if (!e) {
std::cerr << "Uncaught exception: " << qPrintable(ctx->engine->exception.toString(ctx)->toQString()) << std::endl;
+ return;
+ }
+
+ if (QQmlJS::VM::SyntaxErrorObject *err = e->asSyntaxError()) {
+ QQmlJS::VM::DiagnosticMessage *msg = err->message();
+ if (!msg) {
+ std::cerr << "Uncaught exception: Syntax error" << std::endl;
+ return;
+ }
+
+ for (; msg; msg = msg->next) {
+ if (msg->fileName)
+ std::cerr << qPrintable(msg->fileName->toQString());
+ std::cerr << ':' << msg->startLine << ':' << msg->startColumn << ": ";
+ if (msg->type == QQmlJS::VM::DiagnosticMessage::Error)
+ std::cerr << "error";
+ else
+ std::cerr << "warning";
+ std::cerr << ": " << qPrintable(msg->message->toQString()) << std::endl;
+ }
+ } else {
+ std::cerr << "Uncaught exception: " << qPrintable(e->value.toString(ctx)->toQString()) << std::endl;
+ }
}
#ifndef QMLJS_NO_LLVM
return object;
}
+Object *ExecutionEngine::newSyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *message)
+{
+ SyntaxErrorObject *object = new SyntaxErrorObject(ctx, message);
+ object->prototype = syntaxErrorPrototype;
+ return object;
+}
+
Object *ExecutionEngine::newMathObject(ExecutionContext *ctx)
{
MathObject *object = new MathObject(ctx);
FunctionObject *newRegExpCtor(ExecutionContext *ctx);
Object *newErrorObject(const Value &value);
+ Object *newSyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *message);
Object *newMathObject(ExecutionContext *ctx);
Object *newActivationObject(DeclarativeEnvironment *ctx);
namespace QQmlJS {
namespace VM {
+DiagnosticMessage::DiagnosticMessage()
+ : fileName(0)
+ , offset(0)
+ , length(0)
+ , startLine(0)
+ , startColumn(0)
+ , type(0)
+ , message(0)
+ , next(0)
+{}
+
DeclarativeEnvironment::DeclarativeEnvironment(ExecutionEngine *e)
{
engine = e;
throwError(Value::fromObject(engine->newErrorObject(v)));
}
+void ExecutionContext::throwSyntaxError(DiagnosticMessage *message)
+{
+ throwError(Value::fromObject(engine->newSyntaxErrorObject(this, message)));
+}
+
void ExecutionContext::throwTypeError()
{
Value v = Value::fromString(this, QStringLiteral("Type error"));
struct ExecutionContext;
struct DeclarativeEnvironment;
+struct DiagnosticMessage
+{
+ enum { Error, Warning };
+
+ String *fileName;
+ quint32 offset;
+ quint32 length;
+ quint32 startLine;
+ unsigned startColumn: 31;
+ unsigned type: 1;
+ String *message;
+ DiagnosticMessage *next;
+
+ DiagnosticMessage();
+};
+
// This merges LexicalEnvironment and EnvironmentRecord from
// Sec. 10.2 into one class
struct DeclarativeEnvironment
void throwError(Value value);
void throwError(const QString &message);
+ void throwSyntaxError(DiagnosticMessage *message);
void throwTypeError();
void throwReferenceError(Value value);
void throwUnimplemented(const QString &message);
const bool parsed = parser.parseProgram();
- foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
- std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn
- << ": error: " << qPrintable(m.message) << std::endl;
+ VM::DiagnosticMessage *error = 0, **errIt = &error;
+ foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
+ if (m.isError()) {
+ *errIt = new VM::DiagnosticMessage; // FIXME: should we ask the engine to create this object?
+ (*errIt)->fileName = ctx->engine->newString(fileName);
+ (*errIt)->offset = m.loc.offset;
+ (*errIt)->length = m.loc.length;
+ (*errIt)->startLine = m.loc.startLine;
+ (*errIt)->startColumn = m.loc.startColumn;
+ (*errIt)->type = VM::DiagnosticMessage::Error;
+ (*errIt)->message = ctx->engine->newString(m.message);
+ errIt = &(*errIt)->next;
+ } else {
+ std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn
+ << ": warning: " << qPrintable(m.message) << std::endl;
+ }
}
+ if (error)
+ ctx->throwSyntaxError(error);
if (parsed) {
using namespace AST;
__put__(ctx, QLatin1String("name"), Value::fromString(ctx, className()));
}
+SyntaxErrorObject::SyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *message)
+ : ErrorObject(ctx->argument(0))
+ , msg(message)
+{
+ if (message)
+ value = Value::fromString(message->message);
+ setNameProperty(ctx);
+}
+
+
Value ScriptFunction::construct(VM::ExecutionContext *ctx)
{
Object *obj = ctx->engine->newObject();
virtual ErrorObject *asErrorObject() { return this; }
virtual Value __get__(ExecutionContext *ctx, String *name);
+ virtual struct SyntaxErrorObject *asSyntaxError() { return 0; }
+
protected:
void setNameProperty(ExecutionContext *ctx);
};
};
struct SyntaxErrorObject: ErrorObject {
- SyntaxErrorObject(ExecutionContext *ctx)
- : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); }
+ SyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *msg);
virtual QString className() { return QStringLiteral("SyntaxError"); }
+
+ virtual SyntaxErrorObject *asSyntaxError() { return this; }
+ DiagnosticMessage *message() { return msg; }
+
+private:
+ DiagnosticMessage *msg;
};
struct TypeErrorObject: ErrorObject {
Value SyntaxErrorCtor::construct(ExecutionContext *ctx)
{
- ctx->thisObject = Value::fromObject(new SyntaxErrorObject(ctx));
+ ctx->thisObject = Value::fromObject(new SyntaxErrorObject(ctx, 0));
return ctx->thisObject;
}
struct SyntaxErrorPrototype: SyntaxErrorObject
{
- SyntaxErrorPrototype(ExecutionContext *ctx): SyntaxErrorObject(ctx) {}
+ SyntaxErrorPrototype(ExecutionContext *ctx): SyntaxErrorObject(ctx, 0) {}
void init(ExecutionContext *ctx, const Value &ctor) { ErrorPrototype::init(ctx, ctor, this); }
};