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/debug/debug.h" | 5 #include "src/debug/debug.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 1872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1883 HandleScope scope(data->isolate); | 1883 HandleScope scope(data->isolate); |
1884 data->debug->OnAsyncTaskEvent(debug::kDebugPromiseCollected, data->id); | 1884 data->debug->OnAsyncTaskEvent(debug::kDebugPromiseCollected, data->id); |
1885 } | 1885 } |
1886 | 1886 |
1887 void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) { | 1887 void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) { |
1888 CollectedCallbackData* data = | 1888 CollectedCallbackData* data = |
1889 reinterpret_cast<CollectedCallbackData*>(info.GetParameter()); | 1889 reinterpret_cast<CollectedCallbackData*>(info.GetParameter()); |
1890 GlobalHandles::Destroy(data->location); | 1890 GlobalHandles::Destroy(data->location); |
1891 info.SetSecondPassCallback(&SendAsyncTaskEventCancel); | 1891 info.SetSecondPassCallback(&SendAsyncTaskEventCancel); |
1892 } | 1892 } |
| 1893 |
| 1894 // In an async function, reuse the existing stack related to the outer |
| 1895 // Promise. Otherwise, e.g. in a direct call to then, save a new stack. |
| 1896 // Promises with multiple reactions with one or more of them being async |
| 1897 // functions will not get a good stack trace, as async functions require |
| 1898 // different stacks from direct Promise use, but we save and restore a |
| 1899 // stack once for all reactions. |
| 1900 // |
| 1901 // If this isn't a case of async function, we return false, otherwise |
| 1902 // we set the correct id and return true. |
| 1903 // |
| 1904 // TODO(littledan): Improve this case. |
| 1905 int GetReferenceAsyncTaskId(Isolate* isolate, Handle<JSPromise> promise) { |
| 1906 Handle<Symbol> handled_by_symbol = |
| 1907 isolate->factory()->promise_handled_by_symbol(); |
| 1908 Handle<Object> handled_by_promise = |
| 1909 JSObject::GetDataProperty(promise, handled_by_symbol); |
| 1910 if (!handled_by_promise->IsJSPromise()) { |
| 1911 return isolate->debug()->NextAsyncTaskId(promise); |
| 1912 } |
| 1913 Handle<JSPromise> handled_by_promise_js = |
| 1914 Handle<JSPromise>::cast(handled_by_promise); |
| 1915 Handle<Symbol> async_stack_id_symbol = |
| 1916 isolate->factory()->promise_async_stack_id_symbol(); |
| 1917 Handle<Object> async_task_id = |
| 1918 JSObject::GetDataProperty(handled_by_promise_js, async_stack_id_symbol); |
| 1919 if (!async_task_id->IsSmi()) { |
| 1920 return isolate->debug()->NextAsyncTaskId(promise); |
| 1921 } |
| 1922 return Handle<Smi>::cast(async_task_id)->value(); |
| 1923 } |
1893 } // namespace | 1924 } // namespace |
1894 | 1925 |
| 1926 void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise, |
| 1927 Handle<Object> parent) { |
| 1928 if (!debug_delegate_) return; |
| 1929 int id = GetReferenceAsyncTaskId(isolate_, promise); |
| 1930 switch (type) { |
| 1931 case PromiseHookType::kInit: |
| 1932 debug_delegate_->PromiseEventOccurred( |
| 1933 debug::kDebugPromiseCreated, id, |
| 1934 parent->IsJSPromise() ? GetReferenceAsyncTaskId( |
| 1935 isolate_, Handle<JSPromise>::cast(parent)) |
| 1936 : 0); |
| 1937 return; |
| 1938 case PromiseHookType::kResolve: |
| 1939 // We can't use this hook because it's called before promise object will |
| 1940 // get resolved status. |
| 1941 return; |
| 1942 case PromiseHookType::kBefore: |
| 1943 OnAsyncTaskEvent(debug::kDebugWillHandle, id); |
| 1944 return; |
| 1945 case PromiseHookType::kAfter: |
| 1946 OnAsyncTaskEvent(debug::kDebugDidHandle, id); |
| 1947 return; |
| 1948 } |
| 1949 } |
| 1950 |
1895 int Debug::NextAsyncTaskId(Handle<JSObject> promise) { | 1951 int Debug::NextAsyncTaskId(Handle<JSObject> promise) { |
1896 LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol()); | 1952 LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol()); |
1897 Maybe<bool> maybe = JSReceiver::HasProperty(&it); | 1953 Maybe<bool> maybe = JSReceiver::HasProperty(&it); |
1898 if (maybe.ToChecked()) { | 1954 if (maybe.ToChecked()) { |
1899 MaybeHandle<Object> result = Object::GetProperty(&it); | 1955 MaybeHandle<Object> result = Object::GetProperty(&it); |
1900 return Handle<Smi>::cast(result.ToHandleChecked())->value(); | 1956 return Handle<Smi>::cast(result.ToHandleChecked())->value(); |
1901 } | 1957 } |
1902 Handle<Smi> async_id = | 1958 Handle<Smi> async_id = |
1903 handle(Smi::FromInt(++thread_local_.async_task_count_), isolate_); | 1959 handle(Smi::FromInt(++thread_local_.async_task_count_), isolate_); |
1904 Object::SetProperty(&it, async_id, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED) | 1960 Object::SetProperty(&it, async_id, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 shared->set_debug_is_blackboxed(is_blackboxed); | 2007 shared->set_debug_is_blackboxed(is_blackboxed); |
1952 shared->set_computed_debug_is_blackboxed(true); | 2008 shared->set_computed_debug_is_blackboxed(true); |
1953 } | 2009 } |
1954 return shared->debug_is_blackboxed(); | 2010 return shared->debug_is_blackboxed(); |
1955 } | 2011 } |
1956 | 2012 |
1957 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { | 2013 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { |
1958 if (in_debug_scope() || ignore_events()) return; | 2014 if (in_debug_scope() || ignore_events()) return; |
1959 | 2015 |
1960 if (debug_delegate_) { | 2016 if (debug_delegate_) { |
1961 debug_delegate_->PromiseEventOccurred(type, id); | 2017 debug_delegate_->PromiseEventOccurred(type, id, 0); |
1962 if (!non_inspector_listener_exists()) return; | 2018 if (!non_inspector_listener_exists()) return; |
1963 } | 2019 } |
1964 | 2020 |
1965 HandleScope scope(isolate_); | 2021 HandleScope scope(isolate_); |
1966 DebugScope debug_scope(this); | 2022 DebugScope debug_scope(this); |
1967 if (debug_scope.failed()) return; | 2023 if (debug_scope.failed()) return; |
1968 | 2024 |
1969 // Create the script collected state object. | 2025 // Create the script collected state object. |
1970 Handle<Object> event_data; | 2026 Handle<Object> event_data; |
1971 // Bail out and don't call debugger if exception. | 2027 // Bail out and don't call debugger if exception. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2086 if (is_active || in_debug_scope()) { | 2142 if (is_active || in_debug_scope()) { |
2087 // Note that the debug context could have already been loaded to | 2143 // Note that the debug context could have already been loaded to |
2088 // bootstrap test cases. | 2144 // bootstrap test cases. |
2089 isolate_->compilation_cache()->Disable(); | 2145 isolate_->compilation_cache()->Disable(); |
2090 is_active = Load(); | 2146 is_active = Load(); |
2091 } else if (is_loaded()) { | 2147 } else if (is_loaded()) { |
2092 isolate_->compilation_cache()->Enable(); | 2148 isolate_->compilation_cache()->Enable(); |
2093 Unload(); | 2149 Unload(); |
2094 } | 2150 } |
2095 is_active_ = is_active; | 2151 is_active_ = is_active; |
| 2152 isolate_->DebugStateUpdated(); |
2096 } | 2153 } |
2097 | 2154 |
2098 void Debug::UpdateHookOnFunctionCall() { | 2155 void Debug::UpdateHookOnFunctionCall() { |
2099 STATIC_ASSERT(StepFrame > StepIn); | 2156 STATIC_ASSERT(StepFrame > StepIn); |
2100 STATIC_ASSERT(LastStepAction == StepFrame); | 2157 STATIC_ASSERT(LastStepAction == StepFrame); |
2101 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn || | 2158 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn || |
2102 isolate_->needs_side_effect_check(); | 2159 isolate_->needs_side_effect_check(); |
2103 } | 2160 } |
2104 | 2161 |
2105 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { | 2162 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2334 return v8::Utils::ToLocal(callback_data_); | 2391 return v8::Utils::ToLocal(callback_data_); |
2335 } | 2392 } |
2336 | 2393 |
2337 | 2394 |
2338 v8::Isolate* EventDetailsImpl::GetIsolate() const { | 2395 v8::Isolate* EventDetailsImpl::GetIsolate() const { |
2339 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); | 2396 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); |
2340 } | 2397 } |
2341 | 2398 |
2342 } // namespace internal | 2399 } // namespace internal |
2343 } // namespace v8 | 2400 } // namespace v8 |
OLD | NEW |