WebCore/bindings/v8/ScriptCallStack.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  * 
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "ScriptCallStack.h"
       
    33 
       
    34 #include "InspectorValues.h"
       
    35 #include "ScriptController.h"
       
    36 #include "ScriptDebugServer.h"
       
    37 #include "ScriptScope.h"
       
    38 #include "V8Binding.h"
       
    39 
       
    40 #include <v8-debug.h>
       
    41 
       
    42 namespace WebCore {
       
    43 
       
    44 static void getFrameLocation(v8::Handle<v8::StackFrame> frame, String* sourceName, int* sourceLineNumber, String* functionName)
       
    45 {
       
    46     ASSERT(!frame.IsEmpty());
       
    47     v8::Local<v8::String> sourceNameValue(frame->GetScriptName());
       
    48     v8::Local<v8::String> functionNameValue(frame->GetFunctionName());
       
    49     *sourceName = sourceNameValue.IsEmpty() ? "" : toWebCoreString(sourceNameValue);
       
    50     *functionName = functionNameValue.IsEmpty() ? "" : toWebCoreString(functionNameValue);
       
    51     *sourceLineNumber = frame->GetLineNumber();
       
    52 }
       
    53 
       
    54 static void getTopFrameLocation(v8::Handle<v8::StackTrace> stackTrace, String* sourceName, int* sourceLineNumber, String* functionName)
       
    55 {
       
    56     if (stackTrace->GetFrameCount() <= 0) {
       
    57         // Successfully grabbed stack trace, but there are no frames. It may happen in case of a syntax error for example.
       
    58         // Fallback to setting lineNumber to 0, and source and function name to "undefined".
       
    59         *sourceName = "undefined";
       
    60         *sourceLineNumber = 0;
       
    61         *functionName = "undefined";
       
    62     } else {
       
    63         v8::Handle<v8::StackFrame> frame = stackTrace->GetFrame(0);
       
    64         getFrameLocation(frame, sourceName, sourceLineNumber, functionName);
       
    65     }
       
    66 }
       
    67 
       
    68 static PassOwnPtr<ScriptCallFrame> toScriptCallFrame(v8::Handle<v8::StackFrame> frame)
       
    69 {
       
    70     String sourceName;
       
    71     int sourceLineNumber;
       
    72     String functionName;
       
    73     getFrameLocation(frame, &sourceName, &sourceLineNumber, &functionName);
       
    74     return new ScriptCallFrame(functionName, sourceName, sourceLineNumber);
       
    75 }
       
    76 
       
    77 static void toScriptCallFramesVector(v8::Local<v8::Context> context, v8::Handle<v8::StackTrace> stackTrace, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames)
       
    78 {
       
    79     v8::Context::Scope contextScope(context);
       
    80     int frameCount = stackTrace->GetFrameCount();
       
    81     for (int i = 0; i < frameCount; i++) {
       
    82         v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i);
       
    83         scriptCallFrames.append(toScriptCallFrame(stackFrame));
       
    84     }
       
    85 }
       
    86 
       
    87 const int ScriptCallStack::maxCallStackSizeToCapture = 200;
       
    88 
       
    89 PassOwnPtr<ScriptCallStack> ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount, int framCountLimit)
       
    90 {
       
    91     v8::HandleScope scope;
       
    92     v8::Local<v8::Context> context = v8::Context::GetCurrent();
       
    93     v8::Context::Scope contextScope(context);
       
    94     v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(framCountLimit));
       
    95 
       
    96     if (stackTrace.IsEmpty())
       
    97         return 0;
       
    98 
       
    99     String sourceName;
       
   100     int sourceLineNumber;
       
   101     String functionName;
       
   102     getTopFrameLocation(stackTrace, &sourceName, &sourceLineNumber, &functionName);
       
   103 
       
   104     Vector<OwnPtr<ScriptCallFrame> > scriptCallFrames;
       
   105     if (framCountLimit > 1)
       
   106         toScriptCallFramesVector(context, stackTrace, scriptCallFrames);
       
   107 
       
   108     return new ScriptCallStack(ScriptState::forContext(context), new ScriptCallFrame(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount), scriptCallFrames);
       
   109 }
       
   110 
       
   111 PassOwnPtr<ScriptCallStack> ScriptCallStack::create(ScriptState* state, v8::Handle<v8::StackTrace> stackTrace)
       
   112 {
       
   113     v8::HandleScope scope;
       
   114     Vector<OwnPtr<ScriptCallFrame> > scriptCallFrames;
       
   115     toScriptCallFramesVector(state->context(), stackTrace, scriptCallFrames);
       
   116 
       
   117     String sourceName;
       
   118     int sourceLineNumber;
       
   119     String functionName;
       
   120     getTopFrameLocation(stackTrace, &sourceName, &sourceLineNumber, &functionName);
       
   121 
       
   122     return new ScriptCallStack(state, new ScriptCallFrame(functionName, sourceName, sourceLineNumber), scriptCallFrames);
       
   123 }
       
   124 
       
   125 ScriptCallStack::ScriptCallStack(ScriptState* scriptState, PassOwnPtr<ScriptCallFrame> topFrame, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames)
       
   126     : m_topFrame(topFrame)
       
   127     , m_scriptState(scriptState)
       
   128 {
       
   129     m_scriptCallFrames.swap(scriptCallFrames);
       
   130 }
       
   131 
       
   132 ScriptCallStack::~ScriptCallStack()
       
   133 {
       
   134 }
       
   135 
       
   136 const ScriptCallFrame& ScriptCallStack::at(unsigned index)
       
   137 {
       
   138     if (!index && m_topFrame)
       
   139         return *m_topFrame;
       
   140     return *m_scriptCallFrames.at(index);
       
   141 }
       
   142 
       
   143 unsigned ScriptCallStack::size()
       
   144 {
       
   145     if (m_scriptCallFrames.isEmpty())
       
   146         return 1;
       
   147     return m_scriptCallFrames.size();
       
   148 }
       
   149 
       
   150 
       
   151 bool ScriptCallStack::stackTrace(int frameLimit, const RefPtr<InspectorArray>& stackTrace)
       
   152 {
       
   153 #if ENABLE(INSPECTOR)
       
   154     if (!v8::Context::InContext())
       
   155         return false;
       
   156     v8::Handle<v8::Context> context = v8::Context::GetCurrent();
       
   157     if (context.IsEmpty())
       
   158         return false;
       
   159     v8::HandleScope scope;
       
   160     v8::Context::Scope contextScope(context);
       
   161     v8::Handle<v8::StackTrace> trace(v8::StackTrace::CurrentStackTrace(frameLimit));
       
   162     int frameCount = trace->GetFrameCount();
       
   163     if (trace.IsEmpty() || !frameCount)
       
   164         return false;
       
   165     for (int i = 0; i < frameCount; ++i) {
       
   166         v8::Handle<v8::StackFrame> frame = trace->GetFrame(i);
       
   167         RefPtr<InspectorObject> frameObject = InspectorObject::create();
       
   168         v8::Local<v8::String> scriptName = frame->GetScriptName();
       
   169         frameObject->setString("scriptName", scriptName.IsEmpty() ? "" : toWebCoreString(scriptName));
       
   170         v8::Local<v8::String> functionName = frame->GetFunctionName();
       
   171         frameObject->setString("functionName", functionName.IsEmpty() ? "" : toWebCoreString(functionName));
       
   172         frameObject->setNumber("lineNumber", frame->GetLineNumber());
       
   173         frameObject->setNumber("column", frame->GetColumn());
       
   174         stackTrace->push(frameObject);
       
   175     }
       
   176     return true;
       
   177 #else
       
   178     return false;
       
   179 #endif
       
   180 }
       
   181 
       
   182 } // namespace WebCore