• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Library General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public License
16  *  along with this library; see the file COPYING.LIB.  If not, write to
17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  *  Boston, MA 02110-1301, USA.
19  *
20  */
21 #include "config.h"
22 #include <assert.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "JSValue.h"
27 #include "JSObject.h"
28 #include "types.h"
29 #include "interpreter.h"
30 
31 #include "npruntime_internal.h"
32 
33 #include "runtime.h"
34 #include "runtime_object.h"
35 
36 
37 #define LOG(formatAndArgs...) { \
38     fprintf (stderr, "%s:  ", __PRETTY_FUNCTION__); \
39     fprintf(stderr, formatAndArgs); \
40 }
41 
42 
43 // ------------------ NP Interface definition --------------------
44 typedef struct
45 {
46     NPObject object;
47     double doubleValue;
48     int intValue;
49     NPVariant stringValue;
50     bool boolValue;
51 } MyObject;
52 
53 
54 static bool identifiersInitialized = false;
55 
56 #define ID_DOUBLE_VALUE                         0
57 #define ID_INT_VALUE                            1
58 #define ID_STRING_VALUE                         2
59 #define ID_BOOLEAN_VALUE                        3
60 #define ID_NULL_VALUE                           4
61 #define ID_UNDEFINED_VALUE                      5
62 #define NUM_PROPERTY_IDENTIFIERS                6
63 
64 static NPIdentifier myPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
65 static const NPUTF8 *myPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
66     "doubleValue",
67     "intValue",
68     "stringValue",
69     "booleanValue",
70     "nullValue",
71     "undefinedValue"
72 };
73 
74 #define ID_LOG_MESSAGE                          0
75 #define ID_SET_DOUBLE_VALUE                     1
76 #define ID_SET_INT_VALUE                        2
77 #define ID_SET_STRING_VALUE                     3
78 #define ID_SET_BOOLEAN_VALUE                    4
79 #define ID_GET_DOUBLE_VALUE                     5
80 #define ID_GET_INT_VALUE                        6
81 #define ID_GET_STRING_VALUE                     7
82 #define ID_GET_BOOLEAN_VALUE                    8
83 #define NUM_METHOD_IDENTIFIERS                  9
84 
85 static NPIdentifier myMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
86 static const NPUTF8 *myMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
87     "logMessage",
88     "setDoubleValue",
89     "setIntValue",
90     "setStringValue",
91     "setBooleanValue",
92     "getDoubleValue",
93     "getIntValue",
94     "getStringValue",
95     "getBooleanValue"
96 };
97 
initializeIdentifiers()98 static void initializeIdentifiers()
99 {
100     NPN_GetStringIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers);
101     NPN_GetStringIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers);
102 };
103 
myHasProperty(NPClass * theClass,NPIdentifier name)104 bool myHasProperty (NPClass *theClass, NPIdentifier name)
105 {
106     int i;
107     for (i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) {
108         if (name == myPropertyIdentifiers[i]){
109             return true;
110         }
111     }
112     return false;
113 }
114 
myHasMethod(NPClass * theClass,NPIdentifier name)115 bool myHasMethod (NPClass *theClass, NPIdentifier name)
116 {
117     int i;
118     for (i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
119         if (name == myMethodIdentifiers[i]){
120             return true;
121         }
122     }
123     return false;
124 }
125 
126 
logMessage(const NPVariant * message)127 void logMessage (const NPVariant *message)
128 {
129     if (message->type == NPVariantStringType) {
130         char msgBuf[1024];
131         strncpy (msgBuf, message->value.stringValue.UTF8Characters, message->value.stringValue.UTF8Length);
132         msgBuf[message->value.stringValue.UTF8Length] = 0;
133         printf ("%s\n", msgBuf);
134     }
135     else if (message->type == NPVariantDoubleType)
136         printf ("%f\n", (float)message->value.doubleValue);
137     else if (message->type == NPVariantInt32Type)
138         printf ("%d\n", message->value.intValue);
139     else if (message->type == NPVariantObjectType)
140         printf ("%p\n", message->value.objectValue);
141 }
142 
setDoubleValue(MyObject * obj,const NPVariant * variant)143 void setDoubleValue (MyObject *obj, const NPVariant *variant)
144 {
145     if (!NPN_VariantToDouble (variant, &obj->doubleValue)) {
146         NPUTF8 *msg = "Attempt to set double value with invalid type.";
147         NPString aString;
148         aString.UTF8Characters = msg;
149         aString.UTF8Length = strlen (msg);
150         NPN_SetException ((NPObject *)obj, &aString);
151     }
152 }
153 
setIntValue(MyObject * obj,const NPVariant * variant)154 void setIntValue (MyObject *obj, const NPVariant *variant)
155 {
156     if (!NPN_VariantToInt32 (variant, &obj->intValue)) {
157         NPUTF8 *msg = "Attempt to set int value with invalid type.";
158         NPString aString;
159         aString.UTF8Characters = msg;
160         aString.UTF8Length = strlen (msg);
161         NPN_SetException ((NPObject *)obj, &aString);
162     }
163 }
164 
setStringValue(MyObject * obj,const NPVariant * variant)165 void setStringValue (MyObject *obj, const NPVariant *variant)
166 {
167     NPN_ReleaseVariantValue (&obj->stringValue);
168     NPN_InitializeVariantWithVariant (&obj->stringValue, variant);
169 }
170 
setBooleanValue(MyObject * obj,const NPVariant * variant)171 void setBooleanValue (MyObject *obj, const NPVariant *variant)
172 {
173     if (!NPN_VariantToBool (variant, (NPBool *)&obj->boolValue)) {
174         NPUTF8 *msg = "Attempt to set bool value with invalid type.";
175         NPString aString;
176         aString.UTF8Characters = msg;
177         aString.UTF8Length = strlen (msg);
178         NPN_SetException ((NPObject *)obj, &aString);
179     }
180 }
181 
getDoubleValue(MyObject * obj,NPVariant * variant)182 void getDoubleValue (MyObject *obj, NPVariant *variant)
183 {
184     NPN_InitializeVariantWithDouble (variant, obj->doubleValue);
185 }
186 
getIntValue(MyObject * obj,NPVariant * variant)187 void getIntValue (MyObject *obj, NPVariant *variant)
188 {
189     NPN_InitializeVariantWithInt32 (variant, obj->intValue);
190 }
191 
getStringValue(MyObject * obj,NPVariant * variant)192 void getStringValue (MyObject *obj, NPVariant *variant)
193 {
194     NPN_InitializeVariantWithVariant (variant, &obj->stringValue);
195 }
196 
getBooleanValue(MyObject * obj,NPVariant * variant)197 void getBooleanValue (MyObject *obj, NPVariant *variant)
198 {
199     NPN_InitializeVariantWithBool (variant, obj->boolValue);
200 }
201 
myGetProperty(MyObject * obj,NPIdentifier name,NPVariant * variant)202 void myGetProperty (MyObject *obj, NPIdentifier name, NPVariant *variant)
203 {
204     if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]){
205         getDoubleValue (obj, variant);
206     }
207     else if (name == myPropertyIdentifiers[ID_INT_VALUE]){
208         getIntValue (obj, variant);
209     }
210     else if (name == myPropertyIdentifiers[ID_STRING_VALUE]){
211         getStringValue (obj, variant);
212     }
213     else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]){
214         getBooleanValue (obj, variant);
215     }
216     else if (name == myPropertyIdentifiers[ID_NULL_VALUE]){
217         return NPN_InitializeVariantAsNull (variant);
218     }
219     else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]){
220         return NPN_InitializeVariantAsUndefined (variant);
221     }
222     else
223         NPN_InitializeVariantAsUndefined(variant);
224 }
225 
mySetProperty(MyObject * obj,NPIdentifier name,const NPVariant * variant)226 void mySetProperty (MyObject *obj, NPIdentifier name, const NPVariant *variant)
227 {
228     if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]) {
229         setDoubleValue (obj, variant);
230     }
231     else if (name == myPropertyIdentifiers[ID_INT_VALUE]) {
232         setIntValue (obj, variant);
233     }
234     else if (name == myPropertyIdentifiers[ID_STRING_VALUE]) {
235         setStringValue (obj, variant);
236     }
237     else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]) {
238         setBooleanValue (obj, variant);
239     }
240     else if (name == myPropertyIdentifiers[ID_NULL_VALUE]) {
241         // Do nothing!
242     }
243     else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]) {
244         // Do nothing!
245     }
246 }
247 
myInvoke(MyObject * obj,NPIdentifier name,NPVariant * args,unsigned argCount,NPVariant * result)248 void myInvoke (MyObject *obj, NPIdentifier name, NPVariant *args, unsigned argCount, NPVariant *result)
249 {
250     if (name == myMethodIdentifiers[ID_LOG_MESSAGE]) {
251         if (argCount == 1 && NPN_VariantIsString(&args[0]))
252             logMessage (&args[0]);
253         NPN_InitializeVariantAsVoid (result);
254     }
255     else if (name == myMethodIdentifiers[ID_SET_DOUBLE_VALUE]) {
256         if (argCount == 1 && NPN_VariantIsDouble (&args[0]))
257             setDoubleValue (obj, &args[0]);
258         NPN_InitializeVariantAsVoid (result);
259     }
260     else if (name == myMethodIdentifiers[ID_SET_INT_VALUE]) {
261         if (argCount == 1 && (NPN_VariantIsDouble (&args[0]) || NPN_VariantIsInt32 (&args[0])))
262             setIntValue (obj, &args[0]);
263         NPN_InitializeVariantAsVoid (result);
264     }
265     else if (name == myMethodIdentifiers[ID_SET_STRING_VALUE]) {
266         if (argCount == 1 && NPN_VariantIsString (&args[0]))
267             setStringValue (obj, &args[0]);
268         NPN_InitializeVariantAsVoid (result);
269     }
270     else if (name == myMethodIdentifiers[ID_SET_BOOLEAN_VALUE]) {
271         if (argCount == 1 && NPN_VariantIsBool (&args[0]))
272             setBooleanValue (obj, &args[0]);
273         NPN_InitializeVariantAsVoid (result);
274     }
275     else if (name == myMethodIdentifiers[ID_GET_DOUBLE_VALUE]) {
276         getDoubleValue (obj, result);
277     }
278     else if (name == myMethodIdentifiers[ID_GET_INT_VALUE]) {
279         getIntValue (obj, result);
280     }
281     else if (name == myMethodIdentifiers[ID_GET_STRING_VALUE]) {
282         getStringValue (obj, result);
283     }
284     else if (name == myMethodIdentifiers[ID_GET_BOOLEAN_VALUE]) {
285         getBooleanValue (obj, result);
286     }
287     else
288         NPN_InitializeVariantAsUndefined (result);
289 }
290 
myAllocate()291 NPObject *myAllocate ()
292 {
293     MyObject *newInstance = (MyObject *)malloc (sizeof(MyObject));
294 
295     if (!identifiersInitialized) {
296         identifiersInitialized = true;
297         initializeIdentifiers();
298     }
299 
300 
301     newInstance->doubleValue = 666.666;
302     newInstance->intValue = 1234;
303     newInstance->boolValue = true;
304     newInstance->stringValue.type = NPVariantType_String;
305     newInstance->stringValue.value.stringValue.UTF8Length = strlen ("Hello world");
306     newInstance->stringValue.value.stringValue.UTF8Characters = strdup ("Hello world");
307 
308     return (NPObject *)newInstance;
309 }
310 
myInvalidate()311 void myInvalidate ()
312 {
313     // Make sure we've released any remaining references to JavaScript objects.
314 }
315 
myDeallocate(MyObject * obj)316 void myDeallocate (MyObject *obj)
317 {
318     free ((void *)obj);
319 }
320 
321 static NPClass _myFunctionPtrs = {
322     kNPClassStructVersionCurrent,
323     (NPAllocateFunctionPtr) myAllocate,
324     (NPDeallocateFunctionPtr) myDeallocate,
325     (NPInvalidateFunctionPtr) myInvalidate,
326     (NPHasMethodFunctionPtr) myHasMethod,
327     (NPInvokeFunctionPtr) myInvoke,
328     (NPHasPropertyFunctionPtr) myHasProperty,
329     (NPGetPropertyFunctionPtr) myGetProperty,
330     (NPSetPropertyFunctionPtr) mySetProperty,
331 };
332 static NPClass *myFunctionPtrs = &_myFunctionPtrs;
333 
334 // --------------------------------------------------------
335 
336 using namespace JSC;
337 using namespace JSC::Bindings;
338 
339 class GlobalImp : public ObjectImp {
340 public:
className() const341   virtual UString className() const { return "global"; }
342 };
343 
344 #define BufferSize 200000
345 static char code[BufferSize];
346 
readJavaScriptFromFile(const char * file)347 const char *readJavaScriptFromFile (const char *file)
348 {
349     FILE *f = fopen(file, "r");
350     if (!f) {
351         fprintf(stderr, "Error opening %s.\n", file);
352         return 0;
353     }
354 
355     int num = fread(code, 1, BufferSize, f);
356     code[num] = '\0';
357     if(num >= BufferSize)
358         fprintf(stderr, "Warning: File may have been too long.\n");
359 
360     fclose(f);
361 
362     return code;
363 }
364 
main(int argc,char ** argv)365 int main(int argc, char **argv)
366 {
367     // expecting a filename
368     if (argc < 2) {
369         fprintf(stderr, "You have to specify at least one filename\n");
370         return -1;
371     }
372 
373     bool ret = true;
374     {
375         JSLock lock;
376 
377         // create interpreter w/ global object
378         Object global(new GlobalImp());
379         Interpreter interp;
380         interp.setGlobalObject(global);
381         ExecState *exec = interp.globalExec();
382 
383         MyObject *myObject = (MyObject *)NPN_CreateObject (myFunctionPtrs);
384 
385         global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage, (void *)myObject));
386 
387         for (int i = 1; i < argc; i++) {
388             const char *code = readJavaScriptFromFile(argv[i]);
389 
390             if (code) {
391                 // run
392                 Completion comp(interp.evaluate(code));
393 
394                 if (comp.complType() == Throw) {
395                     Value exVal = comp.value();
396                     char *msg = exVal.toString(exec).ascii();
397                     int lineno = -1;
398                     if (exVal.type() == ObjectType) {
399                         Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
400                         if (lineVal.type() == NumberType)
401                             lineno = int(lineVal.toNumber(exec));
402                     }
403                     if (lineno != -1)
404                         fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
405                     else
406                         fprintf(stderr,"Exception: %s\n",msg);
407                     ret = false;
408                 }
409                 else if (comp.complType() == ReturnValue) {
410                     char *msg = comp.value().toString(interp.globalExec()).ascii();
411                     fprintf(stderr,"Return value: %s\n",msg);
412                 }
413             }
414         }
415 
416         NPN_ReleaseObject ((NPObject *)myObject);
417 
418     } // end block, so that Interpreter and global get deleted
419 
420     return ret ? 0 : 3;
421 }
422