Index: src/debug/debug-interface.cc |
diff --git a/src/debug/debug-interface.cc b/src/debug/debug-interface.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f83026378aae962bba033c9b642e0a597d7ef1ca |
--- /dev/null |
+++ b/src/debug/debug-interface.cc |
@@ -0,0 +1,149 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/debug/debug-interface.h" |
+ |
+#include "src/debug/debug.h" |
+#include "src/factory.h" |
+#include "src/isolate-inl.h" |
+#include "src/vm-state-inl.h" |
+ |
+namespace v8 { |
+ |
+namespace i = internal; |
+ |
+static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { |
+ if (isolate->has_scheduled_exception()) { |
+ return isolate->scheduled_exception() == |
+ isolate->heap()->termination_exception(); |
+ } |
+ return false; |
+} |
+ |
+#define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate)) |
+ |
+namespace { |
+ |
+class InternalEscapableScope : public v8::EscapableHandleScope { |
+ public: |
+ explicit inline InternalEscapableScope(i::Isolate* isolate) |
+ : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {} |
+}; |
+ |
+class CallDepthScope { |
Yang
2016/10/17 09:53:25
This and some other parts are duplicates of what's
kozy
2016/10/17 14:38:06
Done.
|
+ public: |
+ explicit CallDepthScope(i::Isolate* isolate, Local<Context> context) |
+ : isolate_(isolate), context_(context), escaped_(false) { |
+ // TODO(dcarney): remove this when blink stops crashing. |
+ DCHECK(!isolate_->external_caught_exception()); |
+ isolate_->IncrementJsCallsFromApiCounter(); |
+ isolate_->handle_scope_implementer()->IncrementCallDepth(); |
+ if (!context.IsEmpty()) { |
+ i::Handle<i::Context> env = Utils::OpenHandle(*context); |
+ i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); |
+ if (isolate->context() != nullptr && |
+ isolate->context()->native_context() == env->native_context() && |
+ impl->LastEnteredContextWas(env)) { |
+ context_ = Local<Context>(); |
+ } else { |
+ context_->Enter(); |
+ } |
+ } |
+ } |
+ ~CallDepthScope() { |
+ if (!context_.IsEmpty()) context_->Exit(); |
+ if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); |
+ } |
+ |
+ void Escape() { |
+ DCHECK(!escaped_); |
+ escaped_ = true; |
+ auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
+ handle_scope_implementer->DecrementCallDepth(); |
+ bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); |
+ isolate_->OptionalRescheduleException(call_depth_is_zero); |
+ } |
+ |
+ private: |
+ i::Isolate* const isolate_; |
+ Local<Context> context_; |
+ bool escaped_; |
+}; |
+ |
+} // namespace |
+ |
+bool DebugInterface::SetDebugEventListener(Isolate* isolate, EventCallback that, |
+ Local<Value> data) { |
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ ENTER_V8(i_isolate); |
+ i::HandleScope scope(i_isolate); |
+ i::Handle<i::Object> foreign = i_isolate->factory()->undefined_value(); |
+ if (that != NULL) { |
+ foreign = i_isolate->factory()->NewForeign(FUNCTION_ADDR(that)); |
+ } |
+ i_isolate->debug()->SetEventListener(foreign, Utils::OpenHandle(*data, true)); |
+ return true; |
+} |
+ |
+Local<Context> DebugInterface::GetDebugContext(Isolate* isolate) { |
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ ENTER_V8(i_isolate); |
+ return Utils::ToLocal(i_isolate->debug()->GetDebugContext()); |
+} |
+ |
+MaybeLocal<Value> DebugInterface::Call(Local<Context> context, |
+ v8::Local<v8::Function> fun, |
+ v8::Local<v8::Value> data) { |
+ auto isolate = context.IsEmpty() |
+ ? i::Isolate::Current() |
+ : reinterpret_cast<i::Isolate*>(context->GetIsolate()); |
+ if (IsExecutionTerminatingCheck(isolate)) { |
+ return MaybeLocal<Value>(); |
+ } |
+ InternalEscapableScope handle_scope(isolate); |
+ CallDepthScope call_depth_scope(isolate, context); |
+ ENTER_V8(isolate); |
+ bool has_pending_exception = false; |
+ i::Handle<i::Object> data_obj; |
+ if (data.IsEmpty()) { |
+ data_obj = isolate->factory()->undefined_value(); |
+ } else { |
+ data_obj = Utils::OpenHandle(*data); |
+ } |
+ Local<Value> result; |
+ has_pending_exception = !ToLocal<Value>( |
+ isolate->debug()->Call(Utils::OpenHandle(*fun), data_obj), &result); |
+ if (has_pending_exception) { |
+ call_depth_scope.Escape(); |
+ return result; |
+ } |
+ return handle_scope.Escape(result); |
+} |
+ |
+void DebugInterface::SetLiveEditEnabled(Isolate* isolate, bool enable) { |
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ internal_isolate->debug()->set_live_edit_enabled(enable); |
+} |
+ |
+void DebugInterface::DebugBreak(Isolate* isolate) { |
+ reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak(); |
+} |
+ |
+void DebugInterface::CancelDebugBreak(Isolate* isolate) { |
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
+ internal_isolate->stack_guard()->ClearDebugBreak(); |
+} |
+ |
+MaybeLocal<Array> DebugInterface::GetInternalProperties(Isolate* v8_isolate, |
+ Local<Value> value) { |
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); |
+ ENTER_V8(isolate); |
+ i::Handle<i::Object> val = Utils::OpenHandle(*value); |
+ i::Handle<i::JSArray> result; |
+ if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) |
+ return MaybeLocal<Array>(); |
+ return Utils::ToLocal(result); |
+} |
+ |
+} // namespace v8 |