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