WebKit/mac/WebView/WebScriptDebugger.mm
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008 Apple 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
       
     6  * are met:
       
     7  *
       
     8  * 1.  Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer.
       
    10  * 2.  Redistributions in binary form must reproduce the above copyright
       
    11  *     notice, this list of conditions and the following disclaimer in the
       
    12  *     documentation and/or other materials provided with the distribution.
       
    13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    14  *     its contributors may be used to endorse or promote products derived
       
    15  *     from this software without specific prior written permission.
       
    16  *
       
    17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    27  */
       
    28 
       
    29 #import "WebScriptDebugger.h"
       
    30 
       
    31 #import "WebDelegateImplementationCaching.h"
       
    32 #import "WebFrameInternal.h"
       
    33 #import "WebScriptDebugDelegate.h"
       
    34 #import "WebViewInternal.h"
       
    35 #import <JavaScriptCore/DebuggerCallFrame.h>
       
    36 #import <JavaScriptCore/JSGlobalObject.h>
       
    37 #import <JavaScriptCore/SourceCode.h>
       
    38 #import <WebCore/DOMWindow.h>
       
    39 #import <WebCore/Frame.h>
       
    40 #import <WebCore/JSDOMWindow.h>
       
    41 #import <WebCore/KURL.h>
       
    42 #import <WebCore/ScriptController.h>
       
    43 
       
    44 using namespace JSC;
       
    45 using namespace WebCore;
       
    46 
       
    47 @interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
       
    48 - (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debugger:(WebScriptDebugger *)debugger caller:(WebScriptCallFrame *)caller debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame;
       
    49 - (void)_setDebuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame;
       
    50 - (void)_clearDebuggerCallFrame;
       
    51 @end
       
    52 
       
    53 NSString *toNSString(const UString& s)
       
    54 {
       
    55     if (s.isEmpty())
       
    56         return nil;
       
    57     return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(s.data()) length:s.size()];
       
    58 }
       
    59 
       
    60 static NSString *toNSString(const SourceCode& s)
       
    61 {
       
    62     if (!s.length())
       
    63         return nil;
       
    64     return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(s.data()) length:s.length()];
       
    65 }
       
    66 
       
    67 // convert UString to NSURL
       
    68 static NSURL *toNSURL(const UString& s)
       
    69 {
       
    70     if (s.isEmpty())
       
    71         return nil;
       
    72     return KURL(ParsedURLString, ustringToString(s));
       
    73 }
       
    74 
       
    75 static WebFrame *toWebFrame(JSGlobalObject* globalObject)
       
    76 {
       
    77     JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
       
    78     return kit(window->impl()->frame());
       
    79 }
       
    80 
       
    81 WebScriptDebugger::WebScriptDebugger(JSGlobalObject* globalObject)
       
    82     : m_callingDelegate(false)
       
    83     , m_globalObject(globalObject)
       
    84 {
       
    85     attach(globalObject);
       
    86     initGlobalCallFrame(globalObject->globalExec());
       
    87 }
       
    88 
       
    89 void WebScriptDebugger::initGlobalCallFrame(const DebuggerCallFrame& debuggerCallFrame)
       
    90 {
       
    91     m_callingDelegate = true;
       
    92 
       
    93     WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
       
    94 
       
    95     m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]);
       
    96     m_globalCallFrame = m_topCallFrame;
       
    97 
       
    98     WebView *webView = [webFrame webView];
       
    99     WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
       
   100     if (implementations->didEnterCallFrameFunc)
       
   101         CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), static_cast<NSInteger>(0), -1, webFrame);
       
   102 
       
   103     m_callingDelegate = false;
       
   104 }
       
   105 
       
   106 // callbacks - relay to delegate
       
   107 void WebScriptDebugger::sourceParsed(ExecState* exec, const SourceCode& source, int errorLine, const UString& errorMsg)
       
   108 {
       
   109     if (m_callingDelegate)
       
   110         return;
       
   111 
       
   112     m_callingDelegate = true;
       
   113 
       
   114     NSString *nsSource = toNSString(source);
       
   115     NSURL *nsURL = toNSURL(source.provider()->url());
       
   116 
       
   117     WebFrame *webFrame = toWebFrame(exec->dynamicGlobalObject());
       
   118     WebView *webView = [webFrame webView];
       
   119     WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
       
   120 
       
   121     if (errorLine == -1) {
       
   122         if (implementations->didParseSourceFunc) {
       
   123             if (implementations->didParseSourceExpectsBaseLineNumber)
       
   124                 CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:), nsSource, source.firstLine(), nsURL, source.provider()->asID(), webFrame);
       
   125             else
       
   126                 CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:), nsSource, [nsURL absoluteString], source.provider()->asID(), webFrame);
       
   127         }
       
   128     } else {
       
   129         NSString* nsErrorMessage = toNSString(errorMsg);
       
   130         NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys:nsErrorMessage, WebScriptErrorDescriptionKey, [NSNumber numberWithUnsignedInt:errorLine], WebScriptErrorLineNumberKey, nil];
       
   131         NSError *error = [[NSError alloc] initWithDomain:WebScriptErrorDomain code:WebScriptGeneralErrorCode userInfo:info];
       
   132 
       
   133         if (implementations->failedToParseSourceFunc)
       
   134             CallScriptDebugDelegate(implementations->failedToParseSourceFunc, webView, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:), nsSource, source.firstLine(), nsURL, error, webFrame);
       
   135 
       
   136         [error release];
       
   137         [info release];
       
   138     }
       
   139 
       
   140     m_callingDelegate = false;
       
   141 }
       
   142 
       
   143 void WebScriptDebugger::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
       
   144 {
       
   145     if (m_callingDelegate)
       
   146         return;
       
   147 
       
   148     m_callingDelegate = true;
       
   149 
       
   150     WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
       
   151 
       
   152     m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]);
       
   153 
       
   154     WebView *webView = [webFrame webView];
       
   155     WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
       
   156     if (implementations->didEnterCallFrameFunc)
       
   157         CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
       
   158 
       
   159     m_callingDelegate = false;
       
   160 }
       
   161 
       
   162 void WebScriptDebugger::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
       
   163 {
       
   164     if (m_callingDelegate)
       
   165         return;
       
   166 
       
   167     m_callingDelegate = true;
       
   168 
       
   169     WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
       
   170     WebView *webView = [webFrame webView];
       
   171 
       
   172     [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
       
   173 
       
   174     WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
       
   175     if (implementations->willExecuteStatementFunc)
       
   176         CallScriptDebugDelegate(implementations->willExecuteStatementFunc, webView, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
       
   177 
       
   178     m_callingDelegate = false;
       
   179 }
       
   180 
       
   181 void WebScriptDebugger::returnEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
       
   182 {
       
   183     if (m_callingDelegate)
       
   184         return;
       
   185 
       
   186     m_callingDelegate = true;
       
   187 
       
   188     WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
       
   189     WebView *webView = [webFrame webView];
       
   190 
       
   191     [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
       
   192 
       
   193     WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
       
   194     if (implementations->willLeaveCallFrameFunc)
       
   195         CallScriptDebugDelegate(implementations->willLeaveCallFrameFunc, webView, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
       
   196 
       
   197     [m_topCallFrame.get() _clearDebuggerCallFrame];
       
   198     m_topCallFrame = [m_topCallFrame.get() caller];
       
   199 
       
   200     m_callingDelegate = false;
       
   201 }
       
   202 
       
   203 void WebScriptDebugger::exception(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, bool hasHandler)
       
   204 {
       
   205     if (m_callingDelegate)
       
   206         return;
       
   207 
       
   208     m_callingDelegate = true;
       
   209 
       
   210     WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
       
   211     WebView *webView = [webFrame webView];
       
   212     [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
       
   213 
       
   214     WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
       
   215     if (implementations->exceptionWasRaisedFunc)
       
   216         CallScriptDebugDelegate(implementations->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
       
   217 
       
   218     m_callingDelegate = false;
       
   219 }
       
   220 
       
   221 void WebScriptDebugger::willExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno)
       
   222 {
       
   223 }
       
   224 
       
   225 void WebScriptDebugger::didExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno)
       
   226 {
       
   227 }
       
   228 
       
   229 void WebScriptDebugger::didReachBreakpoint(const DebuggerCallFrame&, intptr_t, int)
       
   230 {
       
   231     return;
       
   232 }