• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2007 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 "config.h"
30#import "ObjCController.h"
31
32// Avoid compile error in DOMPrivate.h.
33@class NSFont;
34
35#import <JavaScriptCore/JavaScriptCore.h>
36#import <WebKit/DOMAbstractView.h>
37#import <WebKit/DOMPrivate.h>
38#import <WebKit/WebScriptObject.h>
39#import <WebKit/WebView.h>
40#import <pthread.h>
41#import <wtf/Assertions.h>
42
43// Remove this once hasWebScriptKey has been made public.
44@interface WebScriptObject (StagedForPublic)
45- (BOOL)hasWebScriptKey:(NSString *)name;
46@end
47
48static void* runJavaScriptThread(void* arg)
49{
50    JSGlobalContextRef ctx = JSGlobalContextCreate(0);
51    JSStringRef scriptRef = JSStringCreateWithUTF8CString("'Hello World!'");
52
53    JSValueRef exception = 0;
54    JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception);
55    ASSERT(!exception);
56
57    JSGlobalContextRelease(ctx);
58    JSStringRelease(scriptRef);
59
60    return 0;
61}
62
63@implementation ObjCController
64
65+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
66{
67    if (0
68            || aSelector == @selector(classNameOf:)
69            || aSelector == @selector(objectOfClass:)
70            || aSelector == @selector(arrayOfString)
71            || aSelector == @selector(identityIsEqual::)
72            || aSelector == @selector(longLongRoundTrip:)
73            || aSelector == @selector(unsignedLongLongRoundTrip:)
74            || aSelector == @selector(testWrapperRoundTripping:)
75            || aSelector == @selector(accessStoredWebScriptObject)
76            || aSelector == @selector(storeWebScriptObject:)
77            || aSelector == @selector(testValueForKey)
78            || aSelector == @selector(testHasWebScriptKey:)
79            || aSelector == @selector(testArray)
80            || aSelector == @selector(setSelectElement:selectedIndex:allowingMultiple:)
81        )
82        return NO;
83    return YES;
84}
85
86+ (NSString *)webScriptNameForSelector:(SEL)aSelector
87{
88    if (aSelector == @selector(classNameOf:))
89        return @"className";
90    if (aSelector == @selector(objectOfClass:))
91        return @"objectOfClass";
92    if (aSelector == @selector(arrayOfString))
93        return @"arrayOfString";
94    if (aSelector == @selector(identityIsEqual::))
95        return @"identityIsEqual";
96    if (aSelector == @selector(longLongRoundTrip:))
97        return @"longLongRoundTrip";
98    if (aSelector == @selector(unsignedLongLongRoundTrip:))
99        return @"unsignedLongLongRoundTrip";
100    if (aSelector == @selector(testWrapperRoundTripping:))
101        return @"testWrapperRoundTripping";
102    if (aSelector == @selector(storeWebScriptObject:))
103        return @"storeWebScriptObject";
104    if (aSelector == @selector(testValueForKey))
105        return @"testValueForKey";
106    if (aSelector == @selector(testHasWebScriptKey:))
107        return @"testHasWebScriptKey";
108    if (aSelector == @selector(testArray))
109        return @"testArray";
110    if (aSelector == @selector(setSelectElement:selectedIndex:allowingMultiple:))
111        return @"setSelectElementSelectedIndexAllowingMultiple";
112
113    return nil;
114}
115
116- (NSString *)classNameOf:(id)object
117{
118    if (!object)
119        return @"nil";
120    return NSStringFromClass([object class]);
121}
122
123- (id)objectOfClass:(NSString *)aClass
124{
125    if ([aClass isEqualToString:@"NSNull"])
126        return [NSNull null];
127    if ([aClass isEqualToString:@"WebUndefined"])
128        return [WebUndefined undefined];
129    if ([aClass isEqualToString:@"NSCFBoolean"])
130        return [NSNumber numberWithBool:true];
131    if ([aClass isEqualToString:@"NSCFNumber"])
132        return [NSNumber numberWithInt:1];
133    if ([aClass isEqualToString:@"NSCFString"])
134        return @"";
135    if ([aClass isEqualToString:@"WebScriptObject"])
136        return self;
137    if ([aClass isEqualToString:@"NSArray"])
138        return [NSArray array];
139
140    return nil;
141}
142
143- (NSArray *)arrayOfString
144{
145    NSString *strings[3];
146    strings[0] = @"one";
147    strings[1] = @"two";
148    strings[2] = @"three";
149    NSArray *array = [NSArray arrayWithObjects:strings count:3];
150    return array;
151}
152
153- (BOOL)identityIsEqual:(WebScriptObject *)a :(WebScriptObject *)b
154{
155    if ([a isKindOfClass:[NSString class]] && [b isKindOfClass:[NSString class]])
156        return [(NSString *)a isEqualToString:(NSString *)b];
157    return a == b;
158}
159
160- (long long)longLongRoundTrip:(long long)num
161{
162    return num;
163}
164
165- (unsigned long long)unsignedLongLongRoundTrip:(unsigned long long)num
166{
167    return num;
168}
169
170- (void)testValueForKey
171{
172    ASSERT(storedWebScriptObject);
173
174    @try {
175        [storedWebScriptObject valueForKey:@"ThisKeyDoesNotExist"];
176    } @catch (NSException *e) {
177    }
178
179    pthread_t pthread;
180    pthread_create(&pthread, 0, &runJavaScriptThread, 0);
181    pthread_join(pthread, 0);
182}
183
184- (BOOL)testHasWebScriptKey:(NSString *)key
185{
186    ASSERT(storedWebScriptObject);
187    return [storedWebScriptObject hasWebScriptKey:key];
188}
189
190- (BOOL)testWrapperRoundTripping:(WebScriptObject *)webScriptObject
191{
192    JSObjectRef jsObject = [webScriptObject JSObject];
193
194    if (!jsObject)
195        return false;
196
197    if (!webScriptObject)
198        return false;
199
200    if ([[webScriptObject evaluateWebScript:@"({ })"] class] != [webScriptObject class])
201        return false;
202
203    [webScriptObject setValue:[NSNumber numberWithInt:666] forKey:@"key"];
204    if (![[webScriptObject valueForKey:@"key"] isKindOfClass:[NSNumber class]] ||
205        ![[webScriptObject valueForKey:@"key"] isEqualToNumber:[NSNumber numberWithInt:666]])
206        return false;
207
208    [webScriptObject removeWebScriptKey:@"key"];
209    @try {
210        if ([webScriptObject valueForKey:@"key"])
211            return false;
212    } @catch(NSException *exception) {
213        // NSObject throws an exception if the key doesn't exist.
214    }
215
216    [webScriptObject setWebScriptValueAtIndex:0 value:webScriptObject];
217    if ([webScriptObject webScriptValueAtIndex:0] != webScriptObject)
218        return false;
219
220    if ([[webScriptObject stringRepresentation] isEqualToString:@"[Object object]"])
221        return false;
222
223    if ([webScriptObject callWebScriptMethod:@"returnThis" withArguments:nil] != webScriptObject)
224        return false;
225
226    return true;
227}
228
229- (void)accessStoredWebScriptObject
230{
231#if !ASSERT_DISABLED
232    BOOL isWindowObject = [storedWebScriptObject isKindOfClass:[DOMAbstractView class]];
233    JSObjectRef jsObject = [storedWebScriptObject JSObject];
234    ASSERT((jsObject && isWindowObject) || (!jsObject && !isWindowObject));
235#endif
236    [storedWebScriptObject callWebScriptMethod:@"" withArguments:nil];
237    [storedWebScriptObject evaluateWebScript:@""];
238    [storedWebScriptObject setValue:[WebUndefined undefined] forKey:@"key"];
239    [storedWebScriptObject valueForKey:@"key"];
240    [storedWebScriptObject removeWebScriptKey:@"key"];
241    [storedWebScriptObject stringRepresentation];
242    [storedWebScriptObject webScriptValueAtIndex:0];
243    [storedWebScriptObject setWebScriptValueAtIndex:0 value:[WebUndefined undefined]];
244    [storedWebScriptObject setException:@"exception"];
245}
246
247- (void)storeWebScriptObject:(WebScriptObject *)webScriptObject
248{
249    if (webScriptObject == storedWebScriptObject)
250        return;
251
252    [storedWebScriptObject release];
253    storedWebScriptObject = [webScriptObject retain];
254}
255
256- (NSArray *)testArray
257{
258    return [NSArray array];
259}
260
261- (void)dealloc
262{
263    [storedWebScriptObject release];
264    [super dealloc];
265}
266
267- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args
268{
269    // FIXME: Perhaps we should log that this has been called.
270    return nil;
271}
272
273// MARK: -
274// MARK: Testing Objective-C DOM HTML Bindings
275
276- (void)setSelectElement:(WebScriptObject *)element selectedIndex:(int)index allowingMultiple:(BOOL)allowingMultiple
277{
278    if (![element isKindOfClass:[DOMHTMLSelectElement class]])
279        return;
280
281    DOMHTMLSelectElement *select = (DOMHTMLSelectElement*)element;
282    [select _activateItemAtIndex:index allowMultipleSelection:allowingMultiple];
283}
284
285@end
286