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

Side by Side Diff: sky/engine/bindings-dart/core/dart/DartScriptDebugServer.cpp

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

Powered by Google App Engine
This is Rietveld 408576698