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