diff -r 000000000000 -r 4f2f89ce4247 WebKit/mac/WebView/WebScriptDebugger.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebKit/mac/WebView/WebScriptDebugger.mm Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebScriptDebugger.h" + +#import "WebDelegateImplementationCaching.h" +#import "WebFrameInternal.h" +#import "WebScriptDebugDelegate.h" +#import "WebViewInternal.h" +#import +#import +#import +#import +#import +#import +#import +#import + +using namespace JSC; +using namespace WebCore; + +@interface WebScriptCallFrame (WebScriptDebugDelegateInternal) +- (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debugger:(WebScriptDebugger *)debugger caller:(WebScriptCallFrame *)caller debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame; +- (void)_setDebuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame; +- (void)_clearDebuggerCallFrame; +@end + +NSString *toNSString(const UString& s) +{ + if (s.isEmpty()) + return nil; + return [NSString stringWithCharacters:reinterpret_cast(s.data()) length:s.size()]; +} + +static NSString *toNSString(const SourceCode& s) +{ + if (!s.length()) + return nil; + return [NSString stringWithCharacters:reinterpret_cast(s.data()) length:s.length()]; +} + +// convert UString to NSURL +static NSURL *toNSURL(const UString& s) +{ + if (s.isEmpty()) + return nil; + return KURL(ParsedURLString, ustringToString(s)); +} + +static WebFrame *toWebFrame(JSGlobalObject* globalObject) +{ + JSDOMWindow* window = static_cast(globalObject); + return kit(window->impl()->frame()); +} + +WebScriptDebugger::WebScriptDebugger(JSGlobalObject* globalObject) + : m_callingDelegate(false) + , m_globalObject(globalObject) +{ + attach(globalObject); + initGlobalCallFrame(globalObject->globalExec()); +} + +void WebScriptDebugger::initGlobalCallFrame(const DebuggerCallFrame& debuggerCallFrame) +{ + m_callingDelegate = true; + + WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject()); + + m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]); + m_globalCallFrame = m_topCallFrame; + + WebView *webView = [webFrame webView]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->didEnterCallFrameFunc) + CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), static_cast(0), -1, webFrame); + + m_callingDelegate = false; +} + +// callbacks - relay to delegate +void WebScriptDebugger::sourceParsed(ExecState* exec, const SourceCode& source, int errorLine, const UString& errorMsg) +{ + if (m_callingDelegate) + return; + + m_callingDelegate = true; + + NSString *nsSource = toNSString(source); + NSURL *nsURL = toNSURL(source.provider()->url()); + + WebFrame *webFrame = toWebFrame(exec->dynamicGlobalObject()); + WebView *webView = [webFrame webView]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + + if (errorLine == -1) { + if (implementations->didParseSourceFunc) { + if (implementations->didParseSourceExpectsBaseLineNumber) + CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:), nsSource, source.firstLine(), nsURL, source.provider()->asID(), webFrame); + else + CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:), nsSource, [nsURL absoluteString], source.provider()->asID(), webFrame); + } + } else { + NSString* nsErrorMessage = toNSString(errorMsg); + NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys:nsErrorMessage, WebScriptErrorDescriptionKey, [NSNumber numberWithUnsignedInt:errorLine], WebScriptErrorLineNumberKey, nil]; + NSError *error = [[NSError alloc] initWithDomain:WebScriptErrorDomain code:WebScriptGeneralErrorCode userInfo:info]; + + if (implementations->failedToParseSourceFunc) + CallScriptDebugDelegate(implementations->failedToParseSourceFunc, webView, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:), nsSource, source.firstLine(), nsURL, error, webFrame); + + [error release]; + [info release]; + } + + m_callingDelegate = false; +} + +void WebScriptDebugger::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_callingDelegate) + return; + + m_callingDelegate = true; + + WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject()); + + m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]); + + WebView *webView = [webFrame webView]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->didEnterCallFrameFunc) + CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); + + m_callingDelegate = false; +} + +void WebScriptDebugger::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_callingDelegate) + return; + + m_callingDelegate = true; + + WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject()); + WebView *webView = [webFrame webView]; + + [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame]; + + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->willExecuteStatementFunc) + CallScriptDebugDelegate(implementations->willExecuteStatementFunc, webView, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); + + m_callingDelegate = false; +} + +void WebScriptDebugger::returnEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_callingDelegate) + return; + + m_callingDelegate = true; + + WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject()); + WebView *webView = [webFrame webView]; + + [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame]; + + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->willLeaveCallFrameFunc) + CallScriptDebugDelegate(implementations->willLeaveCallFrameFunc, webView, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); + + [m_topCallFrame.get() _clearDebuggerCallFrame]; + m_topCallFrame = [m_topCallFrame.get() caller]; + + m_callingDelegate = false; +} + +void WebScriptDebugger::exception(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, bool hasHandler) +{ + if (m_callingDelegate) + return; + + m_callingDelegate = true; + + WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject()); + WebView *webView = [webFrame webView]; + [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame]; + + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->exceptionWasRaisedFunc) + CallScriptDebugDelegate(implementations->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); + + m_callingDelegate = false; +} + +void WebScriptDebugger::willExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno) +{ +} + +void WebScriptDebugger::didExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno) +{ +} + +void WebScriptDebugger::didReachBreakpoint(const DebuggerCallFrame&, intptr_t, int) +{ + return; +}