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 200using namespace JSC; 201using namespace JSC::Bindings; 202 203class GlobalImp : public ObjectImp { 204public: 205 virtual UString className() const { return "global"; } 206}; 207 208#define BufferSize 200000 209static char code[BufferSize]; 210 211const 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 229int 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