OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2010-2011 Google Inc. All rights reserved. | 2 * Copyright (c) 2010-2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 25 matching lines...) Expand all Loading... |
36 #include "V8JavaScriptCallFrame.h" | 36 #include "V8JavaScriptCallFrame.h" |
37 #include "bindings/v8/ScopedPersistent.h" | 37 #include "bindings/v8/ScopedPersistent.h" |
38 #include "bindings/v8/ScriptObject.h" | 38 #include "bindings/v8/ScriptObject.h" |
39 #include "bindings/v8/V8Binding.h" | 39 #include "bindings/v8/V8Binding.h" |
40 #include "bindings/v8/V8RecursionScope.h" | 40 #include "bindings/v8/V8RecursionScope.h" |
41 #include "bindings/v8/V8ScriptRunner.h" | 41 #include "bindings/v8/V8ScriptRunner.h" |
42 #include "core/inspector/JavaScriptCallFrame.h" | 42 #include "core/inspector/JavaScriptCallFrame.h" |
43 #include "core/inspector/ScriptDebugListener.h" | 43 #include "core/inspector/ScriptDebugListener.h" |
44 #include "wtf/StdLibExtras.h" | 44 #include "wtf/StdLibExtras.h" |
45 #include "wtf/Vector.h" | 45 #include "wtf/Vector.h" |
| 46 #include "wtf/dtoa/utils.h" |
46 | 47 |
47 namespace WebCore { | 48 namespace WebCore { |
48 | 49 |
49 namespace { | 50 namespace { |
50 | 51 |
51 class ClientDataImpl : public v8::Debug::ClientData { | 52 class ClientDataImpl : public v8::Debug::ClientData { |
52 public: | 53 public: |
53 ClientDataImpl(PassOwnPtr<ScriptDebugServer::Task> task) : m_task(task) { } | 54 ClientDataImpl(PassOwnPtr<ScriptDebugServer::Task> task) : m_task(task) { } |
54 virtual ~ClientDataImpl() { } | 55 virtual ~ClientDataImpl() { } |
55 ScriptDebugServer::Task* task() const { return m_task.get(); } | 56 ScriptDebugServer::Task* task() const { return m_task.get(); } |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 void* p = v8::Handle<v8::External>::Cast(data)->Value(); | 376 void* p = v8::Handle<v8::External>::Cast(data)->Value(); |
376 return static_cast<ScriptDebugServer*>(p); | 377 return static_cast<ScriptDebugServer*>(p); |
377 } | 378 } |
378 | 379 |
379 v8::Handle<v8::Value> ScriptDebugServer::breakProgramCallback(const v8::Argument
s& args) | 380 v8::Handle<v8::Value> ScriptDebugServer::breakProgramCallback(const v8::Argument
s& args) |
380 { | 381 { |
381 ASSERT(2 == args.Length()); | 382 ASSERT(2 == args.Length()); |
382 | 383 |
383 ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data()); | 384 ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data()); |
384 v8::Handle<v8::Value> exception; | 385 v8::Handle<v8::Value> exception; |
385 thisPtr->breakProgram(v8::Handle<v8::Object>::Cast(args[0]), exception); | 386 v8::Handle<v8::Array> hitBreakpoints; |
| 387 thisPtr->breakProgram(v8::Handle<v8::Object>::Cast(args[0]), exception, hitB
reakpoints); |
386 return v8::Undefined(); | 388 return v8::Undefined(); |
387 } | 389 } |
388 | 390 |
389 void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState, v8::
Handle<v8::Value> exception) | 391 void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState, v8::
Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) |
390 { | 392 { |
391 // Don't allow nested breaks. | 393 // Don't allow nested breaks. |
392 if (isPaused()) | 394 if (isPaused()) |
393 return; | 395 return; |
394 | 396 |
395 ScriptDebugListener* listener = getDebugListenerForContext(m_pausedContext); | 397 ScriptDebugListener* listener = getDebugListenerForContext(m_pausedContext); |
396 if (!listener) | 398 if (!listener) |
397 return; | 399 return; |
398 | 400 |
| 401 Vector<String> breakpointIds; |
| 402 if (!hitBreakpointNumbers.IsEmpty()) { |
| 403 breakpointIds.resize(hitBreakpointNumbers->Length()); |
| 404 for (size_t i = 0; i < hitBreakpointNumbers->Length(); i++) |
| 405 breakpointIds[i] = toWebCoreStringWithUndefinedOrNullCheck(hitBreakp
ointNumbers->Get(i)); |
| 406 } |
| 407 |
399 m_executionState.set(m_isolate, executionState); | 408 m_executionState.set(m_isolate, executionState); |
400 ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedContext
); | 409 ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedContext
); |
401 listener->didPause(currentCallFrameState, currentCallFrame(), ScriptValue(ex
ception)); | 410 listener->didPause(currentCallFrameState, currentCallFrame(), ScriptValue(ex
ception), breakpointIds); |
402 | 411 |
403 m_runningNestedMessageLoop = true; | 412 m_runningNestedMessageLoop = true; |
404 runMessageLoopOnPause(m_pausedContext); | 413 runMessageLoopOnPause(m_pausedContext); |
405 m_runningNestedMessageLoop = false; | 414 m_runningNestedMessageLoop = false; |
406 } | 415 } |
407 | 416 |
| 417 void ScriptDebugServer::breakProgram(const v8::Debug::EventDetails& eventDetails
, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) |
| 418 { |
| 419 m_pausedContext = *eventDetails.GetEventContext(); |
| 420 breakProgram(eventDetails.GetExecutionState(), exception, hitBreakpointNumbe
rs); |
| 421 m_pausedContext.Clear(); |
| 422 } |
| 423 |
408 void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& even
tDetails) | 424 void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& even
tDetails) |
409 { | 425 { |
410 ScriptDebugServer* thisPtr = toScriptDebugServer(eventDetails.GetCallbackDat
a()); | 426 ScriptDebugServer* thisPtr = toScriptDebugServer(eventDetails.GetCallbackDat
a()); |
411 thisPtr->handleV8DebugEvent(eventDetails); | 427 thisPtr->handleV8DebugEvent(eventDetails); |
412 } | 428 } |
413 | 429 |
414 void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD
etails) | 430 void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD
etails) |
415 { | 431 { |
416 v8::DebugEvent event = eventDetails.GetEvent(); | 432 v8::DebugEvent event = eventDetails.GetEvent(); |
417 | 433 |
(...skipping 29 matching lines...) Expand all Loading... |
447 v8::Handle<v8::Value> scriptName = getScriptNameFunction->Call(m_deb
uggerScript.get(), 1, argv1); | 463 v8::Handle<v8::Value> scriptName = getScriptNameFunction->Call(m_deb
uggerScript.get(), 1, argv1); |
448 | 464 |
449 v8::Handle<v8::Function> setScriptSourceFunction = v8::Local<v8::Fun
ction>::Cast(m_debuggerScript.get()->Get(v8::String::New("setScriptSource"))); | 465 v8::Handle<v8::Function> setScriptSourceFunction = v8::Local<v8::Fun
ction>::Cast(m_debuggerScript.get()->Get(v8::String::New("setScriptSource"))); |
450 String patchedScript = preprocessor->preprocessSourceCode(toWebCoreS
tringWithUndefinedOrNullCheck(script), toWebCoreStringWithUndefinedOrNullCheck(s
criptName)); | 466 String patchedScript = preprocessor->preprocessSourceCode(toWebCoreS
tringWithUndefinedOrNullCheck(script), toWebCoreStringWithUndefinedOrNullCheck(s
criptName)); |
451 | 467 |
452 v8::Handle<v8::Value> argv2[] = { eventDetails.GetEventData(), v8Str
ing(patchedScript, debugContext->GetIsolate()) }; | 468 v8::Handle<v8::Value> argv2[] = { eventDetails.GetEventData(), v8Str
ing(patchedScript, debugContext->GetIsolate()) }; |
453 setScriptSourceFunction->Call(m_debuggerScript.get(), 2, argv2); | 469 setScriptSourceFunction->Call(m_debuggerScript.get(), 2, argv2); |
454 m_scriptPreprocessor = preprocessor.release(); | 470 m_scriptPreprocessor = preprocessor.release(); |
455 } else if (event == v8::AfterCompile) { | 471 } else if (event == v8::AfterCompile) { |
456 v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); | 472 v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); |
457 v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Func
tion>::Cast(m_debuggerScript.get()->Get(v8::String::NewSymbol("getAfterCompileSc
ript"))); | 473 v8::Handle<v8::Function> getAfterCompileScript = v8::Local<v8::Funct
ion>::Cast(m_debuggerScript.get()->Get(v8::String::NewSymbol("getAfterCompileScr
ipt"))); |
458 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; | 474 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; |
459 v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debugge
rScript.get(), 1, argv); | 475 v8::Handle<v8::Value> value = getAfterCompileScript->Call(m_debugger
Script.get(), 1, argv); |
460 ASSERT(value->IsObject()); | 476 ASSERT(value->IsObject()); |
461 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); | 477 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); |
462 dispatchDidParseSource(listener, object); | 478 dispatchDidParseSource(listener, object); |
463 } else if (event == v8::Break || event == v8::Exception) { | 479 } else if (event == v8::Exception) { |
464 v8::Handle<v8::Value> exception; | 480 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackT
race(1); |
465 if (event == v8::Exception) { | 481 // Stack trace is empty in case of syntax error. Silently continue e
xecution in such cases. |
466 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentSt
ackTrace(1); | 482 if (!stackTrace->GetFrameCount()) |
467 // Stack trace is empty in case of syntax error. Silently contin
ue execution in such cases. | 483 return; |
468 if (!stackTrace->GetFrameCount()) | 484 v8::Handle<v8::Object> eventData = eventDetails.GetEventData(); |
469 return; | 485 v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8::Stri
ng::NewSymbol("exception")); |
470 v8::Handle<v8::Object> eventData = eventDetails.GetEventData(); | 486 ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFu
nction()); |
471 v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8::
String::NewSymbol("exception")); | 487 v8::Handle<v8::Value> argv[] = { v8Undefined() }; |
472 ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->
IsFunction()); | 488 V8RecursionScope::MicrotaskSuppression scope; |
473 v8::Handle<v8::Value> argv[] = { v8Undefined() }; | 489 v8::Handle<v8::Value> exception = v8::Handle<v8::Function>::Cast(exc
eptionGetterValue)->Call(eventData, 0, argv); |
474 V8RecursionScope::MicrotaskSuppression scope; | |
475 exception = v8::Handle<v8::Function>::Cast(exceptionGetterValue)
->Call(eventData, 0, argv); | |
476 } | |
477 | 490 |
478 m_pausedContext = *eventContext; | 491 breakProgram(eventDetails, exception, v8::Handle<v8::Array>()); |
479 breakProgram(eventDetails.GetExecutionState(), exception); | 492 } else if (event == v8::Break) { |
480 m_pausedContext.Clear(); | 493 v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8
::Function>::Cast(m_debuggerScript.get()->Get(v8::String::NewSymbol("getBreakpoi
ntNumbers"))); |
| 494 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; |
| 495 v8::Handle<v8::Value> hitBreakpoints = getBreakpointNumbersFunction-
>Call(m_debuggerScript.get(), ARRAY_SIZE(argv), argv); |
| 496 ASSERT(hitBreakpoints->IsArray()); |
| 497 |
| 498 breakProgram(eventDetails, v8::Handle<v8::Value>(), hitBreakpoints.A
s<v8::Array>()); |
481 } | 499 } |
482 } | 500 } |
483 } | 501 } |
484 | 502 |
485 void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8
::Handle<v8::Object> object) | 503 void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8
::Handle<v8::Object> object) |
486 { | 504 { |
487 String sourceID = toWebCoreStringWithUndefinedOrNullCheck(object->Get(v8::St
ring::NewSymbol("id"))); | 505 String sourceID = toWebCoreStringWithUndefinedOrNullCheck(object->Get(v8::St
ring::NewSymbol("id"))); |
488 | 506 |
489 ScriptDebugListener::Script script; | 507 ScriptDebugListener::Script script; |
490 script.url = toWebCoreStringWithUndefinedOrNullCheck(object->Get(v8::String:
:NewSymbol("name"))); | 508 script.url = toWebCoreStringWithUndefinedOrNullCheck(object->Get(v8::String:
:NewSymbol("name"))); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 *wasThrown = true; | 620 *wasThrown = true; |
603 *result = ScriptValue(tryCatch.Exception()); | 621 *result = ScriptValue(tryCatch.Exception()); |
604 v8::Local<v8::Message> message = tryCatch.Message(); | 622 v8::Local<v8::Message> message = tryCatch.Message(); |
605 if (!message.IsEmpty()) | 623 if (!message.IsEmpty()) |
606 *exceptionMessage = toWebCoreStringWithUndefinedOrNullCheck(message-
>Get()); | 624 *exceptionMessage = toWebCoreStringWithUndefinedOrNullCheck(message-
>Get()); |
607 } else | 625 } else |
608 *result = ScriptValue(value); | 626 *result = ScriptValue(value); |
609 } | 627 } |
610 | 628 |
611 } // namespace WebCore | 629 } // namespace WebCore |
OLD | NEW |