Home | History | Annotate | Download | only in bridge
      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