Move compilation error handling into a separate class.
In addition to Parser, other phases (such as scope analysis) need to handle compilation errors in the future. PendingCompilationErrorHandled takes care of error handling in a unified way. Split from https://codereview.chromium.org/943543002/ . R=rossberg@chromium.org BUG= Review URL: https://codereview.chromium.org/960543002 Cr-Commit-Position: refs/heads/master@{#26853}
This commit is contained in:
parent
b00ff50d52
commit
238ad54d0f
2
BUILD.gn
2
BUILD.gn
@ -859,6 +859,8 @@ source_set("v8_base") {
|
|||||||
"src/ostreams.h",
|
"src/ostreams.h",
|
||||||
"src/parser.cc",
|
"src/parser.cc",
|
||||||
"src/parser.h",
|
"src/parser.h",
|
||||||
|
"src/pending-compilation-error-handler.cc",
|
||||||
|
"src/pending-compilation-error-handler.h",
|
||||||
"src/perf-jit.cc",
|
"src/perf-jit.cc",
|
||||||
"src/perf-jit.h",
|
"src/perf-jit.h",
|
||||||
"src/preparse-data-format.h",
|
"src/preparse-data-format.h",
|
||||||
|
@ -608,12 +608,9 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
|
|||||||
// and we want to report the stack overflow later.
|
// and we want to report the stack overflow later.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parser_->has_pending_error_ = true;
|
parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
|
||||||
parser_->pending_error_location_ = source_location;
|
source_location.end_pos,
|
||||||
parser_->pending_error_message_ = message;
|
message, arg, error_type);
|
||||||
parser_->pending_error_char_arg_ = arg;
|
|
||||||
parser_->pending_error_arg_ = NULL;
|
|
||||||
parser_->pending_error_type_ = error_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -640,12 +637,9 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
|
|||||||
// and we want to report the stack overflow later.
|
// and we want to report the stack overflow later.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parser_->has_pending_error_ = true;
|
parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
|
||||||
parser_->pending_error_location_ = source_location;
|
source_location.end_pos,
|
||||||
parser_->pending_error_message_ = message;
|
message, arg, error_type);
|
||||||
parser_->pending_error_char_arg_ = NULL;
|
|
||||||
parser_->pending_error_arg_ = arg;
|
|
||||||
parser_->pending_error_type_ = error_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -789,11 +783,6 @@ Parser::Parser(CompilationInfo* info, uintptr_t stack_limit, uint32_t hash_seed,
|
|||||||
compile_options_(info->compile_options()),
|
compile_options_(info->compile_options()),
|
||||||
cached_parse_data_(NULL),
|
cached_parse_data_(NULL),
|
||||||
parsing_lazy_arrow_parameters_(false),
|
parsing_lazy_arrow_parameters_(false),
|
||||||
has_pending_error_(false),
|
|
||||||
pending_error_message_(NULL),
|
|
||||||
pending_error_arg_(NULL),
|
|
||||||
pending_error_char_arg_(NULL),
|
|
||||||
pending_error_type_(kSyntaxError),
|
|
||||||
total_preparse_skipped_(0),
|
total_preparse_skipped_(0),
|
||||||
pre_parse_timer_(NULL),
|
pre_parse_timer_(NULL),
|
||||||
parsing_on_main_thread_(true) {
|
parsing_on_main_thread_(true) {
|
||||||
@ -4283,57 +4272,6 @@ void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Parser::ThrowPendingError(Isolate* isolate, Handle<Script> script) {
|
|
||||||
DCHECK(ast_value_factory()->IsInternalized());
|
|
||||||
if (has_pending_error_) {
|
|
||||||
MessageLocation location(script, pending_error_location_.beg_pos,
|
|
||||||
pending_error_location_.end_pos);
|
|
||||||
Factory* factory = isolate->factory();
|
|
||||||
bool has_arg =
|
|
||||||
pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
|
|
||||||
Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
|
|
||||||
if (pending_error_arg_ != NULL) {
|
|
||||||
Handle<String> arg_string = pending_error_arg_->string();
|
|
||||||
elements->set(0, *arg_string);
|
|
||||||
} else if (pending_error_char_arg_ != NULL) {
|
|
||||||
Handle<String> arg_string =
|
|
||||||
factory->NewStringFromUtf8(CStrVector(pending_error_char_arg_))
|
|
||||||
.ToHandleChecked();
|
|
||||||
elements->set(0, *arg_string);
|
|
||||||
}
|
|
||||||
isolate->debug()->OnCompileError(script);
|
|
||||||
|
|
||||||
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
|
|
||||||
Handle<Object> error;
|
|
||||||
switch (pending_error_type_) {
|
|
||||||
case kReferenceError:
|
|
||||||
error = factory->NewReferenceError(pending_error_message_, array);
|
|
||||||
break;
|
|
||||||
case kSyntaxError:
|
|
||||||
error = factory->NewSyntaxError(pending_error_message_, array);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<JSObject> jserror = Handle<JSObject>::cast(error);
|
|
||||||
|
|
||||||
Handle<Name> key_start_pos = factory->error_start_pos_symbol();
|
|
||||||
JSObject::SetProperty(jserror, key_start_pos,
|
|
||||||
handle(Smi::FromInt(location.start_pos()), isolate),
|
|
||||||
SLOPPY).Check();
|
|
||||||
|
|
||||||
Handle<Name> key_end_pos = factory->error_end_pos_symbol();
|
|
||||||
JSObject::SetProperty(jserror, key_end_pos,
|
|
||||||
handle(Smi::FromInt(location.end_pos()), isolate),
|
|
||||||
SLOPPY).Check();
|
|
||||||
|
|
||||||
Handle<Name> key_script = factory->error_script_symbol();
|
|
||||||
JSObject::SetProperty(jserror, key_script, script, SLOPPY).Check();
|
|
||||||
|
|
||||||
isolate->Throw(*error, &location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
|
void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
|
||||||
// Internalize strings.
|
// Internalize strings.
|
||||||
ast_value_factory()->Internalize(isolate);
|
ast_value_factory()->Internalize(isolate);
|
||||||
@ -4343,7 +4281,8 @@ void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
|
|||||||
if (stack_overflow()) {
|
if (stack_overflow()) {
|
||||||
isolate->StackOverflow();
|
isolate->StackOverflow();
|
||||||
} else {
|
} else {
|
||||||
ThrowPendingError(isolate, script);
|
DCHECK(pending_error_handler_.has_pending_error());
|
||||||
|
pending_error_handler_.ThrowPendingError(isolate, script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "src/allocation.h"
|
#include "src/allocation.h"
|
||||||
#include "src/ast.h"
|
#include "src/ast.h"
|
||||||
#include "src/compiler.h" // For CachedDataMode
|
#include "src/compiler.h" // For CachedDataMode
|
||||||
|
#include "src/pending-compilation-error-handler.h"
|
||||||
#include "src/preparse-data.h"
|
#include "src/preparse-data.h"
|
||||||
#include "src/preparse-data-format.h"
|
#include "src/preparse-data-format.h"
|
||||||
#include "src/preparser.h"
|
#include "src/preparser.h"
|
||||||
@ -843,13 +844,7 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
|
|
||||||
bool parsing_lazy_arrow_parameters_; // for lazily parsed arrow functions.
|
bool parsing_lazy_arrow_parameters_; // for lazily parsed arrow functions.
|
||||||
|
|
||||||
// Pending errors.
|
PendingCompilationErrorHandler pending_error_handler_;
|
||||||
bool has_pending_error_;
|
|
||||||
Scanner::Location pending_error_location_;
|
|
||||||
const char* pending_error_message_;
|
|
||||||
const AstRawString* pending_error_arg_;
|
|
||||||
const char* pending_error_char_arg_;
|
|
||||||
ParseErrorType pending_error_type_;
|
|
||||||
|
|
||||||
// Other information which will be stored in Parser and moved to Isolate after
|
// Other information which will be stored in Parser and moved to Isolate after
|
||||||
// parsing.
|
// parsing.
|
||||||
|
62
src/pending-compilation-error-handler.cc
Normal file
62
src/pending-compilation-error-handler.cc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/pending-compilation-error-handler.h"
|
||||||
|
|
||||||
|
#include "src/debug.h"
|
||||||
|
#include "src/handles.h"
|
||||||
|
#include "src/isolate.h"
|
||||||
|
#include "src/messages.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate,
|
||||||
|
Handle<Script> script) {
|
||||||
|
if (!has_pending_error_) return;
|
||||||
|
MessageLocation location(script, start_position_, end_position_);
|
||||||
|
Factory* factory = isolate->factory();
|
||||||
|
bool has_arg = arg_ != NULL || char_arg_ != NULL;
|
||||||
|
Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
|
||||||
|
if (arg_ != NULL) {
|
||||||
|
Handle<String> arg_string = arg_->string();
|
||||||
|
elements->set(0, *arg_string);
|
||||||
|
} else if (char_arg_ != NULL) {
|
||||||
|
Handle<String> arg_string =
|
||||||
|
factory->NewStringFromUtf8(CStrVector(char_arg_)).ToHandleChecked();
|
||||||
|
elements->set(0, *arg_string);
|
||||||
|
}
|
||||||
|
isolate->debug()->OnCompileError(script);
|
||||||
|
|
||||||
|
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
|
||||||
|
Handle<Object> error;
|
||||||
|
|
||||||
|
switch (error_type_) {
|
||||||
|
case kReferenceError:
|
||||||
|
error = factory->NewReferenceError(message_, array);
|
||||||
|
break;
|
||||||
|
case kSyntaxError:
|
||||||
|
error = factory->NewSyntaxError(message_, array);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<JSObject> jserror = Handle<JSObject>::cast(error);
|
||||||
|
|
||||||
|
Handle<Name> key_start_pos = factory->error_start_pos_symbol();
|
||||||
|
JSObject::SetProperty(jserror, key_start_pos,
|
||||||
|
handle(Smi::FromInt(location.start_pos()), isolate),
|
||||||
|
SLOPPY).Check();
|
||||||
|
|
||||||
|
Handle<Name> key_end_pos = factory->error_end_pos_symbol();
|
||||||
|
JSObject::SetProperty(jserror, key_end_pos,
|
||||||
|
handle(Smi::FromInt(location.end_pos()), isolate),
|
||||||
|
SLOPPY).Check();
|
||||||
|
|
||||||
|
Handle<Name> key_script = factory->error_script_symbol();
|
||||||
|
JSObject::SetProperty(jserror, key_script, script, SLOPPY).Check();
|
||||||
|
|
||||||
|
isolate->Throw(*error, &location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace v8::internal
|
77
src/pending-compilation-error-handler.h
Normal file
77
src/pending-compilation-error-handler.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef V8_PENDING_COMPILATION_ERROR_HANDLER_H_
|
||||||
|
#define V8_PENDING_COMPILATION_ERROR_HANDLER_H_
|
||||||
|
|
||||||
|
#include "src/base/macros.h"
|
||||||
|
#include "src/globals.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class AstRawString;
|
||||||
|
template <class T>
|
||||||
|
class Handle;
|
||||||
|
class Isolate;
|
||||||
|
class Script;
|
||||||
|
|
||||||
|
// Helper class for handling pending compilation errors consistently in various
|
||||||
|
// compilation phases.
|
||||||
|
class PendingCompilationErrorHandler {
|
||||||
|
public:
|
||||||
|
PendingCompilationErrorHandler()
|
||||||
|
: has_pending_error_(false),
|
||||||
|
start_position_(-1),
|
||||||
|
end_position_(-1),
|
||||||
|
message_(nullptr),
|
||||||
|
arg_(nullptr),
|
||||||
|
char_arg_(nullptr),
|
||||||
|
error_type_(kSyntaxError) {}
|
||||||
|
|
||||||
|
void ReportMessageAt(int start_position, int end_position,
|
||||||
|
const char* message, const char* arg = nullptr,
|
||||||
|
ParseErrorType error_type = kSyntaxError) {
|
||||||
|
if (has_pending_error_) return;
|
||||||
|
has_pending_error_ = true;
|
||||||
|
start_position_ = start_position;
|
||||||
|
end_position_ = end_position;
|
||||||
|
message_ = message;
|
||||||
|
char_arg_ = arg;
|
||||||
|
arg_ = nullptr;
|
||||||
|
error_type_ = error_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportMessageAt(int start_position, int end_position,
|
||||||
|
const char* message, const AstRawString* arg,
|
||||||
|
ParseErrorType error_type = kSyntaxError) {
|
||||||
|
if (has_pending_error_) return;
|
||||||
|
has_pending_error_ = true;
|
||||||
|
start_position_ = start_position;
|
||||||
|
end_position_ = end_position;
|
||||||
|
message_ = message;
|
||||||
|
char_arg_ = nullptr;
|
||||||
|
arg_ = arg;
|
||||||
|
error_type_ = error_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_pending_error() const { return has_pending_error_; }
|
||||||
|
|
||||||
|
void ThrowPendingError(Isolate* isolate, Handle<Script> script);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool has_pending_error_;
|
||||||
|
int start_position_;
|
||||||
|
int end_position_;
|
||||||
|
const char* message_;
|
||||||
|
const AstRawString* arg_;
|
||||||
|
const char* char_arg_;
|
||||||
|
ParseErrorType error_type_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(PendingCompilationErrorHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
||||||
|
#endif // V8_PENDING_COMPILATION_ERROR_HANDLER_H_
|
@ -767,6 +767,8 @@
|
|||||||
'../../src/ostreams.h',
|
'../../src/ostreams.h',
|
||||||
'../../src/parser.cc',
|
'../../src/parser.cc',
|
||||||
'../../src/parser.h',
|
'../../src/parser.h',
|
||||||
|
'../../src/pending-compilation-error-handler.cc',
|
||||||
|
'../../src/pending-compilation-error-handler.h',
|
||||||
'../../src/perf-jit.cc',
|
'../../src/perf-jit.cc',
|
||||||
'../../src/perf-jit.h',
|
'../../src/perf-jit.h',
|
||||||
'../../src/preparse-data-format.h',
|
'../../src/preparse-data-format.h',
|
||||||
|
Loading…
Reference in New Issue
Block a user