2 * Copyright (C) 2005 Apple Computer, 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 "WebDataSource.h"
30 #import "WebDataSourceInternal.h"
31 #import "WebFrameInternal.h"
32 #import "WebScriptDebugDelegate.h"
33 #import "WebScriptDebugger.h"
34 #import "WebViewInternal.h"
35 #import <WebCore/Frame.h>
36 #import <WebCore/ScriptController.h>
37 #import <WebCore/WebScriptObjectPrivate.h>
38 #import <WebCore/runtime_root.h>
39 #import <debugger/Debugger.h>
40 #import <debugger/DebuggerActivation.h>
41 #import <debugger/DebuggerCallFrame.h>
42 #import <interpreter/CallFrame.h>
43 #import <runtime/Completion.h>
44 #import <runtime/JSFunction.h>
45 #import <runtime/JSGlobalObject.h>
46 #import <runtime/JSLock.h>
49 using namespace WebCore;
51 // FIXME: these error strings should be public for future use by WebScriptObject and in WebScriptObject.h
52 NSString * const WebScriptErrorDomain = @"WebScriptErrorDomain";
53 NSString * const WebScriptErrorDescriptionKey = @"WebScriptErrorDescription";
54 NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
56 @interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
58 - (id)_convertValueToObjcValue:(JSValue)value;
62 @interface WebScriptCallFramePrivate : NSObject {
64 WebScriptObject *globalObject; // the global object's proxy (not retained)
65 WebScriptCallFrame *caller; // previous stack frame
66 DebuggerCallFrame* debuggerCallFrame;
67 WebScriptDebugger* debugger;
71 @implementation WebScriptCallFramePrivate
75 delete debuggerCallFrame;
82 // One of these is created to represent each stack frame. Additionally, there is a "global"
83 // frame to represent the outermost scope. This global frame is always the last frame in
84 // the chain of callers.
86 // The delegate can assign a "wrapper" to each frame object so it can relay calls through its
87 // own exported interface. This class is private to WebCore (and the delegate).
89 @implementation WebScriptCallFrame (WebScriptDebugDelegateInternal)
91 - (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debugger:(WebScriptDebugger *)debugger caller:(WebScriptCallFrame *)caller debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame
93 if ((self = [super init])) {
94 _private = [[WebScriptCallFramePrivate alloc] init];
95 _private->globalObject = globalObj;
96 _private->caller = [caller retain];
97 _private->debugger = debugger;
102 - (void)_setDebuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame
104 if (!_private->debuggerCallFrame)
105 _private->debuggerCallFrame = new DebuggerCallFrame(debuggerCallFrame);
107 *_private->debuggerCallFrame = debuggerCallFrame;
110 - (void)_clearDebuggerCallFrame
112 delete _private->debuggerCallFrame;
113 _private->debuggerCallFrame = 0;
116 - (id)_convertValueToObjcValue:(JSValue)value
121 WebScriptObject *globalObject = _private->globalObject;
122 if (value == [globalObject _imp])
125 Bindings::RootObject* root1 = [globalObject _originRootObject];
129 Bindings::RootObject* root2 = [globalObject _rootObject];
133 return [WebScriptObject _convertValueToObjcValue:value originRootObject:root1 rootObject:root2];
140 @implementation WebScriptCallFrame
149 - (void)setUserInfo:(id)userInfo
151 if (userInfo != _userInfo) {
153 _userInfo = [userInfo retain];
162 - (WebScriptCallFrame *)caller
164 return _private->caller;
167 // Returns an array of scope objects (most local first).
168 // The properties of each scope object are the variables for that scope.
169 // Note that the last entry in the array will _always_ be the global object (windowScriptObject),
170 // whose properties are the global variables.
172 - (NSArray *)scopeChain
174 if (!_private->debuggerCallFrame)
175 return [NSArray array];
177 JSLock lock(SilenceAssertionsOnly);
179 const ScopeChainNode* scopeChain = _private->debuggerCallFrame->scopeChain();
180 if (!scopeChain->next) // global frame
181 return [NSArray arrayWithObject:_private->globalObject];
183 NSMutableArray *scopes = [[NSMutableArray alloc] init];
185 ScopeChainIterator end = scopeChain->end();
186 for (ScopeChainIterator it = scopeChain->begin(); it != end; ++it) {
187 JSObject* object = it->get();
188 if (object->isActivationObject())
189 object = new (scopeChain->globalData) DebuggerActivation(*scopeChain->globalData, object);
190 [scopes addObject:[self _convertValueToObjcValue:object]];
193 NSArray *result = [NSArray arrayWithArray:scopes];
198 // Returns the name of the function for this frame, if available.
199 // Returns nil for anonymous functions and for the global frame.
201 - (NSString *)functionName
203 if (!_private->debuggerCallFrame)
206 const UString* functionName = _private->debuggerCallFrame->functionName();
207 return functionName ? toNSString(*functionName) : nil;
210 // Returns the pending exception for this frame (nil if none).
214 if (!_private->debuggerCallFrame)
217 JSValue exception = _private->debuggerCallFrame->exception();
218 return exception ? [self _convertValueToObjcValue:exception] : nil;
221 // Evaluate some JavaScript code in the context of this frame.
222 // The code is evaluated as if by "eval", and the result is returned.
223 // If there is an (uncaught) exception, it is returned as though _it_ were the result.
224 // Calling this method on the global frame is not quite the same as calling the WebScriptObject
225 // method of the same name, due to the treatment of exceptions.
227 - (id)evaluateWebScript:(NSString *)script
229 if (!_private->debuggerCallFrame)
232 JSLock lock(SilenceAssertionsOnly);
234 // If this is the global call frame and there is no dynamic global object,
235 // Dashcode is attempting to execute JS in the evaluator using a stale
236 // WebScriptCallFrame. Instead, we need to set the dynamic global object
237 // and evaluate the JS in the global object's global call frame.
238 JSGlobalObject* globalObject = _private->debugger->globalObject();
239 if (self == _private->debugger->globalCallFrame() && !globalObject->globalData().dynamicGlobalObject) {
240 JSGlobalObject* globalObject = _private->debugger->globalObject();
242 DynamicGlobalObjectScope globalObjectScope(globalObject->globalExec(), globalObject);
245 JSValue result = evaluateInGlobalCallFrame(stringToUString(script), exception, globalObject);
247 return [self _convertValueToObjcValue:exception];
248 return result ? [self _convertValueToObjcValue:result] : nil;
252 JSValue result = _private->debuggerCallFrame->evaluate(stringToUString(script), exception);
254 return [self _convertValueToObjcValue:exception];
255 return result ? [self _convertValueToObjcValue:result] : nil;