OLD | NEW |
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 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 { | 1811 namespace { |
1812 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, | 1812 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, |
1813 Handle<JSPromise> promise); | 1813 Handle<JSPromise> promise); |
1814 | 1814 |
1815 bool PromiseHandlerCheck(Isolate* isolate, Handle<JSReceiver> handler, | 1815 bool PromiseHandlerCheck(Isolate* isolate, Handle<JSReceiver> handler, |
1816 Handle<JSObject> deferred) { | 1816 Handle<JSReceiver> deferred_promise) { |
1817 // Recurse to the forwarding Promise, if any. This may be due to | 1817 // Recurse to the forwarding Promise, if any. This may be due to |
1818 // - await reaction forwarding to the throwaway Promise, which has | 1818 // - await reaction forwarding to the throwaway Promise, which has |
1819 // a dependency edge to the outer Promise. | 1819 // a dependency edge to the outer Promise. |
1820 // - PromiseIdResolveHandler forwarding to the output of .then | 1820 // - PromiseIdResolveHandler forwarding to the output of .then |
1821 // - Promise.all/Promise.race forwarding to a throwaway Promise, which | 1821 // - Promise.all/Promise.race forwarding to a throwaway Promise, which |
1822 // has a dependency edge to the generated outer Promise. | 1822 // has a dependency edge to the generated outer Promise. |
1823 // Otherwise, this is a real reject handler for the Promise. | 1823 // Otherwise, this is a real reject handler for the Promise. |
1824 Handle<Symbol> key = isolate->factory()->promise_forwarding_handler_symbol(); | 1824 Handle<Symbol> key = isolate->factory()->promise_forwarding_handler_symbol(); |
1825 Handle<Object> forwarding_handler = JSReceiver::GetDataProperty(handler, key); | 1825 Handle<Object> forwarding_handler = JSReceiver::GetDataProperty(handler, key); |
1826 if (forwarding_handler->IsUndefined(isolate)) { | 1826 if (forwarding_handler->IsUndefined(isolate)) { |
1827 return true; | 1827 return true; |
1828 } | 1828 } |
1829 | 1829 |
1830 // TODO(gsathya): Remove this once we get rid of deferred objects. | 1830 if (!deferred_promise->IsJSPromise()) { |
1831 Handle<String> promise_str = isolate->factory()->promise_string(); | |
1832 Handle<Object> deferred_promise_obj = | |
1833 JSObject::GetDataProperty(deferred, promise_str); | |
1834 if (!deferred_promise_obj->IsJSPromise()) { | |
1835 return true; | 1831 return true; |
1836 } | 1832 } |
1837 | 1833 |
1838 return InternalPromiseHasUserDefinedRejectHandler( | 1834 return InternalPromiseHasUserDefinedRejectHandler( |
1839 isolate, Handle<JSPromise>::cast(deferred_promise_obj)); | 1835 isolate, Handle<JSPromise>::cast(deferred_promise)); |
1840 } | 1836 } |
1841 | 1837 |
1842 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, | 1838 bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, |
1843 Handle<JSPromise> promise) { | 1839 Handle<JSPromise> promise) { |
1844 // If this promise was marked as being handled by a catch block | 1840 // If this promise was marked as being handled by a catch block |
1845 // in an async function, then it has a user-defined reject handler. | 1841 // in an async function, then it has a user-defined reject handler. |
1846 if (promise->handled_hint()) return true; | 1842 if (promise->handled_hint()) return true; |
1847 | 1843 |
1848 // If this Promise is subsumed by another Promise (a Promise resolved | 1844 // If this Promise is subsumed by another Promise (a Promise resolved |
1849 // with another Promise, or an intermediate, hidden, throwaway Promise | 1845 // with another Promise, or an intermediate, hidden, throwaway Promise |
1850 // within async/await), then recurse on the outer Promise. | 1846 // within async/await), then recurse on the outer Promise. |
1851 // In this case, the dependency is one possible way that the Promise | 1847 // In this case, the dependency is one possible way that the Promise |
1852 // could be resolved, so it does not subsume the other following cases. | 1848 // could be resolved, so it does not subsume the other following cases. |
1853 Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol(); | 1849 Handle<Symbol> key = isolate->factory()->promise_handled_by_symbol(); |
1854 Handle<Object> outer_promise_obj = JSObject::GetDataProperty(promise, key); | 1850 Handle<Object> outer_promise_obj = JSObject::GetDataProperty(promise, key); |
1855 if (outer_promise_obj->IsJSPromise() && | 1851 if (outer_promise_obj->IsJSPromise() && |
1856 InternalPromiseHasUserDefinedRejectHandler( | 1852 InternalPromiseHasUserDefinedRejectHandler( |
1857 isolate, Handle<JSPromise>::cast(outer_promise_obj))) { | 1853 isolate, Handle<JSPromise>::cast(outer_promise_obj))) { |
1858 return true; | 1854 return true; |
1859 } | 1855 } |
1860 | 1856 |
1861 Handle<Object> queue(promise->reject_reactions(), isolate); | 1857 Handle<Object> queue(promise->reject_reactions(), isolate); |
1862 Handle<Object> deferred(promise->deferred(), isolate); | 1858 Handle<Object> deferred_promise(promise->deferred_promise(), isolate); |
1863 | 1859 |
1864 if (queue->IsUndefined(isolate)) { | 1860 if (queue->IsUndefined(isolate)) { |
1865 return false; | 1861 return false; |
1866 } | 1862 } |
1867 | 1863 |
1868 if (queue->IsCallable()) { | 1864 if (queue->IsCallable()) { |
1869 return PromiseHandlerCheck(isolate, Handle<JSReceiver>::cast(queue), | 1865 return PromiseHandlerCheck(isolate, Handle<JSReceiver>::cast(queue), |
1870 Handle<JSObject>::cast(deferred)); | 1866 Handle<JSReceiver>::cast(deferred_promise)); |
1871 } | 1867 } |
1872 | 1868 |
1873 Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue); | 1869 Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue); |
1874 Handle<FixedArray> deferred_arr = Handle<FixedArray>::cast(deferred); | 1870 Handle<FixedArray> deferred_promise_arr = |
1875 for (int i = 0; i < deferred_arr->length(); i++) { | 1871 Handle<FixedArray>::cast(deferred_promise); |
| 1872 for (int i = 0; i < deferred_promise_arr->length(); i++) { |
1876 Handle<JSReceiver> queue_item(JSReceiver::cast(queue_arr->get(i))); | 1873 Handle<JSReceiver> queue_item(JSReceiver::cast(queue_arr->get(i))); |
1877 Handle<JSObject> deferred_item(JSObject::cast(deferred_arr->get(i))); | 1874 Handle<JSReceiver> deferred_promise_item( |
1878 if (PromiseHandlerCheck(isolate, queue_item, deferred_item)) { | 1875 JSReceiver::cast(deferred_promise_arr->get(i))); |
| 1876 if (PromiseHandlerCheck(isolate, queue_item, deferred_promise_item)) { |
1879 return true; | 1877 return true; |
1880 } | 1878 } |
1881 } | 1879 } |
1882 | 1880 |
1883 return false; | 1881 return false; |
1884 } | 1882 } |
1885 | 1883 |
1886 } // namespace | 1884 } // namespace |
1887 | 1885 |
1888 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) { | 1886 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) { |
(...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3292 void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info, | 3290 void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info, |
3293 MaybeHandle<Object>* result, | 3291 MaybeHandle<Object>* result, |
3294 MaybeHandle<Object>* maybe_exception) { | 3292 MaybeHandle<Object>* maybe_exception) { |
3295 PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name()); | 3293 PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name()); |
3296 | 3294 |
3297 Handle<JSPromise> promise(info->promise(), this); | 3295 Handle<JSPromise> promise(info->promise(), this); |
3298 Handle<Object> value(info->value(), this); | 3296 Handle<Object> value(info->value(), this); |
3299 Handle<Object> tasks(info->tasks(), this); | 3297 Handle<Object> tasks(info->tasks(), this); |
3300 Handle<JSFunction> promise_handle_fn = promise_handle(); | 3298 Handle<JSFunction> promise_handle_fn = promise_handle(); |
3301 Handle<Object> undefined = factory()->undefined_value(); | 3299 Handle<Object> undefined = factory()->undefined_value(); |
3302 Handle<Object> deferred(info->deferred(), this); | 3300 Handle<Object> deferred_promise(info->deferred_promise(), this); |
3303 | 3301 |
3304 if (deferred->IsFixedArray()) { | 3302 if (deferred_promise->IsFixedArray()) { |
3305 DCHECK(tasks->IsFixedArray()); | 3303 DCHECK(tasks->IsFixedArray()); |
3306 Handle<FixedArray> deferred_arr = Handle<FixedArray>::cast(deferred); | 3304 Handle<FixedArray> deferred_promise_arr = |
| 3305 Handle<FixedArray>::cast(deferred_promise); |
| 3306 Handle<FixedArray> deferred_on_resolve_arr( |
| 3307 FixedArray::cast(info->deferred_on_resolve()), this); |
| 3308 Handle<FixedArray> deferred_on_reject_arr( |
| 3309 FixedArray::cast(info->deferred_on_reject()), this); |
3307 Handle<FixedArray> tasks_arr = Handle<FixedArray>::cast(tasks); | 3310 Handle<FixedArray> tasks_arr = Handle<FixedArray>::cast(tasks); |
3308 for (int i = 0; i < deferred_arr->length(); i++) { | 3311 for (int i = 0; i < deferred_promise_arr->length(); i++) { |
3309 Handle<Object> argv[] = {promise, value, handle(tasks_arr->get(i), this), | 3312 Handle<Object> argv[] = {promise, |
3310 handle(deferred_arr->get(i), this)}; | 3313 value, |
| 3314 handle(tasks_arr->get(i), this), |
| 3315 handle(deferred_promise_arr->get(i), this), |
| 3316 handle(deferred_on_resolve_arr->get(i), this), |
| 3317 handle(deferred_on_reject_arr->get(i), this)}; |
3311 *result = Execution::TryCall(this, promise_handle_fn, undefined, | 3318 *result = Execution::TryCall(this, promise_handle_fn, undefined, |
3312 arraysize(argv), argv, maybe_exception); | 3319 arraysize(argv), argv, maybe_exception); |
3313 // If execution is terminating, just bail out. | 3320 // If execution is terminating, just bail out. |
3314 if (result->is_null() && maybe_exception->is_null()) { | 3321 if (result->is_null() && maybe_exception->is_null()) { |
3315 return; | 3322 return; |
3316 } | 3323 } |
3317 } | 3324 } |
3318 } else { | 3325 } else { |
3319 Handle<Object> argv[] = {promise, value, tasks, deferred}; | 3326 Handle<Object> argv[] = {promise, |
| 3327 value, |
| 3328 tasks, |
| 3329 deferred_promise, |
| 3330 handle(info->deferred_on_resolve(), this), |
| 3331 handle(info->deferred_on_reject(), this)}; |
3320 *result = Execution::TryCall(this, promise_handle_fn, undefined, | 3332 *result = Execution::TryCall(this, promise_handle_fn, undefined, |
3321 arraysize(argv), argv, maybe_exception); | 3333 arraysize(argv), argv, maybe_exception); |
3322 } | 3334 } |
3323 } | 3335 } |
3324 | 3336 |
3325 void Isolate::PromiseResolveThenableJob( | 3337 void Isolate::PromiseResolveThenableJob( |
3326 Handle<PromiseResolveThenableJobInfo> info, MaybeHandle<Object>* result, | 3338 Handle<PromiseResolveThenableJobInfo> info, MaybeHandle<Object>* result, |
3327 MaybeHandle<Object>* maybe_exception) { | 3339 MaybeHandle<Object>* maybe_exception) { |
3328 PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name()); | 3340 PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name()); |
3329 | 3341 |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3648 // Then check whether this scope intercepts. | 3660 // Then check whether this scope intercepts. |
3649 if ((flag & intercept_mask_)) { | 3661 if ((flag & intercept_mask_)) { |
3650 intercepted_flags_ |= flag; | 3662 intercepted_flags_ |= flag; |
3651 return true; | 3663 return true; |
3652 } | 3664 } |
3653 return false; | 3665 return false; |
3654 } | 3666 } |
3655 | 3667 |
3656 } // namespace internal | 3668 } // namespace internal |
3657 } // namespace v8 | 3669 } // namespace v8 |
OLD | NEW |