runtime-promise.cc 7.81 KB
Newer Older
1 2 3
// Copyright 2016 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.
4

5
#include "src/api/api-inl.h"
6
#include "src/debug/debug.h"
7 8
#include "src/execution/arguments-inl.h"
#include "src/execution/microtask-queue.h"
9
#include "src/logging/counters.h"
10
#include "src/objects/elements.h"
11
#include "src/objects/heap-object-inl.h"
12
#include "src/objects/js-promise-inl.h"
13
#include "src/objects/objects-inl.h"
14
#include "src/objects/oddball-inl.h"
15
#include "src/runtime/runtime-utils.h"
16 17 18 19 20

namespace v8 {
namespace internal {

RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) {
21
  DCHECK_EQ(2, args.length());
22
  HandleScope scope(isolate);
23
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
24 25 26 27
  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);

  Handle<Object> rejected_promise = promise;
  if (isolate->debug()->is_active()) {
28 29
    // If the Promise.reject() call is caught, then this will return
    // undefined, which we interpret as being a caught exception event.
30 31
    rejected_promise = isolate->GetPromiseOnStackOnThrow();
  }
32 33
  isolate->RunAllPromiseHooks(PromiseHookType::kResolve, promise,
                              isolate->factory()->undefined_value());
34
  isolate->debug()->OnPromiseReject(rejected_promise, value);
35

36 37 38 39 40
  // Report only if we don't actually have a handler.
  if (!promise->has_handler()) {
    isolate->ReportPromiseReject(promise, value,
                                 v8::kPromiseRejectWithNoHandler);
  }
41
  return ReadOnlyRoots(isolate).undefined_value();
42 43
}

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
RUNTIME_FUNCTION(Runtime_PromiseRejectAfterResolved) {
  DCHECK_EQ(2, args.length());
  HandleScope scope(isolate);
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
  isolate->ReportPromiseReject(promise, reason,
                               v8::kPromiseRejectAfterResolved);
  return ReadOnlyRoots(isolate).undefined_value();
}

RUNTIME_FUNCTION(Runtime_PromiseResolveAfterResolved) {
  DCHECK_EQ(2, args.length());
  HandleScope scope(isolate);
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
  isolate->ReportPromiseReject(promise, resolution,
                               v8::kPromiseResolveAfterResolved);
  return ReadOnlyRoots(isolate).undefined_value();
}

64
RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) {
65
  DCHECK_EQ(1, args.length());
66
  HandleScope scope(isolate);
67
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
68
  // At this point, no revocation has been issued before
69
  CHECK(!promise->has_handler());
70 71
  isolate->ReportPromiseReject(promise, Handle<Object>(),
                               v8::kPromiseHandlerAddedAfterReject);
72
  return ReadOnlyRoots(isolate).undefined_value();
73 74 75 76
}

RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
  HandleScope scope(isolate);
77
  DCHECK_EQ(1, args.length());
78
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
79 80 81

  Handle<CallableTask> microtask = isolate->factory()->NewCallableTask(
      function, handle(function->native_context(), isolate));
82
  MicrotaskQueue* microtask_queue =
83
      function->native_context().microtask_queue();
84
  if (microtask_queue) microtask_queue->EnqueueMicrotask(*microtask);
85
  return ReadOnlyRoots(isolate).undefined_value();
86 87
}

88
RUNTIME_FUNCTION(Runtime_PerformMicrotaskCheckpoint) {
89
  HandleScope scope(isolate);
90
  DCHECK_EQ(0, args.length());
91
  MicrotasksScope::PerformCheckpoint(reinterpret_cast<v8::Isolate*>(isolate));
92
  return ReadOnlyRoots(isolate).undefined_value();
93 94
}

95 96 97 98 99 100 101 102
RUNTIME_FUNCTION(Runtime_RunMicrotaskCallback) {
  HandleScope scope(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_CHECKED(Object, microtask_callback, 0);
  CONVERT_ARG_CHECKED(Object, microtask_data, 1);
  MicrotaskCallback callback = ToCData<MicrotaskCallback>(microtask_callback);
  void* data = ToCData<void*>(microtask_data);
  callback(data);
103
  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
104
  return ReadOnlyRoots(isolate).undefined_value();
105 106
}

107 108
RUNTIME_FUNCTION(Runtime_PromiseStatus) {
  HandleScope scope(isolate);
109
  DCHECK_EQ(1, args.length());
110 111 112 113 114
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);

  return Smi::FromInt(promise->status());
}

115 116 117 118 119 120
RUNTIME_FUNCTION(Runtime_PromiseHookInit) {
  HandleScope scope(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, parent, 1);
  isolate->RunPromiseHook(PromiseHookType::kInit, promise, parent);
121
  return ReadOnlyRoots(isolate).undefined_value();
122 123 124 125 126
}

RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
  HandleScope scope(isolate);
  DCHECK_EQ(1, args.length());
127 128 129 130
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, promise, 0);
  if (promise->IsJSPromise()) {
    isolate->OnPromiseBefore(Handle<JSPromise>::cast(promise));
  }
131
  return ReadOnlyRoots(isolate).undefined_value();
132 133 134 135 136
}

RUNTIME_FUNCTION(Runtime_PromiseHookAfter) {
  HandleScope scope(isolate);
  DCHECK_EQ(1, args.length());
137 138 139 140
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, promise, 0);
  if (promise->IsJSPromise()) {
    isolate->OnPromiseAfter(Handle<JSPromise>::cast(promise));
  }
141
  return ReadOnlyRoots(isolate).undefined_value();
142 143
}

144 145 146 147 148 149
RUNTIME_FUNCTION(Runtime_RejectPromise) {
  HandleScope scope(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
  CONVERT_ARG_HANDLE_CHECKED(Oddball, debug_event, 2);
150 151
  return *JSPromise::Reject(promise, reason,
                            debug_event->BooleanValue(isolate));
152 153 154 155 156 157 158 159 160 161 162 163 164
}

RUNTIME_FUNCTION(Runtime_ResolvePromise) {
  HandleScope scope(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
  Handle<Object> result;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
                                     JSPromise::Resolve(promise, resolution));
  return *result;
}

165 166 167 168
// A helper function to be called when constructing AggregateError objects. This
// takes care of the Error-related construction, e.g., stack traces.
RUNTIME_FUNCTION(Runtime_ConstructAggregateErrorHelper) {
  HandleScope scope(isolate);
169
  DCHECK_EQ(4, args.length());
170 171 172
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, new_target, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, message, 2);
173
  CONVERT_ARG_HANDLE_CHECKED(Object, options, 3);
174 175 176 177 178 179

  DCHECK_EQ(*target, *isolate->aggregate_error_function());

  Handle<Object> result;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, result,
180
      ErrorUtils::Construct(isolate, target, new_target, message, options));
181 182 183
  return *result;
}

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
// A helper function to be called when constructing AggregateError objects. This
// takes care of the Error-related construction, e.g., stack traces.
RUNTIME_FUNCTION(Runtime_ConstructInternalAggregateErrorHelper) {
  HandleScope scope(isolate);
  DCHECK_GE(args.length(), 1);
  CONVERT_ARG_HANDLE_CHECKED(Smi, message, 0);

  Handle<Object> arg0;
  if (args.length() >= 2) {
    DCHECK(args[1].IsObject());
    arg0 = args.at<Object>(1);
  }

  Handle<Object> arg1;
  if (args.length() >= 3) {
    DCHECK(args[2].IsObject());
    arg1 = args.at<Object>(2);
  }

  Handle<Object> arg2;
  if (args.length() >= 4) {
    CHECK(args[3].IsObject());
    arg2 = args.at<Object>(3);
  }

209 210 211 212 213 214 215 216
  Handle<Object> options;
  if (args.length() >= 5) {
    CHECK(args[4].IsObject());
    options = args.at<Object>(4);
  } else {
    options = isolate->factory()->undefined_value();
  }

217 218 219 220 221 222 223
  Handle<Object> message_string = MessageFormatter::Format(
      isolate, MessageTemplate(message->value()), arg0, arg1, arg2);

  Handle<Object> result;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, result,
      ErrorUtils::Construct(isolate, isolate->aggregate_error_function(),
224 225
                            isolate->aggregate_error_function(), message_string,
                            options));
226 227 228
  return *result;
}

229 230
}  // namespace internal
}  // namespace v8