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/js-promise-inl.h"
12 #include "src/runtime/runtime-utils.h"
13
14 namespace v8 {
15 namespace internal {
16
RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack)17 RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) {
18 DCHECK_EQ(2, args.length());
19 HandleScope scope(isolate);
20 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
21 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
22
23 Handle<Object> rejected_promise = promise;
24 if (isolate->debug()->is_active()) {
25 // If the Promise.reject() call is caught, then this will return
26 // undefined, which we interpret as being a caught exception event.
27 rejected_promise = isolate->GetPromiseOnStackOnThrow();
28 }
29 isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
30 isolate->factory()->undefined_value());
31 isolate->debug()->OnPromiseReject(rejected_promise, value);
32
33 // Report only if we don't actually have a handler.
34 if (!promise->has_handler()) {
35 isolate->ReportPromiseReject(promise, value,
36 v8::kPromiseRejectWithNoHandler);
37 }
38 return ReadOnlyRoots(isolate).undefined_value();
39 }
40
RUNTIME_FUNCTION(Runtime_PromiseRejectAfterResolved)41 RUNTIME_FUNCTION(Runtime_PromiseRejectAfterResolved) {
42 DCHECK_EQ(2, args.length());
43 HandleScope scope(isolate);
44 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
45 CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
46 isolate->ReportPromiseReject(promise, reason,
47 v8::kPromiseRejectAfterResolved);
48 return ReadOnlyRoots(isolate).undefined_value();
49 }
50
RUNTIME_FUNCTION(Runtime_PromiseResolveAfterResolved)51 RUNTIME_FUNCTION(Runtime_PromiseResolveAfterResolved) {
52 DCHECK_EQ(2, args.length());
53 HandleScope scope(isolate);
54 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
55 CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
56 isolate->ReportPromiseReject(promise, resolution,
57 v8::kPromiseResolveAfterResolved);
58 return ReadOnlyRoots(isolate).undefined_value();
59 }
60
RUNTIME_FUNCTION(Runtime_PromiseRevokeReject)61 RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) {
62 DCHECK_EQ(1, args.length());
63 HandleScope scope(isolate);
64 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
65 // At this point, no revocation has been issued before
66 CHECK(!promise->has_handler());
67 isolate->ReportPromiseReject(promise, Handle<Object>(),
68 v8::kPromiseHandlerAddedAfterReject);
69 return ReadOnlyRoots(isolate).undefined_value();
70 }
71
RUNTIME_FUNCTION(Runtime_EnqueueMicrotask)72 RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
73 HandleScope scope(isolate);
74 DCHECK_EQ(1, args.length());
75 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
76 Handle<CallableTask> microtask =
77 isolate->factory()->NewCallableTask(function, isolate->native_context());
78 isolate->EnqueueMicrotask(microtask);
79 return ReadOnlyRoots(isolate).undefined_value();
80 }
81
RUNTIME_FUNCTION(Runtime_RunMicrotasks)82 RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
83 HandleScope scope(isolate);
84 DCHECK_EQ(0, args.length());
85 isolate->RunMicrotasks();
86 return ReadOnlyRoots(isolate).undefined_value();
87 }
88
RUNTIME_FUNCTION(Runtime_RunMicrotaskCallback)89 RUNTIME_FUNCTION(Runtime_RunMicrotaskCallback) {
90 HandleScope scope(isolate);
91 DCHECK_EQ(2, args.length());
92 CONVERT_ARG_CHECKED(Object, microtask_callback, 0);
93 CONVERT_ARG_CHECKED(Object, microtask_data, 1);
94 MicrotaskCallback callback = ToCData<MicrotaskCallback>(microtask_callback);
95 void* data = ToCData<void*>(microtask_data);
96 callback(data);
97 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
98 return ReadOnlyRoots(isolate).undefined_value();
99 }
100
RUNTIME_FUNCTION(Runtime_PromiseStatus)101 RUNTIME_FUNCTION(Runtime_PromiseStatus) {
102 HandleScope scope(isolate);
103 DCHECK_EQ(1, args.length());
104 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
105
106 return Smi::FromInt(promise->status());
107 }
108
RUNTIME_FUNCTION(Runtime_PromiseResult)109 RUNTIME_FUNCTION(Runtime_PromiseResult) {
110 HandleScope scope(isolate);
111 DCHECK_EQ(1, args.length());
112 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
113 return promise->result();
114 }
115
RUNTIME_FUNCTION(Runtime_PromiseMarkAsHandled)116 RUNTIME_FUNCTION(Runtime_PromiseMarkAsHandled) {
117 SealHandleScope shs(isolate);
118 DCHECK_EQ(1, args.length());
119 CONVERT_ARG_CHECKED(JSPromise, promise, 0);
120
121 promise->set_has_handler(true);
122 return ReadOnlyRoots(isolate).undefined_value();
123 }
124
RUNTIME_FUNCTION(Runtime_PromiseHookInit)125 RUNTIME_FUNCTION(Runtime_PromiseHookInit) {
126 HandleScope scope(isolate);
127 DCHECK_EQ(2, args.length());
128 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
129 CONVERT_ARG_HANDLE_CHECKED(Object, parent, 1);
130 isolate->RunPromiseHook(PromiseHookType::kInit, promise, parent);
131 return ReadOnlyRoots(isolate).undefined_value();
132 }
133
RUNTIME_FUNCTION(Runtime_AwaitPromisesInit)134 RUNTIME_FUNCTION(Runtime_AwaitPromisesInit) {
135 DCHECK_EQ(3, args.length());
136 HandleScope scope(isolate);
137 CONVERT_ARG_HANDLE_CHECKED(JSPromise, wrapped_value, 0);
138 CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 1);
139 CONVERT_ARG_HANDLE_CHECKED(JSPromise, throwaway, 2);
140 isolate->RunPromiseHook(PromiseHookType::kInit, wrapped_value, outer_promise);
141 isolate->RunPromiseHook(PromiseHookType::kInit, throwaway, wrapped_value);
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 return ReadOnlyRoots(isolate).undefined_value();
149 }
150
RUNTIME_FUNCTION(Runtime_PromiseHookBefore)151 RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
152 HandleScope scope(isolate);
153 DCHECK_EQ(1, args.length());
154 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
155 if (!maybe_promise->IsJSPromise())
156 return ReadOnlyRoots(isolate).undefined_value();
157 Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
158 if (isolate->debug()->is_active()) isolate->PushPromise(promise);
159 if (promise->IsJSPromise()) {
160 isolate->RunPromiseHook(PromiseHookType::kBefore, promise,
161 isolate->factory()->undefined_value());
162 }
163 return ReadOnlyRoots(isolate).undefined_value();
164 }
165
RUNTIME_FUNCTION(Runtime_PromiseHookAfter)166 RUNTIME_FUNCTION(Runtime_PromiseHookAfter) {
167 HandleScope scope(isolate);
168 DCHECK_EQ(1, args.length());
169 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
170 if (!maybe_promise->IsJSPromise())
171 return ReadOnlyRoots(isolate).undefined_value();
172 Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
173 if (isolate->debug()->is_active()) isolate->PopPromise();
174 if (promise->IsJSPromise()) {
175 isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
176 isolate->factory()->undefined_value());
177 }
178 return ReadOnlyRoots(isolate).undefined_value();
179 }
180
RUNTIME_FUNCTION(Runtime_RejectPromise)181 RUNTIME_FUNCTION(Runtime_RejectPromise) {
182 HandleScope scope(isolate);
183 DCHECK_EQ(3, args.length());
184 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
185 CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
186 CONVERT_ARG_HANDLE_CHECKED(Oddball, debug_event, 2);
187 return *JSPromise::Reject(promise, reason,
188 debug_event->BooleanValue(isolate));
189 }
190
RUNTIME_FUNCTION(Runtime_ResolvePromise)191 RUNTIME_FUNCTION(Runtime_ResolvePromise) {
192 HandleScope scope(isolate);
193 DCHECK_EQ(2, args.length());
194 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
195 CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
196 Handle<Object> result;
197 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
198 JSPromise::Resolve(promise, resolution));
199 return *result;
200 }
201
202 } // namespace internal
203 } // namespace v8
204