• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <WebCore/DOMWindow.h>
36#import <WebCore/Frame.h>
37#import <WebCore/JSDOMWindow.h>
38#import <WebCore/KURL.h>
39#import <WebCore/ScriptController.h>
40#import <debugger/DebuggerCallFrame.h>
41#import <runtime/JSGlobalObject.h>
42
43using namespace JSC;
44using namespace WebCore;
45
46@interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
47- (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debugger:(WebScriptDebugger *)debugger caller:(WebScriptCallFrame *)caller debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame;
48- (void)_setDebuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame;
49- (void)_clearDebuggerCallFrame;
50@end
51
52NSString *toNSString(const UString& s)
53{
54    if (s.isEmpty())
55        return nil;
56    return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(s.data()) length:s.size()];
57}
58
59static NSString *toNSString(const SourceCode& s)
60{
61    if (!s.length())
62        return nil;
63    return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(s.data()) length:s.length()];
64}
65
66// convert UString to NSURL
67static NSURL *toNSURL(const UString& s)
68{
69    if (s.isEmpty())
70        return nil;
71    return KURL(s);
72}
73
74static WebFrame *toWebFrame(JSGlobalObject* globalObject)
75{
76    JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
77    return kit(window->impl()->frame());
78}
79
80WebScriptDebugger::WebScriptDebugger(JSGlobalObject* globalObject)
81    : m_callingDelegate(false)
82    , m_globalObject(globalObject)
83{
84    attach(globalObject);
85    initGlobalCallFrame(globalObject->globalExec());
86}
87
88void WebScriptDebugger::initGlobalCallFrame(const DebuggerCallFrame& debuggerCallFrame)
89{
90    m_callingDelegate = true;
91
92    WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
93
94    m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]);
95    m_globalCallFrame = m_topCallFrame;
96
97    WebView *webView = [webFrame webView];
98    WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
99    if (implementations->didEnterCallFrameFunc)
100        CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), static_cast<NSInteger>(0), -1, webFrame);
101
102    m_callingDelegate = false;
103}
104
105// callbacks - relay to delegate
106void WebScriptDebugger::sourceParsed(ExecState* exec, const SourceCode& source, int errorLine, const UString& errorMsg)
107{
108    if (m_callingDelegate)
109        return;
110
111    m_callingDelegate = true;
112
113    NSString *nsSource = toNSString(source);
114    NSURL *nsURL = toNSURL(source.provider()->url());
115
116    WebFrame *webFrame = toWebFrame(exec->dynamicGlobalObject());
117    WebView *webView = [webFrame webView];
118    WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
119
120    if (errorLine == -1) {
121        if (implementations->didParseSourceFunc) {
122            if (implementations->didParseSourceExpectsBaseLineNumber)
123                CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:), nsSource, source.firstLine(), nsURL, source.provider()->asID(), webFrame);
124            else
125                CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:), nsSource, [nsURL absoluteString], source.provider()->asID(), webFrame);
126        }
127    } else {
128        NSString* nsErrorMessage = toNSString(errorMsg);
129        NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys:nsErrorMessage, WebScriptErrorDescriptionKey, [NSNumber numberWithUnsignedInt:errorLine], WebScriptErrorLineNumberKey, nil];
130        NSError *error = [[NSError alloc] initWithDomain:WebScriptErrorDomain code:WebScriptGeneralErrorCode userInfo:info];
131
132        if (implementations->failedToParseSourceFunc)
133            CallScriptDebugDelegate(implementations->failedToParseSourceFunc, webView, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:), nsSource, source.firstLine(), nsURL, error, webFrame);
134
135        [error release];
136        [info release];
137    }
138
139    m_callingDelegate = false;
140}
141
142void WebScriptDebugger::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
143{
144    if (m_callingDelegate)
145        return;
146
147    m_callingDelegate = true;
148
149    WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
150
151    m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]);
152
153    WebView *webView = [webFrame webView];
154    WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
155    if (implementations->didEnterCallFrameFunc)
156        CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
157
158    m_callingDelegate = false;
159}
160
161void WebScriptDebugger::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
162{
163    if (m_callingDelegate)
164        return;
165
166    m_callingDelegate = true;
167
168    WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
169    WebView *webView = [webFrame webView];
170
171    [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
172
173    WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
174    if (implementations->willExecuteStatementFunc)
175        CallScriptDebugDelegate(implementations->willExecuteStatementFunc, webView, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
176
177    m_callingDelegate = false;
178}
179
180void WebScriptDebugger::returnEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
181{
182    if (m_callingDelegate)
183        return;
184
185    m_callingDelegate = true;
186
187    WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
188    WebView *webView = [webFrame webView];
189
190    [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
191
192    WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
193    if (implementations->willLeaveCallFrameFunc)
194        CallScriptDebugDelegate(implementations->willLeaveCallFrameFunc, webView, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
195
196    [m_topCallFrame.get() _clearDebuggerCallFrame];
197    m_topCallFrame = [m_topCallFrame.get() caller];
198
199    m_callingDelegate = false;
200}
201
202void WebScriptDebugger::exception(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
203{
204    if (m_callingDelegate)
205        return;
206
207    m_callingDelegate = true;
208
209    WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
210    WebView *webView = [webFrame webView];
211    [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
212
213    WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
214    if (implementations->exceptionWasRaisedFunc)
215        CallScriptDebugDelegate(implementations->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
216
217    m_callingDelegate = false;
218}
219
220void WebScriptDebugger::willExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno)
221{
222}
223
224void WebScriptDebugger::didExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno)
225{
226}
227
228void WebScriptDebugger::didReachBreakpoint(const DebuggerCallFrame&, intptr_t, int)
229{
230    return;
231}
232