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