Home | History | Annotate | Download | only in mac
      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