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 #include "src/runtime/runtime-utils.h" 5 6 #include "src/arguments.h" 7 #include "src/counters.h" 8 #include "src/debug/debug.h" 9 #include "src/elements.h" 10 #include "src/objects-inl.h" 11 12 namespace v8 { 13 namespace internal { 14 15 namespace { 16 17 void PromiseRejectEvent(Isolate* isolate, Handle<JSPromise> promise, 18 Handle<Object> rejected_promise, Handle<Object> value, 19 bool debug_event) { 20 isolate->RunPromiseHook(PromiseHookType::kResolve, promise, 21 isolate->factory()->undefined_value()); 22 23 if (isolate->debug()->is_active() && debug_event) { 24 isolate->debug()->OnPromiseReject(rejected_promise, value); 25 } 26 27 // Report only if we don't actually have a handler. 28 if (!promise->has_handler()) { 29 isolate->ReportPromiseReject(Handle<JSObject>::cast(promise), value, 30 v8::kPromiseRejectWithNoHandler); 31 } 32 } 33 34 } // namespace 35 36 RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) { 37 DCHECK_EQ(2, args.length()); 38 HandleScope scope(isolate); 39 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 40 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 41 42 Handle<Object> rejected_promise = promise; 43 if (isolate->debug()->is_active()) { 44 // If the Promise.reject call is caught, then this will return 45 // undefined, which will be interpreted by PromiseRejectEvent 46 // as being a caught exception event. 47 rejected_promise = isolate->GetPromiseOnStackOnThrow(); 48 isolate->debug()->OnAsyncTaskEvent( 49 debug::kDebugEnqueuePromiseReject, 50 isolate->debug()->NextAsyncTaskId(promise), 0); 51 } 52 PromiseRejectEvent(isolate, promise, rejected_promise, value, true); 53 return isolate->heap()->undefined_value(); 54 } 55 56 RUNTIME_FUNCTION(Runtime_ReportPromiseReject) { 57 DCHECK_EQ(2, args.length()); 58 HandleScope scope(isolate); 59 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 60 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 61 isolate->ReportPromiseReject(Handle<JSObject>::cast(promise), value, 62 v8::kPromiseRejectWithNoHandler); 63 return isolate->heap()->undefined_value(); 64 } 65 66 RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) { 67 DCHECK_EQ(1, args.length()); 68 HandleScope scope(isolate); 69 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 70 // At this point, no revocation has been issued before 71 CHECK(!promise->has_handler()); 72 isolate->ReportPromiseReject(promise, Handle<Object>(), 73 v8::kPromiseHandlerAddedAfterReject); 74 return isolate->heap()->undefined_value(); 75 } 76 77 RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) { 78 HandleScope scope(isolate); 79 DCHECK_EQ(1, args.length()); 80 CONVERT_ARG_HANDLE_CHECKED(PromiseReactionJobInfo, info, 0); 81 isolate->EnqueueMicrotask(info); 82 return isolate->heap()->undefined_value(); 83 } 84 85 RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) { 86 HandleScope scope(isolate); 87 DCHECK(args.length() == 1); 88 CONVERT_ARG_HANDLE_CHECKED(PromiseResolveThenableJobInfo, info, 0); 89 isolate->EnqueueMicrotask(info); 90 return isolate->heap()->undefined_value(); 91 } 92 93 RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) { 94 HandleScope scope(isolate); 95 DCHECK_EQ(1, args.length()); 96 CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0); 97 isolate->EnqueueMicrotask(microtask); 98 return isolate->heap()->undefined_value(); 99 } 100 101 RUNTIME_FUNCTION(Runtime_RunMicrotasks) { 102 HandleScope scope(isolate); 103 DCHECK_EQ(0, args.length()); 104 isolate->RunMicrotasks(); 105 return isolate->heap()->undefined_value(); 106 } 107 108 RUNTIME_FUNCTION(Runtime_PromiseStatus) { 109 HandleScope scope(isolate); 110 DCHECK_EQ(1, args.length()); 111 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 112 113 return Smi::FromInt(promise->status()); 114 } 115 116 RUNTIME_FUNCTION(Runtime_PromiseResult) { 117 HandleScope scope(isolate); 118 DCHECK_EQ(1, args.length()); 119 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 120 return promise->result(); 121 } 122 123 RUNTIME_FUNCTION(Runtime_PromiseMarkAsHandled) { 124 SealHandleScope shs(isolate); 125 DCHECK_EQ(1, args.length()); 126 CONVERT_ARG_CHECKED(JSPromise, promise, 0); 127 128 promise->set_has_handler(true); 129 return isolate->heap()->undefined_value(); 130 } 131 132 RUNTIME_FUNCTION(Runtime_PromiseHookInit) { 133 HandleScope scope(isolate); 134 DCHECK_EQ(2, args.length()); 135 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 136 CONVERT_ARG_HANDLE_CHECKED(Object, parent, 1); 137 isolate->RunPromiseHook(PromiseHookType::kInit, promise, parent); 138 return isolate->heap()->undefined_value(); 139 } 140 141 RUNTIME_FUNCTION(Runtime_PromiseHookResolve) { 142 HandleScope scope(isolate); 143 DCHECK_EQ(1, args.length()); 144 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 145 isolate->RunPromiseHook(PromiseHookType::kResolve, promise, 146 isolate->factory()->undefined_value()); 147 return isolate->heap()->undefined_value(); 148 } 149 150 RUNTIME_FUNCTION(Runtime_PromiseHookBefore) { 151 HandleScope scope(isolate); 152 DCHECK_EQ(1, args.length()); 153 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 154 if (promise->IsJSPromise()) { 155 isolate->RunPromiseHook(PromiseHookType::kBefore, 156 Handle<JSPromise>::cast(promise), 157 isolate->factory()->undefined_value()); 158 } 159 return isolate->heap()->undefined_value(); 160 } 161 162 RUNTIME_FUNCTION(Runtime_PromiseHookAfter) { 163 HandleScope scope(isolate); 164 DCHECK_EQ(1, args.length()); 165 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 166 if (promise->IsJSPromise()) { 167 isolate->RunPromiseHook(PromiseHookType::kAfter, 168 Handle<JSPromise>::cast(promise), 169 isolate->factory()->undefined_value()); 170 } 171 return isolate->heap()->undefined_value(); 172 } 173 174 } // namespace internal 175 } // namespace v8 176