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

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

Powered by Google App Engine
This is Rietveld 408576698