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

Generated by: LCOV version 1.10