Home | History | Annotate | Download | only in runtime
      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