OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/debug/debug-interface.h" | |
6 | |
7 #include "src/debug/debug.h" | |
8 #include "src/factory.h" | |
9 #include "src/isolate-inl.h" | |
10 #include "src/vm-state-inl.h" | |
11 | |
12 namespace v8 { | |
13 | |
14 namespace i = internal; | |
15 | |
16 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { | |
17 if (isolate->has_scheduled_exception()) { | |
18 return isolate->scheduled_exception() == | |
19 isolate->heap()->termination_exception(); | |
20 } | |
21 return false; | |
22 } | |
23 | |
24 #define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate)) | |
25 | |
26 namespace { | |
27 | |
28 class InternalEscapableScope : public v8::EscapableHandleScope { | |
29 public: | |
30 explicit inline InternalEscapableScope(i::Isolate* isolate) | |
31 : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {} | |
32 }; | |
33 | |
34 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.
| |
35 public: | |
36 explicit CallDepthScope(i::Isolate* isolate, Local<Context> context) | |
37 : isolate_(isolate), context_(context), escaped_(false) { | |
38 // TODO(dcarney): remove this when blink stops crashing. | |
39 DCHECK(!isolate_->external_caught_exception()); | |
40 isolate_->IncrementJsCallsFromApiCounter(); | |
41 isolate_->handle_scope_implementer()->IncrementCallDepth(); | |
42 if (!context.IsEmpty()) { | |
43 i::Handle<i::Context> env = Utils::OpenHandle(*context); | |
44 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); | |
45 if (isolate->context() != nullptr && | |
46 isolate->context()->native_context() == env->native_context() && | |
47 impl->LastEnteredContextWas(env)) { | |
48 context_ = Local<Context>(); | |
49 } else { | |
50 context_->Enter(); | |
51 } | |
52 } | |
53 } | |
54 ~CallDepthScope() { | |
55 if (!context_.IsEmpty()) context_->Exit(); | |
56 if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); | |
57 } | |
58 | |
59 void Escape() { | |
60 DCHECK(!escaped_); | |
61 escaped_ = true; | |
62 auto handle_scope_implementer = isolate_->handle_scope_implementer(); | |
63 handle_scope_implementer->DecrementCallDepth(); | |
64 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); | |
65 isolate_->OptionalRescheduleException(call_depth_is_zero); | |
66 } | |
67 | |
68 private: | |
69 i::Isolate* const isolate_; | |
70 Local<Context> context_; | |
71 bool escaped_; | |
72 }; | |
73 | |
74 } // namespace | |
75 | |
76 bool DebugInterface::SetDebugEventListener(Isolate* isolate, EventCallback that, | |
77 Local<Value> data) { | |
78 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
79 ENTER_V8(i_isolate); | |
80 i::HandleScope scope(i_isolate); | |
81 i::Handle<i::Object> foreign = i_isolate->factory()->undefined_value(); | |
82 if (that != NULL) { | |
83 foreign = i_isolate->factory()->NewForeign(FUNCTION_ADDR(that)); | |
84 } | |
85 i_isolate->debug()->SetEventListener(foreign, Utils::OpenHandle(*data, true)); | |
86 return true; | |
87 } | |
88 | |
89 Local<Context> DebugInterface::GetDebugContext(Isolate* isolate) { | |
90 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
91 ENTER_V8(i_isolate); | |
92 return Utils::ToLocal(i_isolate->debug()->GetDebugContext()); | |
93 } | |
94 | |
95 MaybeLocal<Value> DebugInterface::Call(Local<Context> context, | |
96 v8::Local<v8::Function> fun, | |
97 v8::Local<v8::Value> data) { | |
98 auto isolate = context.IsEmpty() | |
99 ? i::Isolate::Current() | |
100 : reinterpret_cast<i::Isolate*>(context->GetIsolate()); | |
101 if (IsExecutionTerminatingCheck(isolate)) { | |
102 return MaybeLocal<Value>(); | |
103 } | |
104 InternalEscapableScope handle_scope(isolate); | |
105 CallDepthScope call_depth_scope(isolate, context); | |
106 ENTER_V8(isolate); | |
107 bool has_pending_exception = false; | |
108 i::Handle<i::Object> data_obj; | |
109 if (data.IsEmpty()) { | |
110 data_obj = isolate->factory()->undefined_value(); | |
111 } else { | |
112 data_obj = Utils::OpenHandle(*data); | |
113 } | |
114 Local<Value> result; | |
115 has_pending_exception = !ToLocal<Value>( | |
116 isolate->debug()->Call(Utils::OpenHandle(*fun), data_obj), &result); | |
117 if (has_pending_exception) { | |
118 call_depth_scope.Escape(); | |
119 return result; | |
120 } | |
121 return handle_scope.Escape(result); | |
122 } | |
123 | |
124 void DebugInterface::SetLiveEditEnabled(Isolate* isolate, bool enable) { | |
125 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
126 internal_isolate->debug()->set_live_edit_enabled(enable); | |
127 } | |
128 | |
129 void DebugInterface::DebugBreak(Isolate* isolate) { | |
130 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak(); | |
131 } | |
132 | |
133 void DebugInterface::CancelDebugBreak(Isolate* isolate) { | |
134 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
135 internal_isolate->stack_guard()->ClearDebugBreak(); | |
136 } | |
137 | |
138 MaybeLocal<Array> DebugInterface::GetInternalProperties(Isolate* v8_isolate, | |
139 Local<Value> value) { | |
140 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); | |
141 ENTER_V8(isolate); | |
142 i::Handle<i::Object> val = Utils::OpenHandle(*value); | |
143 i::Handle<i::JSArray> result; | |
144 if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) | |
145 return MaybeLocal<Array>(); | |
146 return Utils::ToLocal(result); | |
147 } | |
148 | |
149 } // namespace v8 | |
OLD | NEW |