Remove -enterFrame: and -leaveFrame from WebScriptDebugger
[WebKit-https.git] / WebKit / mac / WebView / WebScriptDebugDelegate.mm
1 /*
2  * Copyright (C) 2005 Apple Computer, 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 "WebScriptDebugDelegatePrivate.h"
30
31 #import "WebCoreScriptDebuggerImp.h"
32 #import "WebDataSource.h"
33 #import "WebDataSourceInternal.h"
34 #import "WebFrameBridge.h"
35 #import "WebFrameInternal.h"
36 #import "WebScriptDebugServerPrivate.h"
37 #import "WebViewInternal.h"
38 #import <JavaScriptCore/ExecState.h>
39 #import <JavaScriptCore/JSGlobalObject.h>
40 #import <JavaScriptCore/function.h>
41 #import <JavaScriptCore/interpreter.h>
42 #import <WebCore/Frame.h>
43 #import <WebCore/WebScriptObjectPrivate.h>
44 #import <WebCore/runtime_root.h>
45
46 using namespace KJS;
47 using namespace WebCore;
48
49 // FIXME: these error strings should be public for future use by WebScriptObject and in WebScriptObject.h
50 NSString * const WebScriptErrorDomain = @"WebScriptErrorDomain";
51 NSString * const WebScriptErrorDescriptionKey = @"WebScriptErrorDescription";
52 NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
53
54 @interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
55
56 - (id)_convertValueToObjcValue:(JSValue *)value;
57
58 @end
59
60 @implementation WebScriptDebugger
61
62 - (WebScriptDebugger *)initWithWebFrame:(WebFrame *)webFrame
63 {
64     if ((self = [super init])) {
65         _webFrame = webFrame;
66         _debugger = new WebCoreScriptDebuggerImp(self, [[self globalObject] _rootObject]->globalObject());
67     }
68     return self;
69 }
70
71 - (void)dealloc
72 {
73     delete _debugger;
74     [super dealloc];
75 }
76
77 - (WebFrame *)webFrame
78 {
79     return _webFrame;
80 }
81
82 - (WebScriptObject *)globalObject
83 {
84     return core(_webFrame)->windowScriptObject();
85 }
86
87 @end
88
89 @interface WebScriptCallFramePrivate : NSObject {
90 @public
91     WebScriptObject        *globalObject;   // the global object's proxy (not retained)
92     WebScriptCallFrame     *caller;         // previous stack frame
93     KJS::ExecState         *state;
94 }
95 @end
96
97 @implementation WebScriptCallFramePrivate
98 - (void)dealloc
99 {
100     [caller release];
101     [super dealloc];
102 }
103 @end
104
105 // WebScriptCallFrame
106 //
107 // One of these is created to represent each stack frame.  Additionally, there is a "global"
108 // frame to represent the outermost scope.  This global frame is always the last frame in
109 // the chain of callers.
110 //
111 // The delegate can assign a "wrapper" to each frame object so it can relay calls through its
112 // own exported interface.  This class is private to WebCore (and the delegate).
113
114 @implementation WebScriptCallFrame (WebScriptDebugDelegateInternal)
115
116 - (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj caller:(WebScriptCallFrame *)caller state:(ExecState *)state
117 {
118     if ((self = [super init])) {
119         _private = [[WebScriptCallFramePrivate alloc] init];
120         _private->globalObject = globalObj;
121         _private->caller = [caller retain];
122         _private->state = state;
123     }
124     return self;
125 }
126
127 - (id)_convertValueToObjcValue:(JSValue *)value
128 {
129     if (!value)
130         return nil;
131
132     WebScriptObject *globalObject = _private->globalObject;
133     if (value == [globalObject _imp])
134         return globalObject;
135
136     Bindings::RootObject* root1 = [globalObject _originRootObject];
137     if (!root1)
138         return nil;
139
140     Bindings::RootObject* root2 = [globalObject _rootObject];
141     if (!root2)
142         return nil;
143
144     return [WebScriptObject _convertValueToObjcValue:value originRootObject:root1 rootObject:root2];
145 }
146
147 @end
148
149
150
151 @implementation WebScriptCallFrame
152
153 - (void) dealloc
154 {
155     [_userInfo release];
156     [_private release];
157     [super dealloc];
158 }
159
160 - (void)setUserInfo:(id)userInfo
161 {
162     if (userInfo != _userInfo) {
163         [_userInfo release];
164         _userInfo = [userInfo retain];
165     }
166 }
167
168 - (id)userInfo
169 {
170     return _userInfo;
171 }
172
173 - (WebScriptCallFrame *)caller
174 {
175     return _private->caller;
176 }
177
178 // Returns an array of scope objects (most local first).
179 // The properties of each scope object are the variables for that scope.
180 // Note that the last entry in the array will _always_ be the global object (windowScriptObject),
181 // whose properties are the global variables.
182
183 - (NSArray *)scopeChain
184 {
185     ExecState* state = _private->state;
186     if (!state->scopeNode())  // global frame
187         return [NSArray arrayWithObject:_private->globalObject];
188
189     ScopeChain      chain  = state->scopeChain();
190     NSMutableArray *scopes = [[NSMutableArray alloc] init];
191
192     while (!chain.isEmpty()) {
193         [scopes addObject:[self _convertValueToObjcValue:chain.top()]];
194         chain.pop();
195     }
196
197     NSArray *result = [NSArray arrayWithArray:scopes];
198     [scopes release];
199     return result;
200 }
201
202 // Returns the name of the function for this frame, if available.
203 // Returns nil for anonymous functions and for the global frame.
204
205 - (NSString *)functionName
206 {
207     ExecState* state = _private->state;
208     if (!state->scopeNode())
209         return nil;
210
211     FunctionImp* func = state->function();
212     if (!func)
213         return nil;
214
215     Identifier fn = func->functionName();
216     return toNSString(fn.ustring());
217 }
218
219 // Returns the pending exception for this frame (nil if none).
220
221 - (id)exception
222 {
223     ExecState* state = _private->state;
224     if (!state->hadException())
225         return nil;
226     return [self _convertValueToObjcValue:state->exception()];
227 }
228
229 // Evaluate some JavaScript code in the context of this frame.
230 // The code is evaluated as if by "eval", and the result is returned.
231 // If there is an (uncaught) exception, it is returned as though _it_ were the result.
232 // Calling this method on the global frame is not quite the same as calling the WebScriptObject
233 // method of the same name, due to the treatment of exceptions.
234
235 // FIXME: If "script" contains var declarations, the machinery to handle local variables
236 // efficiently in JavaScriptCore will not work properly. This could lead to crashes or
237 // incorrect variable values. So this is not appropriate for evaluating arbitrary script.
238 - (id)evaluateWebScript:(NSString *)script
239 {
240     JSLock lock;
241
242     UString code = String(script);
243
244     ExecState* state = _private->state;
245     JSGlobalObject* globalObject = state->dynamicGlobalObject();
246
247     // find "eval"
248     JSObject* eval = NULL;
249     if (state->scopeNode()) {  // "eval" won't work without context (i.e. at global scope)
250         JSValue* v = globalObject->get(state, "eval");
251         if (v->isObject() && static_cast<JSObject*>(v)->implementsCall())
252             eval = static_cast<JSObject*>(v);
253         else
254             // no "eval" - fallback operates on global exec state
255             state = globalObject->globalExec();
256     }
257
258     JSValue* savedException = state->exception();
259     state->clearException();
260
261     // evaluate
262     JSValue* result;
263     if (eval) {
264         List args;
265         args.append(jsString(code));
266         result = eval->call(state, 0, args);
267     } else
268         // no "eval", or no context (i.e. global scope) - use global fallback
269         result = Interpreter::evaluate(state, UString(), 0, code.data(), code.size(), globalObject).value();
270
271     if (state->hadException())
272         result = state->exception();    // (may be redundant depending on which eval path was used)
273     state->setException(savedException);
274
275     return [self _convertValueToObjcValue:result];
276 }
277
278 @end