pending-compilation-error-handler.cc 6.26 KB
Newer Older
1 2 3 4
// 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.

5
#include "src/parsing/pending-compilation-error-handler.h"
6

7
#include "src/ast/ast-value-factory.h"
8
#include "src/base/export-template.h"
9
#include "src/base/logging.h"
10
#include "src/debug/debug.h"
11 12
#include "src/execution/isolate.h"
#include "src/execution/messages.h"
13
#include "src/handles/handles.h"
14
#include "src/heap/local-heap-inl.h"
15
#include "src/objects/objects-inl.h"
16 17 18 19

namespace v8 {
namespace internal {

20 21
void PendingCompilationErrorHandler::MessageDetails::SetString(
    Handle<String> string, Isolate* isolate) {
22
  DCHECK_NE(type_, kMainThreadHandle);
23 24 25 26 27
  type_ = kMainThreadHandle;
  arg_handle_ = string;
}

void PendingCompilationErrorHandler::MessageDetails::SetString(
28
    Handle<String> string, LocalIsolate* isolate) {
29
  DCHECK_NE(type_, kMainThreadHandle);
30 31
  type_ = kMainThreadHandle;
  arg_handle_ = isolate->heap()->NewPersistentHandle(string);
32 33
}

34
template <typename IsolateT>
35
void PendingCompilationErrorHandler::MessageDetails::Prepare(
36
    IsolateT* isolate) {
37 38
  switch (type_) {
    case kAstRawString:
39
      return SetString(arg_->string(), isolate);
40

41 42
    case kNone:
    case kConstCharString:
43 44 45 46
      // We can delay allocation until ArgumentString(isolate).
      // TODO(leszeks): We don't actually have to transfer this string, since
      // it's a root.
      return;
47

48
    case kMainThreadHandle:
49 50 51
      // The message details might already be prepared, so skip them if this is
      // the case.
      return;
52 53 54 55 56 57
  }
}

Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString(
    Isolate* isolate) const {
  switch (type_) {
58 59
    case kMainThreadHandle:
      return arg_handle_;
60 61 62 63
    case kNone:
      return isolate->factory()->undefined_string();
    case kConstCharString:
      return isolate->factory()
64
          ->NewStringFromUtf8(base::CStrVector(char_arg_), AllocationType::kOld)
65 66 67
          .ToHandleChecked();
    case kAstRawString:
      UNREACHABLE();
68 69 70 71 72 73 74 75
  }
}

MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation(
    Handle<Script> script) const {
  return MessageLocation(script, start_position_, end_position_);
}

76 77 78 79
void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
                                                     int end_position,
                                                     MessageTemplate message,
                                                     const char* arg) {
80 81 82
  if (has_pending_error_) return;
  has_pending_error_ = true;

83
  error_details_ = MessageDetails(start_position, end_position, message, arg);
84 85
}

86 87 88 89
void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
                                                     int end_position,
                                                     MessageTemplate message,
                                                     const AstRawString* arg) {
90 91 92
  if (has_pending_error_) return;
  has_pending_error_ = true;

93
  error_details_ = MessageDetails(start_position, end_position, message, arg);
94 95
}

96 97 98 99
void PendingCompilationErrorHandler::ReportWarningAt(int start_position,
                                                     int end_position,
                                                     MessageTemplate message,
                                                     const char* arg) {
100
  warning_messages_.emplace_front(
101
      MessageDetails(start_position, end_position, message, arg));
102 103
}

104 105
template <typename IsolateT>
void PendingCompilationErrorHandler::PrepareWarnings(IsolateT* isolate) {
106 107 108 109 110 111 112 113
  DCHECK(!has_pending_error());

  for (MessageDetails& warning : warning_messages_) {
    warning.Prepare(isolate);
  }
}
template void PendingCompilationErrorHandler::PrepareWarnings(Isolate* isolate);
template void PendingCompilationErrorHandler::PrepareWarnings(
114
    LocalIsolate* isolate);
115 116 117

void PendingCompilationErrorHandler::ReportWarnings(
    Isolate* isolate, Handle<Script> script) const {
118 119 120 121 122 123 124 125 126 127 128 129 130
  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);
  }
}

131
template <typename IsolateT>
132
void PendingCompilationErrorHandler::PrepareErrors(
133
    IsolateT* isolate, AstValueFactory* ast_value_factory) {
134
  if (stack_overflow()) return;
135

136 137 138 139
  DCHECK(has_pending_error());
  // Internalize ast values for throwing the pending error.
  ast_value_factory->Internalize(isolate);
  error_details_.Prepare(isolate);
140
}
141 142 143 144 145
template EXPORT_TEMPLATE_DEFINE(
    V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
    PrepareErrors(Isolate* isolate, AstValueFactory* ast_value_factory);
template EXPORT_TEMPLATE_DEFINE(
    V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
146
    PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory);
147

148 149
void PendingCompilationErrorHandler::ReportErrors(Isolate* isolate,
                                                  Handle<Script> script) const {
150 151 152 153 154 155 156 157
  if (stack_overflow()) {
    isolate->StackOverflow();
  } else {
    DCHECK(has_pending_error());
    ThrowPendingError(isolate, script);
  }
}

158 159
void PendingCompilationErrorHandler::ThrowPendingError(
    Isolate* isolate, Handle<Script> script) const {
160
  if (!has_pending_error_) return;
161 162 163

  MessageLocation location = error_details_.GetLocation(script);
  Handle<String> argument = error_details_.ArgumentString(isolate);
164 165
  isolate->debug()->OnCompileError(script);

166
  Factory* factory = isolate->factory();
167
  Handle<JSObject> error =
168
      factory->NewSyntaxError(error_details_.message(), argument);
169
  isolate->ThrowAt(error, &location);
170
}
171 172

Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
173 174
    Isolate* isolate) {
  error_details_.Prepare(isolate);
175 176
  return MessageFormatter::Format(isolate, error_details_.message(),
                                  error_details_.ArgumentString(isolate));
177 178
}

179 180
}  // namespace internal
}  // namespace v8