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/api-inl.h" 6#include "src/debug/debug.h" 7#include "src/execution/arguments-inl.h" 8#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 17namespace v8 { 18namespace internal { 19 20RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) { 21 DCHECK_EQ(2, args.length()); 22 HandleScope scope(isolate); 23 Handle<JSPromise> promise = args.at<JSPromise>(0); 24 Handle<Object> value = args.at(1); 25 26 Handle<Object> rejected_promise = promise; 27 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 rejected_promise = isolate->GetPromiseOnStackOnThrow(); 31 } 32 isolate->RunAllPromiseHooks(PromiseHookType::kResolve, promise, 33 isolate->factory()->undefined_value()); 34 isolate->debug()->OnPromiseReject(rejected_promise, value); 35 36 // Report only if we don't actually have a handler. 37 if (!promise->has_handler()) { 38 isolate->ReportPromiseReject(promise, value, 39 v8::kPromiseRejectWithNoHandler); 40 } 41 return ReadOnlyRoots(isolate).undefined_value(); 42} 43 44RUNTIME_FUNCTION(Runtime_PromiseRejectAfterResolved) { 45 DCHECK_EQ(2, args.length()); 46 HandleScope scope(isolate); 47 Handle<JSPromise> promise = args.at<JSPromise>(0); 48 Handle<Object> reason = args.at(1); 49 isolate->ReportPromiseReject(promise, reason, 50 v8::kPromiseRejectAfterResolved); 51 return ReadOnlyRoots(isolate).undefined_value(); 52} 53 54RUNTIME_FUNCTION(Runtime_PromiseResolveAfterResolved) { 55 DCHECK_EQ(2, args.length()); 56 HandleScope scope(isolate); 57 Handle<JSPromise> promise = args.at<JSPromise>(0); 58 Handle<Object> resolution = args.at(1); 59 isolate->ReportPromiseReject(promise, resolution, 60 v8::kPromiseResolveAfterResolved); 61 return ReadOnlyRoots(isolate).undefined_value(); 62} 63 64RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) { 65 DCHECK_EQ(1, args.length()); 66 HandleScope scope(isolate); 67 Handle<JSPromise> promise = args.at<JSPromise>(0); 68 // At this point, no revocation has been issued before 69 CHECK(!promise->has_handler()); 70 isolate->ReportPromiseReject(promise, Handle<Object>(), 71 v8::kPromiseHandlerAddedAfterReject); 72 return ReadOnlyRoots(isolate).undefined_value(); 73} 74 75RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) { 76 HandleScope scope(isolate); 77 DCHECK_EQ(1, args.length()); 78 Handle<JSFunction> function = args.at<JSFunction>(0); 79 80 Handle<CallableTask> microtask = isolate->factory()->NewCallableTask( 81 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 88RUNTIME_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 95RUNTIME_FUNCTION(Runtime_RunMicrotaskCallback) { 96 HandleScope scope(isolate); 97 DCHECK_EQ(2, args.length()); 98 Object microtask_callback = args[0]; 99 Object microtask_data = args[1]; 100 MicrotaskCallback callback = ToCData<MicrotaskCallback>(microtask_callback); 101 void* data = ToCData<void*>(microtask_data); 102 callback(data); 103 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); 104 return ReadOnlyRoots(isolate).undefined_value(); 105} 106 107RUNTIME_FUNCTION(Runtime_PromiseStatus) { 108 HandleScope scope(isolate); 109 DCHECK_EQ(1, args.length()); 110 Handle<JSPromise> promise = args.at<JSPromise>(0); 111 112 return Smi::FromInt(promise->status()); 113} 114 115RUNTIME_FUNCTION(Runtime_PromiseHookInit) { 116 HandleScope scope(isolate); 117 DCHECK_EQ(2, args.length()); 118 Handle<JSPromise> promise = args.at<JSPromise>(0); 119 Handle<Object> parent = args.at(1); 120 isolate->RunPromiseHook(PromiseHookType::kInit, promise, parent); 121 return ReadOnlyRoots(isolate).undefined_value(); 122} 123 124RUNTIME_FUNCTION(Runtime_PromiseHookBefore) { 125 HandleScope scope(isolate); 126 DCHECK_EQ(1, args.length()); 127 Handle<JSReceiver> promise = args.at<JSReceiver>(0); 128 if (promise->IsJSPromise()) { 129 isolate->OnPromiseBefore(Handle<JSPromise>::cast(promise)); 130 } 131 return ReadOnlyRoots(isolate).undefined_value(); 132} 133 134RUNTIME_FUNCTION(Runtime_PromiseHookAfter) { 135 HandleScope scope(isolate); 136 DCHECK_EQ(1, args.length()); 137 Handle<JSReceiver> promise = args.at<JSReceiver>(0); 138 if (promise->IsJSPromise()) { 139 isolate->OnPromiseAfter(Handle<JSPromise>::cast(promise)); 140 } 141 return ReadOnlyRoots(isolate).undefined_value(); 142} 143 144RUNTIME_FUNCTION(Runtime_RejectPromise) { 145 HandleScope scope(isolate); 146 DCHECK_EQ(3, args.length()); 147 Handle<JSPromise> promise = args.at<JSPromise>(0); 148 Handle<Object> reason = args.at(1); 149 Handle<Oddball> debug_event = args.at<Oddball>(2); 150 return *JSPromise::Reject(promise, reason, 151 debug_event->BooleanValue(isolate)); 152} 153 154RUNTIME_FUNCTION(Runtime_ResolvePromise) { 155 HandleScope scope(isolate); 156 DCHECK_EQ(2, args.length()); 157 Handle<JSPromise> promise = args.at<JSPromise>(0); 158 Handle<Object> resolution = args.at(1); 159 Handle<Object> result; 160 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 161 JSPromise::Resolve(promise, resolution)); 162 return *result; 163} 164 165// A helper function to be called when constructing AggregateError objects. This 166// takes care of the Error-related construction, e.g., stack traces. 167RUNTIME_FUNCTION(Runtime_ConstructAggregateErrorHelper) { 168 HandleScope scope(isolate); 169 DCHECK_EQ(4, args.length()); 170 Handle<JSFunction> target = args.at<JSFunction>(0); 171 Handle<Object> new_target = args.at(1); 172 Handle<Object> message = args.at(2); 173 Handle<Object> options = args.at(3); 174 175 DCHECK_EQ(*target, *isolate->aggregate_error_function()); 176 177 Handle<Object> result; 178 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 179 isolate, result, 180 ErrorUtils::Construct(isolate, target, new_target, message, options)); 181 return *result; 182} 183 184// A helper function to be called when constructing AggregateError objects. This 185// takes care of the Error-related construction, e.g., stack traces. 186RUNTIME_FUNCTION(Runtime_ConstructInternalAggregateErrorHelper) { 187 HandleScope scope(isolate); 188 DCHECK_GE(args.length(), 1); 189 int message_template_index = args.smi_value_at(0); 190 191 Handle<Object> arg0; 192 if (args.length() >= 2) { 193 arg0 = args.at<Object>(1); 194 } 195 196 Handle<Object> arg1; 197 if (args.length() >= 3) { 198 arg1 = args.at<Object>(2); 199 } 200 201 Handle<Object> arg2; 202 if (args.length() >= 4) { 203 arg2 = args.at<Object>(3); 204 } 205 206 Handle<Object> options; 207 if (args.length() >= 5) { 208 options = args.at<Object>(4); 209 } else { 210 options = isolate->factory()->undefined_value(); 211 } 212 213 Handle<Object> message_string = MessageFormatter::Format( 214 isolate, MessageTemplate(message_template_index), arg0, arg1, arg2); 215 216 Handle<Object> result; 217 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 218 isolate, result, 219 ErrorUtils::Construct(isolate, isolate->aggregate_error_function(), 220 isolate->aggregate_error_function(), message_string, 221 options)); 222 return *result; 223} 224 225} // namespace internal 226} // namespace v8 227