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