V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
runtime-promise.cc
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/api-inl.h"
6 #include "src/arguments-inl.h"
7 #include "src/counters.h"
8 #include "src/debug/debug.h"
9 #include "src/elements.h"
10 #include "src/objects-inl.h"
11 #include "src/objects/heap-object-inl.h"
12 #include "src/objects/js-promise-inl.h"
13 #include "src/runtime/runtime-utils.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) {
19  DCHECK_EQ(2, args.length());
20  HandleScope scope(isolate);
21  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
22  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
23 
24  Handle<Object> rejected_promise = promise;
25  if (isolate->debug()->is_active()) {
26  // If the Promise.reject() call is caught, then this will return
27  // undefined, which we interpret as being a caught exception event.
28  rejected_promise = isolate->GetPromiseOnStackOnThrow();
29  }
30  isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
31  isolate->factory()->undefined_value());
32  isolate->debug()->OnPromiseReject(rejected_promise, value);
33 
34  // Report only if we don't actually have a handler.
35  if (!promise->has_handler()) {
36  isolate->ReportPromiseReject(promise, value,
37  v8::kPromiseRejectWithNoHandler);
38  }
39  return ReadOnlyRoots(isolate).undefined_value();
40 }
41 
42 RUNTIME_FUNCTION(Runtime_PromiseRejectAfterResolved) {
43  DCHECK_EQ(2, args.length());
44  HandleScope scope(isolate);
45  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
46  CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
47  isolate->ReportPromiseReject(promise, reason,
48  v8::kPromiseRejectAfterResolved);
49  return ReadOnlyRoots(isolate).undefined_value();
50 }
51 
52 RUNTIME_FUNCTION(Runtime_PromiseResolveAfterResolved) {
53  DCHECK_EQ(2, args.length());
54  HandleScope scope(isolate);
55  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
56  CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
57  isolate->ReportPromiseReject(promise, resolution,
58  v8::kPromiseResolveAfterResolved);
59  return ReadOnlyRoots(isolate).undefined_value();
60 }
61 
62 RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) {
63  DCHECK_EQ(1, args.length());
64  HandleScope scope(isolate);
65  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
66  // At this point, no revocation has been issued before
67  CHECK(!promise->has_handler());
68  isolate->ReportPromiseReject(promise, Handle<Object>(),
69  v8::kPromiseHandlerAddedAfterReject);
70  return ReadOnlyRoots(isolate).undefined_value();
71 }
72 
73 RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
74  HandleScope scope(isolate);
75  DCHECK_EQ(1, args.length());
76  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
77  Handle<CallableTask> microtask =
78  isolate->factory()->NewCallableTask(function, isolate->native_context());
79  isolate->EnqueueMicrotask(microtask);
80  return ReadOnlyRoots(isolate).undefined_value();
81 }
82 
83 RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
84  HandleScope scope(isolate);
85  DCHECK_EQ(0, args.length());
86  isolate->RunMicrotasks();
87  return ReadOnlyRoots(isolate).undefined_value();
88 }
89 
90 RUNTIME_FUNCTION(Runtime_RunMicrotaskCallback) {
91  HandleScope scope(isolate);
92  DCHECK_EQ(2, args.length());
93  CONVERT_ARG_CHECKED(Object, microtask_callback, 0);
94  CONVERT_ARG_CHECKED(Object, microtask_data, 1);
95  MicrotaskCallback callback = ToCData<MicrotaskCallback>(microtask_callback);
96  void* data = ToCData<void*>(microtask_data);
97  callback(data);
98  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
99  return ReadOnlyRoots(isolate).undefined_value();
100 }
101 
102 RUNTIME_FUNCTION(Runtime_PromiseStatus) {
103  HandleScope scope(isolate);
104  DCHECK_EQ(1, args.length());
105  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
106 
107  return Smi::FromInt(promise->status());
108 }
109 
110 RUNTIME_FUNCTION(Runtime_PromiseMarkAsHandled) {
111  SealHandleScope shs(isolate);
112  DCHECK_EQ(1, args.length());
113  CONVERT_ARG_CHECKED(JSPromise, promise, 0);
114 
115  promise->set_has_handler(true);
116  return ReadOnlyRoots(isolate).undefined_value();
117 }
118 
119 RUNTIME_FUNCTION(Runtime_PromiseHookInit) {
120  HandleScope scope(isolate);
121  DCHECK_EQ(2, args.length());
122  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
123  CONVERT_ARG_HANDLE_CHECKED(Object, parent, 1);
124  isolate->RunPromiseHook(PromiseHookType::kInit, promise, parent);
125  return ReadOnlyRoots(isolate).undefined_value();
126 }
127 
128 namespace {
129 
130 Handle<JSPromise> AwaitPromisesInitCommon(Isolate* isolate,
131  Handle<Object> value,
132  Handle<JSPromise> promise,
133  Handle<JSPromise> outer_promise,
134  Handle<JSFunction> reject_handler,
135  bool is_predicted_as_caught) {
136  // Allocate the throwaway promise and fire the appropriate init
137  // hook for the throwaway promise (passing the {promise} as its
138  // parent).
139  Handle<JSPromise> throwaway = isolate->factory()->NewJSPromiseWithoutHook();
140  isolate->RunPromiseHook(PromiseHookType::kInit, throwaway, promise);
141 
142  // On inspector side we capture async stack trace and store it by
143  // outer_promise->async_task_id when async function is suspended first time.
144  // To use captured stack trace later throwaway promise should have the same
145  // async_task_id as outer_promise since we generate WillHandle and DidHandle
146  // events using throwaway promise.
147  throwaway->set_async_task_id(outer_promise->async_task_id());
148 
149  // The Promise will be thrown away and not handled, but it
150  // shouldn't trigger unhandled reject events as its work is done
151  throwaway->set_has_handler(true);
152 
153  // Enable proper debug support for promises.
154  if (isolate->debug()->is_active()) {
155  if (value->IsJSPromise()) {
156  Object::SetProperty(
157  isolate, reject_handler,
158  isolate->factory()->promise_forwarding_handler_symbol(),
159  isolate->factory()->true_value(), LanguageMode::kStrict)
160  .Check();
161  Handle<JSPromise>::cast(value)->set_handled_hint(is_predicted_as_caught);
162  }
163 
164  // Mark the dependency to {outer_promise} in case the {throwaway}
165  // Promise is found on the Promise stack
166  Object::SetProperty(isolate, throwaway,
167  isolate->factory()->promise_handled_by_symbol(),
168  outer_promise, LanguageMode::kStrict)
169  .Check();
170  }
171 
172  return throwaway;
173 }
174 
175 } // namespace
176 
177 RUNTIME_FUNCTION(Runtime_AwaitPromisesInit) {
178  DCHECK_EQ(5, args.length());
179  HandleScope scope(isolate);
180  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
181  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
182  CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 2);
183  CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 3);
184  CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 4);
185  return *AwaitPromisesInitCommon(isolate, value, promise, outer_promise,
186  reject_handler, is_predicted_as_caught);
187 }
188 
189 RUNTIME_FUNCTION(Runtime_AwaitPromisesInitOld) {
190  DCHECK_EQ(5, args.length());
191  HandleScope scope(isolate);
192  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
193  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
194  CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 2);
195  CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 3);
196  CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 4);
197 
198  // Fire the init hook for the wrapper promise (that we created for the
199  // {value} previously).
200  isolate->RunPromiseHook(PromiseHookType::kInit, promise, outer_promise);
201  return *AwaitPromisesInitCommon(isolate, value, promise, outer_promise,
202  reject_handler, is_predicted_as_caught);
203 }
204 
205 RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
206  HandleScope scope(isolate);
207  DCHECK_EQ(1, args.length());
208  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
209  if (!maybe_promise->IsJSPromise())
210  return ReadOnlyRoots(isolate).undefined_value();
211  Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
212  if (isolate->debug()->is_active()) isolate->PushPromise(promise);
213  if (promise->IsJSPromise()) {
214  isolate->RunPromiseHook(PromiseHookType::kBefore, promise,
215  isolate->factory()->undefined_value());
216  }
217  return ReadOnlyRoots(isolate).undefined_value();
218 }
219 
220 RUNTIME_FUNCTION(Runtime_PromiseHookAfter) {
221  HandleScope scope(isolate);
222  DCHECK_EQ(1, args.length());
223  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
224  if (!maybe_promise->IsJSPromise())
225  return ReadOnlyRoots(isolate).undefined_value();
226  Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
227  if (isolate->debug()->is_active()) isolate->PopPromise();
228  if (promise->IsJSPromise()) {
229  isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
230  isolate->factory()->undefined_value());
231  }
232  return ReadOnlyRoots(isolate).undefined_value();
233 }
234 
235 RUNTIME_FUNCTION(Runtime_RejectPromise) {
236  HandleScope scope(isolate);
237  DCHECK_EQ(3, args.length());
238  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
239  CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
240  CONVERT_ARG_HANDLE_CHECKED(Oddball, debug_event, 2);
241  return *JSPromise::Reject(promise, reason,
242  debug_event->BooleanValue(isolate));
243 }
244 
245 RUNTIME_FUNCTION(Runtime_ResolvePromise) {
246  HandleScope scope(isolate);
247  DCHECK_EQ(2, args.length());
248  CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
249  CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
250  Handle<Object> result;
251  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
252  JSPromise::Resolve(promise, resolution));
253  return *result;
254 }
255 
256 } // namespace internal
257 } // namespace v8
Definition: libplatform.h:13