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 "config.h" 27 28 #include "BridgeJSC.h" 29 #include <Foundation/Foundation.h> 30 #include "JSObject.h" 31 #include "JSValue.h" 32 #import <WebKit/WebScriptObject.h> 33 #include "interpreter.h" 34 #include "runtime_object.h" 35 #include <stdio.h> 36 #include <string.h> 37 #include "types.h" 38 39 40 #define LOG(formatAndArgs...) { \ 41 fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \ 42 fprintf(stderr, formatAndArgs); \ 43 } 44 45 @interface MySecondInterface : NSObject 46 { 47 double doubleValue; 48 } 49 50 - init; 51 52 @end 53 54 @implementation MySecondInterface 55 56 - init 57 { 58 LOG ("\n"); 59 doubleValue = 666.666; 60 return self; 61 } 62 63 @end 64 65 @interface MyFirstInterface : NSObject 66 { 67 int myInt; 68 MySecondInterface *mySecondInterface; 69 id jsobject; 70 NSString *string; 71 } 72 73 - (int)getInt; 74 - (void)setInt: (int)anInt; 75 - (MySecondInterface *)getMySecondInterface; 76 - (void)logMessage:(NSString *)message; 77 - (void)setJSObject:(id)jsobject; 78 @end 79 80 @implementation MyFirstInterface 81 82 + (NSString *)webScriptNameForSelector:(SEL)aSelector 83 { 84 if (aSelector == @selector(logMessage:)) 85 return @"logMessage"; 86 if (aSelector == @selector(logMessages:)) 87 return @"logMessages"; 88 if (aSelector == @selector(logMessage:prefix:)) 89 return @"logMessageWithPrefix"; 90 return nil; 91 } 92 93 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector 94 { 95 return NO; 96 } 97 98 + (BOOL)isKeyExcludedFromWebScript:(const char *)name 99 { 100 return NO; 101 } 102 103 /* 104 - (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args 105 { 106 NSLog (@"Call to undefined method %@", name); 107 NSLog (@"%d args\n", [args count]); 108 int i; 109 for (i = 0; i < [args count]; i++) { 110 NSLog (@"%d: %@\n", i, [args objectAtIndex:i]); 111 } 112 return @"success"; 113 } 114 */ 115 116 /* 117 - (id)valueForUndefinedKey:(NSString *)key 118 { 119 NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key); 120 return @"aValue"; 121 } 122 */ 123 124 - (void)setValue:(id)value forUndefinedKey:(NSString *)key 125 { 126 NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key); 127 } 128 129 - init 130 { 131 LOG ("\n"); 132 mySecondInterface = [[MySecondInterface alloc] init]; 133 return self; 134 } 135 136 - (void)dealloc 137 { 138 LOG ("\n"); 139 [mySecondInterface release]; 140 [super dealloc]; 141 } 142 143 - (int)getInt 144 { 145 LOG ("myInt = %d\n", myInt); 146 return myInt; 147 } 148 149 - (void)setInt: (int)anInt 150 { 151 LOG ("anInt = %d\n", anInt); 152 myInt = anInt; 153 } 154 155 - (NSString *)getString 156 { 157 return string; 158 } 159 160 - (MySecondInterface *)getMySecondInterface 161 { 162 LOG ("\n"); 163 return mySecondInterface; 164 } 165 166 - (void)logMessage:(NSString *)message 167 { 168 printf ("%s\n", [message lossyCString]); 169 } 170 171 - (void)logMessages:(id)messages 172 { 173 int i, count = [[messages valueForKey:@"length"] intValue]; 174 for (i = 0; i < count; i++) 175 printf ("%s\n", [[messages webScriptValueAtIndex:i] lossyCString]); 176 } 177 178 - (void)logMessage:(NSString *)message prefix:(NSString *)prefix 179 { 180 printf ("%s:%s\n", [prefix lossyCString], [message lossyCString]); 181 } 182 183 - (void)setJSObject:(id)jso 184 { 185 [jsobject autorelease]; 186 jsobject = [jso retain]; 187 } 188 189 - (void)callJSObject:(int)arg1 :(int)arg2 190 { 191 id foo1 = [jsobject callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:jsobject, [NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil]]; 192 printf ("foo (via call) = %s\n", [[foo1 description] lossyCString] ); 193 id foo2 = [jsobject callWebScriptMethod:@"apply" withArguments:[NSArray arrayWithObjects:jsobject, [NSArray arrayWithObjects:[NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil], nil]]; 194 printf ("foo (via apply) = %s\n", [[foo2 description] lossyCString] ); 195 } 196 197 @end 198 199 200 using namespace JSC; 201 using namespace JSC::Bindings; 202 203 class GlobalImp : public ObjectImp { 204 public: 205 virtual UString className() const { return "global"; } 206 }; 207 208 #define BufferSize 200000 209 static char code[BufferSize]; 210 211 const char *readJavaScriptFromFile (const char *file) 212 { 213 FILE *f = fopen(file, "r"); 214 if (!f) { 215 fprintf(stderr, "Error opening %s.\n", file); 216 return 0; 217 } 218 219 int num = fread(code, 1, BufferSize, f); 220 code[num] = '\0'; 221 if(num >= BufferSize) 222 fprintf(stderr, "Warning: File may have been too long.\n"); 223 224 fclose(f); 225 226 return code; 227 } 228 229 int main(int argc, char **argv) 230 { 231 // expecting a filename 232 if (argc < 2) { 233 fprintf(stderr, "You have to specify at least one filename\n"); 234 return -1; 235 } 236 237 bool ret = true; 238 { 239 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 240 241 JSLock lock; 242 243 // create interpreter w/ global object 244 Object global(new GlobalImp()); 245 Interpreter interp; 246 interp.setGlobalObject(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 [pool drain]; 284 } // end block, so that Interpreter and global get deleted 285 286 return ret ? 0 : 3; 287 } 288