Home | History | Annotate | Download | only in builtins
      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/builtins/builtins-async.h"
      6 #include "src/builtins/builtins-utils.h"
      7 #include "src/builtins/builtins.h"
      8 #include "src/code-factory.h"
      9 #include "src/code-stub-assembler.h"
     10 #include "src/frames-inl.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 Node* AsyncBuiltinsAssembler::Await(
     16     Node* context, Node* generator, Node* value, Node* outer_promise,
     17     const NodeGenerator1& create_closure_context, int on_resolve_context_index,
     18     int on_reject_context_index, bool is_predicted_as_caught) {
     19   // Let promiseCapability be ! NewPromiseCapability(%Promise%).
     20   Node* const wrapped_value = AllocateAndInitJSPromise(context);
     21 
     22   // Perform ! Call(promiseCapability.[[Resolve]], undefined,  promise ).
     23   InternalResolvePromise(context, wrapped_value, value);
     24 
     25   Node* const native_context = LoadNativeContext(context);
     26 
     27   Node* const closure_context = create_closure_context(native_context);
     28   Node* const map = LoadContextElement(
     29       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     30 
     31   // Load and allocate on_resolve closure
     32   Node* const on_resolve_shared_fun =
     33       LoadContextElement(native_context, on_resolve_context_index);
     34   CSA_SLOW_ASSERT(
     35       this, HasInstanceType(on_resolve_shared_fun, SHARED_FUNCTION_INFO_TYPE));
     36   Node* const on_resolve = AllocateFunctionWithMapAndContext(
     37       map, on_resolve_shared_fun, closure_context);
     38 
     39   // Load and allocate on_reject closure
     40   Node* const on_reject_shared_fun =
     41       LoadContextElement(native_context, on_reject_context_index);
     42   CSA_SLOW_ASSERT(
     43       this, HasInstanceType(on_reject_shared_fun, SHARED_FUNCTION_INFO_TYPE));
     44   Node* const on_reject = AllocateFunctionWithMapAndContext(
     45       map, on_reject_shared_fun, closure_context);
     46 
     47   Node* const throwaway_promise =
     48       AllocateAndInitJSPromise(context, wrapped_value);
     49 
     50   // The Promise will be thrown away and not handled, but it shouldn't trigger
     51   // unhandled reject events as its work is done
     52   PromiseSetHasHandler(throwaway_promise);
     53 
     54   Label do_perform_promise_then(this);
     55   GotoIfNot(IsDebugActive(), &do_perform_promise_then);
     56   {
     57     Label common(this);
     58     GotoIf(TaggedIsSmi(value), &common);
     59     GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common);
     60     {
     61       // Mark the reject handler callback to be a forwarding edge, rather
     62       // than a meaningful catch handler
     63       Node* const key =
     64           HeapConstant(factory()->promise_forwarding_handler_symbol());
     65       CallRuntime(Runtime::kSetProperty, context, on_reject, key,
     66                   TrueConstant(), SmiConstant(STRICT));
     67 
     68       if (is_predicted_as_caught) PromiseSetHandledHint(value);
     69     }
     70 
     71     Goto(&common);
     72     Bind(&common);
     73     // Mark the dependency to outer Promise in case the throwaway Promise is
     74     // found on the Promise stack
     75     CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
     76 
     77     Node* const key = HeapConstant(factory()->promise_handled_by_symbol());
     78     CallRuntime(Runtime::kSetProperty, context, throwaway_promise, key,
     79                 outer_promise, SmiConstant(STRICT));
     80   }
     81 
     82   Goto(&do_perform_promise_then);
     83   Bind(&do_perform_promise_then);
     84   InternalPerformPromiseThen(context, wrapped_value, on_resolve, on_reject,
     85                              throwaway_promise, UndefinedConstant(),
     86                              UndefinedConstant());
     87 
     88   return wrapped_value;
     89 }
     90 
     91 }  // namespace internal
     92 }  // namespace v8
     93