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

Side by Side Diff: Source/bindings/dart/DartScriptDebugServer.cpp

Issue 300393002: Merge DevTools Refactor CL to Blink36 (Closed) Base URL: svn://svn.chromium.org/blink/branches/dart/1985
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2014 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 #include "config.h"
31 #include "bindings/dart/DartScriptDebugServer.h"
32
33 #include "bindings/dart/DartController.h"
34 #include "bindings/dart/DartHandleProxy.h"
35 #include "bindings/dart/DartUtilities.h"
36 #include "bindings/dart/V8Converter.h"
37 #include "bindings/v8/PageScriptDebugServer.h"
38 #include "bindings/v8/ScriptController.h"
39 #include "bindings/v8/ScriptState.h"
40 #include "bindings/v8/V8Binding.h"
41 #include "bindings/v8/V8WindowShell.h"
42 #include "core/dom/Document.h"
43 #include "core/frame/DOMWindow.h"
44 #include "core/inspector/InspectorController.h"
45 #include "core/inspector/InspectorDebuggerAgent.h"
46 #include "core/inspector/InspectorInstrumentation.h"
47 #include "core/inspector/InstrumentingAgents.h"
48 #include "core/inspector/JSONParser.h"
49 #include "core/inspector/ScriptDebugListener.h"
50 #include "core/page/Page.h"
51 #include "platform/JSONValues.h"
52 #include "platform/Logging.h"
53 #include "wtf/HashMap.h"
54 #include "wtf/Vector.h"
55
56 namespace WebCore {
57
58 static Dart_ExceptionPauseInfo calculatePauseInfo(ScriptDebugServer::PauseOnExce ptionsState pauseOnExceptionState)
59 {
60 switch (pauseOnExceptionState) {
61 case ScriptDebugServer::DontPauseOnExceptions:
62 return kNoPauseOnExceptions;
63 case ScriptDebugServer::PauseOnAllExceptions:
64 return kPauseOnAllExceptions;
65 case ScriptDebugServer::PauseOnUncaughtExceptions:
66 return kPauseOnUnhandledExceptions;
67 }
68 return kNoPauseOnExceptions;
69 }
70
71 DartBreakpoint::DartBreakpoint(intptr_t breakpointId, Dart_Isolate isolate)
72 : m_breakpointId(breakpointId)
73 , m_isolate(isolate)
74 {
75 }
76
77 DartBreakpointInfo::DartBreakpointInfo(const String& scriptUrl, const ScriptBrea kpoint& scriptBreakpoint)
78 : m_scriptUrl(scriptUrl)
79 , m_scriptBreakpoint(scriptBreakpoint)
80 {
81 }
82
83 DartPageDebug::DartPageDebug(Page* page, size_t pageId)
84 : m_page(page)
85 , m_listener(0)
86 , m_pageId(pageId)
87 , m_nextBreakpointId(1)
88 , m_nextScriptId(1)
89 {
90 }
91
92 DartPageDebug::~DartPageDebug()
93 {
94 for (BreakpointMap::iterator it = m_breakpoints.begin(); it != m_breakpoints .end(); ++it)
95 delete it->value;
96 }
97
98 void DartPageDebug::registerIsolate(Dart_Isolate isolate)
99 {
100 m_isolateMap.add(isolate);
101 }
102
103 intptr_t DartPageDebug::setBreakpointHelper(DartBreakpointInfo* breakpointInfo, const String& breakpointIdString, Dart_Isolate isolate, Dart_Handle& exception)
104 {
105 Dart_Handle scriptURL = DartUtilities::convertSourceString(breakpointInfo->m _scriptUrl);
106 // FIXME: use scriptBreakpoint.columnNumber and ScriptBreakpoint.condition a s well.
107 Dart_Handle ret = Dart_SetBreakpoint(scriptURL, breakpointInfo->m_scriptBrea kpoint.lineNumber + 1);
108 if (Dart_IsError(ret)) {
109 exception = ret;
110 return 0;
111 }
112 ASSERT(Dart_IsInteger(ret));
113 intptr_t breakpointId = DartUtilities::dartToInt(ret, exception);
114 ASSERT(!exception);
115 if (exception) {
116 return 0;
117 }
118 m_breakpointIdMap.set(breakpointId, breakpointIdString);
119 breakpointInfo->m_breakpoints.append(DartBreakpoint(breakpointId, isolate));
120 return breakpointId;
121 }
122
123 String DartPageDebug::setBreakpoint(const String& sourceID, const ScriptBreakpoi nt& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool inter statementLocation)
124 {
125 String breakpointIdString = String::format("{\"dartBreakpoint\":%ld,\"page\" :%ld}", m_nextBreakpointId, m_pageId);
126
127 m_nextBreakpointId++;
128 if (!m_idToScriptUrlMap.contains(sourceID)) {
129 return "Unable to set breakpoint. Unknown sourceID";
130 }
131 Vector<Dart_Isolate> isolates;
132 m_isolateMap.copyValues(isolates);
133 for (Vector<Dart_Isolate>::iterator it = isolates.begin(); it != isolates.en d(); ++it) {
134 Dart_Isolate isolate = *it;
135 DartIsolateScope scope(isolate);
136 DartApiScope apiScope;
137 Dart_Handle exception = 0;
138
139 DartBreakpointInfo* breakpointInfo;
140 BreakpointMap::iterator breakpointIt = m_breakpoints.find(breakpointIdSt ring);
141 if (breakpointIt != m_breakpoints.end()) {
142 breakpointInfo = breakpointIt->value;
143 } else {
144 breakpointInfo = new DartBreakpointInfo(m_idToScriptUrlMap.get(sourc eID), scriptBreakpoint);
145 m_breakpoints.set(breakpointIdString, breakpointInfo);
146 }
147
148 intptr_t breakpointId = setBreakpointHelper(breakpointInfo, breakpointId String, isolate, exception);
149 if (exception) {
150 continue;
151 }
152 Dart_Handle breakpointLine = Dart_GetBreakpointLine(breakpointId);
153 *actualColumnNumber = 0;
154 if (!Dart_IsError(breakpointLine)) {
155 ASSERT(Dart_IsInteger(breakpointLine));
156 *actualLineNumber = DartUtilities::dartToInt(breakpointLine, excepti on) - 1;
157 ASSERT(!exception);
158 } else {
159 *actualLineNumber = 1;
160 }
161 }
162 return breakpointIdString;
163 }
164
165
166 void DartPageDebug::removeBreakpointHelper(DartBreakpointInfo* breakpointInfo)
167 {
168 Vector<DartBreakpoint>& breakpoints = breakpointInfo->m_breakpoints;
169 for (Vector<DartBreakpoint>::iterator it = breakpoints.begin(); it != breakp oints.end(); ++it) {
170 DartBreakpoint& breakpoint = *it;
171 DartIsolateScope scope(breakpoint.m_isolate);
172 DartApiScope apiScope;
173 // perhaps this isn't needed if the isolate will be removed soon anyway.
174 Dart_RemoveBreakpoint(breakpoint.m_breakpointId);
175 }
176 delete breakpointInfo;
177 }
178
179 void DartPageDebug::removeBreakpoint(const String& breakpointId)
180 {
181 if (m_breakpoints.contains(breakpointId)) {
182 removeBreakpointHelper(m_breakpoints.get(breakpointId));
183 m_breakpoints.remove(breakpointId);
184 }
185 }
186
187 void DartPageDebug::clearBreakpointsForIsolate(Dart_Isolate isolate)
188 {
189 // Warning: this code is O(num_isolates * num_breakpoints)
190 for (BreakpointMap::iterator i = m_breakpoints.begin(); i != m_breakpoints.e nd(); ++i) {
191 Vector<DartBreakpoint>& breakpoints = i->value->m_breakpoints;
192 for (size_t j = 0; j < breakpoints.size(); j++) {
193 DartBreakpoint& breakpoint = breakpoints[j];
194 if (breakpoint.m_isolate == isolate) {
195 // No need to actually call Dart_RemoveBreakpoint as the
196 // isolate is about to be shut down.
197 breakpoints.remove(j);
198 break;
199 }
200 }
201 }
202 }
203
204 void DartPageDebug::dispatchDidParseSource(intptr_t libraryId, Dart_Handle scrip tURL, Dart_Isolate isolate)
205 {
206 ASSERT(Dart_IsString(scriptURL));
207 ScriptDebugListener::Script script;
208 script.url = DartUtilities::toString(scriptURL);
209 String sourceID = getScriptId(script.url);
210 script.source = DartUtilities::toString(Dart_ScriptGetSource(libraryId, scri ptURL));
211 // FIXME: track script.sourceMappingURL for dart-dart source map support.
212
213 Dart_Handle info = Dart_ScriptGetTokenInfo(libraryId, scriptURL);
214 ASSERT(Dart_IsList(info));
215 intptr_t infoLength = 0;
216 Dart_Handle ALLOW_UNUSED result = Dart_ListLength(info, &infoLength);
217 ASSERT(!Dart_IsError(result));
218 Dart_Handle elem;
219 int lastLineNumber = 0;
220 int lastColumnNumber = 0;
221 intptr_t lastLineStart = 0;
222 for (intptr_t i = infoLength - 3; i >= 0; i--) {
223 elem = Dart_ListGetAt(info, i);
224 if (Dart_IsNull(elem)) {
225 lastLineStart = i;
226 break;
227 }
228 }
229 Dart_Handle exception = 0;
230 lastLineNumber = DartUtilities::toInteger(Dart_ListGetAt(info, lastLineStart + 1), exception);
231 ASSERT(!exception);
232 lastColumnNumber = DartUtilities::toInteger(Dart_ListGetAt(info, infoLength - 1), exception);
233 ASSERT(!exception);
234
235 script.startLine = 0;
236 script.startColumn = 0;
237 script.endLine = lastLineNumber + 1;
238 script.endColumn = !lastLineNumber ? lastColumnNumber : 0;
239 script.isContentScript = false;
240 script.language = String("dart");
241 script.libraryId = libraryId;
242 m_listener->didParseSource(sourceID, script);
243 }
244
245 String DartPageDebug::getScriptId(const String& url)
246 {
247 HashMap<String, String>::iterator it = m_scriptUrlToIdMap.find(url);
248 if (it == m_scriptUrlToIdMap.end()) {
249 String id = String::format("{\"dartScript\":%ld,\"page\":%ld}", m_nextSc riptId, m_pageId);
250 m_nextScriptId++;
251 m_scriptUrlToIdMap.set(url, id);
252 m_idToScriptUrlMap.set(id, url);
253 return id;
254 }
255 return it->value;
256 }
257
258 void DartPageDebug::clearBreakpoints()
259 {
260 for (BreakpointMap::iterator i = m_breakpoints.begin(); i != m_breakpoints.e nd(); ++i)
261 removeBreakpointHelper(i->value);
262 m_breakpoints.clear();
263 m_breakpointIdMap.clear();
264 }
265
266 void DartPageDebug::registerIsolateScripts(Dart_Isolate isolate)
267 {
268 Dart_Handle libraries = Dart_GetLibraryIds();
269 ASSERT(Dart_IsList(libraries));
270
271 intptr_t librariesLength = 0;
272 Dart_Handle ALLOW_UNUSED result = Dart_ListLength(libraries, &librariesLengt h);
273 ASSERT(!Dart_IsError(result));
274 for (intptr_t i = 0; i < librariesLength; ++i) {
275 Dart_Handle libraryIdHandle = Dart_ListGetAt(libraries, i);
276 ASSERT(!Dart_IsError(libraryIdHandle));
277 Dart_Handle exception = 0;
278 int64_t int64LibraryId = DartUtilities::toInteger(libraryIdHandle, excep tion);
279 ASSERT(!exception);
280 intptr_t libraryId = static_cast<intptr_t>(int64LibraryId);
281 ASSERT(libraryId == int64LibraryId);
282
283 Dart_Handle libraryURL = Dart_GetLibraryURL(libraryId);
284 ASSERT(Dart_IsString(libraryURL));
285
286 // FIXMEDART: we may be doing this more than once per library.
287 Dart_SetLibraryDebuggable(libraryId, true);
288
289 Dart_Handle scripts = Dart_GetScriptURLs(libraryURL);
290 ASSERT(Dart_IsList(scripts));
291
292 intptr_t scriptsLength = 0;
293 result = Dart_ListLength(scripts, &scriptsLength);
294 ASSERT(!Dart_IsError(result));
295 for (intptr_t j = 0; j < scriptsLength; ++j) {
296 Dart_Handle scriptURL = Dart_ListGetAt(scripts, j);
297 dispatchDidParseSource(libraryId, scriptURL, isolate);
298 }
299 }
300 }
301
302 Vector<Dart_Isolate> DartPageDebug::isolates()
303 {
304 Vector<Dart_Isolate> result;
305 m_isolateMap.copyValues(result);
306 return result;
307 }
308
309 void DartPageDebug::addListener(ScriptDebugListener* listener)
310 {
311 ASSERT(!m_listener);
312 m_listener = listener;
313
314 Vector<Dart_Isolate> iter = isolates();
315 for (Vector<Dart_Isolate>::iterator i = iter.begin(); i != iter.end(); ++i) {
316 Dart_Isolate isolate = *i;
317 DartIsolateScope scope(isolate);
318 DartApiScope apiScope;
319 isolateLoaded();
320 }
321 }
322
323 void DartPageDebug::removeListener()
324 {
325 m_listener = 0;
326 Vector<Dart_Isolate> iter = isolates();
327 for (Vector<Dart_Isolate>::iterator i = iter.begin(); i != iter.end(); ++i) {
328 Dart_Isolate isolate = *i;
329 DartIsolateScope scope(isolate);
330 DartApiScope apiScope;
331 Dart_SetPausedEventHandler(0);
332 Dart_SetExceptionThrownHandler(0);
333 Dart_SetIsolateEventHandler(0);
334 Dart_SetExceptionPauseInfo(kNoPauseOnExceptions);
335 }
336 // FIXME: Remove all breakpoints set by the agent. JavaScript does not
337 // remove the breakpoints either.
338 }
339
340 void DartPageDebug::unregisterIsolate(Dart_Isolate isolate)
341 {
342 clearBreakpointsForIsolate(isolate);
343 m_isolateMap.removeByValue(isolate);
344 }
345
346 void DartPageDebug::isolateLoaded()
347 {
348 if (!m_listener)
349 return;
350
351 Dart_Isolate isolate = Dart_CurrentIsolate();
352 Dart_SetPausedEventHandler(DartScriptDebugServer::pausedEventHandler);
353 Dart_SetExceptionThrownHandler(DartScriptDebugServer::exceptionHandler);
354 Dart_SetIsolateEventHandler(DartScriptDebugServer::isolateEventHandler);
355
356 Dart_ExceptionPauseInfo pauseInfo = calculatePauseInfo(
357 DartScriptDebugServer::shared().pauseOnExceptionState());
358 Dart_SetExceptionPauseInfo(pauseInfo);
359
360 ASSERT(isolate);
361 // FIXME: we can get rid of the V8Scope once DartScriptState and
rmacnak 2014/06/03 17:32:34 Can we remove this now?
Jacob 2014/06/03 20:23:13 sadly we can't yet. I updated the comment. with so
362 // ScriptState are refactored.
363 V8Scope v8Scope(DartDOMData::current(), v8::Debug::GetDebugContext());
364
365 LocalFrame* frame = DartUtilities::domWindowForCurrentIsolate()->frame();
366 DartController* controller = DartController::retrieve(frame);
367 Vector<ScriptState*> scriptStates;
368 controller->collectScriptStatesForIsolate(isolate, DartUtilities::currentV8C ontext(), scriptStates);
369 for (size_t i = 0; i< scriptStates.size(); i++)
370 InspectorInstrumentation::didCreateIsolatedContext(frame, scriptStates[i ], 0);
371
372 registerIsolateScripts(isolate);
373
374 for (BreakpointMap::iterator it = m_breakpoints.begin(); it != m_breakpoints .end(); ++it) {
375 Dart_Handle ALLOW_UNUSED exception = 0;
376 setBreakpointHelper(it->value, it->key, isolate, exception);
377 }
378 }
379
380 String DartPageDebug::lookupBreakpointId(intptr_t dartBreakpointId)
381 {
382 if (dartBreakpointId > 0) {
383 BreakpointIdMap::iterator it = m_breakpointIdMap.find(dartBreakpointId);
384 if (it != m_breakpointIdMap.end())
385 return it->value;
386 }
387 return "";
388 }
389
390 DartScriptDebugServer::DartScriptDebugServer()
391 : m_pauseOnExceptionState(DontPauseOnExceptions)
392 , m_breakpointsActivated(true)
393 , m_runningNestedMessageLoop(false)
394 , m_executionState(0)
395 , m_pausedPage(0)
396 , m_clientMessageLoop(0)
397 , m_nextPageId(1)
398 {
399 }
400
401 DartScriptDebugServer::~DartScriptDebugServer()
402 {
403 for (DebugDataMap::iterator it = m_pageIdToDebugDataMap.begin(); it != m_pag eIdToDebugDataMap.end(); ++it)
404 delete it->value;
405 }
406
407 DartPageDebug* DartScriptDebugServer::lookupPageDebugForId(const String& id)
408 {
409 RefPtr<JSONValue> json = parseJSON(id);
410 ASSERT(json && json->type() == JSONValue::TypeObject);
411 if (json && json->type() == JSONValue::TypeObject) {
412 size_t pageId;
413 bool success = json->asObject()->getNumber("page", &pageId);
414 ASSERT(success);
415 if (success)
416 return m_pageIdToDebugDataMap.get(pageId);
417 }
418 return 0;
419 }
420
421 DartPageDebug* DartScriptDebugServer::lookupPageDebug(Page* page)
422 {
423 ASSERT(page);
424 PageToIdMap::iterator it = m_pageToIdMap.find(page);
425 if (it != m_pageToIdMap.end())
426 return m_pageIdToDebugDataMap.get(it->value);
427
428 size_t pageId = m_nextPageId++;
429 m_pageToIdMap.set(page, pageId);
430 DartPageDebug* pageDebug = new DartPageDebug(page, pageId);
431 m_pageIdToDebugDataMap.set(pageId, pageDebug);
432 return pageDebug;
433 }
434
435 String DartScriptDebugServer::getScriptId(const String& url, Dart_Isolate isolat e)
436 {
437 // FIXME: this is a ugly. It would be better to get the domData for the
438 // specified isolate.
439 ASSERT(isolate == Dart_CurrentIsolate());
440 DartPageDebug* pageDebug = lookupPageDebug(DartUtilities::domWindowForCurren tIsolate()->document()->page());
441 ASSERT(pageDebug);
442 if (!pageDebug)
443 return "";
444 return pageDebug->getScriptId(url);
445 }
446
447 void DartScriptDebugServer::registerIsolate(Dart_Isolate isolate, Page* page)
448 {
449 DartIsolateScope scope(isolate);
450 DartApiScope apiScope;
451
452 DartPageDebug* pageDebug = lookupPageDebug(page);
453 pageDebug->registerIsolate(isolate);
454 }
455
456 // FIXMEDART: we aren't really handling adding and removing breakpoints
457 // as new isolates add/remove themselves.
458 String DartScriptDebugServer::setBreakpoint(const String& sourceID, const Script Breakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bo ol interstatementLocation)
459 {
460 DartPageDebug* pageDebug = lookupPageDebugForId(sourceID);
461 ASSERT(pageDebug);
462 if (!pageDebug)
463 return "";
464 return pageDebug->setBreakpoint(sourceID, scriptBreakpoint, actualLineNumber , actualColumnNumber, interstatementLocation);
465 }
466
467 void DartScriptDebugServer::removeBreakpoint(const String& breakpointId)
468 {
469 DartPageDebug* pageDebug = lookupPageDebugForId(breakpointId);
470 if (pageDebug) {
471 pageDebug->removeBreakpoint(breakpointId);
472 }
473 }
474
475 void DartScriptDebugServer::clearBreakpoints()
476 {
477 Vector<DartPageDebug*> list = pages();
478 for (Vector<DartPageDebug*>::iterator it = list.begin(); it != list.end(); + +it)
479 (*it)->clearBreakpoints();
480 }
481
482 void DartScriptDebugServer::setBreakpointsActivated(bool activated)
483 {
484 m_breakpointsActivated = activated;
485 }
486
487 ScriptDebugServer::PauseOnExceptionsState DartScriptDebugServer::pauseOnExceptio nsState()
488 {
489 return m_pauseOnExceptionState;
490 }
491
492 void DartScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pau seOnExceptionState)
493 {
494 if (m_pauseOnExceptionState == pauseOnExceptionState)
495 return;
496 m_pauseOnExceptionState = pauseOnExceptionState;
497
498 Dart_ExceptionPauseInfo pauseInfo = calculatePauseInfo(pauseOnExceptionState );
499
500 Vector<Dart_Isolate> iter = isolates();
501 for (Vector<Dart_Isolate>::iterator it = iter.begin(); it != iter.end(); ++i t) {
502 DartIsolateScope scope(*it);
503 DartApiScope apiScope;
504 Dart_SetExceptionPauseInfo(pauseInfo);
505 }
506 }
507
508 void DartScriptDebugServer::setPauseOnNextStatement(bool pause)
509 {
510 if (isPaused())
511 return;
512 if (pause) {
513 debugBreak();
514 } else {
515 cancelDebugBreak();
516 }
517 }
518
519 bool DartScriptDebugServer::canBreakProgram()
520 {
521 if (!m_breakpointsActivated)
522 return false;
523
524 // FIXME: what is the dart equivalent of
525 // v8::HandleScope scope(m_isolate);
526 // return !m_isolate->GetCurrentContext().IsEmpty();
527 // ?
528 return true;
529 }
530
531 void DartScriptDebugServer::breakProgram()
532 {
533 if (!canBreakProgram())
534 return;
535
536 // FIXME: determine if this method needs to be implemented for Dart.
537 }
538
539 void DartScriptDebugServer::continueProgram()
540 {
541 if (isPaused())
542 quitMessageLoopOnPause();
543 m_executionState = 0;
544 }
545
546 void DartScriptDebugServer::stepIntoStatement()
547 {
548 ASSERT(isPaused());
549 Dart_SetStepInto();
550 continueProgram();
551 }
552
553 void DartScriptDebugServer::stepOverStatement(const ActivationFrame& frame)
554 {
555 ASSERT(isPaused());
556 Dart_SetStepOver();
557 continueProgram();
558 }
559
560 void DartScriptDebugServer::stepOutOfFunction(const ActivationFrame& frame)
561 {
562 ASSERT(isPaused());
563 Dart_SetStepOut();
564 continueProgram();
565 }
566
567 bool DartScriptDebugServer::setScriptSource(const String& sourceID, const String & newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScri ptSourceError>& errorData, StackTrace* newCallFrames, RefPtr<JSONObject>& result )
568 {
569 *error = "Dart does not support live editing source code yet.";
570 return false;
571 }
572
573 bool DartScriptDebugServer::executeSkipPauseRequest(ScriptDebugListener::SkipPau seRequest request, Dart_StackTrace stackTrace)
574 {
575 switch (request) {
576 case ScriptDebugListener::NoSkip:
577 return false;
578 case ScriptDebugListener::Continue:
579 return true;
580 case ScriptDebugListener::StepInto:
581 case ScriptDebugListener::StepOut:
582 break;
583 }
584 ASSERT(0);
585 // FIXMEDART: actually do something jacobr JACOBR
586 return true;
587 }
588
589 StackTrace DartScriptDebugServer::currentCallFrames()
590 {
591 return StackTrace(m_executionState);
592 }
593
594 StackTrace DartScriptDebugServer::currentCallFramesForAsyncStack()
595 {
596 // FIXMEDART: implement propertly. These are the regular not Async call fram es.
597 return StackTrace(m_executionState);
598 }
599
600 bool DartScriptDebugServer::isPaused()
601 {
602 return !!m_executionState;
603 }
604
605 void DartScriptDebugServer::clearCompiledScripts()
606 {
607 // FIXMEDART: is this meaningful for Dart?
608 // Currently tracking what scripts have been compiled is handled by a
609 // different class.
610 }
611
612 void DartScriptDebugServer::setPreprocessorSource(const String& preprocessorSour ce)
613 {
614 // FIXMEDART: support calling a preprocessor on all Dart scripts.
615 }
616
617 DartScriptDebugServer& DartScriptDebugServer::shared()
618 {
619 DEFINE_STATIC_LOCAL(DartScriptDebugServer, server, ());
620 return server;
621 }
622
623 void DartScriptDebugServer::addListener(ScriptDebugListener* listener, Page* pag e)
624 {
625 ScriptController& scriptController = page->mainFrame()->script();
626 if (!scriptController.canExecuteScripts(NotAboutToExecuteScript))
627 return;
628
629 DartPageDebug* pageDebug = lookupPageDebug(page);
630 pageDebug->addListener(listener);
631 }
632
633 Vector<DartPageDebug*> DartScriptDebugServer::pages()
634 {
635 Vector<DartPageDebug*> result;
636 copyValuesToVector(m_pageIdToDebugDataMap, result);
637 return result;
638 }
639
640 Vector<Dart_Isolate> DartScriptDebugServer::isolates()
641 {
642 Vector<Dart_Isolate> result;
643 Vector<DartPageDebug*> allPages = pages();
644 for (Vector<DartPageDebug*>::iterator it = allPages.begin(); it != allPages. end(); ++it) {
645 Vector<Dart_Isolate> forPage = (*it)->isolates();
646 result.appendRange(forPage.begin(), forPage.end());
647 }
648 return result;
649 }
650
651 bool DartScriptDebugServer::resolveCodeLocation(const Dart_CodeLocation& locatio n, int* line, int* column)
652 {
653 // FIXME: cache the results of calling Dart_ScriptGetTokenInfo to improve
654 // performance.
655 Dart_Handle info = Dart_ScriptGetTokenInfo(location.library_id, location.scr ipt_url);
656 ASSERT(Dart_IsList(info));
657 intptr_t infoLength = 0;
658 Dart_Handle ALLOW_UNUSED result = Dart_ListLength(info, &infoLength);
659 ASSERT(!Dart_IsError(result));
660 Dart_Handle elem;
661 bool lineStart = true;
662 int currentLineNumber = 0;
663 for (intptr_t i = 0; i < infoLength; i++) {
664 elem = Dart_ListGetAt(info, i);
665 if (Dart_IsNull(elem)) {
666 lineStart = true;
667 } else {
668 ASSERT(Dart_IsInteger(elem));
669 Dart_Handle exception = 0;
670 int64_t value = DartUtilities::toInteger(elem, exception);
671 ASSERT(!exception);
672 if (lineStart) {
673 // Line number.
674 currentLineNumber = value;
675 lineStart = false;
676 } else {
677 // Token offset.
678 if (value == location.token_pos) {
679 *line = currentLineNumber;
680 ASSERT(i + 1 < infoLength);
681 *column = DartUtilities::toInteger(Dart_ListGetAt(info, i + 1), exception);
682 ASSERT(!exception);
683 return true;
684 }
685 i++; // skip columnNumber.
686 }
687 }
688 }
689 return false;
690 }
691
692 void DartScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page)
693 {
694 if (!m_pageToIdMap.contains(page))
695 return;
696
697 if (m_pausedPage == page)
698 continueProgram();
699
700 DartPageDebug* pageDebug = lookupPageDebug(page);
701 if (pageDebug)
702 pageDebug->removeListener();
703 }
704
705 void DartScriptDebugServer::setClientMessageLoop(PageScriptDebugServer::ClientMe ssageLoop* clientMessageLoop)
706 {
707 m_clientMessageLoop = clientMessageLoop;
708 }
709
710 void DartScriptDebugServer::runMessageLoopOnPause(Dart_Isolate isolate)
711 {
712 LocalFrame* frame = DartUtilities::domWindowForCurrentIsolate()->frame();
713 m_pausedPage = frame->page();
714
715 // Wait for continue or step command.
716 ASSERT(m_clientMessageLoop);
717 if (m_clientMessageLoop)
718 m_clientMessageLoop->run(m_pausedPage);
719
720 DartPageDebug* pageDebug = lookupPageDebug(m_pausedPage);
721 // The listener may have been removed in the nested loop.
722 if (pageDebug && pageDebug->listener())
723 pageDebug->listener()->didContinue();
724
725 m_pausedPage = 0;
726 }
727
728 void DartScriptDebugServer::quitMessageLoopOnPause()
729 {
730 m_clientMessageLoop->quitNow();
731 }
732
733 bool DartScriptDebugServer::canPreprocess(LocalFrame* frame)
734 {
735 // FIXMEDART: support preprocessing Dart source code.
736 return false;
737 }
738
739 // Source to Source processing iff debugger enabled and it has loaded a preproce ssor.
740 PassOwnPtr<ScriptSourceCode> DartScriptDebugServer::preprocess(LocalFrame* frame , const ScriptSourceCode& sourceCode)
741 {
742 // FIXMEDART: support preprocessing Dart source code.
743 return PassOwnPtr<ScriptSourceCode>();
744 }
745
746 String DartScriptDebugServer::preprocessEventListener(LocalFrame* frame, const S tring& source, const String& url, const String& functionName)
747 {
748 // We don't support inline event listeners in Dart so this code should
749 // never be executed.
750 ASSERT_NOT_REACHED();
751 return source;
752 }
753
754 void DartScriptDebugServer::debugBreak()
755 {
756 Vector<Dart_Isolate> iter = isolates();
757 for (Vector<Dart_Isolate>::iterator it = iter.begin(); it != iter.end(); ++i t) {
758 Dart_Isolate isolate = *it;
759 if (!m_interruptCalled.contains(isolate)) {
760 m_interruptCalled.add(isolate);
761 Dart_InterruptIsolate(isolate);
762 }
763 m_interruptCancelled.remove(isolate);
764 }
765 }
766
767 void DartScriptDebugServer::cancelDebugBreak()
768 {
769 // FIXME: it would be nice if the DartVM provided an API to directly cancel
770 // a debug break call like V8 does.
771 for (HashSet<Dart_Isolate>::iterator it = m_interruptCalled.begin(); it != m _interruptCalled.end(); ++it) {
772 m_interruptCancelled.add(*it);
773 }
774 }
775
776 Page* DartScriptDebugServer::inferPage(Dart_Isolate isolate)
777 {
778 for (DebugDataMap::iterator it = m_pageIdToDebugDataMap.begin(); it != m_pag eIdToDebugDataMap.end(); ++it) {
779 DartPageDebug* pageDebug = it->value;
780 if (pageDebug->containsIsolate(isolate)) {
781 return pageDebug->page();
782 }
783 }
784 return 0;
785 }
786
787 void DartScriptDebugServer::unregisterIsolate(Dart_Isolate isolate, Page* page)
788 {
789 m_interruptCalled.remove(isolate);
790 m_interruptCancelled.remove(isolate);
791 if (!page) {
792 // FIXME: We should instead fix the underlying issue where the
793 // reference to the page is lost before we call unregisterIsolate in
794 // some cases.
795 page = inferPage(isolate);
796 ASSERT(page);
797 }
798 DartPageDebug* pageDebug = lookupPageDebug(page);
799 ASSERT(pageDebug);
800 if (pageDebug)
801 pageDebug->unregisterIsolate(isolate);
802 }
803
804 void DartScriptDebugServer::isolateLoaded()
805 {
806 Page* page = DartUtilities::domWindowForCurrentIsolate()->document()->page() ;
807 if (!page || !instrumentationForPage(page)->inspectorDebuggerAgent())
808 return;
809
810 DartPageDebug* pageDebug = lookupPageDebug(page);
811 if (!pageDebug)
812 return;
813
814 pageDebug->isolateLoaded();
815 }
816
817 void DartScriptDebugServer::handleDartDebugEvent(Dart_IsolateId isolateId, intpt r_t breakpointId, Dart_Handle exception, const Dart_CodeLocation& location)
818 {
819 Dart_Isolate isolate = Dart_GetIsolate(isolateId);
820 ASSERT(isolate);
821 Dart_Handle result = 0;
822 Dart_StackTrace stackTrace = 0;
823 result = Dart_GetStackTrace(&stackTrace);
824 ASSERT(!Dart_IsError(result));
825 result = 0;
826 DartPageDebug* pageDebug = lookupPageDebugForCurrentIsolate();
827 if (!pageDebug)
828 return;
829 ScriptDebugListener* listener = pageDebug->listener();
830 if (listener) {
831 DartIsolateScope scope(isolate);
832 DartApiScope apiScope;
833 ScriptCallFrame topFrame = DartUtilities::getTopFrame(stackTrace, result );
834 if (!result) {
835 if (exception) {
836 if (executeSkipPauseRequest(listener->shouldSkipExceptionPause(t opFrame), stackTrace))
837 return;
838 } else {
839 ScriptDebugListener::SkipPauseRequest skipRequest;
840 if (breakpointId != ILLEGAL_BREAKPOINT_ID)
841 skipRequest = listener->shouldSkipBreakpointPause(topFrame);
842 else
843 skipRequest = listener->shouldSkipStepPause(topFrame);
844 if (executeSkipPauseRequest(skipRequest, stackTrace))
845 return;
846 }
847 }
848 handleProgramBreak(isolate, stackTrace, breakpointId, exception, locatio n);
849 }
850 }
851
852 DartPageDebug* DartScriptDebugServer::lookupPageDebugForCurrentIsolate()
853 {
854 Page* page = DartUtilities::domWindowForCurrentIsolate()->document()->page() ;
855 return lookupPageDebug(page);
856 }
857
858 void DartScriptDebugServer::handleProgramBreak(Dart_Isolate isolate, Dart_StackT race stackTrace, intptr_t dartBreakpointId, Dart_Handle exception, const Dart_Co deLocation& location)
859 {
860 ASSERT(isolate == Dart_CurrentIsolate());
861 // Don't allow nested breaks.
862 if (isPaused())
863 return;
864
865 DartPageDebug* pageDebug = lookupPageDebugForCurrentIsolate();
866 if (!pageDebug)
867 return;
868 ScriptDebugListener* listener = pageDebug->listener();
869
870 if (!listener)
871 return;
872
873 Vector<String> breakpointIds;
874 breakpointIds.append(pageDebug->lookupBreakpointId(dartBreakpointId));
875 m_executionState = stackTrace;
876 // FIXME: remove call to DartHandleProxy once ScriptValue is refactored.
877 listener->didPause(DartUtilities::currentScriptState(), currentCallFrames(), exception ? ScriptValue(DartHandleProxy::create(exception), DartUtilities::curr entV8Context()->GetIsolate()) : ScriptValue(), breakpointIds);
878
879 m_runningNestedMessageLoop = true;
880 runMessageLoopOnPause(isolate);
881 m_runningNestedMessageLoop = false;
882 }
883
884 void DartScriptDebugServer::pausedEventHandler(Dart_IsolateId isolateId, intptr_ t breakpointId, const Dart_CodeLocation& location)
885 {
886 DartScriptDebugServer::shared().handleDartDebugEvent(isolateId, breakpointId , 0, location);
887 }
888
889 void DartScriptDebugServer::exceptionHandler(Dart_IsolateId isolateId, Dart_Hand le exception, Dart_StackTrace trace)
890 {
891 DartScriptDebugServer::shared().handleException(isolateId, exception, trace) ;
892 }
893
894 void DartScriptDebugServer::isolateEventHandler(Dart_IsolateId isolateId, Dart_I solateEvent kind)
895 {
896 if (kind == kInterrupted) {
897 DartScriptDebugServer::shared().handleInterrupted(isolateId);
898 }
899 }
900
901 void DartScriptDebugServer::handleInterrupted(Dart_IsolateId isolateId)
902 {
903 Dart_Isolate isolate = Dart_GetIsolate(isolateId);
904
905 if (isolate) {
906 ASSERT(isolate == Dart_CurrentIsolate());
907 if (!m_interruptCalled.contains(isolate)) {
908 return;
909 }
910
911 m_interruptCalled.remove(isolate);
912 if (m_interruptCancelled.contains(isolate)) {
913 m_interruptCancelled.remove(isolate);
914 return;
915 }
916
917 // FIXME: this is a bit of a hack. V8 was also set to pause on the next
918 // code execution. If it attempts to pause while in the middle of
919 // internal V8 debugger logic it will crash so before we do anything we
920 // need to cancel the pending pause sent to V8.
921 // Perhaps it would be slightly less hacky to send a message to
922 // ScriptDebugServer instructing it to cancel pausing V8.
923 v8::Debug::CancelDebugBreak(DartUtilities::currentV8Context()->GetIsolat e());
924
925 // The user really wants to be paused at the start of the first line of
926 // the Dart method not at the method invocation itself. Otherwise,
927 // stepping to the next call steps out of the executing Dart code
928 // which is not what the user expects.
929 Dart_SetStepInto();
930 continueProgram();
931 }
932 }
933
934 void DartScriptDebugServer::handleException(Dart_IsolateId isolateId, Dart_Handl e exception, Dart_StackTrace trace)
935 {
936 Dart_Isolate isolate = Dart_GetIsolate(isolateId);
937 ASSERT(isolate);
938 Dart_CodeLocation location;
939 Dart_Handle ALLOW_UNUSED result;
940 Dart_ActivationFrame frame;
941 result = Dart_GetActivationFrame(trace, 0, &frame);
942 ASSERT(!Dart_IsError(result));
943 result = Dart_ActivationFrameGetLocation(frame, 0, 0, &location);
944 ASSERT(!Dart_IsError(result));
945 handleProgramBreak(isolate, trace, ILLEGAL_BREAKPOINT_ID, exception, locatio n);
946 }
947
948 void DartScriptDebugServer::runScript(ScriptState* scriptState, const String& sc riptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage)
949 {
950 }
951
952 UnifiedScriptDebugServer::UnifiedScriptDebugServer(DartScriptDebugServer* dartSc riptDebugServer, PageScriptDebugServer* scriptDebugServer)
953 {
954 m_v8 = scriptDebugServer;
955 m_dart = dartScriptDebugServer;
956 }
957
958 UnifiedScriptDebugServer& UnifiedScriptDebugServer::shared()
959 {
960 DEFINE_STATIC_LOCAL(UnifiedScriptDebugServer, server, (&DartScriptDebugServe r::shared(), &PageScriptDebugServer::shared()));
961 return server;
962 }
963
964 String UnifiedScriptDebugServer::setBreakpoint(const String& sourceID, const Scr iptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation)
965 {
966 if (isDartSourceID(sourceID))
967 return m_dart->setBreakpoint(sourceID, scriptBreakpoint, actualLineNumbe r, actualColumnNumber, interstatementLocation);
968 return m_v8->setBreakpoint(sourceID, scriptBreakpoint, actualLineNumber, act ualColumnNumber, interstatementLocation);
969 }
970
971 void UnifiedScriptDebugServer::removeBreakpoint(const String& breakpointId)
972 {
973 if (isDartBreakpointId(breakpointId))
974 m_dart->removeBreakpoint(breakpointId);
975 else
976 m_v8->removeBreakpoint(breakpointId);
977 }
978
979 void UnifiedScriptDebugServer::clearBreakpoints()
980 {
981 m_v8->clearBreakpoints();
982 m_dart->clearBreakpoints();
983 }
984
985 void UnifiedScriptDebugServer::setBreakpointsActivated(bool activated)
986 {
987 m_v8->setBreakpointsActivated(activated);
988 m_dart->setBreakpointsActivated(activated);
989 }
990
991 ScriptDebugServer::PauseOnExceptionsState UnifiedScriptDebugServer::pauseOnExcep tionsState()
992 {
993 // Assume Dart and V8 always have a consistent value for
994 // pauseOnExceptionsState.
995 return m_v8->pauseOnExceptionsState();
996 }
997
998 void UnifiedScriptDebugServer::setPauseOnExceptionsState(ScriptDebugServer::Paus eOnExceptionsState pauseOnExceptionsState)
999 {
1000 m_dart->setPauseOnExceptionsState(pauseOnExceptionsState);
1001 m_v8->setPauseOnExceptionsState(pauseOnExceptionsState);
1002 }
1003
1004 void UnifiedScriptDebugServer::setPauseOnNextStatement(bool pause)
1005 {
1006 if (isPaused()) {
1007 return;
1008 }
1009 m_v8->setPauseOnNextStatement(pause);
1010 m_dart->setPauseOnNextStatement(pause);
1011 }
1012
1013 bool UnifiedScriptDebugServer::canBreakProgram()
1014 {
1015 return m_v8->canBreakProgram() || m_dart->canBreakProgram();
1016 }
1017
1018 void UnifiedScriptDebugServer::breakProgram()
1019 {
1020 if (m_v8->canBreakProgram())
1021 m_v8->breakProgram();
1022 if (m_dart->canBreakProgram())
1023 m_dart->breakProgram();
1024 }
1025
1026 void UnifiedScriptDebugServer::continueProgram()
1027 {
1028 m_v8->continueProgram();
1029 m_dart->continueProgram();
1030 }
1031
1032 void UnifiedScriptDebugServer::stepIntoStatement()
1033 {
1034 if (m_v8->isPaused())
1035 m_v8->stepIntoStatement();
1036 else
1037 m_dart->stepIntoStatement();
1038 }
1039
1040 void UnifiedScriptDebugServer::stepOverStatement(const ActivationFrame& frame)
1041 {
1042 if (m_v8->isPaused())
1043 m_v8->stepOverStatement(frame);
1044 else
1045 m_dart->stepOverStatement(frame);
1046 }
1047
1048 void UnifiedScriptDebugServer::stepOutOfFunction(const ActivationFrame& frame)
1049 {
1050 if (m_v8->isPaused())
1051 m_v8->stepOutOfFunction(frame);
1052 else
1053 m_dart->stepOutOfFunction(frame);
1054 }
1055
1056 bool UnifiedScriptDebugServer::isDartSourceID(const String& sourceID)
1057 {
1058 // FIXMEDART: find a cleaner solution.
1059 return sourceID.startsWith(String("{\"dartScript"));
1060 }
1061
1062 bool UnifiedScriptDebugServer::isDartBreakpointId(const String& breakpointId)
1063 {
1064 // FIXMEDART: find a cleaner solution.
1065 return breakpointId.startsWith(String("{\"dartBreakpoint"));
1066 }
1067
1068 bool UnifiedScriptDebugServer::setScriptSource(const String& sourceID, const Str ing& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetS criptSourceError>& errorBuilder, StackTrace* newCallFrames, RefPtr<JSONObject>& result)
1069 {
1070 if (isDartSourceID(sourceID))
1071 return m_dart->setScriptSource(sourceID, newContent, preview, error, err orBuilder, newCallFrames, result);
1072 return m_v8->setScriptSource(sourceID, newContent, preview, error, errorBuil der, newCallFrames, result);
1073 }
1074
1075 StackTrace UnifiedScriptDebugServer::currentCallFrames()
1076 {
1077 // FIXMEDART: we need to figure out how to interleave stack traces where pos sible.
1078 StackTrace v8StackTrace = m_v8->currentCallFrames();
1079 if (!v8StackTrace.isNull())
1080 return v8StackTrace;
1081 return m_dart->currentCallFrames();
1082 }
1083
1084 StackTrace UnifiedScriptDebugServer::currentCallFramesForAsyncStack()
1085 {
1086 // FIXMEDART: we need to figure out how to interleave stack traces where pos sible.
1087 StackTrace v8StackTrace = m_v8->currentCallFramesForAsyncStack();
1088 if (!v8StackTrace.isNull())
1089 return v8StackTrace;
1090 return m_dart->currentCallFramesForAsyncStack();
1091 }
1092
1093
1094 bool UnifiedScriptDebugServer::isPaused()
1095 {
1096 return m_v8->isPaused() || m_dart->isPaused();
1097 }
1098
1099 bool UnifiedScriptDebugServer::runningNestedMessageLoop()
1100 {
1101 return m_dart->runningNestedMessageLoop() || m_v8->runningNestedMessageLoop( );
1102 }
1103
1104 void UnifiedScriptDebugServer::clearCompiledScripts()
1105 {
1106 m_v8->clearCompiledScripts();
1107 m_dart->clearCompiledScripts();
1108 }
1109
1110 void UnifiedScriptDebugServer::setPreprocessorSource(const String& script)
1111 {
1112 m_v8->setPreprocessorSource(script);
1113 m_dart->setPreprocessorSource(script);
1114 }
1115
1116 void UnifiedScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDet ails& eventDetails)
1117 {
1118 m_v8->preprocessBeforeCompile(eventDetails);
1119 // FIXMEDART: tweak the signature and call for dart.
1120 }
1121
1122 PassOwnPtr<ScriptSourceCode> UnifiedScriptDebugServer::preprocess(LocalFrame* fr ame, const ScriptSourceCode& scriptSourceCode)
1123 {
1124 // FIXME: how do we know whether to preprocess with Dart or V8?
1125 return m_v8->preprocess(frame, scriptSourceCode);
1126 }
1127
1128 void UnifiedScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
1129 {
1130 m_v8->addListener(listener, page);
1131 m_dart->addListener(listener, page);
1132 }
1133
1134 void UnifiedScriptDebugServer::removeListener(ScriptDebugListener* listener, Pag e* page)
1135 {
1136 m_v8->removeListener(listener, page);
1137 m_dart->removeListener(listener, page);
1138 }
1139
1140 String UnifiedScriptDebugServer::preprocessEventListener(LocalFrame* frame, cons t String& source, const String& url, const String& functionName)
1141 {
1142 // FIXME: how do we know whether to preprocess with Dart or V8?
1143 return m_v8->preprocessEventListener(frame, source, url, functionName);
1144 }
1145
1146 void UnifiedScriptDebugServer::runScript(ScriptState* scriptState, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage)
1147 {
1148 // FIXME: support runScript for Dart as well.
1149 m_v8->runScript(scriptState, scriptId, result, wasThrown, exceptionMessage);
1150 }
1151
1152 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698