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 48 static 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