예제 #1
0
void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) {
  // First look it up in the pending messages and fast return, it'll be covered
  // by processQueue().
  for (auto it = m_queue.begin(); it != m_queue.end(); ++it) {
    if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) {
      m_queue.remove(it);
      return;
    }
  }

  // Then look it up in the reported errors.
  for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) {
    std::unique_ptr<Message>& message = m_reportedAsErrors.at(i);
    if (!message->isCollected() && message->hasPromise(data.GetPromise())) {
      message->makePromiseStrong();
      Platform::current()
          ->currentThread()
          ->scheduler()
          ->timerTaskRunner()
          ->postTask(BLINK_FROM_HERE, WTF::bind(&RejectedPromises::revokeNow,
                                                RefPtr<RejectedPromises>(this),
                                                passed(std::move(message))));
      m_reportedAsErrors.remove(i);
      return;
    }
  }
}
예제 #2
0
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data)
{
    ASSERT(isMainThread());
    if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
        rejectedPromisesOnMainThread().handlerAdded(data);
        return;
    }

    ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

    v8::Local<v8::Promise> promise = data.GetPromise();

    v8::Isolate* isolate = promise->GetIsolate();
    // There is no entered window during microtask callbacks from V8,
    // thus we call toDOMWindow() instead of enteredDOMWindow().
    LocalDOMWindow* window = currentDOMWindow(isolate);
    if (!window || !window->isCurrentlyDisplayedInFrame())
        return;

    v8::Local<v8::Value> exception = data.GetValue();
    if (V8DOMWrapper::isWrapper(isolate, exception)) {
        // Try to get the stack & location from a wrapped exception object (e.g. DOMException).
        ASSERT(exception->IsObject());
        v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception);
        v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj, V8HiddenValue::error(isolate));
        if (!error.IsEmpty())
            exception = error;
    }

    int scriptId = 0;
    int lineNumber = 0;
    int columnNumber = 0;
    String resourceName;
    String errorMessage;
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr;

    v8::Local<v8::Message> message = v8::Exception::CreateMessage(exception);
    if (!message.IsEmpty()) {
        if (v8Call(message->GetLineNumber(isolate->GetCurrentContext()), lineNumber)
            && v8Call(message->GetStartColumn(isolate->GetCurrentContext()), columnNumber))
            ++columnNumber;
        resourceName = extractResourceName(message, window->document());
        errorMessage = toCoreStringWithNullCheck(message->Get());
        callStack = extractCallStack(isolate, message, &scriptId);
    } else if (!exception.IsEmpty() && exception->IsInt32()) {
        // For Smi's the message would be empty.
        errorMessage = "Uncaught " + String::number(exception.As<v8::Integer>()->Value());
    }

    String messageForConsole = extractMessageForConsole(isolate, data.GetValue());
    if (!messageForConsole.isEmpty())
        errorMessage = "Uncaught " + messageForConsole;

    ScriptState* scriptState = ScriptState::current(isolate);
    rejectedPromisesOnMainThread().rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack);
}
예제 #3
0
void RejectedPromises::rejectedWithNoHandler(
    ScriptState* scriptState,
    v8::PromiseRejectMessage data,
    const String& errorMessage,
    std::unique_ptr<SourceLocation> location,
    AccessControlStatus corsStatus) {
  m_queue.append(Message::create(scriptState, data.GetPromise(),
                                 data.GetValue(), errorMessage,
                                 std::move(location), corsStatus));
}
예제 #4
0
static void promiseRejectHandler(v8::PromiseRejectMessage data, RejectedPromises& rejectedPromises, const String& fallbackResourceName)
{
    if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
        rejectedPromises.handlerAdded(data);
        return;
    }

    ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

    v8::Local<v8::Promise> promise = data.GetPromise();
    v8::Isolate* isolate = promise->GetIsolate();
    ScriptState* scriptState = ScriptState::current(isolate);

    v8::Local<v8::Value> exception = data.GetValue();
    if (V8DOMWrapper::isWrapper(isolate, exception)) {
        // Try to get the stack & location from a wrapped exception object (e.g. DOMException).
        ASSERT(exception->IsObject());
        v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception);
        v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(scriptState, obj, V8HiddenValue::error(isolate));
        if (!error.IsEmpty())
            exception = error;
    }

    int scriptId = 0;
    int lineNumber = 0;
    int columnNumber = 0;
    String resourceName = fallbackResourceName;
    String errorMessage;
    AccessControlStatus corsStatus = NotSharableCrossOrigin;
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr;

    v8::Local<v8::Message> message = v8::Exception::CreateMessage(isolate, exception);
    if (!message.IsEmpty()) {
        V8StringResource<> v8ResourceName(message->GetScriptOrigin().ResourceName());
        if (v8ResourceName.prepare())
            resourceName = v8ResourceName;
        scriptId = message->GetScriptOrigin().ScriptID()->Value();
        if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
            && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
            ++columnNumber;
        // message->Get() can be empty here. https://crbug.com/450330
        errorMessage = toCoreStringWithNullCheck(message->Get());
        callStack = extractCallStack(isolate, message, &scriptId);
        if (message->IsSharedCrossOrigin())
            corsStatus = SharableCrossOrigin;
    }

    String messageForConsole = extractMessageForConsole(isolate, data.GetValue());
    if (!messageForConsole.isEmpty())
        errorMessage = "Uncaught " + messageForConsole;

    rejectedPromises.rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, corsStatus);
}
예제 #5
0
static void promiseRejectHandler(v8::PromiseRejectMessage data,
                                 RejectedPromises& rejectedPromises,
                                 ScriptState* scriptState) {
  if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
    rejectedPromises.handlerAdded(data);
    return;
  }

  ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

  v8::Local<v8::Promise> promise = data.GetPromise();
  v8::Isolate* isolate = promise->GetIsolate();
  ExecutionContext* context = scriptState->getExecutionContext();

  v8::Local<v8::Value> exception = data.GetValue();
  if (V8DOMWrapper::isWrapper(isolate, exception)) {
    // Try to get the stack & location from a wrapped exception object (e.g.
    // DOMException).
    ASSERT(exception->IsObject());
    auto privateError = V8PrivateProperty::getDOMExceptionError(isolate);
    v8::Local<v8::Value> error = privateError.getOrUndefined(
        scriptState->context(), exception.As<v8::Object>());
    if (!error->IsUndefined())
      exception = error;
  }

  String errorMessage;
  AccessControlStatus corsStatus = NotSharableCrossOrigin;
  std::unique_ptr<SourceLocation> location;

  v8::Local<v8::Message> message =
      v8::Exception::CreateMessage(isolate, exception);
  if (!message.IsEmpty()) {
    // message->Get() can be empty here. https://crbug.com/450330
    errorMessage = toCoreStringWithNullCheck(message->Get());
    location = SourceLocation::fromMessage(isolate, message, context);
    if (message->IsSharedCrossOrigin())
      corsStatus = SharableCrossOrigin;
  } else {
    location =
        SourceLocation::create(context->url().getString(), 0, 0, nullptr);
  }

  String messageForConsole = extractMessageForConsole(isolate, data.GetValue());
  if (!messageForConsole.isEmpty())
    errorMessage = "Uncaught " + messageForConsole;

  rejectedPromises.rejectedWithNoHandler(scriptState, data, errorMessage,
                                         std::move(location), corsStatus);
}
예제 #6
0
static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data)
{
    v8::Local<v8::Promise> promise = data.GetPromise();

    // Bail out if called during context initialization.
    v8::Isolate* isolate = promise->GetIsolate();
    ScriptState* scriptState = ScriptState::current(isolate);
    if (!scriptState->contextIsValid())
        return;

    ExecutionContext* executionContext = scriptState->executionContext();
    if (!executionContext)
        return;

    ASSERT(executionContext->isWorkerGlobalScope());
    WorkerScriptController* scriptController = toWorkerGlobalScope(executionContext)->script();
    ASSERT(scriptController);

    if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
        scriptController->rejectedPromises()->handlerAdded(data);
        return;
    }

    ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

    int scriptId = 0;
    int lineNumber = 0;
    int columnNumber = 0;
    String resourceName;
    String errorMessage;

    v8::Local<v8::Message> message = v8::Exception::CreateMessage(data.GetValue());
    if (!message.IsEmpty()) {
        TOSTRING_VOID(V8StringResource<>, resourceName, message->GetScriptOrigin().ResourceName());
        scriptId = message->GetScriptOrigin().ScriptID()->Value();
        if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
            && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
            ++columnNumber;
        // message->Get() can be empty here. https://crbug.com/450330
        errorMessage = toCoreStringWithNullCheck(message->Get());
    }
    scriptController->rejectedPromises()->rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, nullptr);
}
예제 #7
0
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data)
{
    ASSERT(isMainThread());

    v8::Local<v8::Promise> promise = data.GetPromise();

    v8::Isolate* isolate = promise->GetIsolate();
    // There is no entered window during microtask callbacks from V8,
    // thus we call toDOMWindow() instead of enteredDOMWindow().
    LocalDOMWindow* window = currentDOMWindow(isolate);
    if (!window || !window->isCurrentlyDisplayedInFrame())
        return;

    promiseRejectHandler(data, rejectedPromisesOnMainThread(), window->document() ? window->document()->url() : String());
}
예제 #8
0
static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data)
{
    v8::Local<v8::Promise> promise = data.GetPromise();

    // Bail out if called during context initialization.
    v8::Isolate* isolate = promise->GetIsolate();
    ScriptState* scriptState = ScriptState::current(isolate);
    if (!scriptState->contextIsValid())
        return;

    ExecutionContext* executionContext = scriptState->getExecutionContext();
    if (!executionContext)
        return;

    ASSERT(executionContext->isWorkerGlobalScope());
    WorkerOrWorkletScriptController* scriptController = toWorkerGlobalScope(executionContext)->scriptController();
    ASSERT(scriptController);

    promiseRejectHandler(data, *scriptController->getRejectedPromises(), scriptState);
}
예제 #9
0
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) {
  ASSERT(isMainThread());

  v8::Local<v8::Promise> promise = data.GetPromise();

  v8::Isolate* isolate = promise->GetIsolate();

  // TODO(ikilpatrick): Remove this check, extensions tests that use
  // extensions::ModuleSystemTest incorrectly don't have a valid script state.
  LocalDOMWindow* window = currentDOMWindow(isolate);
  if (!window || !window->isCurrentlyDisplayedInFrame())
    return;

  // Bail out if called during context initialization.
  ScriptState* scriptState = ScriptState::current(isolate);
  if (!scriptState->contextIsValid())
    return;

  promiseRejectHandler(data, rejectedPromisesOnMainThread(), scriptState);
}
예제 #10
0
void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::PromiseRejectMessage data, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack, AccessControlStatus corsStatus)
{
    m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue(), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, corsStatus));
}