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

Side by Side Diff: src/isolate.cc

Issue 2604483002: [promises] Move PromiseHasUserDefinedRejectHandler to c++ (Closed)
Patch Set: Remove js check 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;
1825 if (JSReceiver::GetProperty(handler, key).ToHandle(&forwarding_handler)) {
Yang 2016/12/23 08:40:08 Since we do not expect any getters or other side e
gsathya 2016/12/23 17:59:44 Done.
1826 if (forwarding_handler->IsUndefined(isolate)) {
1827 return true;
1828 }
1829
1830 // TODO(gsathya): Remove this once we get rid of deferred objects.
1831 Handle<String> promise_str = isolate->factory()->promise_string();
1832 Handle<Object> deferred_promise_obj;
1833 if (JSObject::GetProperty(deferred, promise_str)
1834 .ToHandle(&deferred_promise_obj)) {
1835 if (!deferred_promise_obj->IsJSPromise()) {
1836 return true;
1837 }
1838
1839 return InternalPromiseHasUserDefinedRejectHandler(
1840 isolate, Handle<JSPromise>::cast(deferred_promise_obj));
1841 }
1842 }
1843
1844 // Otherwise, this is a real reject handler for the Promise
1845 return true;
1846 }
1847
1848 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
1849 Handle<JSPromise> promise) {
1850 // If this promise was marked as being handled by a catch block
1851 // in an async function, then it has a user-defined reject handler.
1852 if (promise->handled_hint()) return true;
1853
1854 // If this Promise is subsumed by another Promise (a Promise resolved
1855 // with another Promise, or an intermediate, hidden, throwaway Promise
1856 // within async/await), then recurse on the outer Promise.
1857 // In this case, the dependency is one possible way that the Promise
1858 // could be resolved, so it does not subsume the other following cases.
1859 Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol();
1860 Handle<Object> outer_promise_obj;
1861 if (JSObject::GetProperty(promise, key).ToHandle(&outer_promise_obj)) {
1862 if (outer_promise_obj->IsJSPromise() &&
1863 InternalPromiseHasUserDefinedRejectHandler(
1864 isolate, Handle<JSPromise>::cast(outer_promise_obj))) {
1865 return true;
1866 }
1867 }
1868
1869 Handle<Object> queue(promise->reject_reactions(), isolate);
1870 Handle<Object> deferred(promise->deferred(), isolate);
1871
1872 if (queue->IsUndefined(isolate)) {
1873 return false;
1874 }
1875
1876 if (queue->IsCallable()) {
1877 return PromiseHandlerCheck(isolate, Handle<JSReceiver>::cast(queue),
1878 Handle<JSObject>::cast(deferred));
1879 }
1880
1881 Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue);
1882 Handle<FixedArray> deferred_arr = Handle<FixedArray>::cast(deferred);
1883 for (int i = 0; i < deferred_arr->length(); i++) {
1884 Handle<JSReceiver> queue_item(JSReceiver::cast(queue_arr->get(i)));
1885 Handle<JSObject> deferred_item(JSObject::cast(deferred_arr->get(i)));
1886 if (PromiseHandlerCheck(isolate, queue_item, deferred_item)) {
1887 return true;
1888 }
1889 }
1890
1891 return false;
1892 }
1893
1894 } // namespace
1895
1811 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) { 1896 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
1812 Handle<JSFunction> fun = promise_has_user_defined_reject_handler(); 1897 if (!promise->IsJSPromise()) return false;
1813 Handle<Object> has_reject_handler; 1898 return InternalPromiseHasUserDefinedRejectHandler(
1814 // If we are, e.g., overflowing the stack, don't try to call out to JS 1899 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 } 1900 }
1827 1901
1828 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1902 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1829 Handle<Object> undefined = factory()->undefined_value(); 1903 Handle<Object> undefined = factory()->undefined_value();
1830 ThreadLocalTop* tltop = thread_local_top(); 1904 ThreadLocalTop* tltop = thread_local_top();
1831 if (tltop->promise_on_stack_ == NULL) return undefined; 1905 if (tltop->promise_on_stack_ == NULL) return undefined;
1832 // Find the top-most try-catch or try-finally handler. 1906 // Find the top-most try-catch or try-finally handler.
1833 CatchType prediction = PredictExceptionCatcher(); 1907 CatchType prediction = PredictExceptionCatcher();
1834 if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) { 1908 if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
1835 return undefined; 1909 return undefined;
1836 } 1910 }
1837 Handle<Object> retval = undefined; 1911 Handle<Object> retval = undefined;
1838 PromiseOnStack* promise_on_stack = tltop->promise_on_stack_; 1912 PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
1839 for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) { 1913 for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
1840 switch (PredictException(it.frame())) { 1914 switch (PredictException(it.frame())) {
1841 case HandlerTable::UNCAUGHT: 1915 case HandlerTable::UNCAUGHT:
1842 continue; 1916 continue;
1843 case HandlerTable::CAUGHT: 1917 case HandlerTable::CAUGHT:
1844 case HandlerTable::DESUGARING: 1918 case HandlerTable::DESUGARING:
1845 if (retval->IsJSObject()) { 1919 if (retval->IsJSPromise()) {
1846 // Caught the result of an inner async/await invocation. 1920 // Caught the result of an inner async/await invocation.
1847 // Mark the inner promise as caught in the "synchronous case" so 1921 // Mark the inner promise as caught in the "synchronous case" so
1848 // that Debug::OnException will see. In the synchronous case, 1922 // that Debug::OnException will see. In the synchronous case,
1849 // namely in the code in an async function before the first 1923 // namely in the code in an async function before the first
1850 // await, the function which has this exception event has not yet 1924 // await, the function which has this exception event has not yet
1851 // returned, so the generated Promise has not yet been marked 1925 // returned, so the generated Promise has not yet been marked
1852 // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol. 1926 // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
1853 Handle<Symbol> key = factory()->promise_handled_hint_symbol(); 1927 Handle<JSPromise>::cast(retval)->set_handled_hint(true);
1854 JSObject::SetProperty(Handle<JSObject>::cast(retval), key,
1855 factory()->true_value(), STRICT)
1856 .Assert();
1857 } 1928 }
1858 return retval; 1929 return retval;
1859 case HandlerTable::PROMISE: 1930 case HandlerTable::PROMISE:
1860 return promise_on_stack 1931 return promise_on_stack
1861 ? Handle<Object>::cast(promise_on_stack->promise()) 1932 ? Handle<Object>::cast(promise_on_stack->promise())
1862 : undefined; 1933 : undefined;
1863 case HandlerTable::ASYNC_AWAIT: { 1934 case HandlerTable::ASYNC_AWAIT: {
1864 // If in the initial portion of async/await, continue the loop to pop up 1935 // 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 1936 // successive async/await stack frames until an asynchronous one with
1866 // dependents is found, or a non-async stack frame is encountered, in 1937 // 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. 3656 // Then check whether this scope intercepts.
3586 if ((flag & intercept_mask_)) { 3657 if ((flag & intercept_mask_)) {
3587 intercepted_flags_ |= flag; 3658 intercepted_flags_ |= flag;
3588 return true; 3659 return true;
3589 } 3660 }
3590 return false; 3661 return false;
3591 } 3662 }
3592 3663
3593 } // namespace internal 3664 } // namespace internal
3594 } // namespace v8 3665 } // 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