8036c41f1e
These functions should only be called in case of a parse error, so speed of calling them should not be a concern. In local testing, this saves ~16k of binary size on a release mode build. Bug: v8:7090 Change-Id: I433df81c2a5811ed922885dbab3ce003427f3d1c Reviewed-on: https://chromium-review.googlesource.com/780693 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Adam Klein <adamk@chromium.org> Cr-Commit-Position: refs/heads/master@{#49551}
146 lines
4.8 KiB
C++
146 lines
4.8 KiB
C++
// 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/ast/ast-value-factory.h"
|
|
#include "src/debug/debug.h"
|
|
#include "src/handles.h"
|
|
#include "src/isolate.h"
|
|
#include "src/messages.h"
|
|
#include "src/objects-inl.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString(
|
|
Isolate* isolate) const {
|
|
if (arg_ != nullptr) return arg_->string();
|
|
if (char_arg_ != nullptr) {
|
|
return isolate->factory()
|
|
->NewStringFromUtf8(CStrVector(char_arg_))
|
|
.ToHandleChecked();
|
|
}
|
|
return isolate->factory()->undefined_string();
|
|
}
|
|
|
|
MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation(
|
|
Handle<Script> script) const {
|
|
return MessageLocation(script, start_position_, end_position_);
|
|
}
|
|
|
|
void PendingCompilationErrorHandler::ReportMessageAt(
|
|
int start_position, int end_position, MessageTemplate::Template message,
|
|
const char* arg, ParseErrorType error_type) {
|
|
if (has_pending_error_) return;
|
|
has_pending_error_ = true;
|
|
|
|
error_details_ =
|
|
MessageDetails(start_position, end_position, message, nullptr, arg);
|
|
error_type_ = error_type;
|
|
}
|
|
|
|
void PendingCompilationErrorHandler::ReportMessageAt(
|
|
int start_position, int end_position, MessageTemplate::Template message,
|
|
const AstRawString* arg, ParseErrorType error_type) {
|
|
if (has_pending_error_) return;
|
|
has_pending_error_ = true;
|
|
|
|
error_details_ =
|
|
MessageDetails(start_position, end_position, message, arg, nullptr);
|
|
error_type_ = error_type;
|
|
}
|
|
|
|
void PendingCompilationErrorHandler::ReportWarningAt(
|
|
int start_position, int end_position, MessageTemplate::Template message,
|
|
const char* arg) {
|
|
warning_messages_.emplace_front(
|
|
MessageDetails(start_position, end_position, message, nullptr, arg));
|
|
}
|
|
|
|
void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate,
|
|
Handle<Script> script) {
|
|
DCHECK(!has_pending_error());
|
|
|
|
for (const MessageDetails& warning : warning_messages_) {
|
|
MessageLocation location = warning.GetLocation(script);
|
|
Handle<String> argument = warning.ArgumentString(isolate);
|
|
Handle<JSMessageObject> message =
|
|
MessageHandler::MakeMessageObject(isolate, warning.message(), &location,
|
|
argument, Handle<FixedArray>::null());
|
|
message->set_error_level(v8::Isolate::kMessageWarning);
|
|
MessageHandler::ReportMessage(isolate, &location, message);
|
|
}
|
|
}
|
|
|
|
void PendingCompilationErrorHandler::ReportErrors(
|
|
Isolate* isolate, Handle<Script> script,
|
|
AstValueFactory* ast_value_factory) {
|
|
if (stack_overflow()) {
|
|
isolate->StackOverflow();
|
|
} else {
|
|
DCHECK(has_pending_error());
|
|
// Internalize ast values for throwing the pending error.
|
|
ast_value_factory->Internalize(isolate);
|
|
ThrowPendingError(isolate, script);
|
|
}
|
|
}
|
|
|
|
void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate,
|
|
Handle<Script> script) {
|
|
if (!has_pending_error_) return;
|
|
|
|
MessageLocation location = error_details_.GetLocation(script);
|
|
Handle<String> argument = error_details_.ArgumentString(isolate);
|
|
isolate->debug()->OnCompileError(script);
|
|
|
|
Factory* factory = isolate->factory();
|
|
Handle<Object> error;
|
|
switch (error_type_) {
|
|
case kReferenceError:
|
|
error = factory->NewReferenceError(error_details_.message(), argument);
|
|
break;
|
|
case kSyntaxError:
|
|
error = factory->NewSyntaxError(error_details_.message(), argument);
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
break;
|
|
}
|
|
|
|
if (!error->IsJSObject()) {
|
|
isolate->Throw(*error, &location);
|
|
return;
|
|
}
|
|
|
|
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),
|
|
LanguageMode::kSloppy)
|
|
.Check();
|
|
|
|
Handle<Name> key_end_pos = factory->error_end_pos_symbol();
|
|
JSObject::SetProperty(jserror, key_end_pos,
|
|
handle(Smi::FromInt(location.end_pos()), isolate),
|
|
LanguageMode::kSloppy)
|
|
.Check();
|
|
|
|
Handle<Name> key_script = factory->error_script_symbol();
|
|
JSObject::SetProperty(jserror, key_script, script, LanguageMode::kSloppy)
|
|
.Check();
|
|
|
|
isolate->Throw(*error, &location);
|
|
}
|
|
|
|
Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
|
|
Isolate* isolate) const {
|
|
return MessageTemplate::FormatMessage(isolate, error_details_.message(),
|
|
error_details_.ArgumentString(isolate));
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|