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