Throw a SyntaxError instead of printing an error message.

Change-Id: I94ef8a4f2bea80bc3689b104e381a9dc134439fa
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Erik Verbruggen 2012-11-28 11:00:23 +01:00 committed by Lars Knoll
parent 61460c7859
commit 4bd20c2ac3
9 changed files with 105 additions and 10 deletions

View File

@ -108,10 +108,32 @@ struct TestHarnessError: FunctionObject
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

View File

@ -316,6 +316,13 @@ Object *ExecutionEngine::newErrorObject(const Value &value)
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);

View File

@ -175,6 +175,7 @@ struct ExecutionEngine
FunctionObject *newRegExpCtor(ExecutionContext *ctx);
Object *newErrorObject(const Value &value);
Object *newSyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *message);
Object *newMathObject(ExecutionContext *ctx);
Object *newActivationObject(DeclarativeEnvironment *ctx);

View File

@ -45,6 +45,17 @@
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;
@ -255,6 +266,11 @@ void ExecutionContext::throwError(const QString &message)
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"));

View File

@ -52,6 +52,22 @@ struct ExecutionEngine;
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
@ -109,6 +125,7 @@ struct ExecutionContext
void throwError(Value value);
void throwError(const QString &message);
void throwSyntaxError(DiagnosticMessage *message);
void throwTypeError();
void throwReferenceError(Value value);
void throwUnimplemented(const QString &message);

View File

@ -525,10 +525,25 @@ QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct
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;
@ -612,6 +627,16 @@ void ErrorObject::setNameProperty(ExecutionContext *ctx)
__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();

View File

@ -566,6 +566,8 @@ struct ErrorObject: Object {
virtual ErrorObject *asErrorObject() { return this; }
virtual Value __get__(ExecutionContext *ctx, String *name);
virtual struct SyntaxErrorObject *asSyntaxError() { return 0; }
protected:
void setNameProperty(ExecutionContext *ctx);
};
@ -589,9 +591,14 @@ struct ReferenceErrorObject: ErrorObject {
};
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 {

View File

@ -2630,7 +2630,7 @@ Value ReferenceErrorCtor::construct(ExecutionContext *ctx)
Value SyntaxErrorCtor::construct(ExecutionContext *ctx)
{
ctx->thisObject = Value::fromObject(new SyntaxErrorObject(ctx));
ctx->thisObject = Value::fromObject(new SyntaxErrorObject(ctx, 0));
return ctx->thisObject;
}

View File

@ -375,7 +375,7 @@ struct ReferenceErrorPrototype: ReferenceErrorObject
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); }
};