Changeset 164507 in webkit


Ignore:
Timestamp:
Feb 21, 2014, 3:35:32 PM (11 years ago)
Author:
Joseph Pecoraro
Message:

Web Inspector: JSContext inspection should report exceptions in the console
https://bugs.webkit.org/show_bug.cgi?id=128776

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

When JavaScript API functions have an exception, let the inspector
know so it can log the JavaScript and Native backtrace that caused
the exception.

Include some clean up of ConsoleMessage and ScriptCallStack construction.

  • API/JSBase.cpp:

(JSEvaluateScript):
(JSCheckScriptSyntax):

  • API/JSObjectRef.cpp:

(JSObjectMakeFunction):
(JSObjectMakeArray):
(JSObjectMakeDate):
(JSObjectMakeError):
(JSObjectMakeRegExp):
(JSObjectGetProperty):
(JSObjectSetProperty):
(JSObjectGetPropertyAtIndex):
(JSObjectSetPropertyAtIndex):
(JSObjectDeleteProperty):
(JSObjectCallAsFunction):
(JSObjectCallAsConstructor):

  • API/JSValue.mm:

(reportExceptionToInspector):
(valueToArray):
(valueToDictionary):

  • API/JSValueRef.cpp:

(JSValueIsEqual):
(JSValueIsInstanceOfConstructor):
(JSValueCreateJSONString):
(JSValueToNumber):
(JSValueToStringCopy):
(JSValueToObject):
When seeing an exception, let the inspector know there was an exception.

  • inspector/JSGlobalObjectInspectorController.h:
  • inspector/JSGlobalObjectInspectorController.cpp:

(Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
(Inspector::JSGlobalObjectInspectorController::appendAPIBacktrace):
(Inspector::JSGlobalObjectInspectorController::reportAPIException):
Log API exceptions by also grabbing the native backtrace.

  • inspector/ScriptCallStack.h:
  • inspector/ScriptCallStack.cpp:

(Inspector::ScriptCallStack::firstNonNativeCallFrame):
(Inspector::ScriptCallStack::append):
Minor extensions to ScriptCallStack to make it easier to work with.

  • inspector/ConsoleMessage.cpp:

(Inspector::ConsoleMessage::ConsoleMessage):
(Inspector::ConsoleMessage::autogenerateMetadata):
Provide better default information if the first call frame was native.

  • inspector/ScriptCallStackFactory.cpp:

(Inspector::createScriptCallStack):
(Inspector::extractSourceInformationFromException):
(Inspector::createScriptCallStackFromException):
Perform the handling here of inserting a fake call frame for exceptions
if there was no call stack (e.g. a SyntaxError) or if the first call
frame had no information.

  • inspector/ConsoleMessage.cpp:

(Inspector::ConsoleMessage::ConsoleMessage):
(Inspector::ConsoleMessage::autogenerateMetadata):

  • inspector/ConsoleMessage.h:
  • inspector/ScriptCallStackFactory.cpp:

(Inspector::createScriptCallStack):
(Inspector::createScriptCallStackForConsole):

  • inspector/ScriptCallStackFactory.h:
  • inspector/agents/InspectorConsoleAgent.cpp:

(Inspector::InspectorConsoleAgent::enable):
(Inspector::InspectorConsoleAgent::addMessageToConsole):
(Inspector::InspectorConsoleAgent::count):

  • inspector/agents/JSGlobalObjectDebuggerAgent.cpp:

(Inspector::JSGlobalObjectDebuggerAgent::breakpointActionLog):
ConsoleMessage cleanup.

Source/WebCore:

Include some clean up of ConsoleMessage and ScriptCallStack construction.

Covered by existing tests.

  • bindings/js/JSDOMBinding.cpp:

(WebCore::reportException):
Simplify code now that createStackTraceFromException handles it.

  • page/ContentSecurityPolicy.cpp:

(WebCore::gatherSecurityPolicyViolationEventData):
(WebCore::ContentSecurityPolicy::reportViolation):
ScriptCallStack can give us the first non-native callframe.

  • inspector/InspectorResourceAgent.cpp:

(WebCore::InspectorResourceAgent::buildInitiatorObject):

  • inspector/PageDebuggerAgent.cpp:

(WebCore::PageDebuggerAgent::breakpointActionLog):

  • inspector/TimelineRecordFactory.cpp:

(WebCore::TimelineRecordFactory::createGenericRecord):

  • page/Console.cpp:

(WebCore::internalAddMessage):
(WebCore::Console::profile):
(WebCore::Console::profileEnd):
(WebCore::Console::timeEnd):

  • page/ContentSecurityPolicy.cpp:

(WebCore::gatherSecurityPolicyViolationEventData):
(WebCore::ContentSecurityPolicy::reportViolation):

  • page/DOMWindow.cpp:

(WebCore::DOMWindow::postMessage):

Source/WebInspectorUI:

  • UserInterface/ConsoleMessageImpl.js:

(WebInspector.ConsoleMessageImpl.prototype._formatMessage):
(WebInspector.ConsoleMessageImpl.prototype._shouldHideURL):
(WebInspector.ConsoleMessageImpl.prototype._firstNonNativeCallFrame):
(WebInspector.ConsoleMessageImpl.prototype._populateStackTraceTreeElement):
Provide better handling for "[native code]" and legacy "undefined"
call frame URLs. Never linkify these. Also, when showing a link
for an exception, always use the first non-native call frame as
the link location.

Location:
trunk/Source
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/Source/JavaScriptCore/API/JSBase.cpp

    r164491 r164507  
    4141#include <wtf/text/StringHash.h>
    4242
     43#if ENABLE(REMOTE_INSPECTOR)
     44#include "JSGlobalObjectInspectorController.h"
     45#endif
     46
    4347using namespace JSC;
    4448
     
    6670        if (exception)
    6771            *exception = toRef(exec, evaluationException);
     72#if ENABLE(REMOTE_INSPECTOR)
     73        // FIXME: If we have a debugger attached we could learn about ParseError exceptions through
     74        // ScriptDebugServer::sourceParsed and this path could produce a duplicate warning. The
     75        // Debugger path is currently ignored by inspector.
     76        // NOTE: If we don't have a debugger, this SourceCode will be forever lost to the inspector.
     77        // We could stash it in the inspector in case an inspector is ever opened.
     78        globalObject->inspectorController().reportAPIException(exec, evaluationException);
     79#endif
    6880        return 0;
    6981    }
     
    95107        if (exception)
    96108            *exception = toRef(exec, syntaxException);
     109#if ENABLE(REMOTE_INSPECTOR)
     110        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, syntaxException);
     111#endif
    97112        return false;
    98113    }
  • TabularUnified trunk/Source/JavaScriptCore/API/JSObjectRef.cpp

    r164491 r164507  
    5656#include "RegExpConstructor.h"
    5757
     58#if ENABLE(REMOTE_INSPECTOR)
     59#include "JSGlobalObjectInspectorController.h"
     60#endif
     61
    5862using namespace JSC;
    5963
     
    146150    JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
    147151    if (exec->hadException()) {
    148         if (exception)
    149             *exception = toRef(exec, exec->exception());
    150         exec->clearException();
     152        JSValue exceptionValue = exec->exception();
     153        if (exception)
     154            *exception = toRef(exec, exceptionValue);
     155        exec->clearException();
     156#if ENABLE(REMOTE_INSPECTOR)
     157        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     158#endif
    151159        result = 0;
    152160    }
     
    174182
    175183    if (exec->hadException()) {
    176         if (exception)
    177             *exception = toRef(exec, exec->exception());
    178         exec->clearException();
     184        JSValue exceptionValue = exec->exception();
     185        if (exception)
     186            *exception = toRef(exec, exceptionValue);
     187        exec->clearException();
     188#if ENABLE(REMOTE_INSPECTOR)
     189        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     190#endif
    179191        result = 0;
    180192    }
     
    198210    JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
    199211    if (exec->hadException()) {
    200         if (exception)
    201             *exception = toRef(exec, exec->exception());
    202         exec->clearException();
     212        JSValue exceptionValue = exec->exception();
     213        if (exception)
     214            *exception = toRef(exec, exceptionValue);
     215        exec->clearException();
     216#if ENABLE(REMOTE_INSPECTOR)
     217        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     218#endif
    203219        result = 0;
    204220    }
     
    221237
    222238    if (exec->hadException()) {
    223         if (exception)
    224             *exception = toRef(exec, exec->exception());
    225         exec->clearException();
     239        JSValue exceptionValue = exec->exception();
     240        if (exception)
     241            *exception = toRef(exec, exceptionValue);
     242        exec->clearException();
     243#if ENABLE(REMOTE_INSPECTOR)
     244        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     245#endif
    226246        result = 0;
    227247    }
     
    245265    JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(),  argList);
    246266    if (exec->hadException()) {
    247         if (exception)
    248             *exception = toRef(exec, exec->exception());
    249         exec->clearException();
     267        JSValue exceptionValue = exec->exception();
     268        if (exception)
     269            *exception = toRef(exec, exceptionValue);
     270        exec->clearException();
     271#if ENABLE(REMOTE_INSPECTOR)
     272        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     273#endif
    250274        result = 0;
    251275    }
     
    309333    JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->vm()));
    310334    if (exec->hadException()) {
    311         if (exception)
    312             *exception = toRef(exec, exec->exception());
    313         exec->clearException();
     335        JSValue exceptionValue = exec->exception();
     336        if (exception)
     337            *exception = toRef(exec, exceptionValue);
     338        exec->clearException();
     339#if ENABLE(REMOTE_INSPECTOR)
     340        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     341#endif
    314342    }
    315343    return toRef(exec, jsValue);
     
    338366
    339367    if (exec->hadException()) {
    340         if (exception)
    341             *exception = toRef(exec, exec->exception());
    342         exec->clearException();
     368        JSValue exceptionValue = exec->exception();
     369        if (exception)
     370            *exception = toRef(exec, exceptionValue);
     371        exec->clearException();
     372#if ENABLE(REMOTE_INSPECTOR)
     373        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     374#endif
    343375    }
    344376}
     
    357389    JSValue jsValue = jsObject->get(exec, propertyIndex);
    358390    if (exec->hadException()) {
    359         if (exception)
    360             *exception = toRef(exec, exec->exception());
    361         exec->clearException();
     391        JSValue exceptionValue = exec->exception();
     392        if (exception)
     393            *exception = toRef(exec, exceptionValue);
     394        exec->clearException();
     395#if ENABLE(REMOTE_INSPECTOR)
     396        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     397#endif
    362398    }
    363399    return toRef(exec, jsValue);
     
    379415    jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false);
    380416    if (exec->hadException()) {
    381         if (exception)
    382             *exception = toRef(exec, exec->exception());
    383         exec->clearException();
     417        JSValue exceptionValue = exec->exception();
     418        if (exception)
     419            *exception = toRef(exec, exceptionValue);
     420        exec->clearException();
     421#if ENABLE(REMOTE_INSPECTOR)
     422        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     423#endif
    384424    }
    385425}
     
    398438    bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->vm()));
    399439    if (exec->hadException()) {
    400         if (exception)
    401             *exception = toRef(exec, exec->exception());
    402         exec->clearException();
     440        JSValue exceptionValue = exec->exception();
     441        if (exception)
     442            *exception = toRef(exec, exceptionValue);
     443        exec->clearException();
     444#if ENABLE(REMOTE_INSPECTOR)
     445        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     446#endif
    403447    }
    404448    return result;
     
    542586    JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
    543587    if (exec->hadException()) {
    544         if (exception)
    545             *exception = toRef(exec, exec->exception());
    546         exec->clearException();
     588        JSValue exceptionValue = exec->exception();
     589        if (exception)
     590            *exception = toRef(exec, exceptionValue);
     591        exec->clearException();
     592#if ENABLE(REMOTE_INSPECTOR)
     593        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     594#endif
    547595        result = 0;
    548596    }
     
    579627    JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
    580628    if (exec->hadException()) {
    581         if (exception)
    582             *exception = toRef(exec, exec->exception());
    583         exec->clearException();
     629        JSValue exceptionValue = exec->exception();
     630        if (exception)
     631            *exception = toRef(exec, exceptionValue);
     632        exec->clearException();
     633#if ENABLE(REMOTE_INSPECTOR)
     634        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     635#endif
    584636        result = 0;
    585637    }
  • TabularUnified trunk/Source/JavaScriptCore/API/JSValue.mm

    r164491 r164507  
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
    2525
     
    4848#import <wtf/text/StringHash.h>
    4949
     50#if ENABLE(REMOTE_INSPECTOR)
     51#import "CallFrame.h"
     52#import "JSGlobalObject.h"
     53#import "JSGlobalObjectInspectorController.h"
     54#endif
     55
    5056#if JSC_OBJC_API_ENABLED
    5157
     
    629635    return last;
    630636}
     637
     638#if ENABLE(REMOTE_INSPECTOR)
     639static void reportExceptionToInspector(JSGlobalContextRef context, JSC::JSValue exception)
     640{
     641    JSC::ExecState* exec = toJS(context);
     642    exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception);
     643}
     644#endif
    631645
    632646static JSContainerConvertor::Task valueToObjectWithoutCopy(JSGlobalContextRef context, JSValueRef value)
     
    782796
    783797    JSC::APIEntryShim shim(toJS(context));
    784     if (!(JSValueIsNull(context, value) || JSValueIsUndefined(context, value)))
    785         *exception = toRef(JSC::createTypeError(toJS(context), ASCIILiteral("Cannot convert primitive to NSArray")));
     798    if (!(JSValueIsNull(context, value) || JSValueIsUndefined(context, value))) {
     799        JSC::JSObject* exceptionObject = JSC::createTypeError(toJS(context), ASCIILiteral("Cannot convert primitive to NSArray"));
     800        *exception = toRef(exceptionObject);
     801#if ENABLE(REMOTE_INSPECTOR)
     802        reportExceptionToInspector(context, exceptionObject);
     803#endif
     804    }
    786805    return nil;
    787806}
     
    799818
    800819    JSC::APIEntryShim shim(toJS(context));
    801     if (!(JSValueIsNull(context, value) || JSValueIsUndefined(context, value)))
    802         *exception = toRef(JSC::createTypeError(toJS(context), ASCIILiteral("Cannot convert primitive to NSDictionary")));
     820    if (!(JSValueIsNull(context, value) || JSValueIsUndefined(context, value))) {
     821        JSC::JSObject* exceptionObject = JSC::createTypeError(toJS(context), ASCIILiteral("Cannot convert primitive to NSDictionary"));
     822        *exception = toRef(exceptionObject);
     823#if ENABLE(REMOTE_INSPECTOR)
     824        reportExceptionToInspector(context, exceptionObject);
     825#endif
     826    }
    803827    return nil;
    804828}
  • TabularUnified trunk/Source/JavaScriptCore/API/JSValueRef.cpp

    r164491 r164507  
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
    2525
     
    4747#if PLATFORM(MAC)
    4848#include <mach-o/dyld.h>
     49#endif
     50
     51#if ENABLE(REMOTE_INSPECTOR)
     52#include "JSGlobalObjectInspectorController.h"
    4953#endif
    5054
     
    203207    bool result = JSValue::equal(exec, jsA, jsB); // false if an exception is thrown
    204208    if (exec->hadException()) {
    205         if (exception)
    206             *exception = toRef(exec, exec->exception());
    207         exec->clearException();
     209        JSValue exceptionValue = exec->exception();
     210        if (exception)
     211            *exception = toRef(exec, exceptionValue);
     212        exec->clearException();
     213#if ENABLE(REMOTE_INSPECTOR)
     214        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     215#endif
    208216    }
    209217    return result;
     
    241249    bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
    242250    if (exec->hadException()) {
    243         if (exception)
    244             *exception = toRef(exec, exec->exception());
    245         exec->clearException();
     251        JSValue exceptionValue = exec->exception();
     252        if (exception)
     253            *exception = toRef(exec, exceptionValue);
     254        exec->clearException();
     255#if ENABLE(REMOTE_INSPECTOR)
     256        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     257#endif
    246258    }
    247259    return result;
     
    345357        *exception = 0;
    346358    if (exec->hadException()) {
    347         if (exception)
    348             *exception = toRef(exec, exec->exception());
    349         exec->clearException();
     359        JSValue exceptionValue = exec->exception();
     360        if (exception)
     361            *exception = toRef(exec, exceptionValue);
     362        exec->clearException();
     363#if ENABLE(REMOTE_INSPECTOR)
     364        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     365#endif
    350366        return 0;
    351367    }
     
    379395    double number = jsValue.toNumber(exec);
    380396    if (exec->hadException()) {
    381         if (exception)
    382             *exception = toRef(exec, exec->exception());
    383         exec->clearException();
     397        JSValue exceptionValue = exec->exception();
     398        if (exception)
     399            *exception = toRef(exec, exceptionValue);
     400        exec->clearException();
     401#if ENABLE(REMOTE_INSPECTOR)
     402        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     403#endif
    384404        number = QNaN;
    385405    }
     
    400420    RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec)));
    401421    if (exec->hadException()) {
    402         if (exception)
    403             *exception = toRef(exec, exec->exception());
    404         exec->clearException();
     422        JSValue exceptionValue = exec->exception();
     423        if (exception)
     424            *exception = toRef(exec, exceptionValue);
     425        exec->clearException();
     426#if ENABLE(REMOTE_INSPECTOR)
     427        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     428#endif
    405429        stringRef.clear();
    406430    }
     
    421445    JSObjectRef objectRef = toRef(jsValue.toObject(exec));
    422446    if (exec->hadException()) {
    423         if (exception)
    424             *exception = toRef(exec, exec->exception());
    425         exec->clearException();
     447        JSValue exceptionValue = exec->exception();
     448        if (exception)
     449            *exception = toRef(exec, exceptionValue);
     450        exec->clearException();
     451#if ENABLE(REMOTE_INSPECTOR)
     452        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
     453#endif
    426454        objectRef = 0;
    427455    }
    428456    return objectRef;
    429 }   
     457}
    430458
    431459void JSValueProtect(JSContextRef ctx, JSValueRef value)
  • TabularUnified trunk/Source/JavaScriptCore/ChangeLog

    r164503 r164507  
     12014-02-21  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: JSContext inspection should report exceptions in the console
     4        https://bugs.webkit.org/show_bug.cgi?id=128776
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        When JavaScript API functions have an exception, let the inspector
     9        know so it can log the JavaScript and Native backtrace that caused
     10        the exception.
     11
     12        Include some clean up of ConsoleMessage and ScriptCallStack construction.
     13
     14        * API/JSBase.cpp:
     15        (JSEvaluateScript):
     16        (JSCheckScriptSyntax):
     17        * API/JSObjectRef.cpp:
     18        (JSObjectMakeFunction):
     19        (JSObjectMakeArray):
     20        (JSObjectMakeDate):
     21        (JSObjectMakeError):
     22        (JSObjectMakeRegExp):
     23        (JSObjectGetProperty):
     24        (JSObjectSetProperty):
     25        (JSObjectGetPropertyAtIndex):
     26        (JSObjectSetPropertyAtIndex):
     27        (JSObjectDeleteProperty):
     28        (JSObjectCallAsFunction):
     29        (JSObjectCallAsConstructor):
     30        * API/JSValue.mm:
     31        (reportExceptionToInspector):
     32        (valueToArray):
     33        (valueToDictionary):
     34        * API/JSValueRef.cpp:
     35        (JSValueIsEqual):
     36        (JSValueIsInstanceOfConstructor):
     37        (JSValueCreateJSONString):
     38        (JSValueToNumber):
     39        (JSValueToStringCopy):
     40        (JSValueToObject):
     41        When seeing an exception, let the inspector know there was an exception.
     42
     43        * inspector/JSGlobalObjectInspectorController.h:
     44        * inspector/JSGlobalObjectInspectorController.cpp:
     45        (Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
     46        (Inspector::JSGlobalObjectInspectorController::appendAPIBacktrace):
     47        (Inspector::JSGlobalObjectInspectorController::reportAPIException):
     48        Log API exceptions by also grabbing the native backtrace.
     49
     50        * inspector/ScriptCallStack.h:
     51        * inspector/ScriptCallStack.cpp:
     52        (Inspector::ScriptCallStack::firstNonNativeCallFrame):
     53        (Inspector::ScriptCallStack::append):
     54        Minor extensions to ScriptCallStack to make it easier to work with.
     55
     56        * inspector/ConsoleMessage.cpp:
     57        (Inspector::ConsoleMessage::ConsoleMessage):
     58        (Inspector::ConsoleMessage::autogenerateMetadata):
     59        Provide better default information if the first call frame was native.
     60
     61        * inspector/ScriptCallStackFactory.cpp:
     62        (Inspector::createScriptCallStack):
     63        (Inspector::extractSourceInformationFromException):
     64        (Inspector::createScriptCallStackFromException):
     65        Perform the handling here of inserting a fake call frame for exceptions
     66        if there was no call stack (e.g. a SyntaxError) or if the first call
     67        frame had no information.
     68
     69        * inspector/ConsoleMessage.cpp:
     70        (Inspector::ConsoleMessage::ConsoleMessage):
     71        (Inspector::ConsoleMessage::autogenerateMetadata):
     72        * inspector/ConsoleMessage.h:
     73        * inspector/ScriptCallStackFactory.cpp:
     74        (Inspector::createScriptCallStack):
     75        (Inspector::createScriptCallStackForConsole):
     76        * inspector/ScriptCallStackFactory.h:
     77        * inspector/agents/InspectorConsoleAgent.cpp:
     78        (Inspector::InspectorConsoleAgent::enable):
     79        (Inspector::InspectorConsoleAgent::addMessageToConsole):
     80        (Inspector::InspectorConsoleAgent::count):
     81        * inspector/agents/JSGlobalObjectDebuggerAgent.cpp:
     82        (Inspector::JSGlobalObjectDebuggerAgent::breakpointActionLog):
     83        ConsoleMessage cleanup.
     84
    1852014-02-21  Oliver Hunt  <oliver@apple.com>
    286
  • TabularUnified trunk/Source/JavaScriptCore/inspector/ConsoleMessage.cpp

    r164491 r164507  
    4646namespace Inspector {
    4747
    48 ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned long requestIdentifier)
     48ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned long requestIdentifier)
    4949    : m_source(source)
    5050    , m_type(type)
     
    5757    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
    5858{
    59     autogenerateMetadata(canGenerateCallStack);
    60 }
    61 
    62 ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned line, unsigned column, JSC::ExecState* state, unsigned long requestIdentifier)
     59}
     60
     61ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned line, unsigned column, JSC::ExecState* state, unsigned long requestIdentifier)
    6362    : m_source(source)
    6463    , m_type(type)
     
    7170    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
    7271{
    73     autogenerateMetadata(canGenerateCallStack, state);
    74 }
    75 
    76 ConsoleMessage::ConsoleMessage(bool, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
    77     : m_source(source)
    78     , m_type(type)
    79     , m_level(level)
    80     , m_message(message)
    81     , m_arguments(nullptr)
     72    autogenerateMetadata(state);
     73}
     74
     75ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
     76    : m_source(source)
     77    , m_type(type)
     78    , m_level(level)
     79    , m_message(message)
     80    , m_url()
    8281    , m_line(0)
    8382    , m_column(0)
     
    8584    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
    8685{
    87     if (callStack && callStack->size()) {
    88         const ScriptCallFrame& frame = callStack->at(0);
    89         m_url = frame.sourceURL();
    90         m_line = frame.lineNumber();
    91         m_column = frame.columnNumber();
    92     }
    9386    m_callStack = callStack;
    94 }
    95 
    96 ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, JSC::ExecState* state, unsigned long requestIdentifier)
     87
     88    const ScriptCallFrame* frame = m_callStack ? m_callStack->firstNonNativeCallFrame() : nullptr;
     89    if (frame) {
     90        m_url = frame->sourceURL();
     91        m_line = frame->lineNumber();
     92        m_column = frame->columnNumber();
     93    }
     94}
     95
     96ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, JSC::ExecState* state, unsigned long requestIdentifier)
    9797    : m_source(source)
    9898    , m_type(type)
     
    106106    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
    107107{
    108     autogenerateMetadata(canGenerateCallStack, state);
     108    autogenerateMetadata(state);
    109109}
    110110
     
    113113}
    114114
    115 // FIXME: Remove the generate without ExecState path. The caller should always provide an ExecState.
    116 void ConsoleMessage::autogenerateMetadata(bool /*canGenerateCallStack*/, JSC::ExecState* state)
    117 {
     115void ConsoleMessage::autogenerateMetadata(JSC::ExecState* state)
     116{
     117    if (!state)
     118        return;
     119
    118120    if (m_type == MessageType::EndGroup)
    119121        return;
    120122
    121     if (state)
    122         m_callStack = createScriptCallStackForConsole(state);
    123     // else if (canGenerateCallStack)
    124     //     m_callStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
    125     else
     123    // FIXME: Should this really be using "for console" in the generic ConsoleMessage autogeneration? This can skip the first frame.
     124    m_callStack = createScriptCallStackForConsole(state, ScriptCallStack::maxCallStackSizeToCapture);
     125
     126    if (const ScriptCallFrame* frame = m_callStack->firstNonNativeCallFrame()) {
     127        m_url = frame->sourceURL();
     128        m_line = frame->lineNumber();
     129        m_column = frame->columnNumber();
    126130        return;
    127 
    128     if (m_callStack && m_callStack->size()) {
    129         const ScriptCallFrame& frame = m_callStack->at(0);
    130         m_url = frame.sourceURL();
    131         m_line = frame.lineNumber();
    132         m_column = frame.columnNumber();
    133         return;
    134     }
    135 
    136     m_callStack.clear();
     131    }
    137132}
    138133
  • TabularUnified trunk/Source/JavaScriptCore/inspector/ConsoleMessage.h

    r164491 r164507  
    5252    WTF_MAKE_FAST_ALLOCATED;
    5353public:
    54     ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, unsigned long requestIdentifier = 0);
    55     ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, const String& url, unsigned line, unsigned column, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0);
    56     ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptCallStack>, unsigned long requestIdentifier = 0);
    57     ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptArguments>, JSC::ExecState*, unsigned long requestIdentifier = 0);
     54    ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned long requestIdentifier = 0);
     55    ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& message, const String& url, unsigned line, unsigned column, JSC::ExecState* = nullptr, unsigned long requestIdentifier = 0);
     56    ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptCallStack>, unsigned long requestIdentifier = 0);
     57    ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptArguments>, JSC::ExecState*, unsigned long requestIdentifier = 0);
    5858    ~ConsoleMessage();
    5959
     
    7575
    7676private:
    77     void autogenerateMetadata(bool canGenerateCallStack, JSC::ExecState* = nullptr);
     77    void autogenerateMetadata(JSC::ExecState* = nullptr);
    7878
    7979    MessageSource m_source;
  • TabularUnified trunk/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp

    r164491 r164507  
    3030
    3131#include "Completion.h"
     32#include "ErrorHandlingScope.h"
    3233#include "InjectedScriptHost.h"
    3334#include "InjectedScriptManager.h"
     
    3940#include "JSGlobalObjectDebuggerAgent.h"
    4041#include "JSGlobalObjectRuntimeAgent.h"
     42#include "ScriptCallStack.h"
     43#include "ScriptCallStackFactory.h"
     44#include <cxxabi.h>
     45#include <dlfcn.h>
     46#include <execinfo.h>
    4147
    4248using namespace JSC;
     
    5258    auto consoleAgent = std::make_unique<JSGlobalObjectConsoleAgent>(m_injectedScriptManager.get());
    5359    auto debuggerAgent = std::make_unique<JSGlobalObjectDebuggerAgent>(m_injectedScriptManager.get(), m_globalObject, consoleAgent.get());
     60
     61    m_consoleAgent = consoleAgent.get();
    5462
    5563    runtimeAgent->setScriptDebugServer(&debuggerAgent->scriptDebugServer());
     
    102110}
    103111
     112void JSGlobalObjectInspectorController::appendAPIBacktrace(ScriptCallStack* callStack)
     113{
     114    static const int framesToShow = 31;
     115    static const int framesToSkip = 3; // WTFGetBacktrace, appendAPIBacktrace, reportAPIException.
     116
     117    void* samples[framesToShow + framesToSkip];
     118    int frames = framesToShow + framesToSkip;
     119    WTFGetBacktrace(samples, &frames);
     120
     121    void** stack = samples + framesToSkip;
     122    int size = frames - framesToSkip;
     123    for (int i = 0; i < size; ++i) {
     124        const char* mangledName = nullptr;
     125        char* cxaDemangled = nullptr;
     126        Dl_info info;
     127        if (dladdr(stack[i], &info) && info.dli_sname)
     128            mangledName = info.dli_sname;
     129        if (mangledName)
     130            cxaDemangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, nullptr);
     131        if (mangledName || cxaDemangled)
     132            callStack->append(ScriptCallFrame(cxaDemangled ? cxaDemangled : mangledName, ASCIILiteral("[native code]"), 0, 0));
     133        else
     134            callStack->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), 0, 0));
     135        free(cxaDemangled);
     136    }
     137}
     138
     139void JSGlobalObjectInspectorController::reportAPIException(ExecState* exec, JSValue exception)
     140{
     141    if (isTerminatedExecutionException(exception))
     142        return;
     143
     144    ErrorHandlingScope errorScope(exec->vm());
     145
     146    RefPtr<ScriptCallStack> callStack = createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture);
     147    appendAPIBacktrace(callStack.get());
     148
     149    // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not evaluate JavaScript handling exceptions
     150    // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
     151    String errorMessage = exception.toString(exec)->value(exec);
     152    exec->clearException();
     153
     154    m_consoleAgent->addMessageToConsole(MessageSource::JS, MessageType::Log, MessageLevel::Error, errorMessage, callStack);
     155}
     156
    104157InspectorFunctionCallHandler JSGlobalObjectInspectorController::functionCallHandler() const
    105158{
  • TabularUnified trunk/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.h

    r164491 r164507  
    3838class ExecState;
    3939class JSGlobalObject;
     40class JSValue;
    4041}
    4142
     
    4445class InjectedScriptManager;
    4546class InspectorBackendDispatcher;
     47class InspectorConsoleAgent;
    4648class InspectorFrontendChannel;
     49class ScriptCallStack;
    4750
    4851class JSGlobalObjectInspectorController final : public InspectorEnvironment {
     
    5962    void globalObjectDestroyed();
    6063
     64    void reportAPIException(JSC::ExecState*, JSC::JSValue exception);
     65
    6166    virtual bool developerExtrasEnabled() const override { return true; }
    6267    virtual bool canAccessInspectedScriptState(JSC::ExecState*) const override { return true; }
     
    6772
    6873private:
     74    void appendAPIBacktrace(ScriptCallStack* callStack);
     75
    6976    JSC::JSGlobalObject& m_globalObject;
    7077    std::unique_ptr<InjectedScriptManager> m_injectedScriptManager;
     78    InspectorConsoleAgent* m_consoleAgent;
    7179    InspectorAgentRegistry m_agents;
    7280    InspectorFrontendChannel* m_inspectorFrontendChannel;
  • TabularUnified trunk/Source/JavaScriptCore/inspector/ScriptCallStack.cpp

    r164491 r164507  
    3737namespace Inspector {
    3838
     39PassRefPtr<ScriptCallStack> ScriptCallStack::create()
     40{
     41    return adoptRef(new ScriptCallStack);
     42}
     43
    3944PassRefPtr<ScriptCallStack> ScriptCallStack::create(Vector<ScriptCallFrame>& frames)
    4045{
    4146    return adoptRef(new ScriptCallStack(frames));
     47}
     48
     49ScriptCallStack::ScriptCallStack()
     50{
    4251}
    4352
     
    6069{
    6170    return m_frames.size();
     71}
     72
     73const ScriptCallFrame* ScriptCallStack::firstNonNativeCallFrame() const
     74{
     75    if (!m_frames.size())
     76        return nullptr;
     77
     78    for (size_t i = 0; i < m_frames.size(); ++i) {
     79        const ScriptCallFrame& frame = m_frames[i];
     80        if (frame.sourceURL() != "[native code]")
     81            return &frame;
     82    }
     83
     84    return nullptr;
     85}
     86
     87void ScriptCallStack::append(const ScriptCallFrame& frame)
     88{
     89    m_frames.append(frame);
    6290}
    6391
  • TabularUnified trunk/Source/JavaScriptCore/inspector/ScriptCallStack.h

    r164491 r164507  
    4848    static const size_t maxCallStackSizeToCapture = 200;
    4949   
     50    static PassRefPtr<ScriptCallStack> create();
    5051    static PassRefPtr<ScriptCallStack> create(Vector<ScriptCallFrame>&);
    5152
     
    5455    const ScriptCallFrame& at(size_t) const;
    5556    size_t size() const;
     57
     58    const ScriptCallFrame* firstNonNativeCallFrame() const;
     59
     60    void append(const ScriptCallFrame&);
    5661
    5762    bool isEqual(ScriptCallStack*) const;
     
    6267
    6368private:
     69    ScriptCallStack();
    6470    ScriptCallStack(Vector<ScriptCallFrame>&);
    6571
  • TabularUnified trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp

    r164491 r164507  
    8484};
    8585
    86 PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize, bool emptyIsAllowed)
     86PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize)
    8787{
     88    if (!exec)
     89        return ScriptCallStack::create();
     90
    8891    Vector<ScriptCallFrame> frames;
    8992
    90     if (exec) {
    91         CallFrame* frame = exec->vm().topCallFrame;
    92         CreateScriptCallStackFunctor functor(false, frames, maxStackSize);
    93         frame->iterate(functor);
    94     }
    95 
    96     if (frames.isEmpty() && !emptyIsAllowed) {
    97         // No frames found. It may happen in the case where
    98         // a bound function is called from native code for example.
    99         // Fallback to setting lineNumber to 0, and source and function name to "undefined".
    100         frames.append(ScriptCallFrame(ASCIILiteral("undefined"), ASCIILiteral("undefined"), 0, 0));
    101     }
     93    CallFrame* frame = exec->vm().topCallFrame;
     94    CreateScriptCallStackFunctor functor(false, frames, maxStackSize);
     95    frame->iterate(functor);
    10296
    10397    return ScriptCallStack::create(frames);
    10498}
    10599
    106 PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize)
     100PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState* exec, size_t maxStackSize)
    107101{
     102    if (!exec)
     103        return ScriptCallStack::create();
     104
    108105    Vector<ScriptCallFrame> frames;
    109106
     
    120117}
    121118
    122 PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState* exec)
     119static void extractSourceInformationFromException(JSC::ExecState* exec, JSObject* exceptionObject, int* lineNumber, int* columnNumber, String* sourceURL)
    123120{
    124     // FIXME: Caller should use createScriptCallStack alternative with the exec and appropriate max.
    125     return createScriptCallStack(exec, ScriptCallStack::maxCallStackSizeToCapture);
     121    // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not need to evaluate JavaScript handling exceptions
     122    JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line"));
     123    *lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
     124    JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column"));
     125    *columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0;
     126    JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL"));
     127    *sourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : String("undefined");
     128    exec->clearException();
    126129}
    127130
     
    131134    RefCountedArray<StackFrame> stackTrace = exec->vm().exceptionStack();
    132135    for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) {
    133         if (!stackTrace[i].callee && frames.size())
    134             break;
    135 
    136136        unsigned line;
    137137        unsigned column;
    138138        stackTrace[i].computeLineAndColumn(line, column);
    139139        String functionName = stackTrace[i].friendlyFunctionName(exec);
    140         frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, line, column));
     140        frames.append(ScriptCallFrame(functionName, stackTrace[i].friendlySourceURL(), line, column));
    141141    }
    142142
    143     // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
    144     // Fallback to getting at least the line and sourceURL from the exception if it has values and the exceptionStack doesn't.
    145     if (frames.size() > 0) {
    146         const ScriptCallFrame& firstCallFrame = frames.first();
    147         JSObject* exceptionObject = exception.toObject(exec);
    148         if (exception.isObject() && firstCallFrame.sourceURL().isEmpty()) {
    149             JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line"));
    150             int lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
    151             JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column"));
    152             int columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0;
    153             JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL"));
    154             String exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined");
    155             frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, columnNumber);
     143    // Fallback to getting at least the line and sourceURL from the exception object if it has values and the exceptionStack doesn't.
     144    JSObject* exceptionObject = exception.toObject(exec);
     145    if (exception.isObject()) {
     146        int lineNumber;
     147        int columnNumber;
     148        String exceptionSourceURL;
     149        if (!frames.size()) {
     150            extractSourceInformationFromException(exec, exceptionObject, &lineNumber, &columnNumber, &exceptionSourceURL);
     151            frames.append(ScriptCallFrame(String(), exceptionSourceURL, lineNumber, columnNumber));
     152        } else {
     153            if (stackTrace[0].sourceURL.isEmpty()) {
     154                const ScriptCallFrame& firstCallFrame = frames.first();
     155                extractSourceInformationFromException(exec, exceptionObject, &lineNumber, &columnNumber, &exceptionSourceURL);
     156                frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, columnNumber);
     157            }
    156158        }
    157159    }
  • TabularUnified trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.h

    r164491 r164507  
    4646
    4747// FIXME: The subtle differences between these should be eliminated.
    48 JS_EXPORT_PRIVATE PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState*, size_t maxStackSize, bool emptyIsAllowed);
    4948JS_EXPORT_PRIVATE PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState*, size_t maxStackSize);
    50 JS_EXPORT_PRIVATE PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState*);
     49JS_EXPORT_PRIVATE PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState*, size_t maxStackSize);
    5150JS_EXPORT_PRIVATE PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState*, JSC::JSValue& exception, size_t maxStackSize);
    5251JS_EXPORT_PRIVATE PassRefPtr<ScriptArguments> createScriptArguments(JSC::ExecState*, unsigned skipArgumentCount);
  • TabularUnified trunk/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.cpp

    r164491 r164507  
    8181
    8282    if (m_expiredConsoleMessageCount) {
    83         ConsoleMessage expiredMessage(!isWorkerAgent(), MessageSource::Other, MessageType::Log, MessageLevel::Warning, String::format("%d console messages are not shown.", m_expiredConsoleMessageCount));
     83        ConsoleMessage expiredMessage(MessageSource::Other, MessageType::Log, MessageLevel::Warning, String::format("%d console messages are not shown.", m_expiredConsoleMessageCount));
    8484        expiredMessage.addToFrontend(m_frontendDispatcher.get(), m_injectedScriptManager, false);
    8585    }
     
    129129    }
    130130
    131     addConsoleMessage(std::make_unique<ConsoleMessage>(!isWorkerAgent(), source, type, level, message, callStack, requestIdentifier));
     131    addConsoleMessage(std::make_unique<ConsoleMessage>(source, type, level, message, callStack, requestIdentifier));
    132132}
    133133
     
    142142    }
    143143
    144     addConsoleMessage(std::make_unique<ConsoleMessage>(!isWorkerAgent(), source, type, level, message, arguments, state, requestIdentifier));
     144    addConsoleMessage(std::make_unique<ConsoleMessage>(source, type, level, message, arguments, state, requestIdentifier));
    145145}
    146146
     
    155155    }
    156156
    157     bool canGenerateCallStack = !isWorkerAgent() && m_frontendDispatcher;
    158     addConsoleMessage(std::make_unique<ConsoleMessage>(canGenerateCallStack, source, type, level, message, scriptID, lineNumber, columnNumber, state, requestIdentifier));
     157    addConsoleMessage(std::make_unique<ConsoleMessage>(source, type, level, message, scriptID, lineNumber, columnNumber, state, requestIdentifier));
    159158}
    160159
     
    198197void InspectorConsoleAgent::count(JSC::ExecState* state, PassRefPtr<ScriptArguments> arguments)
    199198{
    200     RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state));
     199    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state, ScriptCallStack::maxCallStackSizeToCapture));
    201200    const ScriptCallFrame& lastCaller = callStack->at(0);
    202201    // Follow Firebug's behavior of counting with null and undefined title in
  • TabularUnified trunk/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.cpp

    r164491 r164507  
    7070void JSGlobalObjectDebuggerAgent::breakpointActionLog(JSC::ExecState* exec, const String& message)
    7171{
    72     m_consoleAgent->addMessageToConsole(MessageSource::JS, MessageType::Log, MessageLevel::Log, message, createScriptCallStack(exec, ScriptCallStack::maxCallStackSizeToCapture, true), 0);
     72    m_consoleAgent->addMessageToConsole(MessageSource::JS, MessageType::Log, MessageLevel::Log, message, createScriptCallStack(exec, ScriptCallStack::maxCallStackSizeToCapture), 0);
    7373}
    7474
  • TabularUnified trunk/Source/WebCore/ChangeLog

    r164505 r164507  
     12014-02-21  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: JSContext inspection should report exceptions in the console
     4        https://bugs.webkit.org/show_bug.cgi?id=128776
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        Include some clean up of ConsoleMessage and ScriptCallStack construction.
     9
     10        Covered by existing tests.
     11
     12        * bindings/js/JSDOMBinding.cpp:
     13        (WebCore::reportException):
     14        Simplify code now that createStackTraceFromException handles it.
     15
     16        * page/ContentSecurityPolicy.cpp:
     17        (WebCore::gatherSecurityPolicyViolationEventData):
     18        (WebCore::ContentSecurityPolicy::reportViolation):
     19        ScriptCallStack can give us the first non-native callframe.
     20
     21        * inspector/InspectorResourceAgent.cpp:
     22        (WebCore::InspectorResourceAgent::buildInitiatorObject):
     23        * inspector/PageDebuggerAgent.cpp:
     24        (WebCore::PageDebuggerAgent::breakpointActionLog):
     25        * inspector/TimelineRecordFactory.cpp:
     26        (WebCore::TimelineRecordFactory::createGenericRecord):
     27        * page/Console.cpp:
     28        (WebCore::internalAddMessage):
     29        (WebCore::Console::profile):
     30        (WebCore::Console::profileEnd):
     31        (WebCore::Console::timeEnd):
     32        * page/ContentSecurityPolicy.cpp:
     33        (WebCore::gatherSecurityPolicyViolationEventData):
     34        (WebCore::ContentSecurityPolicy::reportViolation):
     35        * page/DOMWindow.cpp:
     36        (WebCore::DOMWindow::postMessage):
     37
    1382014-02-21  Benjamin Poulain  <benjamin@webkit.org>
    239
  • TabularUnified trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp

    r164505 r164507  
    172172    int columnNumber = 0;
    173173    String exceptionSourceURL;
    174     if (callStack->size()) {
    175         const ScriptCallFrame& frame = callStack->at(0);
    176         lineNumber = frame.lineNumber();
    177         columnNumber = frame.columnNumber();
    178         exceptionSourceURL = frame.sourceURL();
    179     } else {
    180         // There may not be an exceptionStack for a <script> SyntaxError. Fallback to getting at least the line and sourceURL from the exception.
    181         JSObject* exceptionObject = exception.toObject(exec);
    182         JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line"));
    183         lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
    184         JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column"));
    185         columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0;
    186         JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL"));
    187         exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined");
     174    if (const ScriptCallFrame* callFrame = callStack->firstNonNativeCallFrame()) {
     175        lineNumber = callFrame->lineNumber();
     176        columnNumber = callFrame->columnNumber();
     177        exceptionSourceURL = callFrame->sourceURL();
    188178    }
    189179
  • TabularUnified trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp

    r164491 r164507  
    440440PassRefPtr<Inspector::TypeBuilder::Network::Initiator> InspectorResourceAgent::buildInitiatorObject(Document* document)
    441441{
    442     RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), ScriptCallStack::maxCallStackSizeToCapture, true);
     442    RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), ScriptCallStack::maxCallStackSizeToCapture);
    443443    if (stackTrace && stackTrace->size() > 0) {
    444444        RefPtr<Inspector::TypeBuilder::Network::Initiator> initiatorObject = Inspector::TypeBuilder::Network::Initiator::create()
  • TabularUnified trunk/Source/WebCore/inspector/PageDebuggerAgent.cpp

    r164491 r164507  
    118118void PageDebuggerAgent::breakpointActionLog(JSC::ExecState* exec, const String& message)
    119119{
    120     m_pageAgent->page()->console().addMessage(MessageSource::JS, MessageLevel::Log, message, createScriptCallStack(exec, ScriptCallStack::maxCallStackSizeToCapture, true));
     120    m_pageAgent->page()->console().addMessage(MessageSource::JS, MessageLevel::Log, message, createScriptCallStack(exec, ScriptCallStack::maxCallStackSizeToCapture));
    121121}
    122122
  • TabularUnified trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp

    r164491 r164507  
    5858
    5959    if (maxCallStackDepth) {
    60         RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), maxCallStackDepth, true);
     60        RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), maxCallStackDepth);
    6161        if (stackTrace && stackTrace->size())
    6262            record->setValue("stackTrace", stackTrace->buildInspectorArray());
  • TabularUnified trunk/Source/WebCore/page/Console.cpp

    r164491 r164507  
    7878
    7979    size_t stackSize = printTrace ? ScriptCallStack::maxCallStackSizeToCapture : 1;
    80     RefPtr<ScriptCallStack> callStack(createScriptCallStack(state, stackSize));
     80    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state, stackSize));
    8181    const ScriptCallFrame& lastCaller = callStack->at(0);
    8282
     
    204204    ScriptProfiler::start(state, resolvedTitle);
    205205
    206     RefPtr<ScriptCallStack> callStack(createScriptCallStack(state, 1));
     206    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state, 1));
    207207    const ScriptCallFrame& lastCaller = callStack->at(0);
    208208    InspectorInstrumentation::addStartProfilingMessageToConsole(page, resolvedTitle, lastCaller.lineNumber(), lastCaller.columnNumber(), lastCaller.sourceURL());
     
    223223
    224224    m_profiles.append(profile);
    225     RefPtr<ScriptCallStack> callStack(createScriptCallStack(state, 1));
     225    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state, 1));
    226226    InspectorInstrumentation::addProfile(page, profile, callStack);
    227227}
     
    234234void Console::timeEnd(JSC::ExecState* state, const String& title)
    235235{
    236     RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state));
     236    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state, 1));
    237237    InspectorInstrumentation::stopConsoleTiming(m_frame, title, callStack.release());
    238238}
  • TabularUnified trunk/Source/WebCore/page/ContentSecurityPolicy.cpp

    r164491 r164507  
    170170    ASSERT_NOT_REACHED();
    171171    return FeatureObserver::NumberOfFeatures;
    172 }
    173 
    174 const ScriptCallFrame& getFirstNonNativeFrame(PassRefPtr<ScriptCallStack> stack)
    175 {
    176     int frameNumber = 0;
    177     if (!stack->at(0).lineNumber() && stack->size() > 1 && stack->at(1).lineNumber())
    178         frameNumber = 1;
    179 
    180     return stack->at(frameNumber);
    181172}
    182173
     
    17281719    init.lineNumber = 0;
    17291720
    1730     RefPtr<ScriptCallStack> stack = createScriptCallStack(JSMainThreadExecState::currentState(), 2, false);
    1731     if (!stack)
    1732         return;
    1733 
    1734     const ScriptCallFrame& callFrame = getFirstNonNativeFrame(stack);
    1735 
    1736     if (callFrame.lineNumber()) {
    1737         URL source = URL(ParsedURLString, callFrame.sourceURL());
     1721    RefPtr<ScriptCallStack> stack = createScriptCallStack(JSMainThreadExecState::currentState(), 2);
     1722    const ScriptCallFrame* callFrame = stack->firstNonNativeCallFrame();
     1723    if (callFrame && callFrame->lineNumber()) {
     1724        URL source = URL(URL(), callFrame->sourceURL());
    17381725        init.sourceFile = stripURLForUseInReport(document, source);
    1739         init.lineNumber = callFrame.lineNumber();
     1726        init.lineNumber = callFrame->lineNumber();
    17401727    }
    17411728}
     
    17781765
    17791766    RefPtr<InspectorObject> cspReport = InspectorObject::create();
    1780     cspReport->setString("document-uri", document->url().strippedForUseAsReferrer());
    1781     cspReport->setString("referrer", document->referrer());
    1782     cspReport->setString("violated-directive", directiveText);
     1767    cspReport->setString(ASCIILiteral("document-uri"), document->url().strippedForUseAsReferrer());
     1768    cspReport->setString(ASCIILiteral("referrer"), document->referrer());
     1769    cspReport->setString(ASCIILiteral("violated-directive"), directiveText);
    17831770#if ENABLE(CSP_NEXT)
    17841771    if (experimentalFeaturesEnabled())
    1785         cspReport->setString("effective-directive", effectiveDirective);
     1772        cspReport->setString(ASCIILiteral("effective-directive"), effectiveDirective);
    17861773#else
    17871774    UNUSED_PARAM(effectiveDirective);
    17881775#endif
    1789     cspReport->setString("original-policy", header);
    1790     cspReport->setString("blocked-uri", stripURLForUseInReport(document, blockedURL));
    1791 
    1792     RefPtr<ScriptCallStack> stack = createScriptCallStack(JSMainThreadExecState::currentState(), 2, false);
    1793     if (stack) {
    1794         const ScriptCallFrame& callFrame = getFirstNonNativeFrame(stack);
    1795 
    1796         if (callFrame.lineNumber()) {
    1797             URL source = URL(ParsedURLString, callFrame.sourceURL());
    1798             cspReport->setString("source-file", stripURLForUseInReport(document, source));
    1799             cspReport->setNumber("line-number", callFrame.lineNumber());
    1800         }
     1776    cspReport->setString(ASCIILiteral("original-policy"), header);
     1777    cspReport->setString(ASCIILiteral("blocked-uri"), stripURLForUseInReport(document, blockedURL));
     1778
     1779    RefPtr<ScriptCallStack> stack = createScriptCallStack(JSMainThreadExecState::currentState(), 2);
     1780    const ScriptCallFrame* callFrame = stack->firstNonNativeCallFrame();
     1781    if (callFrame && callFrame->lineNumber()) {
     1782        URL source = URL(URL(), callFrame->sourceURL());
     1783        cspReport->setString(ASCIILiteral("source-file"), stripURLForUseInReport(document, source));
     1784        cspReport->setNumber(ASCIILiteral("line-number"), callFrame->lineNumber());
    18011785    }
    18021786
    18031787    RefPtr<InspectorObject> reportObject = InspectorObject::create();
    1804     reportObject->setObject("csp-report", cspReport.release());
     1788    reportObject->setObject(ASCIILiteral("csp-report"), cspReport.release());
    18051789
    18061790    RefPtr<FormData> report = FormData::create(reportObject->toJSONString().utf8());
  • TabularUnified trunk/Source/WebCore/page/DOMWindow.cpp

    r164491 r164507  
    847847    RefPtr<ScriptCallStack> stackTrace;
    848848    if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument))
    849         stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), ScriptCallStack::maxCallStackSizeToCapture, true);
     849        stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), ScriptCallStack::maxCallStackSizeToCapture);
    850850
    851851    // Schedule the message.
  • TabularUnified trunk/Source/WebInspectorUI/ChangeLog

    r164491 r164507  
     12014-02-21  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: JSContext inspection should report exceptions in the console
     4        https://bugs.webkit.org/show_bug.cgi?id=128776
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * UserInterface/ConsoleMessageImpl.js:
     9        (WebInspector.ConsoleMessageImpl.prototype._formatMessage):
     10        (WebInspector.ConsoleMessageImpl.prototype._shouldHideURL):
     11        (WebInspector.ConsoleMessageImpl.prototype._firstNonNativeCallFrame):
     12        (WebInspector.ConsoleMessageImpl.prototype._populateStackTraceTreeElement):
     13        Provide better handling for "[native code]" and legacy "undefined"
     14        call frame URLs. Never linkify these. Also, when showing a link
     15        for an exception, always use the first non-native call frame as
     16        the link location.
     17
    1182014-02-21  Joseph Pecoraro  <pecoraro@apple.com>
    219
  • TabularUnified trunk/Source/WebInspectorUI/UserInterface/ConsoleMessageImpl.js

    r164491 r164507  
    110110
    111111        if (this.source !== WebInspector.ConsoleMessage.MessageSource.Network || this._request) {
    112             if (this._stackTrace && this._stackTrace.length && this._stackTrace[0].url) {
    113                 var urlElement = this._linkifyCallFrame(this._stackTrace[0]);
     112            var firstNonNativeCallFrame = this._firstNonNativeCallFrame();
     113            if (firstNonNativeCallFrame) {
     114                var urlElement = this._linkifyCallFrame(firstNonNativeCallFrame);
    114115                this._formattedMessage.appendChild(urlElement);
    115             } else if (this.url && this.url !== "undefined") {
     116            } else if (this.url && !this._shouldHideURL(this.url)) {
    116117                var urlElement = this._linkifyLocation(this.url, this.line, this.column);
    117118                this._formattedMessage.appendChild(urlElement);
     
    144145    {
    145146        return !!this._stackTrace && this._stackTrace.length && (this.source === WebInspector.ConsoleMessage.MessageSource.Network || this.level === WebInspector.ConsoleMessage.MessageLevel.Error || this.type === WebInspector.ConsoleMessage.MessageType.Trace);
     147    },
     148
     149    _shouldHideURL: function(url)
     150    {
     151        return url === "undefined" || url === "[native code]";
     152    },
     153
     154    _firstNonNativeCallFrame: function()
     155    {
     156        if (!this._stackTrace)
     157            return null;
     158
     159        for (var i = 0; i < this._stackTrace.length; i++) {
     160            var frame = this._stackTrace[i];
     161            if (!frame.url || frame.url === "[native code]")
     162                continue;
     163            return frame;
     164        }
     165
     166        return null;
    146167    },
    147168
     
    527548            content.appendChild(messageTextElement);
    528549
    529             if (frame.url) {
     550            if (frame.url && !this._shouldHideURL(frame.url)) {
    530551                var urlElement = this._linkifyCallFrame(frame);
    531552                content.appendChild(urlElement);
Note: See TracChangeset for help on using the changeset viewer.