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

7
#include "src/ast/ast-value-factory.h"
8
#include "src/debug/debug.h"
9 10 11
#include "src/handles.h"
#include "src/isolate.h"
#include "src/messages.h"
12
#include "src/objects-inl.h"
13 14 15 16

namespace v8 {
namespace internal {

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
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_);
}

33
void PendingCompilationErrorHandler::ReportMessageAt(
34
    int start_position, int end_position, MessageTemplate message,
35 36 37 38 39 40 41 42 43 44
    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(
45
    int start_position, int end_position, MessageTemplate message,
46 47 48 49 50 51 52 53 54
    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;
}

55 56 57 58
void PendingCompilationErrorHandler::ReportWarningAt(int start_position,
                                                     int end_position,
                                                     MessageTemplate message,
                                                     const char* arg) {
59 60 61 62
  warning_messages_.emplace_front(
      MessageDetails(start_position, end_position, message, nullptr, arg));
}

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
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);
  }
}

78 79 80 81 82 83 84 85
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.
86
    ast_value_factory->Internalize(isolate);
87 88 89 90
    ThrowPendingError(isolate, script);
  }
}

91 92 93
void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate,
                                                       Handle<Script> script) {
  if (!has_pending_error_) return;
94 95 96

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

99
  Factory* factory = isolate->factory();
100 101 102
  Handle<Object> error;
  switch (error_type_) {
    case kReferenceError:
103
      error = factory->NewReferenceError(error_details_.message(), argument);
104 105
      break;
    case kSyntaxError:
106
      error = factory->NewSyntaxError(error_details_.message(), argument);
107 108 109
      break;
    default:
      UNREACHABLE();
110 111 112
      break;
  }

113 114 115 116 117
  if (!error->IsJSObject()) {
    isolate->Throw(*error, &location);
    return;
  }

118 119 120
  Handle<JSObject> jserror = Handle<JSObject>::cast(error);

  Handle<Name> key_start_pos = factory->error_start_pos_symbol();
121 122
  Object::SetProperty(isolate, jserror, key_start_pos,
                      handle(Smi::FromInt(location.start_pos()), isolate),
123 124
                      StoreOrigin::kMaybeKeyed,
                      Just(ShouldThrow::kThrowOnError))
125
      .Check();
126 127

  Handle<Name> key_end_pos = factory->error_end_pos_symbol();
128 129
  Object::SetProperty(isolate, jserror, key_end_pos,
                      handle(Smi::FromInt(location.end_pos()), isolate),
130 131
                      StoreOrigin::kMaybeKeyed,
                      Just(ShouldThrow::kThrowOnError))
132
      .Check();
133 134

  Handle<Name> key_script = factory->error_script_symbol();
135
  Object::SetProperty(isolate, jserror, key_script, script,
136 137
                      StoreOrigin::kMaybeKeyed,
                      Just(ShouldThrow::kThrowOnError))
138
      .Check();
139 140 141

  isolate->Throw(*error, &location);
}
142 143 144

Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
    Isolate* isolate) const {
145 146 147
  return MessageFormatter::FormatMessage(
      isolate, error_details_.message(),
      error_details_.ArgumentString(isolate));
148 149
}

150 151
}  // namespace internal
}  // namespace v8