Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: src/isolate.cc

Issue 2604483002: [promises] Move PromiseHasUserDefinedRejectHandler to c++ (Closed)
Patch Set: use getdataproperty Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/isolate.h" 5 #include "src/isolate.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <fstream> // NOLINT(readability/streams) 9 #include <fstream> // NOLINT(readability/streams)
10 #include <sstream> 10 #include <sstream>
(...skipping 1790 matching lines...) Expand 10 before | Expand all | Expand 10 after
1801 void Isolate::PopPromise() { 1801 void Isolate::PopPromise() {
1802 ThreadLocalTop* tltop = thread_local_top(); 1802 ThreadLocalTop* tltop = thread_local_top();
1803 if (tltop->promise_on_stack_ == NULL) return; 1803 if (tltop->promise_on_stack_ == NULL) return;
1804 PromiseOnStack* prev = tltop->promise_on_stack_->prev(); 1804 PromiseOnStack* prev = tltop->promise_on_stack_->prev();
1805 Handle<Object> global_promise = tltop->promise_on_stack_->promise(); 1805 Handle<Object> global_promise = tltop->promise_on_stack_->promise();
1806 delete tltop->promise_on_stack_; 1806 delete tltop->promise_on_stack_;
1807 tltop->promise_on_stack_ = prev; 1807 tltop->promise_on_stack_ = prev;
1808 global_handles()->Destroy(global_promise.location()); 1808 global_handles()->Destroy(global_promise.location());
1809 } 1809 }
1810 1810
1811 namespace {
1812 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
1813 Handle<JSPromise> promise);
1814
1815 bool PromiseHandlerCheck(Isolate* isolate, Handle<JSReceiver> handler,
1816 Handle<JSObject> deferred) {
1817 // Recurse to the forwarding Promise, if any. This may be due to
1818 // - await reaction forwarding to the throwaway Promise, which has
1819 // a dependency edge to the outer Promise.
1820 // - PromiseIdResolveHandler forwarding to the output of .then
1821 // - Promise.all/Promise.race forwarding to a throwaway Promise, which
1822 // has a dependency edge to the generated outer Promise.
1823 Handle<Symbol> key = isolate->factory()->promise_forwarding_handler_symbol();
1824 Handle<Object> forwarding_handler = JSReceiver::GetDataProperty(handler, key);
1825 if (forwarding_handler->IsUndefined(isolate)) {
1826 return true;
1827 }
1828
1829 // TODO(gsathya): Remove this once we get rid of deferred objects.
1830 Handle<String> promise_str = isolate->factory()->promise_string();
1831 Handle<Object> deferred_promise_obj =
1832 JSObject::GetDataProperty(deferred, promise_str);
1833 if (!deferred_promise_obj->IsJSPromise()) {
1834 return true;
1835 }
1836
1837 return InternalPromiseHasUserDefinedRejectHandler(
1838 isolate, Handle<JSPromise>::cast(deferred_promise_obj));
1839
1840 // Otherwise, this is a real reject handler for the Promise
1841 return true;
1842 }
1843
1844 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
1845 Handle<JSPromise> promise) {
1846 // If this promise was marked as being handled by a catch block
1847 // in an async function, then it has a user-defined reject handler.
1848 if (promise->handled_hint()) return true;
1849
1850 // If this Promise is subsumed by another Promise (a Promise resolved
1851 // with another Promise, or an intermediate, hidden, throwaway Promise
1852 // within async/await), then recurse on the outer Promise.
1853 // In this case, the dependency is one possible way that the Promise
1854 // could be resolved, so it does not subsume the other following cases.
1855 Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol();
1856 Handle<Object> outer_promise_obj = JSObject::GetDataProperty(promise, key);
1857 if (outer_promise_obj->IsJSPromise() &&
1858 InternalPromiseHasUserDefinedRejectHandler(
1859 isolate, Handle<JSPromise>::cast(outer_promise_obj))) {
1860 return true;
1861 }
1862
1863 Handle<Object> queue(promise->reject_reactions(), isolate);
1864 Handle<Object> deferred(promise->deferred(), isolate);
1865
1866 if (queue->IsUndefined(isolate)) {
1867 return false;
1868 }
1869
1870 if (queue->IsCallable()) {
1871 return PromiseHandlerCheck(isolate, Handle<JSReceiver>::cast(queue),
1872 Handle<JSObject>::cast(deferred));
1873 }
1874
1875 Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue);
1876 Handle<FixedArray> deferred_arr = Handle<FixedArray>::cast(deferred);
1877 for (int i = 0; i < deferred_arr->length(); i++) {
1878 Handle<JSReceiver> queue_item(JSReceiver::cast(queue_arr->get(i)));
1879 Handle<JSObject> deferred_item(JSObject::cast(deferred_arr->get(i)));
1880 if (PromiseHandlerCheck(isolate, queue_item, deferred_item)) {
1881 return true;
1882 }
1883 }
1884
1885 return false;
1886 }
1887
1888 } // namespace
1889
1811 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) { 1890 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
1812 Handle<JSFunction> fun = promise_has_user_defined_reject_handler(); 1891 if (!promise->IsJSPromise()) return false;
1813 Handle<Object> has_reject_handler; 1892 return InternalPromiseHasUserDefinedRejectHandler(
1814 // If we are, e.g., overflowing the stack, don't try to call out to JS 1893 this, Handle<JSPromise>::cast(promise));
1815 if (!AllowJavascriptExecution::IsAllowed(this)) return false;
1816 // Call the registered function to check for a handler
1817 if (Execution::TryCall(this, fun, promise, 0, NULL)
1818 .ToHandle(&has_reject_handler)) {
1819 return has_reject_handler->IsTrue(this);
1820 }
1821 // If an exception is thrown in the course of execution of this built-in
1822 // function, it indicates either a bug, or a synthetic uncatchable
1823 // exception in the shutdown path. In either case, it's OK to predict either
1824 // way in DevTools.
1825 return false;
1826 } 1894 }
1827 1895
1828 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1896 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1829 Handle<Object> undefined = factory()->undefined_value(); 1897 Handle<Object> undefined = factory()->undefined_value();
1830 ThreadLocalTop* tltop = thread_local_top(); 1898 ThreadLocalTop* tltop = thread_local_top();
1831 if (tltop->promise_on_stack_ == NULL) return undefined; 1899 if (tltop->promise_on_stack_ == NULL) return undefined;
1832 // Find the top-most try-catch or try-finally handler. 1900 // Find the top-most try-catch or try-finally handler.
1833 CatchType prediction = PredictExceptionCatcher(); 1901 CatchType prediction = PredictExceptionCatcher();
1834 if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) { 1902 if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
1835 return undefined; 1903 return undefined;
1836 } 1904 }
1837 Handle<Object> retval = undefined; 1905 Handle<Object> retval = undefined;
1838 PromiseOnStack* promise_on_stack = tltop->promise_on_stack_; 1906 PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
1839 for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) { 1907 for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
1840 switch (PredictException(it.frame())) { 1908 switch (PredictException(it.frame())) {
1841 case HandlerTable::UNCAUGHT: 1909 case HandlerTable::UNCAUGHT:
1842 continue; 1910 continue;
1843 case HandlerTable::CAUGHT: 1911 case HandlerTable::CAUGHT:
1844 case HandlerTable::DESUGARING: 1912 case HandlerTable::DESUGARING:
1845 if (retval->IsJSObject()) { 1913 if (retval->IsJSPromise()) {
1846 // Caught the result of an inner async/await invocation. 1914 // Caught the result of an inner async/await invocation.
1847 // Mark the inner promise as caught in the "synchronous case" so 1915 // Mark the inner promise as caught in the "synchronous case" so
1848 // that Debug::OnException will see. In the synchronous case, 1916 // that Debug::OnException will see. In the synchronous case,
1849 // namely in the code in an async function before the first 1917 // namely in the code in an async function before the first
1850 // await, the function which has this exception event has not yet 1918 // await, the function which has this exception event has not yet
1851 // returned, so the generated Promise has not yet been marked 1919 // returned, so the generated Promise has not yet been marked
1852 // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol. 1920 // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
1853 Handle<Symbol> key = factory()->promise_handled_hint_symbol(); 1921 Handle<JSPromise>::cast(retval)->set_handled_hint(true);
1854 JSObject::SetProperty(Handle<JSObject>::cast(retval), key,
1855 factory()->true_value(), STRICT)
1856 .Assert();
1857 } 1922 }
1858 return retval; 1923 return retval;
1859 case HandlerTable::PROMISE: 1924 case HandlerTable::PROMISE:
1860 return promise_on_stack 1925 return promise_on_stack
1861 ? Handle<Object>::cast(promise_on_stack->promise()) 1926 ? Handle<Object>::cast(promise_on_stack->promise())
1862 : undefined; 1927 : undefined;
1863 case HandlerTable::ASYNC_AWAIT: { 1928 case HandlerTable::ASYNC_AWAIT: {
1864 // If in the initial portion of async/await, continue the loop to pop up 1929 // If in the initial portion of async/await, continue the loop to pop up
1865 // successive async/await stack frames until an asynchronous one with 1930 // successive async/await stack frames until an asynchronous one with
1866 // dependents is found, or a non-async stack frame is encountered, in 1931 // dependents is found, or a non-async stack frame is encountered, in
(...skipping 1718 matching lines...) Expand 10 before | Expand all | Expand 10 after
3585 // Then check whether this scope intercepts. 3650 // Then check whether this scope intercepts.
3586 if ((flag & intercept_mask_)) { 3651 if ((flag & intercept_mask_)) {
3587 intercepted_flags_ |= flag; 3652 intercepted_flags_ |= flag;
3588 return true; 3653 return true;
3589 } 3654 }
3590 return false; 3655 return false;
3591 } 3656 }
3592 3657
3593 } // namespace internal 3658 } // namespace internal
3594 } // namespace v8 3659 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap-symbols.h ('k') | src/js/async-await.js » ('j') | src/runtime/runtime-promise.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698