2
* Copyright (C) 2008 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
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.
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.
29
#import "WebScriptDebugger.h"
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/SourceProvider.h>
38
#import <JavaScriptCore/StrongInlines.h>
39
#import <WebCore/DOMWindow.h>
40
#import <WebCore/Frame.h>
41
#import <WebCore/JSDOMWindow.h>
42
#import <WebCore/KURL.h>
43
#import <WebCore/ScriptController.h>
46
using namespace WebCore;
48
@interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
49
- (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debugger:(WebScriptDebugger *)debugger caller:(WebScriptCallFrame *)caller debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame;
50
- (void)_setDebuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame;
51
- (void)_clearDebuggerCallFrame;
54
static NSString *toNSString(SourceProvider* sourceProvider)
56
const String& sourceString = sourceProvider->source();
57
if (sourceString.isEmpty())
62
// Convert String to NSURL.
63
static NSURL *toNSURL(const String& s)
67
return KURL(ParsedURLString, s);
70
static WebFrame *toWebFrame(JSGlobalObject* globalObject)
72
JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
73
return kit(window->impl()->frame());
76
WebScriptDebugger::WebScriptDebugger(JSGlobalObject* globalObject)
77
: m_callingDelegate(false)
78
, m_globalObject(globalObject->globalData(), globalObject)
81
initGlobalCallFrame(globalObject->globalExec());
84
void WebScriptDebugger::initGlobalCallFrame(const DebuggerCallFrame& debuggerCallFrame)
86
m_callingDelegate = true;
88
WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
90
m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]);
91
m_globalCallFrame = m_topCallFrame;
93
WebView *webView = [webFrame webView];
94
WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
95
if (implementations->didEnterCallFrameFunc)
96
CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), static_cast<NSInteger>(0), -1, webFrame);
98
m_callingDelegate = false;
101
// callbacks - relay to delegate
102
void WebScriptDebugger::sourceParsed(ExecState* exec, SourceProvider* sourceProvider, int errorLine, const String& errorMsg)
104
if (m_callingDelegate)
107
m_callingDelegate = true;
109
NSString *nsSource = toNSString(sourceProvider);
110
NSURL *nsURL = toNSURL(sourceProvider->url());
111
int firstLine = sourceProvider->startPosition().m_line.oneBasedInt();
113
WebFrame *webFrame = toWebFrame(exec->dynamicGlobalObject());
114
WebView *webView = [webFrame webView];
115
WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
117
if (errorLine == -1) {
118
if (implementations->didParseSourceFunc) {
119
if (implementations->didParseSourceExpectsBaseLineNumber)
120
CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:), nsSource, firstLine, nsURL, sourceProvider->asID(), webFrame);
122
CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:), nsSource, [nsURL absoluteString], sourceProvider->asID(), webFrame);
125
NSString* nsErrorMessage = nsStringNilIfEmpty(errorMsg);
126
NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys:nsErrorMessage, WebScriptErrorDescriptionKey, [NSNumber numberWithUnsignedInt:errorLine], WebScriptErrorLineNumberKey, nil];
127
NSError *error = [[NSError alloc] initWithDomain:WebScriptErrorDomain code:WebScriptGeneralErrorCode userInfo:info];
129
if (implementations->failedToParseSourceFunc)
130
CallScriptDebugDelegate(implementations->failedToParseSourceFunc, webView, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:), nsSource, firstLine, nsURL, error, webFrame);
136
m_callingDelegate = false;
139
void WebScriptDebugger::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int columnNumber)
141
if (m_callingDelegate)
144
m_callingDelegate = true;
146
WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
148
m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]);
150
WebView *webView = [webFrame webView];
151
WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
152
if (implementations->didEnterCallFrameFunc)
153
CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
155
m_callingDelegate = false;
158
void WebScriptDebugger::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int columnNumber)
160
if (m_callingDelegate)
163
m_callingDelegate = true;
165
WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
166
WebView *webView = [webFrame webView];
168
[m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
170
WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
171
if (implementations->willExecuteStatementFunc)
172
CallScriptDebugDelegate(implementations->willExecuteStatementFunc, webView, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
174
m_callingDelegate = false;
177
void WebScriptDebugger::returnEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int columnNumber)
179
if (m_callingDelegate)
182
m_callingDelegate = true;
184
WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
185
WebView *webView = [webFrame webView];
187
[m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
189
WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView);
190
if (implementations->willLeaveCallFrameFunc)
191
CallScriptDebugDelegate(implementations->willLeaveCallFrameFunc, webView, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
193
[m_topCallFrame.get() _clearDebuggerCallFrame];
194
m_topCallFrame = [m_topCallFrame.get() caller];
196
m_callingDelegate = false;
199
void WebScriptDebugger::exception(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int columnNumber, bool hasHandler)
201
if (m_callingDelegate)
204
m_callingDelegate = true;
206
WebFrame *webFrame = toWebFrame(debuggerCallFrame.dynamicGlobalObject());
207
WebView *webView = [webFrame webView];
208
[m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame];
210
WebScriptDebugDelegateImplementationCache* cache = WebViewGetScriptDebugDelegateImplementations(webView);
211
if (cache->exceptionWasRaisedFunc) {
212
if (cache->exceptionWasRaisedExpectsHasHandlerFlag)
213
CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:), m_topCallFrame.get(), hasHandler, sourceID, lineNumber, webFrame);
215
CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame);
218
m_callingDelegate = false;
221
void WebScriptDebugger::willExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno, int columnno)
223
callEvent(debuggerCallFrame, sourceID, lineno, columnno);
226
void WebScriptDebugger::didExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineno, int columnno)
228
returnEvent(debuggerCallFrame, sourceID, lineno, columnno);
231
void WebScriptDebugger::didReachBreakpoint(const DebuggerCallFrame&, intptr_t, int, int)