WebCore/ChangeLog

 12010-04-07 Jaime Yap <jaimeyap@google.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Adds the ability to get the function symbol name when looking up the call location
 6 for records sent by the InspectorTimelineAgent.
 7 https://bugs.webkit.org/show_bug.cgi?id=36839
 8
 9 No new tests.
 10
 11 * bindings/js/ScriptCallStack.cpp:
 12 (WebCore::ScriptCallStack::callLocation):
 13 * bindings/js/ScriptCallStack.h:
 14 * bindings/v8/ScriptCallStack.cpp:
 15 (WebCore::ScriptCallStack::create):
 16 (WebCore::ScriptCallStack::callLocation):
 17 (WebCore::ScriptCallStack::ScriptCallStack):
 18 * bindings/v8/ScriptCallStack.h:
 19 * bindings/v8/ScriptDebugServer.cpp:
 20 (WebCore::ScriptDebugServer::createUtilityContext):
 21 (WebCore::ScriptDebugServer::topStackFrame):
 22 * bindings/v8/ScriptDebugServer.h:
 23 (WebCore::ScriptDebugServer::utilityContext):
 24 * bindings/v8/V8Proxy.cpp:
 25 * bindings/v8/V8Proxy.h:
 26 * inspector/TimelineRecordFactory.cpp:
 27 (WebCore::TimelineRecordFactory::createGenericRecord):
 28
1292010-04-07 Enrica Casucci <enrica@apple.com>
230
331 Reviewed by Darin Adler.
57223

WebCore/bindings/js/ScriptCallStack.cpp

@@void ScriptCallStack::initialize()
101101 m_initialized = true;
102102}
103103
104 bool ScriptCallStack::callLocation(String*, int*)
 104bool ScriptCallStack::callLocation(String*, int*, String*)
105105{
106106 return false;
107107}
57156

WebCore/bindings/js/ScriptCallStack.h

@@namespace WebCore {
5353 // frame retrieval methods
5454 const ScriptCallFrame &at(unsigned);
5555 unsigned size();
56  static bool callLocation(String*, int*);
 56 static bool callLocation(String*, int*, String*);
5757
5858 private:
5959 void initialize();
57156

WebCore/bindings/v8/ScriptCallStack.cpp

3232#include "ScriptCallStack.h"
3333
3434#include "ScriptController.h"
 35#include "ScriptDebugServer.h"
3536
3637#include <v8.h>
3738
3839#include "V8Binding.h"
39 #include "V8Proxy.h"
4040
4141namespace WebCore {
4242
4343ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) {
4444 String sourceName;
4545 int sourceLineNumber;
46  if (!callLocation(&sourceName, &sourceLineNumber))
 46 String funcName;
 47 if (!callLocation(&sourceName, &sourceLineNumber, &funcName))
4748 return 0;
48  return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber);
 49 return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber, funcName);
4950}
5051
51 bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber)
 52bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber, String* functionName)
5253{
53  if (!V8Proxy::sourceName(*sourceName) || !V8Proxy::sourceLineNumber(*sourceLineNumber))
 54 if (!ScriptDebugServer::topStackFrame(*sourceName, *sourceLineNumber, *functionName))
5455 return false;
5556 *sourceLineNumber += 1;
5657 return true;
5758}
5859
59 ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber)
60  : m_lastCaller(String(), sourceName, sourceLineNumber, arguments, skipArgumentCount)
 60ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String functionName)
 61 : m_lastCaller(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount)
6162 , m_scriptState(ScriptState::current())
6263{
6364}
57156

WebCore/bindings/v8/ScriptCallStack.h

@@namespace WebCore {
4747 static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0);
4848 ~ScriptCallStack();
4949
50  static bool callLocation(String* sourceName, int* sourceLineNumber);
 50 static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName);
5151
5252 const ScriptCallFrame& at(unsigned) const;
5353 // FIXME: implement retrieving and storing call stack trace

@@namespace WebCore {
5757 ScriptState* globalState() const { return m_scriptState; }
5858
5959 private:
60  ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber);
 60 ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName);
6161
6262 ScriptCallFrame m_lastCaller;
6363 ScriptState* m_scriptState;
57156

WebCore/bindings/v8/ScriptDebugServer.cpp

3333
3434#if ENABLE(JAVASCRIPT_DEBUGGER)
3535
 36#include "V8Binding.h"
 37#include <v8-debug.h>
 38
3639#include <wtf/StdLibExtras.h>
3740
3841namespace WebCore {
3942
 43v8::Persistent<v8::Context> ScriptDebugServer::s_utilityContext;
 44
4045ScriptDebugServer& ScriptDebugServer::shared()
4146{
4247 DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ());
4348 return server;
4449}
4550
 51// Create the utility context for holding JavaScript functions used internally
 52// which are not visible to JavaScript executing on the page.
 53void ScriptDebugServer::createUtilityContext()
 54{
 55 ASSERT(s_utilityContext.IsEmpty());
 56
 57 v8::HandleScope scope;
 58 v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New();
 59 s_utilityContext = v8::Context::New(0, globalTemplate);
 60 v8::Context::Scope contextScope(s_utilityContext);
 61
 62 // Compile JavaScript function for retrieving the source line, the source
 63 // name and the symbol name for the top JavaScript stack frame.
 64 DEFINE_STATIC_LOCAL(const char*, topStackFrame,
 65 ("function topStackFrame(exec_state) {"
 66 " if (!exec_state.frameCount())"
 67 " return undefined;"
 68 " var frame = exec_state.frame(0);"
 69 " var func = frame.func();"
 70 " var scriptName;"
 71 " if (func.resolved() && func.script())"
 72 " scriptName = func.script().name();"
 73 " return [scriptName, frame.sourceLine(), (func.name() || func.inferredName())];"
 74 "}"));
 75 v8::Script::Compile(v8::String::New(topStackFrame))->Run();
 76}
 77
 78bool ScriptDebugServer::topStackFrame(String& sourceName, int& lineNumber, String& functionName)
 79{
 80 v8::HandleScope scope;
 81 v8::Handle<v8::Context> v8UtilityContext = utilityContext();
 82 if (v8UtilityContext.IsEmpty())
 83 return false;
 84 v8::Context::Scope contextScope(v8UtilityContext);
 85 v8::Handle<v8::Function> topStackFrame;
 86 topStackFrame = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("topStackFrame")));
 87 if (topStackFrame.IsEmpty())
 88 return false;
 89 v8::Handle<v8::Value> value = v8::Debug::Call(topStackFrame);
 90 if (value.IsEmpty())
 91 return false;
 92 // If there is no top stack frame, we still return success, but fill the input params with defaults.
 93 if (value->IsUndefined()) {
 94 // Fallback to setting lineNumber to 0, and source and function name to "undefined".
 95 sourceName = toWebCoreString(value);
 96 lineNumber = 0;
 97 functionName = toWebCoreString(value);
 98 return true;
 99 }
 100 if (!value->IsArray())
 101 return false;
 102 v8::Local<v8::Object> jsArray = value->ToObject();
 103 v8::Local<v8::Value> sourceNameValue = jsArray->Get(0);
 104 v8::Local<v8::Value> lineNumberValue = jsArray->Get(1);
 105 v8::Local<v8::Value> functionNameValue = jsArray->Get(2);
 106 if (sourceNameValue.IsEmpty() || lineNumberValue.IsEmpty() || functionNameValue.IsEmpty())
 107 return false;
 108 sourceName = toWebCoreString(sourceNameValue);
 109 lineNumber = lineNumberValue->Int32Value();
 110 functionName = toWebCoreString(functionNameValue);
 111 return true;
 112}
 113
46114} // namespace WebCore
47115
48116#endif // ENABLE(JAVASCRIPT_DEBUGGER)
57156

WebCore/bindings/v8/ScriptDebugServer.h

@@class ScriptDebugListener;
4747class ScriptDebugServer : public Noncopyable {
4848public:
4949 static ScriptDebugServer& shared();
 50
 51 // Function for retrieving the source name, line number and function name for the top
 52 // JavaScript stack frame.
 53 //
 54 // It will return true if the caller information was successfully retrieved and written
 55 // into the function parameters, otherwise the function will return false. It may
 56 // fail due to a stack overflow in the underlying JavaScript implementation, handling
 57 // of such exception is up to the caller.
 58 static bool topStackFrame(String& sourceName, int& lineNumber, String& functionName);
5059
5160 void addListener(ScriptDebugListener*, Page*) { }
5261 void removeListener(ScriptDebugListener*, Page*) { }

@@public:
8089private:
8190 ScriptDebugServer() { }
8291 ~ScriptDebugServer() { }
 92
 93 static void createUtilityContext();
 94
 95 // Returns a local handle of the utility context.
 96 static v8::Local<v8::Context> utilityContext()
 97 {
 98 if (s_utilityContext.IsEmpty())
 99 createUtilityContext();
 100 return v8::Local<v8::Context>::New(s_utilityContext);
 101 }
 102
 103 // Utility context holding JavaScript functions used internally.
 104 static v8::Persistent<v8::Context> s_utilityContext;
83105};
84106
85107} // namespace WebCore
57156

WebCore/bindings/v8/V8Proxy.cpp

6868#include <stdio.h>
6969#include <utility>
7070#include <v8.h>
71 #include <v8-debug.h>
7271#include <wtf/Assertions.h>
7372#include <wtf/OwnArrayPtr.h>
7473#include <wtf/StdLibExtras.h>

7776
7877namespace WebCore {
7978
80 v8::Persistent<v8::Context> V8Proxy::m_utilityContext;
81 
8279// Static list of registered extensions
8380V8Extensions V8Proxy::m_extensions;
8481

@@void V8Proxy::processConsoleMessages()
755752 V8ConsoleMessage::processDelayed();
756753}
757754
758 // Create the utility context for holding JavaScript functions used internally
759 // which are not visible to JavaScript executing on the page.
760 void V8Proxy::createUtilityContext()
761 {
762  ASSERT(m_utilityContext.IsEmpty());
763 
764  v8::HandleScope scope;
765  v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New();
766  m_utilityContext = v8::Context::New(0, globalTemplate);
767  v8::Context::Scope contextScope(m_utilityContext);
768 
769  // Compile JavaScript function for retrieving the source line of the top
770  // JavaScript stack frame.
771  DEFINE_STATIC_LOCAL(const char*, frameSourceLineSource,
772  ("function frameSourceLine(exec_state) {"
773  " if (!exec_state.frameCount())"
774  " return undefined;"
775  " return exec_state.frame(0).sourceLine();"
776  "}"));
777  v8::Script::Compile(v8::String::New(frameSourceLineSource))->Run();
778 
779  // Compile JavaScript function for retrieving the source name of the top
780  // JavaScript stack frame.
781  DEFINE_STATIC_LOCAL(const char*, frameSourceNameSource,
782  ("function frameSourceName(exec_state) {"
783  " if (!exec_state.frameCount())"
784  " return undefined;"
785  " var frame = exec_state.frame(0);"
786  " if (frame.func().resolved() && "
787  " frame.func().script() && "
788  " frame.func().script().name()) {"
789  " return frame.func().script().name();"
790  " }"
791  "}"));
792  v8::Script::Compile(v8::String::New(frameSourceNameSource))->Run();
793 }
794 
795 bool V8Proxy::sourceLineNumber(int& result)
796 {
797  v8::HandleScope scope;
798  v8::Handle<v8::Context> v8UtilityContext = V8Proxy::utilityContext();
799  if (v8UtilityContext.IsEmpty())
800  return false;
801  v8::Context::Scope contextScope(v8UtilityContext);
802  v8::Handle<v8::Function> frameSourceLine;
803  frameSourceLine = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceLine")));
804  if (frameSourceLine.IsEmpty())
805  return false;
806  v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceLine);
807  if (value.IsEmpty())
808  return false;
809  result = value->Int32Value();
810  return true;
811 }
812 
813 bool V8Proxy::sourceName(String& result)
814 {
815  v8::HandleScope scope;
816  v8::Handle<v8::Context> v8UtilityContext = utilityContext();
817  if (v8UtilityContext.IsEmpty())
818  return false;
819  v8::Context::Scope contextScope(v8UtilityContext);
820  v8::Handle<v8::Function> frameSourceName;
821  frameSourceName = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceName")));
822  if (frameSourceName.IsEmpty())
823  return false;
824  v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceName);
825  if (value.IsEmpty())
826  return false;
827  result = toWebCoreString(value);
828  return true;
829 }
830 
831755void V8Proxy::registerExtensionWithV8(v8::Extension* extension)
832756{
833757 // If the extension exists in our list, it was already registered with V8.
57156

WebCore/bindings/v8/V8Proxy.h

@@namespace WebCore {
296296 // Process any pending JavaScript console messages.
297297 static void processConsoleMessages();
298298
299  // Function for retrieving the line number and source name for the top
300  // JavaScript stack frame.
301  //
302  // It will return true if the line number was successfully retrieved and written
303  // into the |result| parameter, otherwise the function will return false. It may
304  // fail due to a stck overflow in the underlying JavaScript implentation, handling
305  // of such exception is up to the caller.
306  static bool sourceLineNumber(int& result);
307  static bool sourceName(String& result);
308 
309299 v8::Local<v8::Context> context();
310300 v8::Local<v8::Context> mainWorldContext();
311301

@@namespace WebCore {
356346 static const char* svgExceptionName(int exceptionCode);
357347#endif
358348
359  static void createUtilityContext();
360 
361  // Returns a local handle of the utility context.
362  static v8::Local<v8::Context> utilityContext()
363  {
364  if (m_utilityContext.IsEmpty())
365  createUtilityContext();
366  return v8::Local<v8::Context>::New(m_utilityContext);
367  }
368 
369349 Frame* m_frame;
370350
371351 // For the moment, we have one of these. Soon we will have one per DOMWrapperWorld.
372352 RefPtr<V8DOMWindowShell> m_windowShell;
373 
374  // Utility context holding JavaScript functions used internally.
375  static v8::Persistent<v8::Context> m_utilityContext;
376353
377354 int m_handlerLineNumber;
378355
57156

WebCore/inspector/TimelineRecordFactory.cpp

@@ScriptObject TimelineRecordFactory::crea
5151
5252 String sourceName;
5353 int sourceLineNumber;
54  if (ScriptCallStack::callLocation(&sourceName, &sourceLineNumber) && sourceName != "undefined") {
 54 String functionName;
 55 if (ScriptCallStack::callLocation(&sourceName, &sourceLineNumber, &functionName) && sourceName != "undefined") {
5556 record.set("callerScriptName", sourceName);
5657 record.set("callerScriptLine", sourceLineNumber);
 58 record.set("callerFunctionName", functionName);
5759 }
5860 return record;
5961}
57156

LayoutTests/ChangeLog

 12010-04-07 Jaime Yap <jaimeyap@google.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4 Tests expectations changed due to the addition of the function symbol name for
 5 the call location for records sent by the InspectorTimelineAgent.
 6 https://bugs.webkit.org/show_bug.cgi?id=36839
 7
 8 No new tests.
 9
 10 * inspector/timeline-test.js:
 11 * platform/chromium-win/inspector/timeline-event-dispatch-expected.txt:
 12 * platform/chromium-win/inspector/timeline-mark-timeline-expected.txt:
 13 * platform/chromium-win/inspector/timeline-network-resource-expected.txt:
 14 * platform/chromium-win/inspector/timeline-paint-expected.txt:
 15 * platform/chromium-win/inspector/timeline-parse-html-expected.txt:
 16
1172010-04-07 Ojan Vafai <ojan@chromium.org>
218
319 Reviewed by Simon Fraser.
57223

LayoutTests/inspector/timeline-test.js

@@var timelineNonDeterministicProps = {
1010 width : 1,
1111 callerScriptName: 1,
1212 callerScriptLine: 1,
 13 callerFunctionName: 1,
1314 url : 1,
1415 usedHeapSize: 1,
1516 totalHeapSize: 1,
57156

LayoutTests/platform/chromium-win/inspector/timeline-event-dispatch-expected.txt

@@EventDispatch Properties:
55+ startTime : * DEFINED *
66+ callerScriptName : * DEFINED *
77+ callerScriptLine : * DEFINED *
 8+ callerFunctionName : * DEFINED *
89+ data : {
910+- type : mousedown
1011+ }
57156

LayoutTests/platform/chromium-win/inspector/timeline-mark-timeline-expected.txt

@@MarkTimeline Properties:
44+ startTime : * DEFINED *
55+ callerScriptName : * DEFINED *
66+ callerScriptLine : * DEFINED *
 7+ callerFunctionName : * DEFINED *
78+ data : {
89+- message : MARK TIMELINE
910+ }
57156

LayoutTests/platform/chromium-win/inspector/timeline-network-resource-expected.txt

@@ResourceSendRequest Properties:
55+ startTime : * DEFINED *
66+ callerScriptName : * DEFINED *
77+ callerScriptLine : * DEFINED *
 8+ callerFunctionName : * DEFINED *
89+ data : {
910+- identifier : * DEFINED *
1011+- url : * DEFINED *
57156

LayoutTests/platform/chromium-win/inspector/timeline-paint-expected.txt

@@Paint Properties:
44+ startTime : * DEFINED *
55+ callerScriptName : * DEFINED *
66+ callerScriptLine : * DEFINED *
 7+ callerFunctionName : * DEFINED *
78+ data : {
89+- x : 0
910+- y : 0
57156

LayoutTests/platform/chromium-win/inspector/timeline-parse-html-expected.txt

@@ParseHTML Properties:
44+ startTime : * DEFINED *
55+ callerScriptName : * DEFINED *
66+ callerScriptLine : * DEFINED *
 7+ callerFunctionName : * DEFINED *
78+ data : {
89+- length : 9
910+- startLine : 0
57156