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