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

Side by Side Diff: Source/bindings/v8/ScriptDebugServer.cpp

Issue 13575004: Apply script preprocessor to Web page scripts only. (Closed) Base URL: https://chromium.googlesource.com/external/WebKit_trimmed.git@master
Patch Set: move clearScriptPreprocessor() to ScriptController::clearWindowShell Created 7 years, 5 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
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 16 matching lines...) Expand all
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "bindings/v8/ScriptDebugServer.h" 32 #include "bindings/v8/ScriptDebugServer.h"
33 33
34 #include "DebuggerScriptSource.h" 34 #include "DebuggerScriptSource.h"
35 #include "V8JavaScriptCallFrame.h" 35 #include "V8JavaScriptCallFrame.h"
36 #include "bindings/v8/ScopedPersistent.h" 36 #include "bindings/v8/ScopedPersistent.h"
37 #include "bindings/v8/ScriptController.h"
37 #include "bindings/v8/ScriptObject.h" 38 #include "bindings/v8/ScriptObject.h"
38 #include "bindings/v8/V8Binding.h" 39 #include "bindings/v8/V8Binding.h"
39 #include "bindings/v8/V8ScriptRunner.h" 40 #include "bindings/v8/V8ScriptRunner.h"
40 #include "core/inspector/JavaScriptCallFrame.h" 41 #include "core/inspector/JavaScriptCallFrame.h"
41 #include "core/inspector/ScriptDebugListener.h" 42 #include "core/inspector/ScriptDebugListener.h"
42 #include "wtf/StdLibExtras.h" 43 #include "wtf/StdLibExtras.h"
43 #include "wtf/Vector.h" 44 #include "wtf/Vector.h"
44 #include "wtf/dtoa/utils.h" 45 #include "wtf/dtoa/utils.h"
45 46
46 namespace WebCore { 47 namespace WebCore {
(...skipping 12 matching lines...) Expand all
59 } 60 }
60 61
61 v8::Local<v8::Value> ScriptDebugServer::callDebuggerMethod(const char* functionN ame, int argc, v8::Handle<v8::Value> argv[]) 62 v8::Local<v8::Value> ScriptDebugServer::callDebuggerMethod(const char* functionN ame, int argc, v8::Handle<v8::Value> argv[])
62 { 63 {
63 v8::Handle<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate) ; 64 v8::Handle<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate) ;
64 v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(debuggerSc ript->Get(v8::String::NewSymbol(functionName))); 65 v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(debuggerSc ript->Get(v8::String::NewSymbol(functionName)));
65 ASSERT(v8::Context::InContext()); 66 ASSERT(v8::Context::InContext());
66 return V8ScriptRunner::callInternalFunction(function, debuggerScript, argc, argv, m_isolate); 67 return V8ScriptRunner::callInternalFunction(function, debuggerScript, argc, argv, m_isolate);
67 } 68 }
68 69
69 class ScriptDebugServer::ScriptPreprocessor {
70 WTF_MAKE_NONCOPYABLE(ScriptPreprocessor);
71 public:
72 ScriptPreprocessor(const String& preprocessorScript, v8::Isolate* isolate)
73 : m_isolate(isolate)
74 {
75 v8::HandleScope scope(m_isolate);
76
77 v8::Local<v8::Context> context = v8::Context::New(m_isolate);
78 if (context.IsEmpty())
79 return;
80 v8::Context::Scope contextScope(context);
81
82 String wrappedScript = "(" + preprocessorScript + ")";
83 v8::Handle<v8::String> preprocessor = v8::String::New(wrappedScript.utf8 ().data(), wrappedScript.utf8().length());
84
85 v8::Local<v8::Value> preprocessorFunction = V8ScriptRunner::compileAndRu nInternalScript(preprocessor, m_isolate);
86 if (preprocessorFunction.IsEmpty() || !preprocessorFunction->IsFunction( ))
87 return;
88
89 m_utilityContext.set(isolate, context);
90 m_preprocessorFunction.set(isolate, v8::Handle<v8::Function>::Cast(prepr ocessorFunction));
91 }
92
93 String preprocessSourceCode(const String& sourceCode, const String& sourceNa me)
94 {
95 v8::HandleScope handleScope(m_isolate);
96
97 if (m_preprocessorFunction.isEmpty())
98 return sourceCode;
99
100 v8::Local<v8::Context> context = m_utilityContext.newLocal(m_isolate);
101 v8::Context::Scope contextScope(context);
102
103 v8::Handle<v8::String> sourceCodeString = v8::String::New(sourceCode.utf 8().data(), sourceCode.utf8().length());
104
105 v8::Handle<v8::String> sourceNameString = v8::String::New(sourceName.utf 8().data(), sourceName.utf8().length());
106 v8::Handle<v8::Value> argv[] = { sourceCodeString, sourceNameString };
107 v8::Handle<v8::Value> resultValue = V8ScriptRunner::callInternalFunction (m_preprocessorFunction.newLocal(m_isolate), context->Global(), WTF_ARRAY_LENGTH (argv), argv, m_isolate);
108
109 if (!resultValue.IsEmpty() && resultValue->IsString()) {
110 v8::String::Utf8Value utf8Value(resultValue);
111 return String::fromUTF8(*utf8Value, utf8Value.length());
112 }
113 return sourceCode;
114 }
115
116 ~ScriptPreprocessor()
117 {
118 }
119
120 private:
121 ScopedPersistent<v8::Context> m_utilityContext;
122 String m_preprocessorBody;
123 ScopedPersistent<v8::Function> m_preprocessorFunction;
124 v8::Isolate* m_isolate;
125 };
126
127 ScriptDebugServer::ScriptDebugServer(v8::Isolate* isolate) 70 ScriptDebugServer::ScriptDebugServer(v8::Isolate* isolate)
128 : m_pauseOnExceptionsState(DontPauseOnExceptions) 71 : m_pauseOnExceptionsState(DontPauseOnExceptions)
129 , m_breakpointsActivated(true) 72 , m_breakpointsActivated(true)
130 , m_runningNestedMessageLoop(false) 73 , m_runningNestedMessageLoop(false)
131 , m_isolate(isolate) 74 , m_isolate(isolate)
132 { 75 {
133 } 76 }
134 77
135 ScriptDebugServer::~ScriptDebugServer() 78 ScriptDebugServer::~ScriptDebugServer()
136 { 79 {
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 return false; 301 return false;
359 } 302 }
360 303
361 304
362 void ScriptDebugServer::updateCallStack(ScriptValue* callFrame) 305 void ScriptDebugServer::updateCallStack(ScriptValue* callFrame)
363 { 306 {
364 if (isPaused()) 307 if (isPaused())
365 *callFrame = currentCallFrame(); 308 *callFrame = currentCallFrame();
366 } 309 }
367 310
311 ScriptController* ScriptDebugServer::scriptController(v8::Handle<v8::Context> co ntext)
312 {
313 return 0;
314 }
368 315
369 void ScriptDebugServer::setScriptPreprocessor(const String& preprocessorBody) 316 void ScriptDebugServer::preprocessEval(v8::Handle<v8::Context> eventContext, v8: :Handle<v8::Object> eventData)
370 { 317 {
371 m_scriptPreprocessor.clear(); 318 ScriptController* controller = scriptController(eventContext);
372 if (!preprocessorBody.isEmpty()) 319 if (!controller)
373 m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(preprocessorBody, m_isolate)); 320 return;
321
322 // Don't examine event unless we are preprocessing Web page code.
323 if (!controller->hasScriptPreprocessor() || controller->isPreprocessingScrip t())
324 return;
325
326 v8::Local<v8::Context> debugContext = v8::Debug::GetDebugContext();
327 v8::Context::Scope contextScope(debugContext);
328
329 // <script> tag source and attribute value source are preprocessed before we enter V8.
330 // Avoid preprocessing any internal scripts by processing only eval source i n this V8 event handler.
331 v8::Handle<v8::Value> argvEventData[] = { eventData };
332 String typeInfo = toWebCoreStringWithUndefinedOrNullCheck(callDebuggerMethod ("getScriptCompilationTypeInfo", WTF_ARRAY_LENGTH(argvEventData), argvEventData) );
333 if (!typeInfo.startsWith("eval"))
334 return;
335
336 // The name and source are in the JS event data.
337 String scriptName = toWebCoreStringWithUndefinedOrNullCheck(callDebuggerMeth od("getScriptName", WTF_ARRAY_LENGTH(argvEventData), argvEventData));
338 String script = toWebCoreStringWithUndefinedOrNullCheck(callDebuggerMethod(" getScriptSource", WTF_ARRAY_LENGTH(argvEventData), argvEventData));
339
340 String patchedScript = controller->preprocess(script, scriptName);
341
342 v8::Handle<v8::Value> argvPatchedScript[] = { eventData, v8String(patchedScr ipt, debugContext->GetIsolate()) };
343 callDebuggerMethod("setScriptSource", WTF_ARRAY_LENGTH(argvPatchedScript), a rgvPatchedScript);
374 } 344 }
375 345
376 ScriptValue ScriptDebugServer::currentCallFrame() 346 ScriptValue ScriptDebugServer::currentCallFrame()
377 { 347 {
378 ASSERT(isPaused()); 348 ASSERT(isPaused());
379 v8::HandleScope handleScope(m_isolate); 349 v8::HandleScope handleScope(m_isolate);
380 v8::Handle<v8::Value> argv[] = { m_executionState.newLocal(m_isolate) }; 350 v8::Handle<v8::Value> argv[] = { m_executionState.newLocal(m_isolate) };
381 v8::Handle<v8::Value> currentCallFrameV8 = callDebuggerMethod("currentCallFr ame", 1, argv); 351 v8::Handle<v8::Value> currentCallFrameV8 = callDebuggerMethod("currentCallFr ame", 1, argv);
382 352
383 ASSERT(!currentCallFrameV8.IsEmpty()); 353 ASSERT(!currentCallFrameV8.IsEmpty());
(...skipping 17 matching lines...) Expand all
401 371
402 static ScriptDebugServer* toScriptDebugServer(v8::Handle<v8::Value> data) 372 static ScriptDebugServer* toScriptDebugServer(v8::Handle<v8::Value> data)
403 { 373 {
404 void* p = v8::Handle<v8::External>::Cast(data)->Value(); 374 void* p = v8::Handle<v8::External>::Cast(data)->Value();
405 return static_cast<ScriptDebugServer*>(p); 375 return static_cast<ScriptDebugServer*>(p);
406 } 376 }
407 377
408 void ScriptDebugServer::breakProgramCallback(const v8::FunctionCallbackInfo<v8:: Value>& args) 378 void ScriptDebugServer::breakProgramCallback(const v8::FunctionCallbackInfo<v8:: Value>& args)
409 { 379 {
410 ASSERT(2 == args.Length()); 380 ASSERT(2 == args.Length());
411
412 ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data()); 381 ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data());
413 v8::Handle<v8::Value> exception; 382 v8::Handle<v8::Value> exception;
414 v8::Handle<v8::Array> hitBreakpoints; 383 v8::Handle<v8::Array> hitBreakpoints;
415 thisPtr->handleProgramBreak(v8::Handle<v8::Object>::Cast(args[0]), exception , hitBreakpoints); 384 thisPtr->handleProgramBreak(v8::Handle<v8::Object>::Cast(args[0]), exception , hitBreakpoints);
416 } 385 }
417 386
418 void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState , v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) 387 void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState , v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers)
419 { 388 {
420 // Don't allow nested breaks. 389 // Don't allow nested breaks.
421 if (isPaused()) 390 if (isPaused())
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 } 434 }
466 435
467 if (event != v8::Break && event != v8::Exception && event != v8::AfterCompil e && event != v8::BeforeCompile) 436 if (event != v8::Break && event != v8::Exception && event != v8::AfterCompil e && event != v8::BeforeCompile)
468 return; 437 return;
469 438
470 v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext(); 439 v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext();
471 ASSERT(!eventContext.IsEmpty()); 440 ASSERT(!eventContext.IsEmpty());
472 441
473 ScriptDebugListener* listener = getDebugListenerForContext(eventContext); 442 ScriptDebugListener* listener = getDebugListenerForContext(eventContext);
474 if (listener) { 443 if (listener) {
475 v8::HandleScope scope(m_isolate);
476 v8::Local<v8::Context> debugContext = v8::Debug::GetDebugContext();
477 v8::Handle<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isol ate);
478 if (event == v8::BeforeCompile) { 444 if (event == v8::BeforeCompile) {
479 445 preprocessEval(eventContext, eventDetails.GetEventData());
480 if (!m_scriptPreprocessor)
481 return;
482
483 OwnPtr<ScriptPreprocessor> preprocessor(m_scriptPreprocessor.release ());
484 v8::Context::Scope contextScope(debugContext);
485 v8::Handle<v8::Function> getScriptSourceFunction = v8::Local<v8::Fun ction>::Cast(debuggerScript->Get(v8::String::New("getScriptSource")));
486 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
487 v8::Handle<v8::Value> script = V8ScriptRunner::callInternalFunction( getScriptSourceFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate );
488
489 v8::Handle<v8::Function> getScriptNameFunction = v8::Local<v8::Funct ion>::Cast(debuggerScript->Get(v8::String::New("getScriptName")));
490 v8::Handle<v8::Value> argv1[] = { eventDetails.GetEventData() };
491 v8::Handle<v8::Value> scriptName = V8ScriptRunner::callInternalFunct ion(getScriptNameFunction, debuggerScript, WTF_ARRAY_LENGTH(argv1), argv1, m_iso late);
492 v8::Handle<v8::Function> setScriptSourceFunction = v8::Local<v8::Fun ction>::Cast(debuggerScript->Get(v8::String::New("setScriptSource")));
493 String patchedScript = preprocessor->preprocessSourceCode(toWebCoreS tringWithUndefinedOrNullCheck(script), toWebCoreStringWithUndefinedOrNullCheck(s criptName));
494
495 v8::Handle<v8::Value> argv2[] = { eventDetails.GetEventData(), v8Str ing(patchedScript, m_isolate) };
496 V8ScriptRunner::callInternalFunction(setScriptSourceFunction, debugg erScript, WTF_ARRAY_LENGTH(argv2), argv2, m_isolate);
497 m_scriptPreprocessor = preprocessor.release();
498 } else if (event == v8::AfterCompile) { 446 } else if (event == v8::AfterCompile) {
499 v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); 447 v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
500 v8::Handle<v8::Function> getAfterCompileScript = v8::Local<v8::Funct ion>::Cast(debuggerScript->Get(v8::String::NewSymbol("getAfterCompileScript"))); 448 v8::Handle<v8::Function> getAfterCompileScript = v8::Local<v8::Funct ion>::Cast(m_debuggerScript.get()->Get(v8::String::NewSymbol("getAfterCompileScr ipt")));
haraken 2013/07/11 01:13:59 ScopedPersistent::get() returns an unsafe handle a
johnjbarton 2013/07/11 19:14:42 Done.
501 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; 449 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
502 v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(g etAfterCompileScript, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate); 450 v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(g etAfterCompileScript, m_debuggerScript.get(), WTF_ARRAY_LENGTH(argv), argv, m_is olate);
haraken 2013/07/11 01:13:59 Ditto.
johnjbarton 2013/07/11 19:14:42 Done.
503 ASSERT(value->IsObject()); 451 ASSERT(value->IsObject());
504 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 452 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
505 dispatchDidParseSource(listener, object); 453 dispatchDidParseSource(listener, object);
506 } else if (event == v8::Exception) { 454 } else if (event == v8::Exception) {
507 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackT race(1); 455 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackT race(1);
508 // Stack trace is empty in case of syntax error. Silently continue e xecution in such cases. 456 // Stack trace is empty in case of syntax error. Silently continue e xecution in such cases.
509 if (!stackTrace->GetFrameCount()) 457 if (!stackTrace->GetFrameCount())
510 return; 458 return;
511 v8::Handle<v8::Object> eventData = eventDetails.GetEventData(); 459 v8::Handle<v8::Object> eventData = eventDetails.GetEventData();
512 v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8::Stri ng::NewSymbol("exception")); 460 v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8::Stri ng::NewSymbol("exception"));
513 ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFu nction()); 461 ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFu nction());
514 v8::Handle<v8::Value> exception = V8ScriptRunner::callInternalFuncti on(v8::Handle<v8::Function>::Cast(exceptionGetterValue), eventData, 0, 0, m_isol ate); 462 v8::Handle<v8::Value> exception = V8ScriptRunner::callInternalFuncti on(v8::Handle<v8::Function>::Cast(exceptionGetterValue), eventData, 0, 0, m_isol ate);
515 handleProgramBreak(eventDetails, exception, v8::Handle<v8::Array>()) ; 463 handleProgramBreak(eventDetails, exception, v8::Handle<v8::Array>()) ;
516 } else if (event == v8::Break) { 464 } else if (event == v8::Break) {
517 v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8 ::Function>::Cast(debuggerScript->Get(v8::String::NewSymbol("getBreakpointNumber s"))); 465 v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8 ::Function>::Cast(m_debuggerScript.get()->Get(v8::String::NewSymbol("getBreakpoi ntNumbers")));
haraken 2013/07/11 01:13:59 Ditto.
johnjbarton 2013/07/11 19:14:42 Done.
518 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; 466 v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
519 v8::Handle<v8::Value> hitBreakpoints = V8ScriptRunner::callInternalF unction(getBreakpointNumbersFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), ar gv, m_isolate); 467 v8::Handle<v8::Value> hitBreakpoints = V8ScriptRunner::callInternalF unction(getBreakpointNumbersFunction, m_debuggerScript.get(), WTF_ARRAY_LENGTH(a rgv), argv, m_isolate);
haraken 2013/07/11 01:13:59 Ditto.
johnjbarton 2013/07/11 19:14:42 Done.
520 ASSERT(hitBreakpoints->IsArray()); 468 ASSERT(hitBreakpoints->IsArray());
521 469
522 handleProgramBreak(eventDetails, v8::Handle<v8::Value>(), hitBreakpo ints.As<v8::Array>()); 470 handleProgramBreak(eventDetails, v8::Handle<v8::Value>(), hitBreakpo ints.As<v8::Array>());
523 } 471 }
524 } 472 }
525 } 473 }
526 474
527 void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8 ::Handle<v8::Object> object) 475 void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8 ::Handle<v8::Object> object)
528 { 476 {
529 String sourceID = toWebCoreStringWithUndefinedOrNullCheck(object->Get(v8::St ring::NewSymbol("id"))); 477 String sourceID = toWebCoreStringWithUndefinedOrNullCheck(object->Get(v8::St ring::NewSymbol("id")));
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 *wasThrown = true; 592 *wasThrown = true;
645 *result = ScriptValue(tryCatch.Exception()); 593 *result = ScriptValue(tryCatch.Exception());
646 v8::Local<v8::Message> message = tryCatch.Message(); 594 v8::Local<v8::Message> message = tryCatch.Message();
647 if (!message.IsEmpty()) 595 if (!message.IsEmpty())
648 *exceptionMessage = toWebCoreStringWithUndefinedOrNullCheck(message- >Get()); 596 *exceptionMessage = toWebCoreStringWithUndefinedOrNullCheck(message- >Get());
649 } else 597 } else
650 *result = ScriptValue(value); 598 *result = ScriptValue(value);
651 } 599 }
652 600
653 } // namespace WebCore 601 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698