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