Fixed <rdar://problem/3964634> undefined property value from binding seems to evalua...
[WebKit-https.git] / JavaScriptCore / bindings / testbindings.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include <Foundation/Foundation.h>
27
28 #import <WebKit/WebScriptObject.h>
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "value.h"
34 #include "object.h"
35 #include "types.h"
36 #include "interpreter.h"
37
38 #include "runtime.h"
39 #include "runtime_object.h"
40
41 #define LOG(formatAndArgs...) { \
42     fprintf (stderr, "%s:  ", __PRETTY_FUNCTION__); \
43     fprintf(stderr, formatAndArgs); \
44 }
45
46 @interface MySecondInterface : NSObject
47 {
48     double doubleValue;
49 }
50
51 - init;
52
53 @end
54
55 @implementation MySecondInterface
56
57 - init
58 {
59     LOG ("\n");
60     doubleValue = 666.666;
61     return self;
62 }
63
64 @end
65
66 @interface MyFirstInterface : NSObject
67 {
68         int myInt;
69         MySecondInterface *mySecondInterface;
70         id jsobject;
71         NSString *string;
72 }
73
74 - (int)getInt;
75 - (void)setInt: (int)anInt;
76 - (MySecondInterface *)getMySecondInterface;
77 - (void)logMessage:(NSString *)message;
78 - (void)setJSObject:(id)jsobject;
79 @end
80
81 @implementation MyFirstInterface
82
83 + (NSString *)webScriptNameForSelector:(SEL)aSelector
84 {
85     if (aSelector == @selector(logMessage:))
86         return @"logMessage";
87     if (aSelector == @selector(logMessages:))
88         return @"logMessages";
89     if (aSelector == @selector(logMessage:prefix:))
90         return @"logMessageWithPrefix";
91     return nil;
92 }
93
94 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
95 {
96     return NO;
97 }
98
99 + (BOOL)isKeyExcludedFromWebScript:(const char *)name
100 {
101     return NO;
102 }
103
104 /*
105 - (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args;
106 {
107         NSLog (@"Call to undefined method %@", name);
108         NSLog (@"%d args\n", [args count]);
109         int i;
110         for (i = 0; i < [args count]; i++) {
111                 NSLog (@"%d: %@\n", i, [args objectAtIndex:i]);
112         }
113         return @"success";
114 }
115 */
116
117 /*
118 - (id)valueForUndefinedKey:(NSString *)key
119 {
120         NSLog (@"%s:  key = %@", __PRETTY_FUNCTION__, key);
121         return @"aValue";
122 }
123 */
124
125 - (void)setValue:(id)value forUndefinedKey:(NSString *)key
126 {
127         NSLog (@"%s:  key = %@", __PRETTY_FUNCTION__, key);
128 }
129
130 - init
131 {
132     LOG ("\n");
133     mySecondInterface = [[MySecondInterface alloc] init];
134     return self;
135 }
136
137 - (void)dealloc
138 {
139     LOG ("\n");
140     [mySecondInterface release];
141     [super dealloc];
142 }
143
144 - (int)getInt 
145 {
146     LOG ("myInt = %d\n", myInt);
147     return myInt;
148 }
149
150 - (void)setInt: (int)anInt 
151 {
152     LOG ("anInt = %d\n", anInt);
153     myInt = anInt;
154 }
155
156 - (NSString *)getString
157 {
158         return string;
159 }
160
161 - (MySecondInterface *)getMySecondInterface 
162 {
163     LOG ("\n");
164     return mySecondInterface;
165 }
166
167 - (void)logMessage:(NSString *)message
168 {
169     printf ("%s\n", [message lossyCString]);
170 }
171
172 - (void)logMessages:(id)messages
173 {
174     int i, count = [[messages valueForKey:@"length"] intValue];
175     for (i = 0; i < count; i++)
176         printf ("%s\n", [[messages webScriptValueAtIndex:i] lossyCString]);
177 }
178
179 - (void)logMessage:(NSString *)message prefix:(NSString *)prefix
180 {
181     printf ("%s:%s\n", [prefix lossyCString], [message lossyCString]);
182 }
183
184 - (void)setJSObject:(id)jso
185 {
186     [jsobject autorelease];
187     jsobject = [jso retain];
188 }
189
190 - (void)callJSObject:(int)arg1 :(int)arg2
191 {
192     id foo1 = [jsobject callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:jsobject, [NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil]];
193     printf ("foo (via call) = %s\n", [[foo1 description] lossyCString] );
194     id foo2 = [jsobject callWebScriptMethod:@"apply" withArguments:[NSArray arrayWithObjects:jsobject, [NSArray arrayWithObjects:[NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil], nil]];
195     printf ("foo (via apply) = %s\n", [[foo2 description] lossyCString] );
196 }
197
198 @end
199
200
201 using namespace KJS;
202 using namespace KJS::Bindings;
203
204 class GlobalImp : public ObjectImp {
205 public:
206   virtual UString className() const { return "global"; }
207 };
208
209 #define BufferSize 200000
210 static char code[BufferSize];
211
212 const char *readJavaScriptFromFile (const char *file)
213 {
214     FILE *f = fopen(file, "r");
215     if (!f) {
216         fprintf(stderr, "Error opening %s.\n", file);
217         return 0;
218     }
219     
220     int num = fread(code, 1, BufferSize, f);
221     code[num] = '\0';
222     if(num >= BufferSize)
223         fprintf(stderr, "Warning: File may have been too long.\n");
224
225     fclose(f);
226     
227     return code;
228 }
229
230 int main(int argc, char **argv)
231 {
232     // expecting a filename
233     if (argc < 2) {
234         fprintf(stderr, "You have to specify at least one filename\n");
235         return -1;
236     }
237     
238     bool ret = true;
239     {
240         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
241         
242         Interpreter::lock();
243         
244         // create interpreter w/ global object
245         Object global(new GlobalImp());
246         Interpreter interp(global);
247         ExecState *exec = interp.globalExec();
248         
249         MyFirstInterface *myInterface = [[MyFirstInterface alloc] init];
250         
251         global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::ObjectiveCLanguage, (void *)myInterface));
252         
253         for (int i = 1; i < argc; i++) {
254             const char *code = readJavaScriptFromFile(argv[i]);
255             
256             if (code) {
257                 // run
258                 Completion comp(interp.evaluate(code));
259                 
260                 if (comp.complType() == Throw) {
261                     Value exVal = comp.value();
262                     char *msg = exVal.toString(exec).ascii();
263                     int lineno = -1;
264                     if (exVal.type() == ObjectType) {
265                         Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
266                         if (lineVal.type() == NumberType)
267                             lineno = int(lineVal.toNumber(exec));
268                     }
269                     if (lineno != -1)
270                         fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
271                     else
272                         fprintf(stderr,"Exception: %s\n",msg);
273                     ret = false;
274                 }
275                 else if (comp.complType() == ReturnValue) {
276                     char *msg = comp.value().toString(interp.globalExec()).ascii();
277                     fprintf(stderr,"Return value: %s\n",msg);
278                 }
279             }
280         }
281         
282         [myInterface release];
283         
284         Interpreter::unlock();
285         
286 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_3
287         [pool release];
288 #else
289         [pool drain];
290 #endif
291     } // end block, so that Interpreter and global get deleted
292     
293     return ret ? 0 : 3;
294 }