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

Side by Side Diff: sky/engine/v8_inspector/ScriptDebugServer.cpp

Issue 922053002: Remove unused V8 integration code in Sky (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « sky/engine/v8_inspector/ScriptDebugServer.h ('k') | sky/engine/v8_inspector/ScriptRegexp.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2010-2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "sky/engine/config.h"
32 #include "sky/engine/v8_inspector/ScriptDebugServer.h"
33
34 #include "gen/sky/bindings/core/v8/V8JavaScriptCallFrame.h"
35 #include "sky/engine/bindings/core/v8/ScopedPersistent.h"
36 #include "sky/engine/bindings/core/v8/ScriptCallStackFactory.h"
37 #include "sky/engine/bindings/core/v8/ScriptController.h"
38 #include "sky/engine/bindings/core/v8/ScriptSourceCode.h"
39 #include "sky/engine/bindings/core/v8/ScriptValue.h"
40 #include "sky/engine/bindings/core/v8/V8Binding.h"
41 #include "sky/engine/bindings/core/v8/V8ScriptRunner.h"
42 #include "sky/engine/core/inspector/JavaScriptCallFrame.h"
43 #include "sky/engine/platform/JSONValues.h"
44 #include "sky/engine/v8_inspector/read_from_source_tree.h"
45 #include "sky/engine/v8_inspector/ScriptDebugListener.h"
46 #include "sky/engine/wtf/dtoa/utils.h"
47 #include "sky/engine/wtf/StdLibExtras.h"
48 #include "sky/engine/wtf/text/CString.h"
49 #include "sky/engine/wtf/Vector.h"
50
51 namespace blink {
52
53 namespace {
54
55 class ClientDataImpl : public v8::Debug::ClientData {
56 public:
57 ClientDataImpl(PassOwnPtr<ScriptDebugServer::Task> task) : m_task(task) { }
58 virtual ~ClientDataImpl() { }
59 ScriptDebugServer::Task* task() const { return m_task.get(); }
60 private:
61 OwnPtr<ScriptDebugServer::Task> m_task;
62 };
63
64 const char stepIntoV8MethodName[] = "stepIntoStatement";
65 const char stepOutV8MethodName[] = "stepOutOfFunction";
66 }
67
68 v8::Local<v8::Value> ScriptDebugServer::callDebuggerMethod(const char* functionN ame, int argc, v8::Handle<v8::Value> argv[])
69 {
70 v8::Handle<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate) ;
71 v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(debuggerSc ript->Get(v8AtomicString(m_isolate, functionName)));
72 ASSERT(m_isolate->InContext());
73 return V8ScriptRunner::callInternalFunction(function, debuggerScript, argc, argv, m_isolate);
74 }
75
76 ScriptDebugServer::ScriptDebugServer(v8::Isolate* isolate)
77 : m_pauseOnExceptionsState(DontPauseOnExceptions)
78 , m_breakpointsActivated(true)
79 , m_isolate(isolate)
80 , m_runningNestedMessageLoop(false)
81 {
82 }
83
84 ScriptDebugServer::~ScriptDebugServer()
85 {
86 }
87
88 String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBrea kpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool i nterstatementLocation)
89 {
90 v8::HandleScope scope(m_isolate);
91 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
92 v8::Context::Scope contextScope(debuggerContext);
93
94 v8::Local<v8::Object> info = v8::Object::New(m_isolate);
95 info->Set(v8AtomicString(m_isolate, "sourceID"), v8String(debuggerContext->G etIsolate(), sourceID));
96 info->Set(v8AtomicString(m_isolate, "lineNumber"), v8::Integer::New(debugger Context->GetIsolate(), scriptBreakpoint.lineNumber));
97 info->Set(v8AtomicString(m_isolate, "columnNumber"), v8::Integer::New(debugg erContext->GetIsolate(), scriptBreakpoint.columnNumber));
98 info->Set(v8AtomicString(m_isolate, "interstatementLocation"), v8Boolean(int erstatementLocation, debuggerContext->GetIsolate()));
99 info->Set(v8AtomicString(m_isolate, "condition"), v8String(debuggerContext-> GetIsolate(), scriptBreakpoint.condition));
100
101 v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Ca st(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "setBreak point")));
102 v8::Handle<v8::Value> breakpointId = v8::Debug::Call(setBreakpointFunction, info);
103 if (breakpointId.IsEmpty() || !breakpointId->IsString())
104 return "";
105 *actualLineNumber = info->Get(v8AtomicString(m_isolate, "lineNumber"))->Int3 2Value();
106 *actualColumnNumber = info->Get(v8AtomicString(m_isolate, "columnNumber"))-> Int32Value();
107 return toCoreString(breakpointId.As<v8::String>());
108 }
109
110 void ScriptDebugServer::removeBreakpoint(const String& breakpointId)
111 {
112 v8::HandleScope scope(m_isolate);
113 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
114 v8::Context::Scope contextScope(debuggerContext);
115
116 v8::Local<v8::Object> info = v8::Object::New(m_isolate);
117 info->Set(v8AtomicString(m_isolate, "breakpointId"), v8String(debuggerContex t->GetIsolate(), breakpointId));
118
119 v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>: :Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "remov eBreakpoint")));
120 v8::Debug::Call(removeBreakpointFunction, info);
121 }
122
123 void ScriptDebugServer::clearBreakpoints()
124 {
125 ensureDebuggerScriptCompiled();
126 v8::HandleScope scope(m_isolate);
127 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
128 v8::Context::Scope contextScope(debuggerContext);
129
130 v8::Handle<v8::Function> clearBreakpoints = v8::Local<v8::Function>::Cast(m_ debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "clearBreakpoi nts")));
131 v8::Debug::Call(clearBreakpoints);
132 }
133
134 void ScriptDebugServer::setBreakpointsActivated(bool activated)
135 {
136 ensureDebuggerScriptCompiled();
137 v8::HandleScope scope(m_isolate);
138 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
139 v8::Context::Scope contextScope(debuggerContext);
140
141 v8::Local<v8::Object> info = v8::Object::New(m_isolate);
142 info->Set(v8AtomicString(m_isolate, "enabled"), v8::Boolean::New(m_isolate, activated));
143 v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>:: Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "setBre akpointsActivated")));
144 v8::Debug::Call(setBreakpointsActivated, info);
145
146 m_breakpointsActivated = activated;
147 }
148
149 ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsSt ate()
150 {
151 ensureDebuggerScriptCompiled();
152 v8::HandleScope scope(m_isolate);
153 v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
154
155 v8::Handle<v8::Value> argv[] = { v8Undefined() };
156 v8::Handle<v8::Value> result = callDebuggerMethod("pauseOnExceptionsState", 0, argv);
157 return static_cast<ScriptDebugServer::PauseOnExceptionsState>(result->Int32V alue());
158 }
159
160 void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn ExceptionsState)
161 {
162 ensureDebuggerScriptCompiled();
163 v8::HandleScope scope(m_isolate);
164 v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
165
166 v8::Handle<v8::Value> argv[] = { v8::Int32::New(m_isolate, pauseOnExceptions State) };
167 callDebuggerMethod("setPauseOnExceptionsState", 1, argv);
168 }
169
170 void ScriptDebugServer::setPauseOnNextStatement(bool pause)
171 {
172 ASSERT(!isPaused());
173 if (pause)
174 v8::Debug::DebugBreak(m_isolate);
175 else
176 v8::Debug::CancelDebugBreak(m_isolate);
177 }
178
179 bool ScriptDebugServer::pausingOnNextStatement()
180 {
181 return v8::Debug::CheckDebugBreak(m_isolate);
182 }
183
184 bool ScriptDebugServer::canBreakProgram()
185 {
186 if (!m_breakpointsActivated)
187 return false;
188 return m_isolate->InContext();
189 }
190
191 void ScriptDebugServer::breakProgram()
192 {
193 if (!canBreakProgram())
194 return;
195
196 v8::HandleScope scope(m_isolate);
197 if (m_breakProgramCallbackTemplate.isEmpty()) {
198 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(m_iso late);
199 templ->SetCallHandler(&ScriptDebugServer::breakProgramCallback, v8::Exte rnal::New(m_isolate, this));
200 m_breakProgramCallbackTemplate.set(m_isolate, templ);
201 }
202
203 v8::Handle<v8::Function> breakProgramFunction = m_breakProgramCallbackTempla te.newLocal(m_isolate)->GetFunction();
204 v8::Debug::Call(breakProgramFunction);
205 }
206
207 void ScriptDebugServer::continueProgram()
208 {
209 if (isPaused())
210 quitMessageLoopOnPause();
211 m_pausedScriptState.clear();
212 m_executionState.Clear();
213 }
214
215 void ScriptDebugServer::stepIntoStatement()
216 {
217 ASSERT(isPaused());
218 ASSERT(!m_executionState.IsEmpty());
219 v8::HandleScope handleScope(m_isolate);
220 v8::Handle<v8::Value> argv[] = { m_executionState };
221 callDebuggerMethod(stepIntoV8MethodName, 1, argv);
222 continueProgram();
223 }
224
225 void ScriptDebugServer::stepOverStatement()
226 {
227 ASSERT(isPaused());
228 ASSERT(!m_executionState.IsEmpty());
229 v8::HandleScope handleScope(m_isolate);
230 v8::Handle<v8::Value> argv[] = { m_executionState };
231 callDebuggerMethod("stepOverStatement", 1, argv);
232 continueProgram();
233 }
234
235 void ScriptDebugServer::stepOutOfFunction()
236 {
237 ASSERT(isPaused());
238 ASSERT(!m_executionState.IsEmpty());
239 v8::HandleScope handleScope(m_isolate);
240 v8::Handle<v8::Value> argv[] = { m_executionState };
241 callDebuggerMethod(stepOutV8MethodName, 1, argv);
242 continueProgram();
243 }
244
245 bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne wContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSo urceError>& errorData, ScriptValue* newCallFrames, RefPtr<JSONObject>* result)
246 {
247 class EnableLiveEditScope {
248 public:
249 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { v8::Debug::SetLiveEditEnabled(m_isolate, true); }
250 ~EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(m_isolate, false) ; }
251 private:
252 v8::Isolate* m_isolate;
253 };
254
255 ensureDebuggerScriptCompiled();
256 v8::HandleScope scope(m_isolate);
257
258 OwnPtr<v8::Context::Scope> contextScope;
259 v8::Handle<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
260 if (!isPaused())
261 contextScope = adoptPtr(new v8::Context::Scope(debuggerContext));
262
263 v8::Handle<v8::Value> argv[] = { v8String(m_isolate, sourceID), v8String(m_i solate, newContent), v8Boolean(preview, m_isolate) };
264
265 v8::Local<v8::Value> v8result;
266 {
267 EnableLiveEditScope enableLiveEditScope(m_isolate);
268 v8::TryCatch tryCatch;
269 tryCatch.SetVerbose(false);
270 v8result = callDebuggerMethod("liveEditScriptSource", 3, argv);
271 if (tryCatch.HasCaught()) {
272 v8::Local<v8::Message> message = tryCatch.Message();
273 if (!message.IsEmpty())
274 *error = toCoreStringWithUndefinedOrNullCheck(message->Get());
275 else
276 *error = "Unknown error.";
277 return false;
278 }
279 }
280 ASSERT(!v8result.IsEmpty());
281 v8::Local<v8::Object> resultTuple = v8result->ToObject();
282 int code = static_cast<int>(resultTuple->Get(0)->ToInteger()->Value());
283 switch (code) {
284 case 0:
285 {
286 v8::Local<v8::Value> normalResult = resultTuple->Get(1);
287 RefPtr<JSONValue> jsonResult = v8ToJSONValue(m_isolate, normalResult , JSONValue::maxDepth);
288 if (jsonResult)
289 *result = jsonResult->asObject();
290 // Call stack may have changed after if the edited function was on t he stack.
291 if (!preview && isPaused())
292 *newCallFrames = currentCallFrames();
293 return true;
294 }
295 // Compile error.
296 case 1:
297 {
298 RefPtr<TypeBuilder::Debugger::SetScriptSourceError::CompileError> co mpileError =
299 TypeBuilder::Debugger::SetScriptSourceError::CompileError::creat e()
300 .setMessage(toCoreStringWithUndefinedOrNullCheck(resultTuple ->Get(2)))
301 .setLineNumber(resultTuple->Get(3)->ToInteger()->Value())
302 .setColumnNumber(resultTuple->Get(4)->ToInteger()->Value());
303
304 *error = toCoreStringWithUndefinedOrNullCheck(resultTuple->Get(1));
305 errorData = TypeBuilder::Debugger::SetScriptSourceError::create();
306 errorData->setCompileError(compileError);
307 return false;
308 }
309 }
310 *error = "Unknown error.";
311 return false;
312 }
313
314 int ScriptDebugServer::frameCount()
315 {
316 ASSERT(isPaused());
317 ASSERT(!m_executionState.IsEmpty());
318 v8::Handle<v8::Value> argv[] = { m_executionState };
319 v8::Handle<v8::Value> result = callDebuggerMethod("frameCount", WTF_ARRAY_LE NGTH(argv), argv);
320 if (result->IsInt32())
321 return result->Int32Value();
322 return 0;
323 }
324
325 PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::toJavaScriptCallFrameUnsafe(c onst ScriptValue& value)
326 {
327 if (value.isEmpty())
328 return nullptr;
329 ASSERT(value.isObject());
330 return V8JavaScriptCallFrame::toNative(v8::Handle<v8::Object>::Cast(value.v8 ValueUnsafe()));
331 }
332
333 PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::wrapCallFrames(int maximumLim it, ScopeInfoDetails scopeDetails)
334 {
335 const int scopeBits = 2;
336 COMPILE_ASSERT(NoScopes < (1 << scopeBits), not_enough_bits_to_encode_ScopeI nfoDetails);
337
338 ASSERT(maximumLimit >= 0);
339 int data = (maximumLimit << scopeBits) | scopeDetails;
340 v8::Handle<v8::Value> currentCallFrameV8;
341 if (m_executionState.IsEmpty()) {
342 v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Functi on>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "c urrentCallFrame")));
343 currentCallFrameV8 = v8::Debug::Call(currentCallFrameFunction, v8::Integ er::New(m_isolate, data));
344 } else {
345 v8::Handle<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_is olate, data) };
346 currentCallFrameV8 = callDebuggerMethod("currentCallFrame", WTF_ARRAY_LE NGTH(argv), argv);
347 }
348 ASSERT(!currentCallFrameV8.IsEmpty());
349 if (!currentCallFrameV8->IsObject())
350 return nullptr;
351 return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle< v8::Object>::Cast(currentCallFrameV8));
352 }
353
354 ScriptValue ScriptDebugServer::currentCallFramesInner(ScopeInfoDetails scopeDeta ils)
355 {
356 if (!m_isolate->InContext())
357 return ScriptValue();
358 v8::HandleScope handleScope(m_isolate);
359
360 // Filter out stack traces entirely consisting of V8's internal scripts.
361 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(m_i solate, 1);
362 if (!stackTrace->GetFrameCount())
363 return ScriptValue();
364
365 RefPtr<JavaScriptCallFrame> currentCallFrame = wrapCallFrames(0, scopeDetail s);
366 if (!currentCallFrame)
367 return ScriptValue();
368
369 ScriptState* scriptState = m_pausedScriptState ? m_pausedScriptState.get() : ScriptState::current(m_isolate);
370 ScriptState::Scope scope(scriptState);
371 return ScriptValue(scriptState, toV8(currentCallFrame.release(), scriptState ->context()->Global(), m_isolate));
372 }
373
374 ScriptValue ScriptDebugServer::currentCallFrames()
375 {
376 return currentCallFramesInner(AllScopes);
377 }
378
379 ScriptValue ScriptDebugServer::currentCallFramesForAsyncStack()
380 {
381 return currentCallFramesInner(FastAsyncScopes);
382 }
383
384 PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::callFrameNoScopes(int index)
385 {
386 v8::Handle<v8::Value> currentCallFrameV8;
387 if (m_executionState.IsEmpty()) {
388 v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Functi on>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "c urrentCallFrameByIndex")));
389 currentCallFrameV8 = v8::Debug::Call(currentCallFrameFunction, v8::Integ er::New(m_isolate, index));
390 } else {
391 v8::Handle<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_is olate, index) };
392 currentCallFrameV8 = callDebuggerMethod("currentCallFrameByIndex", WTF_A RRAY_LENGTH(argv), argv);
393 }
394 ASSERT(!currentCallFrameV8.IsEmpty());
395 if (!currentCallFrameV8->IsObject())
396 return nullptr;
397 return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle< v8::Object>::Cast(currentCallFrameV8));
398 }
399
400 void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task, v8::Isolate* isol ate)
401 {
402 v8::Debug::DebugBreakForCommand(isolate, new ClientDataImpl(task));
403 }
404
405 void ScriptDebugServer::runPendingTasks()
406 {
407 v8::Debug::ProcessDebugMessages();
408 }
409
410 static ScriptDebugServer* toScriptDebugServer(v8::Handle<v8::Value> data)
411 {
412 void* p = v8::Handle<v8::External>::Cast(data)->Value();
413 return static_cast<ScriptDebugServer*>(p);
414 }
415
416 void ScriptDebugServer::breakProgramCallback(const v8::FunctionCallbackInfo<v8:: Value>& info)
417 {
418 ASSERT(2 == info.Length());
419 ScriptDebugServer* thisPtr = toScriptDebugServer(info.Data());
420 ScriptState* pausedScriptState = ScriptState::current(thisPtr->m_isolate);
421 v8::Handle<v8::Value> exception;
422 v8::Handle<v8::Array> hitBreakpoints;
423 thisPtr->handleProgramBreak(pausedScriptState, v8::Handle<v8::Object>::Cast( info[0]), exception, hitBreakpoints);
424 }
425
426 void ScriptDebugServer::handleProgramBreak(ScriptState* pausedScriptState, v8::H andle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8 ::Array> hitBreakpointNumbers)
427 {
428 // Don't allow nested breaks.
429 if (isPaused())
430 return;
431
432 ScriptDebugListener* listener = getDebugListenerForContext(pausedScriptState ->context());
433 if (!listener)
434 return;
435
436 Vector<String> breakpointIds;
437 if (!hitBreakpointNumbers.IsEmpty()) {
438 breakpointIds.resize(hitBreakpointNumbers->Length());
439 for (size_t i = 0; i < hitBreakpointNumbers->Length(); i++) {
440 v8::Handle<v8::Value> hitBreakpointNumber = hitBreakpointNumbers->Ge t(i);
441 ASSERT(!hitBreakpointNumber.IsEmpty() && hitBreakpointNumber->IsInt3 2());
442 breakpointIds[i] = String::number(hitBreakpointNumber->Int32Value()) ;
443 }
444 }
445
446 m_pausedScriptState = pausedScriptState;
447 m_executionState = executionState;
448 ScriptDebugListener::SkipPauseRequest result = listener->didPause(pausedScri ptState, currentCallFrames(), ScriptValue(pausedScriptState, exception), breakpo intIds);
449 if (result == ScriptDebugListener::NoSkip) {
450 m_runningNestedMessageLoop = true;
451 runMessageLoopOnPause(pausedScriptState->context());
452 m_runningNestedMessageLoop = false;
453 }
454 m_pausedScriptState.clear();
455 m_executionState.Clear();
456
457 if (result == ScriptDebugListener::StepInto) {
458 v8::Handle<v8::Value> argv[] = { executionState };
459 callDebuggerMethod(stepIntoV8MethodName, 1, argv);
460 } else if (result == ScriptDebugListener::StepOut) {
461 v8::Handle<v8::Value> argv[] = { executionState };
462 callDebuggerMethod(stepOutV8MethodName, 1, argv);
463 }
464 }
465
466 void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& even tDetails)
467 {
468 ScriptDebugServer* thisPtr = toScriptDebugServer(eventDetails.GetCallbackDat a());
469 thisPtr->handleV8DebugEvent(eventDetails);
470 }
471
472 static v8::Handle<v8::Value> callInternalGetterFunction(v8::Handle<v8::Object> o bject, const char* functionName, v8::Isolate* isolate)
473 {
474 v8::Handle<v8::Value> getterValue = object->Get(v8AtomicString(isolate, func tionName));
475 ASSERT(!getterValue.IsEmpty() && getterValue->IsFunction());
476 return V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(g etterValue), object, 0, 0, isolate);
477 }
478
479 void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD etails)
480 {
481 v8::DebugEvent event = eventDetails.GetEvent();
482
483 if (event == v8::BreakForCommand) {
484 ClientDataImpl* data = static_cast<ClientDataImpl*>(eventDetails.GetClie ntData());
485 data->task()->run();
486 return;
487 }
488
489 if (event != v8::AsyncTaskEvent && event != v8::Break && event != v8::Except ion && event != v8::AfterCompile && event != v8::BeforeCompile && event != v8::C ompileError && event != v8::PromiseEvent)
490 return;
491
492 v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext();
493 ASSERT(!eventContext.IsEmpty());
494
495 ScriptDebugListener* listener = getDebugListenerForContext(eventContext);
496 if (listener) {
497 v8::HandleScope scope(m_isolate);
498 v8::Handle<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isol ate);
499 if (event == v8::AfterCompile || event == v8::CompileError) {
500 v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
501 v8::Handle<v8::Function> getAfterCompileScript = v8::Local<v8::Funct ion>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getAfterCompileScript" )));
502 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
503 v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(g etAfterCompileScript, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate);
504 ASSERT(value->IsObject());
505 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
506 dispatchDidParseSource(listener, object, event != v8::AfterCompile ? CompileError : CompileSuccess);
507 } else if (event == v8::Exception) {
508 v8::Handle<v8::Object> eventData = eventDetails.GetEventData();
509 v8::Handle<v8::Value> exception = callInternalGetterFunction(eventDa ta, "exception", m_isolate);
510 handleProgramBreak(ScriptState::from(eventContext), eventDetails.Get ExecutionState(), exception, v8::Handle<v8::Array>());
511 } else if (event == v8::Break) {
512 v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8 ::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getBreakpointNu mbers")));
513 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
514 v8::Handle<v8::Value> hitBreakpoints = V8ScriptRunner::callInternalF unction(getBreakpointNumbersFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), ar gv, m_isolate);
515 ASSERT(hitBreakpoints->IsArray());
516 handleProgramBreak(ScriptState::from(eventContext), eventDetails.Get ExecutionState(), v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>());
517 } else if (event == v8::AsyncTaskEvent) {
518 handleV8AsyncTaskEvent(listener, ScriptState::from(eventContext), ev entDetails.GetExecutionState(), eventDetails.GetEventData());
519 } else if (event == v8::PromiseEvent) {
520 handleV8PromiseEvent(listener, ScriptState::from(eventContext), even tDetails.GetExecutionState(), eventDetails.GetEventData());
521 }
522 }
523 }
524
525 void ScriptDebugServer::handleV8AsyncTaskEvent(ScriptDebugListener* listener, Sc riptState* pausedScriptState, v8::Handle<v8::Object> executionState, v8::Handle< v8::Object> eventData)
526 {
527 String type = toCoreStringWithUndefinedOrNullCheck(callInternalGetterFunctio n(eventData, "type", m_isolate));
528 String name = toCoreStringWithUndefinedOrNullCheck(callInternalGetterFunctio n(eventData, "name", m_isolate));
529 int id = callInternalGetterFunction(eventData, "id", m_isolate)->ToInteger() ->Value();
530
531 m_pausedScriptState = pausedScriptState;
532 m_executionState = executionState;
533 listener->didReceiveV8AsyncTaskEvent(pausedScriptState->executionContext(), type, name, id);
534 m_pausedScriptState.clear();
535 m_executionState.Clear();
536 }
537
538 void ScriptDebugServer::handleV8PromiseEvent(ScriptDebugListener* listener, Scri ptState* pausedScriptState, v8::Handle<v8::Object> executionState, v8::Handle<v8 ::Object> eventData)
539 {
540 v8::Handle<v8::Value> argv[] = { eventData };
541 v8::Local<v8::Object> promiseDetails = callDebuggerMethod("getPromiseDetails ", 1, argv)->ToObject();
542 v8::Handle<v8::Object> promise = promiseDetails->Get(v8AtomicString(m_isolat e, "promise"))->ToObject();
543 int status = promiseDetails->Get(v8AtomicString(m_isolate, "status"))->ToInt eger()->Value();
544 v8::Handle<v8::Value> parentPromise = promiseDetails->Get(v8AtomicString(m_i solate, "parentPromise"));
545
546 m_pausedScriptState = pausedScriptState;
547 m_executionState = executionState;
548 listener->didReceiveV8PromiseEvent(pausedScriptState, promise, parentPromise , status);
549 m_pausedScriptState.clear();
550 m_executionState.Clear();
551 }
552
553 void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8 ::Handle<v8::Object> object, CompileResult compileResult)
554 {
555 v8::Handle<v8::Value> id = object->Get(v8AtomicString(m_isolate, "id"));
556 ASSERT(!id.IsEmpty() && id->IsInt32());
557 String sourceID = String::number(id->Int32Value());
558
559 ScriptDebugListener::Script script;
560 script.url = toCoreStringWithUndefinedOrNullCheck(object->Get(v8AtomicString (m_isolate, "name")));
561 script.sourceURL = toCoreStringWithUndefinedOrNullCheck(object->Get(v8Atomic String(m_isolate, "sourceURL")));
562 script.sourceMappingURL = toCoreStringWithUndefinedOrNullCheck(object->Get(v 8AtomicString(m_isolate, "sourceMappingURL")));
563 script.source = toCoreStringWithUndefinedOrNullCheck(object->Get(v8AtomicStr ing(m_isolate, "source")));
564 script.startLine = object->Get(v8AtomicString(m_isolate, "startLine"))->ToIn teger()->Value();
565 script.startColumn = object->Get(v8AtomicString(m_isolate, "startColumn"))-> ToInteger()->Value();
566 script.endLine = object->Get(v8AtomicString(m_isolate, "endLine"))->ToIntege r()->Value();
567 script.endColumn = object->Get(v8AtomicString(m_isolate, "endColumn"))->ToIn teger()->Value();
568 script.isContentScript = object->Get(v8AtomicString(m_isolate, "isContentScr ipt"))->ToBoolean()->Value();
569
570 listener->didParseSource(sourceID, script, compileResult);
571 }
572
573 void ScriptDebugServer::ensureDebuggerScriptCompiled()
574 {
575 if (!m_debuggerScript.isEmpty())
576 return;
577
578 v8::HandleScope scope(m_isolate);
579 v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
580
581 std::string buffer;
582 inspector::ReadFileFromSourceTree("DebuggerScript.js", &buffer);
583 v8::Handle<v8::String> source = v8String(m_isolate, String::fromUTF8(buffer) );
584 v8::Local<v8::Value> value = V8ScriptRunner::compileAndRunInternalScript(sou rce, m_isolate);
585 ASSERT(!value.IsEmpty());
586 ASSERT(value->IsObject());
587 m_debuggerScript.set(m_isolate, v8::Handle<v8::Object>::Cast(value));
588 }
589
590 void ScriptDebugServer::discardDebuggerScript()
591 {
592 ASSERT(!m_debuggerScript.isEmpty());
593 m_debuggerScript.clear();
594 }
595
596 v8::Local<v8::Value> ScriptDebugServer::functionScopes(v8::Handle<v8::Function> function)
597 {
598 ensureDebuggerScriptCompiled();
599
600 v8::Handle<v8::Value> argv[] = { function };
601 return callDebuggerMethod("getFunctionScopes", 1, argv);
602 }
603
604 v8::Local<v8::Value> ScriptDebugServer::collectionEntries(v8::Handle<v8::Object> & object)
605 {
606 ensureDebuggerScriptCompiled();
607
608 v8::Handle<v8::Value> argv[] = { object };
609 return callDebuggerMethod("getCollectionEntries", 1, argv);
610 }
611
612 v8::Local<v8::Value> ScriptDebugServer::getInternalProperties(v8::Handle<v8::Obj ect>& object)
613 {
614 if (m_debuggerScript.isEmpty())
615 return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate));
616
617 v8::Handle<v8::Value> argv[] = { object };
618 return callDebuggerMethod("getInternalProperties", 1, argv);
619 }
620
621 v8::Handle<v8::Value> ScriptDebugServer::setFunctionVariableValue(v8::Handle<v8: :Value> functionValue, int scopeNumber, const String& variableName, v8::Handle<v 8::Value> newValue)
622 {
623 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
624 if (m_debuggerScript.isEmpty())
625 return m_isolate->ThrowException(v8::String::NewFromUtf8(m_isolate, "Deb ugging is not enabled."));
626
627 v8::Handle<v8::Value> argv[] = {
628 functionValue,
629 v8::Handle<v8::Value>(v8::Integer::New(debuggerContext->GetIsolate(), sc opeNumber)),
630 v8String(debuggerContext->GetIsolate(), variableName),
631 newValue
632 };
633 return callDebuggerMethod("setFunctionVariableValue", 4, argv);
634 }
635
636 bool ScriptDebugServer::isPaused()
637 {
638 return m_pausedScriptState;
639 }
640
641 void ScriptDebugServer::compileScript(ScriptState* scriptState, const String& ex pression, const String& sourceURL, String* scriptId, String* exceptionDetailsTex t, int* lineNumber, int* columnNumber, RefPtr<ScriptCallStack>* stackTrace)
642 {
643 if (scriptState->contextIsEmpty())
644 return;
645 ScriptState::Scope scope(scriptState);
646
647 v8::Handle<v8::String> source = v8String(m_isolate, expression);
648 v8::TryCatch tryCatch;
649 v8::Local<v8::Script> script = V8ScriptRunner::compileScript(source, sourceU RL, TextPosition(), m_isolate);
650 if (tryCatch.HasCaught()) {
651 v8::Local<v8::Message> message = tryCatch.Message();
652 if (!message.IsEmpty()) {
653 *exceptionDetailsText = toCoreStringWithUndefinedOrNullCheck(message ->Get());
654 *lineNumber = message->GetLineNumber();
655 *columnNumber = message->GetStartColumn();
656 *stackTrace = createScriptCallStack(message->GetStackTrace(), messag e->GetStackTrace()->GetFrameCount(), m_isolate);
657 }
658 return;
659 }
660 if (script.IsEmpty())
661 return;
662
663 *scriptId = String::number(script->GetUnboundScript()->GetId());
664 m_compiledScripts.set(*scriptId, adoptPtr(new ScopedPersistent<v8::Script>(m _isolate, script)));
665 }
666
667 void ScriptDebugServer::clearCompiledScripts()
668 {
669 m_compiledScripts.clear();
670 }
671
672 void ScriptDebugServer::runScript(ScriptState* scriptState, const String& script Id, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lin eNumber, int* columnNumber, RefPtr<ScriptCallStack>* stackTrace)
673 {
674 if (!m_compiledScripts.contains(scriptId))
675 return;
676 v8::HandleScope handleScope(m_isolate);
677 ScopedPersistent<v8::Script>* scriptHandle = m_compiledScripts.get(scriptId) ;
678 v8::Local<v8::Script> script = scriptHandle->newLocal(m_isolate);
679 m_compiledScripts.remove(scriptId);
680 if (script.IsEmpty())
681 return;
682
683 if (scriptState->contextIsEmpty())
684 return;
685 ScriptState::Scope scope(scriptState);
686 v8::TryCatch tryCatch;
687 v8::Local<v8::Value> value = V8ScriptRunner::runCompiledScript(script, scrip tState->executionContext(), m_isolate);
688 *wasThrown = false;
689 if (tryCatch.HasCaught()) {
690 *wasThrown = true;
691 *result = ScriptValue(scriptState, tryCatch.Exception());
692 v8::Local<v8::Message> message = tryCatch.Message();
693 if (!message.IsEmpty()) {
694 *exceptionDetailsText = toCoreStringWithUndefinedOrNullCheck(message ->Get());
695 *lineNumber = message->GetLineNumber();
696 *columnNumber = message->GetStartColumn();
697 *stackTrace = createScriptCallStack(message->GetStackTrace(), messag e->GetStackTrace()->GetFrameCount(), m_isolate);
698 }
699 } else {
700 *result = ScriptValue(scriptState, value);
701 }
702 }
703
704 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/v8_inspector/ScriptDebugServer.h ('k') | sky/engine/v8_inspector/ScriptRegexp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698