LCOV - code coverage report
Current view: top level - src/runtime - runtime-promise.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 122 122 100.0 %
Date: 2019-02-19 Functions: 19 35 54.3 %

          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        2415 : RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) {
      21             :   DCHECK_EQ(2, args.length());
      22         805 :   HandleScope scope(isolate);
      23        1610 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
      24         805 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
      25             : 
      26             :   Handle<Object> rejected_promise = promise;
      27         805 :   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        1610 :                           isolate->factory()->undefined_value());
      34         805 :   isolate->debug()->OnPromiseReject(rejected_promise, value);
      35             : 
      36             :   // Report only if we don't actually have a handler.
      37         805 :   if (!promise->has_handler()) {
      38             :     isolate->ReportPromiseReject(promise, value,
      39         805 :                                  v8::kPromiseRejectWithNoHandler);
      40             :   }
      41         805 :   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        4367 : RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) {
      65             :   DCHECK_EQ(1, args.length());
      66        4367 :   HandleScope scope(isolate);
      67        8734 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
      68             :   // At this point, no revocation has been issued before
      69        4367 :   CHECK(!promise->has_handler());
      70             :   isolate->ReportPromiseReject(promise, Handle<Object>(),
      71        4367 :                                v8::kPromiseHandlerAddedAfterReject);
      72        4367 :   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        7919 : RUNTIME_FUNCTION(Runtime_PerformMicrotaskCheckpoint) {
      86        7919 :   HandleScope scope(isolate);
      87             :   DCHECK_EQ(0, args.length());
      88        7919 :   MicrotasksScope::PerformCheckpoint(reinterpret_cast<v8::Isolate*>(isolate));
      89        7919 :   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         457 :   CONVERT_ARG_CHECKED(Object, microtask_callback, 0);
      96         457 :   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       14224 : RUNTIME_FUNCTION(Runtime_PromiseHookInit) {
     122       14224 :   HandleScope scope(isolate);
     123             :   DCHECK_EQ(2, args.length());
     124       28448 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     125       14224 :   CONVERT_ARG_HANDLE_CHECKED(Object, parent, 1);
     126       14224 :   isolate->RunPromiseHook(PromiseHookType::kInit, promise, parent);
     127       14224 :   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             :           isolate->factory()->true_value(), StoreOrigin::kMaybeKeyed,
     162        3097 :           Just(ShouldThrow::kThrowOnError))
     163        6194 :           .Check();
     164        6194 :       Handle<JSPromise>::cast(value)->set_handled_hint(is_predicted_as_caught);
     165             :     }
     166             : 
     167             :     // Mark the dependency to {outer_promise} in case the {throwaway}
     168             :     // Promise is found on the Promise stack
     169             :     Object::SetProperty(isolate, throwaway,
     170             :                         isolate->factory()->promise_handled_by_symbol(),
     171             :                         outer_promise, StoreOrigin::kMaybeKeyed,
     172        4292 :                         Just(ShouldThrow::kThrowOnError))
     173        8584 :         .Check();
     174             :   }
     175             : 
     176        4328 :   return throwaway;
     177             : }
     178             : 
     179             : }  // namespace
     180             : 
     181        3115 : RUNTIME_FUNCTION(Runtime_AwaitPromisesInit) {
     182             :   DCHECK_EQ(5, args.length());
     183        3115 :   HandleScope scope(isolate);
     184        3115 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
     185        6230 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
     186        6230 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 2);
     187        6230 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 3);
     188        9345 :   CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 4);
     189             :   return *AwaitPromisesInitCommon(isolate, value, promise, outer_promise,
     190        6230 :                                   reject_handler, is_predicted_as_caught);
     191             : }
     192             : 
     193        1213 : RUNTIME_FUNCTION(Runtime_AwaitPromisesInitOld) {
     194             :   DCHECK_EQ(5, args.length());
     195        1213 :   HandleScope scope(isolate);
     196        1213 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
     197        2426 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
     198        2426 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 2);
     199        2426 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 3);
     200        3639 :   CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 4);
     201             : 
     202             :   // Fire the init hook for the wrapper promise (that we created for the
     203             :   // {value} previously).
     204        1213 :   isolate->RunPromiseHook(PromiseHookType::kInit, promise, outer_promise);
     205             :   return *AwaitPromisesInitCommon(isolate, value, promise, outer_promise,
     206        2426 :                                   reject_handler, is_predicted_as_caught);
     207             : }
     208             : 
     209       22951 : RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
     210       11487 :   HandleScope scope(isolate);
     211             :   DCHECK_EQ(1, args.length());
     212       22974 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
     213       22974 :   if (!maybe_promise->IsJSPromise())
     214             :     return ReadOnlyRoots(isolate).undefined_value();
     215       11464 :   Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
     216       22752 :   if (isolate->debug()->is_active()) isolate->PushPromise(promise);
     217       22928 :   if (promise->IsJSPromise()) {
     218             :     isolate->RunPromiseHook(PromiseHookType::kBefore, promise,
     219       22928 :                             isolate->factory()->undefined_value());
     220             :   }
     221       11487 :   return ReadOnlyRoots(isolate).undefined_value();
     222             : }
     223             : 
     224       22911 : RUNTIME_FUNCTION(Runtime_PromiseHookAfter) {
     225       11467 :   HandleScope scope(isolate);
     226             :   DCHECK_EQ(1, args.length());
     227       22934 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
     228       22934 :   if (!maybe_promise->IsJSPromise())
     229             :     return ReadOnlyRoots(isolate).undefined_value();
     230       11444 :   Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
     231       11444 :   if (isolate->debug()->is_active()) isolate->PopPromise();
     232       22888 :   if (promise->IsJSPromise()) {
     233             :     isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
     234       22888 :                             isolate->factory()->undefined_value());
     235             :   }
     236       11467 :   return ReadOnlyRoots(isolate).undefined_value();
     237             : }
     238             : 
     239        4846 : RUNTIME_FUNCTION(Runtime_RejectPromise) {
     240        4846 :   HandleScope scope(isolate);
     241             :   DCHECK_EQ(3, args.length());
     242        9692 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     243        4846 :   CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
     244        9692 :   CONVERT_ARG_HANDLE_CHECKED(Oddball, debug_event, 2);
     245             :   return *JSPromise::Reject(promise, reason,
     246        9692 :                             debug_event->BooleanValue(isolate));
     247             : }
     248             : 
     249       28317 : RUNTIME_FUNCTION(Runtime_ResolvePromise) {
     250       28317 :   HandleScope scope(isolate);
     251             :   DCHECK_EQ(2, args.length());
     252       56634 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     253       28317 :   CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1);
     254             :   Handle<Object> result;
     255       56634 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
     256             :                                      JSPromise::Resolve(promise, resolution));
     257       28317 :   return *result;
     258             : }
     259             : 
     260             : }  // namespace internal
     261      178779 : }  // namespace v8

Generated by: LCOV version 1.10