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

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

Issue 922053002: Remove unused V8 integration code in Sky (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2013 Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "sky/engine/config.h"
31 #include "sky/engine/v8_inspector/InspectorDebuggerAgent.h"
32
33 #include "sky/engine/bindings/core/v8/ScriptSourceCode.h"
34 #include "sky/engine/bindings/core/v8/ScriptValue.h"
35 #include "sky/engine/core/dom/Document.h"
36 #include "sky/engine/core/inspector/ConsoleMessage.h"
37 #include "sky/engine/core/inspector/JavaScriptCallFrame.h"
38 #include "sky/engine/core/inspector/ScriptArguments.h"
39 #include "sky/engine/core/inspector/ScriptAsyncCallStack.h"
40 #include "sky/engine/core/inspector/ScriptCallFrame.h"
41 #include "sky/engine/core/inspector/ScriptCallStack.h"
42 #include "sky/engine/platform/JSONValues.h"
43 #include "sky/engine/v8_inspector/ContentSearchUtils.h"
44 #include "sky/engine/v8_inspector/InjectedScriptManager.h"
45 #include "sky/engine/v8_inspector/InspectorState.h"
46 #include "sky/engine/v8_inspector/ScriptDebugServer.h"
47 #include "sky/engine/v8_inspector/ScriptRegexp.h"
48 #include "sky/engine/wtf/text/StringBuilder.h"
49 #include "sky/engine/wtf/text/WTFString.h"
50
51 using blink::TypeBuilder::Array;
52 using blink::TypeBuilder::Debugger::BreakpointId;
53 using blink::TypeBuilder::Debugger::CallFrame;
54 using blink::TypeBuilder::Debugger::CollectionEntry;
55 using blink::TypeBuilder::Debugger::ExceptionDetails;
56 using blink::TypeBuilder::Debugger::FunctionDetails;
57 using blink::TypeBuilder::Debugger::ScriptId;
58 using blink::TypeBuilder::Debugger::StackTrace;
59 using blink::TypeBuilder::Runtime::RemoteObject;
60
61 namespace {
62
63 static const char v8AsyncTaskEventEnqueue[] = "enqueue";
64 static const char v8AsyncTaskEventWillHandle[] = "willHandle";
65 static const char v8AsyncTaskEventDidHandle[] = "didHandle";
66
67 }
68
69 namespace blink {
70
71 namespace DebuggerAgentState {
72 static const char debuggerEnabled[] = "debuggerEnabled";
73 static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
74 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
75 static const char asyncCallStackDepth[] = "asyncCallStackDepth";
76
77 // Breakpoint properties.
78 static const char url[] = "url";
79 static const char isRegex[] = "isRegex";
80 static const char lineNumber[] = "lineNumber";
81 static const char columnNumber[] = "columnNumber";
82 static const char condition[] = "condition";
83 static const char isAnti[] = "isAnti";
84 static const char skipStackPattern[] = "skipStackPattern";
85 static const char skipAllPauses[] = "skipAllPauses";
86 static const char skipAllPausesExpiresOnReload[] = "skipAllPausesExpiresOnReload ";
87
88 };
89
90 static const int maxSkipStepInCount = 20;
91
92 const char InspectorDebuggerAgent::backtraceObjectGroup[] = "backtrace";
93
94 static String breakpointIdSuffix(InspectorDebuggerAgent::BreakpointSource source )
95 {
96 switch (source) {
97 case InspectorDebuggerAgent::UserBreakpointSource:
98 break;
99 case InspectorDebuggerAgent::DebugCommandBreakpointSource:
100 return ":debug";
101 case InspectorDebuggerAgent::MonitorCommandBreakpointSource:
102 return ":monitor";
103 }
104 return String();
105 }
106
107 static String generateBreakpointId(const String& scriptId, int lineNumber, int c olumnNumber, InspectorDebuggerAgent::BreakpointSource source)
108 {
109 return scriptId + ':' + String::number(lineNumber) + ':' + String::number(co lumnNumber) + breakpointIdSuffix(source);
110 }
111
112 InspectorDebuggerAgent::InspectorDebuggerAgent(InjectedScriptManager* injectedSc riptManager)
113 : InspectorBaseAgent<InspectorDebuggerAgent>("Debugger")
114 , m_injectedScriptManager(injectedScriptManager)
115 , m_frontend(0)
116 , m_pausedScriptState(nullptr)
117 , m_javaScriptPauseScheduled(false)
118 , m_debuggerStepScheduled(false)
119 , m_steppingFromFramework(false)
120 , m_pausingOnNativeEvent(false)
121 , m_listener(nullptr)
122 , m_skippedStepInCount(0)
123 , m_skipAllPauses(false)
124 , m_asyncCallStackTracker(adoptPtr(new AsyncCallStackTracker()))
125 {
126 }
127
128 InspectorDebuggerAgent::~InspectorDebuggerAgent()
129 {
130 }
131
132 void InspectorDebuggerAgent::virtualInit()
133 {
134 // FIXME: make breakReason optional so that there was no need to init it wit h "other".
135 clearBreakDetails();
136 m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServ er::DontPauseOnExceptions);
137 }
138
139 void InspectorDebuggerAgent::enable()
140 {
141 startListeningScriptDebugServer();
142 // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
143 scriptDebugServer().setBreakpointsActivated(true);
144
145 if (m_listener)
146 m_listener->debuggerWasEnabled();
147 }
148
149 void InspectorDebuggerAgent::disable()
150 {
151 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, JSONObject::cr eate());
152 m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServ er::DontPauseOnExceptions);
153 m_state->setString(DebuggerAgentState::skipStackPattern, "");
154 m_state->setLong(DebuggerAgentState::asyncCallStackDepth, 0);
155
156 scriptDebugServer().clearBreakpoints();
157 scriptDebugServer().clearCompiledScripts();
158 stopListeningScriptDebugServer();
159 clear();
160
161 if (m_listener)
162 m_listener->debuggerWasDisabled();
163
164 m_skipAllPauses = false;
165 }
166
167 bool InspectorDebuggerAgent::enabled()
168 {
169 return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
170 }
171
172 void InspectorDebuggerAgent::enable(ErrorString*)
173 {
174 if (enabled())
175 return;
176
177 enable();
178 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
179
180 ASSERT(m_frontend);
181 }
182
183 void InspectorDebuggerAgent::disable(ErrorString*)
184 {
185 if (!enabled())
186 return;
187
188 disable();
189 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
190 }
191
192 static PassOwnPtr<ScriptRegexp> compileSkipCallFramePattern(String patternText)
193 {
194 if (patternText.isEmpty())
195 return nullptr;
196 OwnPtr<ScriptRegexp> result = adoptPtr(new ScriptRegexp(patternText, TextCas eSensitive));
197 if (!result->isValid())
198 result.clear();
199 return result.release();
200 }
201
202 void InspectorDebuggerAgent::restore()
203 {
204 if (enabled()) {
205 m_frontend->globalObjectCleared();
206 enable();
207 long pauseState = m_state->getLong(DebuggerAgentState::pauseOnExceptions State);
208 String error;
209 setPauseOnExceptionsImpl(&error, pauseState);
210 m_cachedSkipStackRegExp = compileSkipCallFramePattern(m_state->getString (DebuggerAgentState::skipStackPattern));
211 m_skipAllPauses = m_state->getBoolean(DebuggerAgentState::skipAllPauses) ;
212 if (m_skipAllPauses && m_state->getBoolean(DebuggerAgentState::skipAllPa usesExpiresOnReload)) {
213 m_skipAllPauses = false;
214 m_state->setBoolean(DebuggerAgentState::skipAllPauses, false);
215 }
216 asyncCallStackTracker().setAsyncCallStackDepth(m_state->getLong(Debugger AgentState::asyncCallStackDepth));
217 }
218 }
219
220 void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
221 {
222 m_frontend = frontend->debugger();
223 }
224
225 void InspectorDebuggerAgent::clearFrontend()
226 {
227 m_frontend = 0;
228
229 if (!enabled())
230 return;
231
232 disable();
233
234 // FIXME: due to m_state->mute() hack in InspectorController, debuggerEnable d is actually set to false only
235 // in InspectorState, but not in cookie. That's why after navigation debugge rEnabled will be true,
236 // but after front-end re-open it will still be false.
237 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
238 }
239
240 void InspectorDebuggerAgent::setBreakpointsActive(ErrorString*, bool active)
241 {
242 scriptDebugServer().setBreakpointsActivated(active);
243 }
244
245 void InspectorDebuggerAgent::setSkipAllPauses(ErrorString*, bool skipped, const bool* untilReload)
246 {
247 m_skipAllPauses = skipped;
248 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
249 m_state->setBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload, asBool (untilReload));
250 }
251
252 void InspectorDebuggerAgent::pageDidCommitLoad()
253 {
254 if (m_state->getBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload)) {
255 m_skipAllPauses = false;
256 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
257 }
258 }
259
260 bool InspectorDebuggerAgent::isPaused()
261 {
262 return scriptDebugServer().isPaused();
263 }
264
265 bool InspectorDebuggerAgent::runningNestedMessageLoop()
266 {
267 return scriptDebugServer().runningNestedMessageLoop();
268 }
269
270 void InspectorDebuggerAgent::addMessageToConsole(ConsoleMessage* consoleMessage)
271 {
272 if (consoleMessage->type() == AssertMessageType && scriptDebugServer().pause OnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions)
273 breakProgram(InspectorFrontend::Debugger::Reason::Assert, nullptr);
274 }
275
276 static PassRefPtr<JSONObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex, bool is Anti)
277 {
278 RefPtr<JSONObject> breakpointObject = JSONObject::create();
279 breakpointObject->setString(DebuggerAgentState::url, url);
280 breakpointObject->setNumber(DebuggerAgentState::lineNumber, lineNumber);
281 breakpointObject->setNumber(DebuggerAgentState::columnNumber, columnNumber);
282 breakpointObject->setString(DebuggerAgentState::condition, condition);
283 breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex);
284 breakpointObject->setBoolean(DebuggerAgentState::isAnti, isAnti);
285 return breakpointObject;
286 }
287
288 static String scriptSourceURL(const ScriptDebugListener::Script& script)
289 {
290 bool hasSourceURL = !script.sourceURL.isEmpty();
291 return hasSourceURL ? script.sourceURL : script.url;
292 }
293
294 static bool matches(const String& url, const String& pattern, bool isRegex)
295 {
296 if (isRegex) {
297 ScriptRegexp regex(pattern, TextCaseSensitive);
298 return regex.match(url) != -1;
299 }
300 return url == pattern;
301 }
302
303 void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int li neNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, c onst bool* isAntiBreakpoint, BreakpointId* outBreakpointId, RefPtr<Array<TypeBui lder::Debugger::Location> >& locations)
304 {
305 locations = Array<TypeBuilder::Debugger::Location>::create();
306 if (!optionalURL == !optionalURLRegex) {
307 *errorString = "Either url or urlRegex must be specified.";
308 return;
309 }
310
311 bool isAntiBreakpointValue = asBool(isAntiBreakpoint);
312
313 String url = optionalURL ? *optionalURL : *optionalURLRegex;
314 int columnNumber;
315 if (optionalColumnNumber) {
316 columnNumber = *optionalColumnNumber;
317 if (columnNumber < 0) {
318 *errorString = "Incorrect column number";
319 return;
320 }
321 } else {
322 columnNumber = isAntiBreakpointValue ? -1 : 0;
323 }
324 String condition = optionalCondition ? *optionalCondition : "";
325 bool isRegex = optionalURLRegex;
326
327 String breakpointId = (isRegex ? "/" + url + "/" : url) + ':' + String::numb er(lineNumber) + ':' + String::number(columnNumber);
328 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState ::javaScriptBreakpoints);
329 if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end()) {
330 *errorString = "Breakpoint at specified location already exists.";
331 return;
332 }
333
334 breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(ur l, lineNumber, columnNumber, condition, isRegex, isAntiBreakpointValue));
335 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCoo kie);
336
337 if (!isAntiBreakpointValue) {
338 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
339 for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
340 if (!matches(scriptSourceURL(it->value), url, isRegex))
341 continue;
342 RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint (breakpointId, it->key, breakpoint, UserBreakpointSource);
343 if (location)
344 locations->addItem(location);
345 }
346 }
347 *outBreakpointId = breakpointId;
348 }
349
350 static bool parseLocation(ErrorString* errorString, PassRefPtr<JSONObject> locat ion, String* scriptId, int* lineNumber, int* columnNumber)
351 {
352 if (!location->getString("scriptId", scriptId) || !location->getNumber("line Number", lineNumber)) {
353 // FIXME: replace with input validation.
354 *errorString = "scriptId and lineNumber are required.";
355 return false;
356 }
357 *columnNumber = 0;
358 location->getNumber("columnNumber", columnNumber);
359 return true;
360 }
361
362 void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPt r<JSONObject>& location, const String* const optionalCondition, BreakpointId* ou tBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
363 {
364 String scriptId;
365 int lineNumber;
366 int columnNumber;
367
368 if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNum ber))
369 return;
370
371 String condition = optionalCondition ? *optionalCondition : emptyString();
372
373 String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumbe r, UserBreakpointSource);
374 if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpo intIdToDebugServerBreakpointIds.end()) {
375 *errorString = "Breakpoint at specified location already exists.";
376 return;
377 }
378 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
379 actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserB reakpointSource);
380 if (actualLocation)
381 *outBreakpointId = breakpointId;
382 else
383 *errorString = "Could not resolve breakpoint";
384 }
385
386 void InspectorDebuggerAgent::removeBreakpoint(ErrorString*, const String& breakp ointId)
387 {
388 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState ::javaScriptBreakpoints);
389 JSONObject::iterator it = breakpointsCookie->find(breakpointId);
390 bool isAntibreakpoint = false;
391 if (it != breakpointsCookie->end()) {
392 RefPtr<JSONObject> breakpointObject = it->value->asObject();
393 breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoi nt);
394 breakpointsCookie->remove(breakpointId);
395 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpoint sCookie);
396 }
397
398 if (!isAntibreakpoint)
399 removeBreakpoint(breakpointId);
400 }
401
402 void InspectorDebuggerAgent::removeBreakpoint(const String& breakpointId)
403 {
404 BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIds Iterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
405 if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpoin tIds.end())
406 return;
407 for (size_t i = 0; i < debugServerBreakpointIdsIterator->value.size(); ++i) {
408 const String& debugServerBreakpointId = debugServerBreakpointIdsIterator ->value[i];
409 scriptDebugServer().removeBreakpoint(debugServerBreakpointId);
410 m_serverBreakpoints.remove(debugServerBreakpointId);
411 }
412 m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIter ator);
413 }
414
415 void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<JSONObject>& location, const bool* interstateLocationOpt)
416 {
417 if (!m_continueToLocationBreakpointId.isEmpty()) {
418 scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
419 m_continueToLocationBreakpointId = "";
420 }
421
422 String scriptId;
423 int lineNumber;
424 int columnNumber;
425
426 if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNum ber))
427 return;
428
429 ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
430 m_continueToLocationBreakpointId = scriptDebugServer().setBreakpoint(scriptI d, breakpoint, &lineNumber, &columnNumber, asBool(interstateLocationOpt));
431 resume(errorString);
432 }
433
434 void InspectorDebuggerAgent::getStepInPositions(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location> >& positions)
435 {
436 if (!isPaused() || m_currentCallStack.isEmpty()) {
437 *errorString = "Attempt to access callframe when debugger is not on paus e";
438 return;
439 }
440 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForOb jectId(callFrameId);
441 if (injectedScript.isEmpty()) {
442 *errorString = "Inspected frame has gone";
443 return;
444 }
445
446 injectedScript.getStepInPositions(errorString, m_currentCallStack, callFrame Id, positions);
447 }
448
449 void InspectorDebuggerAgent::getBacktrace(ErrorString* errorString, RefPtr<Array <CallFrame> >& callFrames, RefPtr<StackTrace>& asyncStackTrace)
450 {
451 if (!assertPaused(errorString))
452 return;
453 m_currentCallStack = scriptDebugServer().currentCallFrames();
454 callFrames = currentCallFrames();
455 asyncStackTrace = currentAsyncStackTrace();
456 }
457
458 PassRefPtr<JavaScriptCallFrame> InspectorDebuggerAgent::topCallFrameSkipUnknownS ources()
459 {
460 for (int index = 0; ; ++index) {
461 RefPtr<JavaScriptCallFrame> frame = scriptDebugServer().callFrameNoScope s(index);
462 if (!frame)
463 return nullptr;
464 String scriptIdString = String::number(frame->sourceID());
465 if (m_scripts.contains(scriptIdString))
466 return frame.release();
467 }
468 }
469
470 String InspectorDebuggerAgent::scriptURL(JavaScriptCallFrame* frame)
471 {
472 String scriptIdString = String::number(frame->sourceID());
473 ScriptsMap::iterator it = m_scripts.find(scriptIdString);
474 if (it == m_scripts.end())
475 return String();
476 return scriptSourceURL(it->value);
477 }
478
479 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipExceptio nPause()
480 {
481 if (m_steppingFromFramework)
482 return ScriptDebugListener::NoSkip;
483
484 // FIXME: Fast return: if (!m_cachedSkipStackRegExp && !has_any_anti_breakpo int) return ScriptDebugListener::NoSkip;
485
486 RefPtr<JavaScriptCallFrame> topFrame = topCallFrameSkipUnknownSources();
487 if (!topFrame)
488 return ScriptDebugListener::NoSkip;
489
490 String topFrameScriptUrl = scriptURL(topFrame.get());
491 if (m_cachedSkipStackRegExp && !topFrameScriptUrl.isEmpty() && m_cachedSkipS tackRegExp->match(topFrameScriptUrl) != -1)
492 return ScriptDebugListener::Continue;
493
494 // Match against breakpoints.
495 if (topFrameScriptUrl.isEmpty())
496 return ScriptDebugListener::NoSkip;
497
498 // Prepare top frame parameters.
499 int topFrameLineNumber = topFrame->line();
500 int topFrameColumnNumber = topFrame->column();
501
502 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState ::javaScriptBreakpoints);
503 for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpoints Cookie->end(); ++it) {
504 RefPtr<JSONObject> breakpointObject = it->value->asObject();
505 bool isAntibreakpoint;
506 breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoi nt);
507 if (!isAntibreakpoint)
508 continue;
509
510 int breakLineNumber;
511 breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakLineNu mber);
512 int breakColumnNumber;
513 breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakColu mnNumber);
514
515 if (breakLineNumber != topFrameLineNumber)
516 continue;
517
518 if (breakColumnNumber != -1 && breakColumnNumber != topFrameColumnNumber )
519 continue;
520
521 bool isRegex;
522 breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
523 String url;
524 breakpointObject->getString(DebuggerAgentState::url, &url);
525 if (!matches(topFrameScriptUrl, url, isRegex))
526 continue;
527
528 return ScriptDebugListener::Continue;
529 }
530
531 return ScriptDebugListener::NoSkip;
532 }
533
534 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipStepPaus e()
535 {
536 if (!m_cachedSkipStackRegExp || m_steppingFromFramework)
537 return ScriptDebugListener::NoSkip;
538
539 RefPtr<JavaScriptCallFrame> topFrame = topCallFrameSkipUnknownSources();
540 String scriptUrl = scriptURL(topFrame.get());
541 if (scriptUrl.isEmpty() || m_cachedSkipStackRegExp->match(scriptUrl) == -1)
542 return ScriptDebugListener::NoSkip;
543
544 if (m_skippedStepInCount == 0) {
545 m_minFrameCountForSkip = scriptDebugServer().frameCount();
546 m_skippedStepInCount = 1;
547 return ScriptDebugListener::StepInto;
548 }
549
550 if (m_skippedStepInCount < maxSkipStepInCount && topFrame->isAtReturn() && s criptDebugServer().frameCount() <= m_minFrameCountForSkip)
551 m_skippedStepInCount = maxSkipStepInCount;
552
553 if (m_skippedStepInCount >= maxSkipStepInCount) {
554 if (m_pausingOnNativeEvent) {
555 m_pausingOnNativeEvent = false;
556 m_skippedStepInCount = 0;
557 return ScriptDebugListener::Continue;
558 }
559 return ScriptDebugListener::StepOut;
560 }
561
562 ++m_skippedStepInCount;
563 return ScriptDebugListener::StepInto;
564 }
565
566 bool InspectorDebuggerAgent::isTopCallFrameInFramework()
567 {
568 if (!m_cachedSkipStackRegExp)
569 return false;
570
571 RefPtr<JavaScriptCallFrame> topFrame = topCallFrameSkipUnknownSources();
572 if (!topFrame)
573 return false;
574
575 String scriptUrl = scriptURL(topFrame.get());
576 return !scriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(scriptUrl) != -1;
577 }
578
579 PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreak point(const String& breakpointId, const String& scriptId, const ScriptBreakpoint & breakpoint, BreakpointSource source)
580 {
581 ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
582 if (scriptIterator == m_scripts.end())
583 return nullptr;
584 Script& script = scriptIterator->value;
585 if (breakpoint.lineNumber < script.startLine || script.endLine < breakpoint. lineNumber)
586 return nullptr;
587
588 int actualLineNumber;
589 int actualColumnNumber;
590 String debugServerBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber, false);
591 if (debugServerBreakpointId.isEmpty())
592 return nullptr;
593
594 m_serverBreakpoints.set(debugServerBreakpointId, std::make_pair(breakpointId , source));
595
596 BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIds Iterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
597 if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpoin tIds.end())
598 m_breakpointIdToDebugServerBreakpointIds.set(breakpointId, Vector<String >()).storedValue->value.append(debugServerBreakpointId);
599 else
600 debugServerBreakpointIdsIterator->value.append(debugServerBreakpointId);
601
602 RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Lo cation::create()
603 .setScriptId(scriptId)
604 .setLineNumber(actualLineNumber);
605 location->setColumnNumber(actualColumnNumber);
606 return location;
607 }
608
609 void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& s criptId, const String& query, const bool* const optionalCaseSensitive, const boo l* const optionalIsRegex, RefPtr<Array<blink::TypeBuilder::Page::SearchMatch> >& results)
610 {
611 ScriptsMap::iterator it = m_scripts.find(scriptId);
612 if (it != m_scripts.end())
613 results = ContentSearchUtils::searchInTextByLines(it->value.source, quer y, asBool(optionalCaseSensitive), asBool(optionalIsRegex));
614 else
615 *error = "No script for id: " + scriptId;
616 }
617
618 void InspectorDebuggerAgent::setScriptSource(ErrorString* error, RefPtr<TypeBuil der::Debugger::SetScriptSourceError>& errorData, const String& scriptId, const S tring& newContent, const bool* const preview, RefPtr<Array<CallFrame> >& newCall Frames, RefPtr<JSONObject>& result, RefPtr<StackTrace>& asyncStackTrace)
619 {
620 if (!scriptDebugServer().setScriptSource(scriptId, newContent, asBool(previe w), error, errorData, &m_currentCallStack, &result))
621 return;
622
623 newCallFrames = currentCallFrames();
624 asyncStackTrace = currentAsyncStackTrace();
625 // FIXME(sky): Used to tell the page agent.
626 }
627
628 void InspectorDebuggerAgent::restartFrame(ErrorString* errorString, const String & callFrameId, RefPtr<Array<CallFrame> >& newCallFrames, RefPtr<JSONObject>& res ult, RefPtr<StackTrace>& asyncStackTrace)
629 {
630 if (!isPaused() || m_currentCallStack.isEmpty()) {
631 *errorString = "Attempt to access callframe when debugger is not on paus e";
632 return;
633 }
634 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForOb jectId(callFrameId);
635 if (injectedScript.isEmpty()) {
636 *errorString = "Inspected frame has gone";
637 return;
638 }
639
640 injectedScript.restartFrame(errorString, m_currentCallStack, callFrameId, &r esult);
641 m_currentCallStack = scriptDebugServer().currentCallFrames();
642 newCallFrames = currentCallFrames();
643 asyncStackTrace = currentAsyncStackTrace();
644 }
645
646 void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& s criptId, String* scriptSource)
647 {
648 ScriptsMap::iterator it = m_scripts.find(scriptId);
649 if (it == m_scripts.end()) {
650 *error = "No script for id: " + scriptId;
651 return;
652 }
653
654 String url = it->value.url;
655 // FIXME(sky): Fetch the script from the page agent?
656 *scriptSource = it->value.source;
657 }
658
659 void InspectorDebuggerAgent::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>& details)
660 {
661 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForOb jectId(functionId);
662 if (injectedScript.isEmpty()) {
663 *errorString = "Function object id is obsolete";
664 return;
665 }
666 injectedScript.getFunctionDetails(errorString, functionId, &details);
667 }
668
669 void InspectorDebuggerAgent::getCollectionEntries(ErrorString* errorString, cons t String& objectId, RefPtr<TypeBuilder::Array<CollectionEntry> >& entries)
670 {
671 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForOb jectId(objectId);
672 if (injectedScript.isEmpty()) {
673 *errorString = "Inspected frame has gone";
674 return;
675 }
676 injectedScript.getCollectionEntries(errorString, objectId, &entries);
677 }
678
679 void InspectorDebuggerAgent::schedulePauseOnNextStatement(InspectorFrontend::Deb ugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
680 {
681 if (m_javaScriptPauseScheduled || isPaused())
682 return;
683 m_breakReason = breakReason;
684 m_breakAuxData = data;
685 m_pausingOnNativeEvent = true;
686 scriptDebugServer().setPauseOnNextStatement(true);
687 }
688
689 void InspectorDebuggerAgent::cancelPauseOnNextStatement()
690 {
691 if (m_javaScriptPauseScheduled || isPaused())
692 return;
693 clearBreakDetails();
694 m_pausingOnNativeEvent = false;
695 scriptDebugServer().setPauseOnNextStatement(false);
696 }
697
698 void InspectorDebuggerAgent::didInstallTimer(ExecutionContext* context, int time rId, int timeout, bool singleShot)
699 {
700 if (asyncCallStackTracker().isEnabled())
701 asyncCallStackTracker().didInstallTimer(context, timerId, singleShot, sc riptDebugServer().currentCallFramesForAsyncStack());
702 }
703
704 void InspectorDebuggerAgent::didRemoveTimer(ExecutionContext* context, int timer Id)
705 {
706 if (asyncCallStackTracker().isEnabled())
707 asyncCallStackTracker().didRemoveTimer(context, timerId);
708 }
709
710 bool InspectorDebuggerAgent::willFireTimer(ExecutionContext* context, int timerI d)
711 {
712 if (asyncCallStackTracker().isEnabled())
713 asyncCallStackTracker().willFireTimer(context, timerId);
714 return true;
715 }
716
717 void InspectorDebuggerAgent::didFireTimer()
718 {
719 if (asyncCallStackTracker().isEnabled())
720 asyncCallStackTracker().didFireAsyncCall();
721 cancelPauseOnNextStatement();
722 }
723
724 void InspectorDebuggerAgent::didRequestAnimationFrame(Document* document, int ca llbackId)
725 {
726 if (asyncCallStackTracker().isEnabled())
727 asyncCallStackTracker().didRequestAnimationFrame(document, callbackId, s criptDebugServer().currentCallFramesForAsyncStack());
728 }
729
730 void InspectorDebuggerAgent::didCancelAnimationFrame(Document* document, int cal lbackId)
731 {
732 if (asyncCallStackTracker().isEnabled())
733 asyncCallStackTracker().didCancelAnimationFrame(document, callbackId);
734 }
735
736 bool InspectorDebuggerAgent::willFireAnimationFrame(Document* document, int call backId)
737 {
738 if (asyncCallStackTracker().isEnabled())
739 asyncCallStackTracker().willFireAnimationFrame(document, callbackId);
740 return true;
741 }
742
743 void InspectorDebuggerAgent::didFireAnimationFrame()
744 {
745 if (asyncCallStackTracker().isEnabled())
746 asyncCallStackTracker().didFireAsyncCall();
747 }
748
749 void InspectorDebuggerAgent::didEnqueueEvent(EventTarget* eventTarget, Event* ev ent)
750 {
751 if (asyncCallStackTracker().isEnabled())
752 asyncCallStackTracker().didEnqueueEvent(eventTarget, event, scriptDebugS erver().currentCallFramesForAsyncStack());
753 }
754
755 void InspectorDebuggerAgent::didRemoveEvent(EventTarget* eventTarget, Event* eve nt)
756 {
757 if (asyncCallStackTracker().isEnabled())
758 asyncCallStackTracker().didRemoveEvent(eventTarget, event);
759 }
760
761 void InspectorDebuggerAgent::willHandleEvent(EventTarget* eventTarget, Event* ev ent, EventListener* listener, bool useCapture)
762 {
763 if (asyncCallStackTracker().isEnabled())
764 asyncCallStackTracker().willHandleEvent(eventTarget, event, listener, us eCapture);
765 }
766
767 void InspectorDebuggerAgent::didHandleEvent()
768 {
769 if (asyncCallStackTracker().isEnabled())
770 asyncCallStackTracker().didFireAsyncCall();
771 cancelPauseOnNextStatement();
772 }
773
774 void InspectorDebuggerAgent::didEnqueueMutationRecord(ExecutionContext* context, MutationObserver* observer)
775 {
776 if (asyncCallStackTracker().isEnabled() && !asyncCallStackTracker().hasEnque uedMutationRecord(context, observer))
777 asyncCallStackTracker().didEnqueueMutationRecord(context, observer, scri ptDebugServer().currentCallFramesForAsyncStack());
778 }
779
780 void InspectorDebuggerAgent::didClearAllMutationRecords(ExecutionContext* contex t, MutationObserver* observer)
781 {
782 if (asyncCallStackTracker().isEnabled())
783 asyncCallStackTracker().didClearAllMutationRecords(context, observer);
784 }
785
786 void InspectorDebuggerAgent::willDeliverMutationRecords(ExecutionContext* contex t, MutationObserver* observer)
787 {
788 if (asyncCallStackTracker().isEnabled())
789 asyncCallStackTracker().willDeliverMutationRecords(context, observer);
790 }
791
792 void InspectorDebuggerAgent::didDeliverMutationRecords()
793 {
794 if (asyncCallStackTracker().isEnabled())
795 asyncCallStackTracker().didFireAsyncCall();
796 }
797
798 // void InspectorDebuggerAgent::didPostExecutionContextTask(ExecutionContext* co ntext, ExecutionContextTask* task)
799 // {
800 // if (asyncCallStackTracker().isEnabled() && !task->taskNameForInstrumentat ion().isEmpty())
801 // asyncCallStackTracker().didPostExecutionContextTask(context, task, sc riptDebugServer().currentCallFramesForAsyncStack());
802 // }
803
804 // void InspectorDebuggerAgent::didKillAllExecutionContextTasks(ExecutionContext * context)
805 // {
806 // if (asyncCallStackTracker().isEnabled())
807 // asyncCallStackTracker().didKillAllExecutionContextTasks(context);
808 // }
809
810 // void InspectorDebuggerAgent::willPerformExecutionContextTask(ExecutionContext * context, ExecutionContextTask* task)
811 // {
812 // if (asyncCallStackTracker().isEnabled())
813 // asyncCallStackTracker().willPerformExecutionContextTask(context, task );
814 // }
815
816 // void InspectorDebuggerAgent::didPerformExecutionContextTask()
817 // {
818 // if (asyncCallStackTracker().isEnabled())
819 // asyncCallStackTracker().didFireAsyncCall();
820 // }
821
822 int InspectorDebuggerAgent::traceAsyncOperationStarting(ExecutionContext* contex t, const String& operationName, int prevOperationId)
823 {
824 if (!asyncCallStackTracker().isEnabled())
825 return 0;
826 if (prevOperationId)
827 asyncCallStackTracker().traceAsyncOperationCompleted(context, prevOperat ionId);
828 return asyncCallStackTracker().traceAsyncOperationStarting(context, operatio nName, scriptDebugServer().currentCallFramesForAsyncStack());
829 }
830
831 void InspectorDebuggerAgent::traceAsyncOperationCompleted(ExecutionContext* cont ext, int operationId)
832 {
833 if (asyncCallStackTracker().isEnabled())
834 asyncCallStackTracker().traceAsyncOperationCompleted(context, operationI d);
835 }
836
837 void InspectorDebuggerAgent::traceAsyncOperationCompletedCallbackStarting(Execut ionContext* context, int operationId)
838 {
839 if (!asyncCallStackTracker().isEnabled())
840 return;
841 asyncCallStackTracker().traceAsyncCallbackStarting(context, operationId);
842 asyncCallStackTracker().traceAsyncOperationCompleted(context, operationId);
843 }
844
845 void InspectorDebuggerAgent::traceAsyncCallbackStarting(ExecutionContext* contex t, int operationId)
846 {
847 if (asyncCallStackTracker().isEnabled())
848 asyncCallStackTracker().traceAsyncCallbackStarting(context, operationId) ;
849 }
850
851 void InspectorDebuggerAgent::traceAsyncCallbackCompleted()
852 {
853 if (asyncCallStackTracker().isEnabled())
854 asyncCallStackTracker().didFireAsyncCall();
855 }
856
857 void InspectorDebuggerAgent::didReceiveV8AsyncTaskEvent(ExecutionContext* contex t, const String& eventType, const String& eventName, int id)
858 {
859 if (!asyncCallStackTracker().isEnabled())
860 return;
861 if (eventType == v8AsyncTaskEventEnqueue)
862 asyncCallStackTracker().didEnqueueV8AsyncTask(context, eventName, id, sc riptDebugServer().currentCallFramesForAsyncStack());
863 else if (eventType == v8AsyncTaskEventWillHandle)
864 asyncCallStackTracker().willHandleV8AsyncTask(context, eventName, id);
865 else if (eventType == v8AsyncTaskEventDidHandle)
866 asyncCallStackTracker().didFireAsyncCall();
867 else
868 ASSERT_NOT_REACHED();
869 }
870
871 void InspectorDebuggerAgent::didReceiveV8PromiseEvent(ScriptState* scriptState, v8::Handle<v8::Object> promise, v8::Handle<v8::Value> parentPromise, int status)
872 {
873 if (!m_promiseTracker.isEnabled())
874 return;
875 m_promiseTracker.didReceiveV8PromiseEvent(scriptState, promise, parentPromis e, status);
876 }
877
878 void InspectorDebuggerAgent::pause(ErrorString*)
879 {
880 if (m_javaScriptPauseScheduled || isPaused())
881 return;
882 clearBreakDetails();
883 m_javaScriptPauseScheduled = true;
884 scriptDebugServer().setPauseOnNextStatement(true);
885 }
886
887 void InspectorDebuggerAgent::resume(ErrorString* errorString)
888 {
889 if (!assertPaused(errorString))
890 return;
891 m_debuggerStepScheduled = false;
892 m_steppingFromFramework = false;
893 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtrac eObjectGroup);
894 scriptDebugServer().continueProgram();
895 }
896
897 void InspectorDebuggerAgent::stepOver(ErrorString* errorString)
898 {
899 if (!assertPaused(errorString))
900 return;
901 m_debuggerStepScheduled = true;
902 m_steppingFromFramework = isTopCallFrameInFramework();
903 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtrac eObjectGroup);
904 scriptDebugServer().stepOverStatement();
905 }
906
907 void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
908 {
909 if (!assertPaused(errorString))
910 return;
911 m_debuggerStepScheduled = true;
912 m_steppingFromFramework = isTopCallFrameInFramework();
913 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtrac eObjectGroup);
914 scriptDebugServer().stepIntoStatement();
915 if (m_listener)
916 m_listener->stepInto();
917 }
918
919 void InspectorDebuggerAgent::stepOut(ErrorString* errorString)
920 {
921 if (!assertPaused(errorString))
922 return;
923 m_debuggerStepScheduled = true;
924 m_steppingFromFramework = isTopCallFrameInFramework();
925 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtrac eObjectGroup);
926 scriptDebugServer().stepOutOfFunction();
927 }
928
929 void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString* errorString, cons t String& stringPauseState)
930 {
931 ScriptDebugServer::PauseOnExceptionsState pauseState;
932 if (stringPauseState == "none")
933 pauseState = ScriptDebugServer::DontPauseOnExceptions;
934 else if (stringPauseState == "all")
935 pauseState = ScriptDebugServer::PauseOnAllExceptions;
936 else if (stringPauseState == "uncaught")
937 pauseState = ScriptDebugServer::PauseOnUncaughtExceptions;
938 else {
939 *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
940 return;
941 }
942 setPauseOnExceptionsImpl(errorString, pauseState);
943 }
944
945 void InspectorDebuggerAgent::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
946 {
947 scriptDebugServer().setPauseOnExceptionsState(static_cast<ScriptDebugServer: :PauseOnExceptionsState>(pauseState));
948 if (scriptDebugServer().pauseOnExceptionsState() != pauseState)
949 *errorString = "Internal error. Could not change pause on exceptions sta te";
950 else
951 m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, pauseState) ;
952 }
953
954 void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptio nsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown, RefPtr<Ty peBuilder::Debugger::ExceptionDetails>& exceptionDetails)
955 {
956 if (!isPaused() || m_currentCallStack.isEmpty()) {
957 *errorString = "Attempt to access callframe when debugger is not on paus e";
958 return;
959 }
960 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForOb jectId(callFrameId);
961 if (injectedScript.isEmpty()) {
962 *errorString = "Inspected frame has gone";
963 return;
964 }
965
966 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = s criptDebugServer().pauseOnExceptionsState();
967 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
968 if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExce ptions)
969 scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::Don tPauseOnExceptions);
970 muteConsole();
971 }
972
973 Vector<ScriptValue> asyncCallStacks;
974 const AsyncCallStackTracker::AsyncCallChain* asyncChain = asyncCallStackTrac ker().isEnabled() ? asyncCallStackTracker().currentAsyncCallChain() : 0;
975 if (asyncChain) {
976 const AsyncCallStackTracker::AsyncCallStackVector& callStacks = asyncCha in->callStacks();
977 asyncCallStacks.resize(callStacks.size());
978 AsyncCallStackTracker::AsyncCallStackVector::const_iterator it = callSta cks.begin();
979 for (size_t i = 0; it != callStacks.end(); ++it, ++i)
980 asyncCallStacks[i] = (*it)->callFrames();
981 }
982
983 injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack, asyncCal lStacks, callFrameId, expression, objectGroup ? *objectGroup : "", asBool(includ eCommandLineAPI), asBool(returnByValue), asBool(generatePreview), &result, wasTh rown, &exceptionDetails);
984 // V8 doesn't generate afterCompile event when it's in debugger therefore th ere is no content of evaluated scripts on frontend
985 // therefore contents of the stack does not provide necessary information
986 if (exceptionDetails)
987 exceptionDetails->setStackTrace(TypeBuilder::Array<TypeBuilder::Console: :CallFrame>::create());
988 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
989 unmuteConsole();
990 if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExcep tionsState)
991 scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExcepti onsState);
992 }
993 }
994
995 namespace {
996
997 PassRefPtr<TypeBuilder::Console::CallFrame> buildInspectorObject(const ScriptCal lFrame& frame)
998 {
999 return TypeBuilder::Console::CallFrame::create()
1000 .setFunctionName(frame.functionName())
1001 .setScriptId(frame.scriptId())
1002 .setUrl(frame.sourceURL())
1003 .setLineNumber(frame.lineNumber())
1004 .setColumnNumber(frame.columnNumber())
1005 .release();
1006 }
1007
1008 PassRefPtr<TypeBuilder::Array<TypeBuilder::Console::CallFrame> > buildInspectorA rray(const RefPtr<ScriptCallStack>& stack)
1009 {
1010 RefPtr<TypeBuilder::Array<TypeBuilder::Console::CallFrame> > frames = TypeBu ilder::Array<TypeBuilder::Console::CallFrame>::create();
1011 for (size_t i = 0; i < stack->size(); i++)
1012 frames->addItem(buildInspectorObject(stack->at(i)));
1013 return frames;
1014 }
1015
1016 } // namespace
1017
1018 void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const Strin g& expression, const String& sourceURL, const int* executionContextId, TypeBuild er::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails)
1019 {
1020 InjectedScript injectedScript = injectedScriptForEval(errorString, execution ContextId);
1021 if (injectedScript.isEmpty()) {
1022 *errorString = "Inspected frame has gone";
1023 return;
1024 }
1025
1026 String scriptIdValue;
1027 String exceptionDetailsText;
1028 int lineNumberValue = 0;
1029 int columnNumberValue = 0;
1030 RefPtr<ScriptCallStack> stackTraceValue;
1031 scriptDebugServer().compileScript(injectedScript.scriptState(), expression, sourceURL, &scriptIdValue, &exceptionDetailsText, &lineNumberValue, &columnNumbe rValue, &stackTraceValue);
1032 if (!scriptIdValue && !exceptionDetailsText) {
1033 *errorString = "Script compilation failed";
1034 return;
1035 }
1036 *scriptId = scriptIdValue;
1037 if (!scriptIdValue.isEmpty())
1038 return;
1039
1040 exceptionDetails = ExceptionDetails::create().setText(exceptionDetailsText);
1041 exceptionDetails->setLine(lineNumberValue);
1042 exceptionDetails->setColumn(columnNumberValue);
1043 if (stackTraceValue && stackTraceValue->size() > 0)
1044 exceptionDetails->setStackTrace(buildInspectorArray(stackTraceValue));
1045 }
1046
1047 void InspectorDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails)
1048 {
1049 InjectedScript injectedScript = injectedScriptForEval(errorString, execution ContextId);
1050 if (injectedScript.isEmpty()) {
1051 *errorString = "Inspected frame has gone";
1052 return;
1053 }
1054
1055 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = s criptDebugServer().pauseOnExceptionsState();
1056 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
1057 if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExce ptions)
1058 scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::Don tPauseOnExceptions);
1059 muteConsole();
1060 }
1061
1062 ScriptValue value;
1063 bool wasThrownValue;
1064 String exceptionDetailsText;
1065 int lineNumberValue = 0;
1066 int columnNumberValue = 0;
1067 RefPtr<ScriptCallStack> stackTraceValue;
1068 scriptDebugServer().runScript(injectedScript.scriptState(), scriptId, &value , &wasThrownValue, &exceptionDetailsText, &lineNumberValue, &columnNumberValue, &stackTraceValue);
1069 if (value.isEmpty()) {
1070 *errorString = "Script execution failed";
1071 return;
1072 }
1073 result = injectedScript.wrapObject(value, objectGroup ? *objectGroup : "");
1074 if (wasThrownValue) {
1075 exceptionDetails = ExceptionDetails::create().setText(exceptionDetailsTe xt);
1076 exceptionDetails->setLine(lineNumberValue);
1077 exceptionDetails->setColumn(columnNumberValue);
1078 if (stackTraceValue && stackTraceValue->size() > 0)
1079 exceptionDetails->setStackTrace(buildInspectorArray(stackTraceValue) );
1080 }
1081
1082 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
1083 unmuteConsole();
1084 if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExcep tionsState)
1085 scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExcepti onsState);
1086 }
1087 }
1088
1089 void InspectorDebuggerAgent::setOverlayMessage(ErrorString*, const String*)
1090 {
1091 }
1092
1093 void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, int scop eNumber, const String& variableName, const RefPtr<JSONObject>& newValue, const S tring* callFrameId, const String* functionObjectId)
1094 {
1095 InjectedScript injectedScript;
1096 if (callFrameId) {
1097 if (!isPaused() || m_currentCallStack.isEmpty()) {
1098 *errorString = "Attempt to access callframe when debugger is not on pause";
1099 return;
1100 }
1101 injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*cal lFrameId);
1102 if (injectedScript.isEmpty()) {
1103 *errorString = "Inspected frame has gone";
1104 return;
1105 }
1106 } else if (functionObjectId) {
1107 injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*fun ctionObjectId);
1108 if (injectedScript.isEmpty()) {
1109 *errorString = "Function object id cannot be resolved";
1110 return;
1111 }
1112 } else {
1113 *errorString = "Either call frame or function object must be specified";
1114 return;
1115 }
1116 String newValueString = newValue->toJSONString();
1117
1118 injectedScript.setVariableValue(errorString, m_currentCallStack, callFrameId , functionObjectId, scopeNumber, variableName, newValueString);
1119 }
1120
1121 void InspectorDebuggerAgent::skipStackFrames(ErrorString* errorString, const Str ing* pattern)
1122 {
1123 OwnPtr<ScriptRegexp> compiled;
1124 String patternValue = pattern ? *pattern : "";
1125 if (!patternValue.isEmpty()) {
1126 compiled = compileSkipCallFramePattern(patternValue);
1127 if (!compiled) {
1128 *errorString = "Invalid regular expression";
1129 return;
1130 }
1131 }
1132 m_state->setString(DebuggerAgentState::skipStackPattern, patternValue);
1133 m_cachedSkipStackRegExp = compiled.release();
1134 }
1135
1136 void InspectorDebuggerAgent::setAsyncCallStackDepth(ErrorString*, int depth)
1137 {
1138 m_state->setLong(DebuggerAgentState::asyncCallStackDepth, depth);
1139 asyncCallStackTracker().setAsyncCallStackDepth(depth);
1140 }
1141
1142 void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directive Text)
1143 {
1144 if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontP auseOnExceptions) {
1145 RefPtr<JSONObject> directive = JSONObject::create();
1146 directive->setString("directiveText", directiveText);
1147 breakProgram(InspectorFrontend::Debugger::Reason::CSPViolation, directiv e.release());
1148 }
1149 }
1150
1151 PassRefPtr<Array<CallFrame> > InspectorDebuggerAgent::currentCallFrames()
1152 {
1153 if (!m_pausedScriptState || m_currentCallStack.isEmpty())
1154 return Array<CallFrame>::create();
1155 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m _pausedScriptState.get());
1156 if (injectedScript.isEmpty()) {
1157 ASSERT_NOT_REACHED();
1158 return Array<CallFrame>::create();
1159 }
1160 return injectedScript.wrapCallFrames(m_currentCallStack, 0);
1161 }
1162
1163 PassRefPtr<StackTrace> InspectorDebuggerAgent::currentAsyncStackTrace()
1164 {
1165 if (!m_pausedScriptState || !asyncCallStackTracker().isEnabled())
1166 return nullptr;
1167 const AsyncCallStackTracker::AsyncCallChain* chain = asyncCallStackTracker() .currentAsyncCallChain();
1168 if (!chain)
1169 return nullptr;
1170 const AsyncCallStackTracker::AsyncCallStackVector& callStacks = chain->callS tacks();
1171 if (callStacks.isEmpty())
1172 return nullptr;
1173 RefPtr<StackTrace> result;
1174 int asyncOrdinal = callStacks.size();
1175 for (AsyncCallStackTracker::AsyncCallStackVector::const_reverse_iterator it = callStacks.rbegin(); it != callStacks.rend(); ++it, --asyncOrdinal) {
1176 ScriptValue callFrames = (*it)->callFrames();
1177 ScriptState* scriptState = callFrames.scriptState();
1178 InjectedScript injectedScript = scriptState ? m_injectedScriptManager->i njectedScriptFor(scriptState) : InjectedScript();
1179 if (injectedScript.isEmpty()) {
1180 result.clear();
1181 continue;
1182 }
1183 RefPtr<StackTrace> next = StackTrace::create()
1184 .setCallFrames(injectedScript.wrapCallFrames(callFrames, asyncOrdina l))
1185 .release();
1186 next->setDescription((*it)->description());
1187 if (result)
1188 next->setAsyncStackTrace(result.release());
1189 result.swap(next);
1190 }
1191 return result.release();
1192 }
1193
1194 String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script, Compi leResult compileResult)
1195 {
1196 bool hasSyntaxError = compileResult != CompileSuccess;
1197 if (hasSyntaxError) {
1198 bool deprecated;
1199 String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source , ContentSearchUtils::JavaScriptMagicComment, &deprecated);
1200 if (!sourceMapURL.isEmpty())
1201 return sourceMapURL;
1202 }
1203
1204 if (!script.sourceMappingURL.isEmpty())
1205 return script.sourceMappingURL;
1206
1207 return String();
1208 // FIXME(sky): Fetch from page agent.
1209 }
1210
1211 // ScriptDebugListener functions
1212
1213 void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script & parsedScript, CompileResult compileResult)
1214 {
1215 Script script = parsedScript;
1216 const bool* isContentScript = script.isContentScript ? &script.isContentScri pt : 0;
1217
1218 bool hasSyntaxError = compileResult != CompileSuccess;
1219 if (!script.startLine && !script.startColumn) {
1220 if (hasSyntaxError) {
1221 bool deprecated;
1222 script.sourceURL = ContentSearchUtils::findSourceURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
1223 }
1224 } else {
1225 script.sourceURL = String();
1226 }
1227
1228 bool hasSourceURL = !script.sourceURL.isEmpty();
1229 String scriptURL = hasSourceURL ? script.sourceURL : script.url;
1230
1231 String sourceMapURL = sourceMapURLForScript(script, compileResult);
1232 String* sourceMapURLParam = sourceMapURL.isNull() ? 0 : &sourceMapURL;
1233
1234 bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : 0;
1235 if (!hasSyntaxError)
1236 m_frontend->scriptParsed(scriptId, scriptURL, script.startLine, script.s tartColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam , hasSourceURLParam);
1237 else
1238 m_frontend->scriptFailedToParse(scriptId, scriptURL, script.startLine, s cript.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapU RLParam, hasSourceURLParam);
1239
1240 m_scripts.set(scriptId, script);
1241
1242 if (scriptURL.isEmpty() || hasSyntaxError)
1243 return;
1244
1245 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState ::javaScriptBreakpoints);
1246 for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpoints Cookie->end(); ++it) {
1247 RefPtr<JSONObject> breakpointObject = it->value->asObject();
1248 bool isAntibreakpoint;
1249 breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoi nt);
1250 if (isAntibreakpoint)
1251 continue;
1252 bool isRegex;
1253 breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
1254 String url;
1255 breakpointObject->getString(DebuggerAgentState::url, &url);
1256 if (!matches(scriptURL, url, isRegex))
1257 continue;
1258 ScriptBreakpoint breakpoint;
1259 breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakpoint. lineNumber);
1260 breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakpoin t.columnNumber);
1261 breakpointObject->getString(DebuggerAgentState::condition, &breakpoint.c ondition);
1262 RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it- >key, scriptId, breakpoint, UserBreakpointSource);
1263 if (location)
1264 m_frontend->breakpointResolved(it->key, location);
1265 }
1266 }
1267
1268 // FIXME(sky): This is a hack to make the debugger not break in the js inspector
1269 // so it works even while v8 is paused. crbug.com/434510
1270 bool InspectorDebuggerAgent::shouldSkipInspectorInternals()
1271 {
1272 RefPtr<JavaScriptCallFrame> topFrame = topCallFrameSkipUnknownSources();
1273 if (!topFrame)
1274 return false;
1275
1276 KURL url = KURL(ParsedURLString, scriptURL(topFrame.get()));
1277 return url.path().startsWith("/sky/framework")
1278 || url.path().startsWith("/sky/services")
1279 || url.path().startsWith("/mojo");
1280 }
1281
1282 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::didPause(ScriptSta te* scriptState, const ScriptValue& callFrames, const ScriptValue& exception, co nst Vector<String>& hitBreakpoints)
1283 {
1284 ScriptDebugListener::SkipPauseRequest result;
1285 if (callFrames.isEmpty() || shouldSkipInspectorInternals())
1286 result = ScriptDebugListener::Continue; // Skip pauses inside V8 interna l scripts and on syntax errors.
1287 else if (m_javaScriptPauseScheduled)
1288 result = ScriptDebugListener::NoSkip; // Don't skip explicit pause reque sts from front-end.
1289 else if (m_skipAllPauses)
1290 result = ScriptDebugListener::Continue;
1291 else if (!hitBreakpoints.isEmpty())
1292 result = ScriptDebugListener::NoSkip; // Don't skip explicit breakpoints even if set in frameworks.
1293 else if (!exception.isEmpty())
1294 result = shouldSkipExceptionPause();
1295 else if (m_debuggerStepScheduled || m_pausingOnNativeEvent)
1296 result = shouldSkipStepPause();
1297 else
1298 result = ScriptDebugListener::NoSkip;
1299
1300 if (result != ScriptDebugListener::NoSkip)
1301 return result;
1302
1303 ASSERT(scriptState && !m_pausedScriptState);
1304 m_pausedScriptState = scriptState;
1305 m_currentCallStack = callFrames;
1306
1307 if (!exception.isEmpty()) {
1308 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptF or(scriptState);
1309 if (!injectedScript.isEmpty()) {
1310 m_breakReason = InspectorFrontend::Debugger::Reason::Exception;
1311 m_breakAuxData = injectedScript.wrapObject(exception, InspectorDebug gerAgent::backtraceObjectGroup)->openAccessors();
1312 // m_breakAuxData might be null after this.
1313 }
1314 }
1315
1316 RefPtr<Array<String> > hitBreakpointIds = Array<String>::create();
1317
1318 for (Vector<String>::const_iterator i = hitBreakpoints.begin(); i != hitBrea kpoints.end(); ++i) {
1319 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator breakpointIter ator = m_serverBreakpoints.find(*i);
1320 if (breakpointIterator != m_serverBreakpoints.end()) {
1321 const String& localId = breakpointIterator->value.first;
1322 hitBreakpointIds->addItem(localId);
1323
1324 BreakpointSource source = breakpointIterator->value.second;
1325 if (m_breakReason == InspectorFrontend::Debugger::Reason::Other && s ource == DebugCommandBreakpointSource)
1326 m_breakReason = InspectorFrontend::Debugger::Reason::DebugComman d;
1327 }
1328 }
1329
1330 m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData, hitBr eakpointIds, currentAsyncStackTrace());
1331 m_javaScriptPauseScheduled = false;
1332 m_debuggerStepScheduled = false;
1333 m_steppingFromFramework = false;
1334 m_pausingOnNativeEvent = false;
1335 m_skippedStepInCount = 0;
1336
1337 if (!m_continueToLocationBreakpointId.isEmpty()) {
1338 scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
1339 m_continueToLocationBreakpointId = "";
1340 }
1341 if (m_listener)
1342 m_listener->didPause();
1343 return result;
1344 }
1345
1346 void InspectorDebuggerAgent::didContinue()
1347 {
1348 m_pausedScriptState = nullptr;
1349 m_currentCallStack = ScriptValue();
1350 clearBreakDetails();
1351 m_frontend->resumed();
1352 }
1353
1354 bool InspectorDebuggerAgent::canBreakProgram()
1355 {
1356 return scriptDebugServer().canBreakProgram();
1357 }
1358
1359 void InspectorDebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::E num breakReason, PassRefPtr<JSONObject> data)
1360 {
1361 if (m_skipAllPauses)
1362 return;
1363 m_breakReason = breakReason;
1364 m_breakAuxData = data;
1365 m_debuggerStepScheduled = false;
1366 m_steppingFromFramework = false;
1367 m_pausingOnNativeEvent = false;
1368 scriptDebugServer().breakProgram();
1369 }
1370
1371 void InspectorDebuggerAgent::clear()
1372 {
1373 m_pausedScriptState = nullptr;
1374 m_currentCallStack = ScriptValue();
1375 m_scripts.clear();
1376 m_breakpointIdToDebugServerBreakpointIds.clear();
1377 asyncCallStackTracker().clear();
1378 m_promiseTracker.clear();
1379 m_continueToLocationBreakpointId = String();
1380 clearBreakDetails();
1381 m_javaScriptPauseScheduled = false;
1382 m_debuggerStepScheduled = false;
1383 m_steppingFromFramework = false;
1384 m_pausingOnNativeEvent = false;
1385 ErrorString error;
1386 setOverlayMessage(&error, 0);
1387 }
1388
1389 bool InspectorDebuggerAgent::assertPaused(ErrorString* errorString)
1390 {
1391 if (!m_pausedScriptState) {
1392 *errorString = "Can only perform operation while paused.";
1393 return false;
1394 }
1395 return true;
1396 }
1397
1398 void InspectorDebuggerAgent::clearBreakDetails()
1399 {
1400 m_breakReason = InspectorFrontend::Debugger::Reason::Other;
1401 m_breakAuxData = nullptr;
1402 }
1403
1404 void InspectorDebuggerAgent::setBreakpoint(const String& scriptId, int lineNumbe r, int columnNumber, BreakpointSource source, const String& condition)
1405 {
1406 String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumbe r, source);
1407 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
1408 resolveBreakpoint(breakpointId, scriptId, breakpoint, source);
1409 }
1410
1411 void InspectorDebuggerAgent::removeBreakpoint(const String& scriptId, int lineNu mber, int columnNumber, BreakpointSource source)
1412 {
1413 removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, so urce));
1414 }
1415
1416 void InspectorDebuggerAgent::reset()
1417 {
1418 m_scripts.clear();
1419 m_breakpointIdToDebugServerBreakpointIds.clear();
1420 asyncCallStackTracker().clear();
1421 m_promiseTracker.clear();
1422 if (m_frontend)
1423 m_frontend->globalObjectCleared();
1424 }
1425
1426 } // namespace blink
1427
OLDNEW
« no previous file with comments | « sky/engine/v8_inspector/InspectorDebuggerAgent.h ('k') | sky/engine/v8_inspector/InspectorFrontendChannel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698