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#import <JavaScriptCore/JavaScriptCore.h> 33#import <WebKit/DOMAbstractView.h> 34#import <WebKit/WebScriptObject.h> 35#import <WebKit/WebView.h> 36#import <pthread.h> 37#import <wtf/Assertions.h> 38 39static void* runJavaScriptThread(void* arg) 40{ 41 JSGlobalContextRef ctx = JSGlobalContextCreate(0); 42 JSStringRef scriptRef = JSStringCreateWithUTF8CString("'Hello World!'"); 43 44 JSValueRef exception = 0; 45 JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception); 46 ASSERT(!exception); 47 48 JSGlobalContextRelease(ctx); 49 JSStringRelease(scriptRef); 50 51 return 0; 52} 53 54@implementation ObjCController 55 56+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector 57{ 58 if (0 59 || aSelector == @selector(classNameOf:) 60 || aSelector == @selector(objectOfClass:) 61 || aSelector == @selector(identityIsEqual::) 62 || aSelector == @selector(longLongRoundTrip:) 63 || aSelector == @selector(unsignedLongLongRoundTrip:) 64 || aSelector == @selector(testWrapperRoundTripping:) 65 || aSelector == @selector(accessStoredWebScriptObject) 66 || aSelector == @selector(storeWebScriptObject:) 67 || aSelector == @selector(testValueForKey) 68 || aSelector == @selector(testArray) 69 ) 70 return NO; 71 return YES; 72} 73 74+ (NSString *)webScriptNameForSelector:(SEL)aSelector 75{ 76 if (aSelector == @selector(classNameOf:)) 77 return @"className"; 78 if (aSelector == @selector(objectOfClass:)) 79 return @"objectOfClass"; 80 if (aSelector == @selector(identityIsEqual::)) 81 return @"identityIsEqual"; 82 if (aSelector == @selector(longLongRoundTrip:)) 83 return @"longLongRoundTrip"; 84 if (aSelector == @selector(unsignedLongLongRoundTrip:)) 85 return @"unsignedLongLongRoundTrip"; 86 if (aSelector == @selector(testWrapperRoundTripping:)) 87 return @"testWrapperRoundTripping"; 88 if (aSelector == @selector(storeWebScriptObject:)) 89 return @"storeWebScriptObject"; 90 if (aSelector == @selector(testValueForKey)) 91 return @"testValueForKey"; 92 if (aSelector == @selector(testArray)) 93 return @"testArray"; 94 95 return nil; 96} 97 98- (NSString *)classNameOf:(id)object 99{ 100 if (!object) 101 return @"nil"; 102 return NSStringFromClass([object class]); 103} 104 105- (id)objectOfClass:(NSString *)aClass 106{ 107 if ([aClass isEqualToString:@"NSNull"]) 108 return [NSNull null]; 109 if ([aClass isEqualToString:@"WebUndefined"]) 110 return [WebUndefined undefined]; 111 if ([aClass isEqualToString:@"NSCFBoolean"]) 112 return [NSNumber numberWithBool:true]; 113 if ([aClass isEqualToString:@"NSCFNumber"]) 114 return [NSNumber numberWithInt:1]; 115 if ([aClass isEqualToString:@"NSCFString"]) 116 return @""; 117 if ([aClass isEqualToString:@"WebScriptObject"]) 118 return self; 119 if ([aClass isEqualToString:@"NSArray"]) 120 return [NSArray array]; 121 122 return nil; 123} 124 125- (BOOL)identityIsEqual:(WebScriptObject *)a :(WebScriptObject *)b 126{ 127 if ([a isKindOfClass:[NSString class]] && [b isKindOfClass:[NSString class]]) 128 return [(NSString *)a isEqualToString:(NSString *)b]; 129 return a == b; 130} 131 132- (long long)longLongRoundTrip:(long long)num 133{ 134 return num; 135} 136 137- (unsigned long long)unsignedLongLongRoundTrip:(unsigned long long)num 138{ 139 return num; 140} 141 142- (void)testValueForKey 143{ 144 ASSERT(storedWebScriptObject); 145 146 @try { 147 [storedWebScriptObject valueForKey:@"ThisKeyDoesNotExist"]; 148 } @catch (NSException *e) { 149 } 150 151 pthread_t pthread; 152 pthread_create(&pthread, 0, &runJavaScriptThread, 0); 153 pthread_join(pthread, 0); 154} 155 156- (BOOL)testWrapperRoundTripping:(WebScriptObject *)webScriptObject 157{ 158 JSObjectRef jsObject = [webScriptObject JSObject]; 159 160 if (!jsObject) 161 return false; 162 163 if (!webScriptObject) 164 return false; 165 166 if ([[webScriptObject evaluateWebScript:@"({ })"] class] != [webScriptObject class]) 167 return false; 168 169 [webScriptObject setValue:[NSNumber numberWithInt:666] forKey:@"key"]; 170 if (![[webScriptObject valueForKey:@"key"] isKindOfClass:[NSNumber class]] || 171 ![[webScriptObject valueForKey:@"key"] isEqualToNumber:[NSNumber numberWithInt:666]]) 172 return false; 173 174 [webScriptObject removeWebScriptKey:@"key"]; 175 @try { 176 if ([webScriptObject valueForKey:@"key"]) 177 return false; 178 } @catch(NSException *exception) { 179 // NSObject throws an exception if the key doesn't exist. 180 } 181 182 [webScriptObject setWebScriptValueAtIndex:0 value:webScriptObject]; 183 if ([webScriptObject webScriptValueAtIndex:0] != webScriptObject) 184 return false; 185 186 if ([[webScriptObject stringRepresentation] isEqualToString:@"[Object object]"]) 187 return false; 188 189 if ([webScriptObject callWebScriptMethod:@"returnThis" withArguments:nil] != webScriptObject) 190 return false; 191 192 return true; 193} 194 195- (void)accessStoredWebScriptObject 196{ 197#if !ASSERT_DISABLED 198 BOOL isWindowObject = [storedWebScriptObject isKindOfClass:[DOMAbstractView class]]; 199#endif 200 JSObjectRef jsObject = [storedWebScriptObject JSObject]; 201 ASSERT((jsObject && isWindowObject) || (!jsObject && !isWindowObject)); 202 203 [storedWebScriptObject callWebScriptMethod:@"" withArguments:nil]; 204 [storedWebScriptObject evaluateWebScript:@""]; 205 [storedWebScriptObject setValue:[WebUndefined undefined] forKey:@"key"]; 206 [storedWebScriptObject valueForKey:@"key"]; 207 [storedWebScriptObject removeWebScriptKey:@"key"]; 208 [storedWebScriptObject stringRepresentation]; 209 [storedWebScriptObject webScriptValueAtIndex:0]; 210 [storedWebScriptObject setWebScriptValueAtIndex:0 value:[WebUndefined undefined]]; 211 [storedWebScriptObject setException:@"exception"]; 212} 213 214- (void)storeWebScriptObject:(WebScriptObject *)webScriptObject 215{ 216 if (webScriptObject == storedWebScriptObject) 217 return; 218 219 [storedWebScriptObject release]; 220 storedWebScriptObject = [webScriptObject retain]; 221} 222 223- (NSArray *)testArray 224{ 225 return [NSArray array]; 226} 227 228- (void)dealloc 229{ 230 [storedWebScriptObject release]; 231 [super dealloc]; 232} 233 234- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args 235{ 236 // FIXME: Perhaps we should log that this has been called. 237 return nil; 238} 239 240@end 241