Updated plugin binding API to reflect latest revision from
[WebKit-https.git] / JavaScriptCore / bindings / testbindings.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  *  Boston, MA 02111-1307, USA.
20  *
21  */
22 #include <assert.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "value.h"
27 #include "object.h"
28 #include "types.h"
29 #include "interpreter.h"
30
31 #include "npruntime.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
98 static void initializeIdentifiers()
99 {
100         NPN_GetIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers);
101         NPN_GetIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers);
102 };
103
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
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
127 void logMessage (const NPVariant *message)
128 {
129         printf ("%s\n", message->value.stringValue.UTF8Characters);
130 }
131
132 void setDoubleValue (MyObject *obj, const NPVariant *variant)
133 {
134         if (!NPN_VariantToDouble (variant, &obj->doubleValue))
135                 NPN_SetExceptionWithUTF8 ((NPObject *)obj, "Attempt to set double value with invalid type.", -1);
136 }
137
138 void setIntValue (MyObject *obj, const NPVariant *variant)
139 {
140         if (!NPN_VariantToInt32 (variant, &obj->intValue))
141                 NPN_SetExceptionWithUTF8 ((NPObject *)obj, "Attempt to set int value with invalid type.", -1);
142 }
143
144 void setStringValue (MyObject *obj, const NPVariant *variant)
145 {
146         NPN_ReleaseVariantValue (&obj->stringValue);
147         NPN_InitializeVariantWithVariant (&obj->stringValue, variant);
148 }
149
150 void setBooleanValue (MyObject *obj, const NPVariant *variant)
151 {
152         if (!NPN_VariantToBool (variant, (NPBool *)&obj->boolValue))
153                 NPN_SetExceptionWithUTF8 ((NPObject *)obj, "Attempt to set bool value with invalid type.", -1);
154 }
155
156 void getDoubleValue (MyObject *obj, NPVariant *variant)
157 {
158         NPN_InitializeVariantWithDouble (variant, obj->doubleValue);
159 }
160
161 void getIntValue (MyObject *obj, NPVariant *variant)
162 {
163         NPN_InitializeVariantWithInt32 (variant, obj->intValue);
164 }
165
166 void getStringValue (MyObject *obj, NPVariant *variant)
167 {
168         NPN_InitializeVariantWithVariant (variant, &obj->stringValue);
169 }
170
171 void getBooleanValue (MyObject *obj, NPVariant *variant)
172 {
173         NPN_InitializeVariantWithBool (variant, obj->boolValue);
174 }
175
176 void myGetProperty (MyObject *obj, NPIdentifier name, NPVariant *variant)
177 {
178         if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]){
179                 getDoubleValue (obj, variant);
180         }
181         else if (name == myPropertyIdentifiers[ID_INT_VALUE]){
182                 getIntValue (obj, variant);
183         }
184         else if (name == myPropertyIdentifiers[ID_STRING_VALUE]){
185                 getStringValue (obj, variant);
186         }
187         else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]){
188                 getBooleanValue (obj, variant);
189         }
190         else if (name == myPropertyIdentifiers[ID_NULL_VALUE]){
191                 return NPN_InitializeVariantAsNull (variant);
192         }
193         else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]){
194                 return NPN_InitializeVariantAsUndefined (variant); 
195         }
196         else
197                 NPN_InitializeVariantAsUndefined(variant);
198 }
199
200 void mySetProperty (MyObject *obj, NPIdentifier name, const NPVariant *variant)
201 {
202         if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]) {
203                 setDoubleValue (obj, variant);
204         }
205         else if (name == myPropertyIdentifiers[ID_INT_VALUE]) {
206                 setIntValue (obj, variant);
207         }
208         else if (name == myPropertyIdentifiers[ID_STRING_VALUE]) {
209                 setStringValue (obj, variant);
210         }
211         else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]) {
212                 setBooleanValue (obj, variant);
213         }
214         else if (name == myPropertyIdentifiers[ID_NULL_VALUE]) {
215                 // Do nothing!
216         }
217         else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]) {
218                 // Do nothing!
219         }
220 }
221
222 void myInvoke (MyObject *obj, NPIdentifier name, NPVariant *args, unsigned argCount, NPVariant *result)
223 {
224         if (name == myMethodIdentifiers[ID_LOG_MESSAGE]) {
225                 if (argCount == 1 && NPN_VariantIsString(&args[0]))
226                         logMessage (&args[0]);
227                 NPN_InitializeVariantAsVoid (result);
228         }
229         else if (name == myMethodIdentifiers[ID_SET_DOUBLE_VALUE]) {
230                 if (argCount == 1 && NPN_VariantIsDouble (&args[0]))
231                         setDoubleValue (obj, &args[0]);
232                 NPN_InitializeVariantAsVoid (result);
233         }
234         else if (name == myMethodIdentifiers[ID_SET_INT_VALUE]) {
235                 if (argCount == 1 && (NPN_VariantIsDouble (&args[0]) || NPN_VariantIsInt32 (&args[0])))
236                         setIntValue (obj, &args[0]);
237                 NPN_InitializeVariantAsVoid (result);
238         }
239         else if (name == myMethodIdentifiers[ID_SET_STRING_VALUE]) {
240                 if (argCount == 1 && NPN_VariantIsString (&args[0]))
241                         setStringValue (obj, &args[0]);
242                 NPN_InitializeVariantAsVoid (result);
243         }
244         else if (name == myMethodIdentifiers[ID_SET_BOOLEAN_VALUE]) {
245                 if (argCount == 1 && NPN_VariantIsBool (&args[0]))
246                         setBooleanValue (obj, &args[0]);
247                 NPN_InitializeVariantAsVoid (result);
248         }
249         else if (name == myMethodIdentifiers[ID_GET_DOUBLE_VALUE]) {
250                 getDoubleValue (obj, result);
251         }
252         else if (name == myMethodIdentifiers[ID_GET_INT_VALUE]) {
253                 getIntValue (obj, result);
254         }
255         else if (name == myMethodIdentifiers[ID_GET_STRING_VALUE]) {
256                 getStringValue (obj, result);
257         }
258         else if (name == myMethodIdentifiers[ID_GET_BOOLEAN_VALUE]) {
259                 getBooleanValue (obj, result);
260         }
261         else 
262                 NPN_InitializeVariantAsUndefined (result);
263 }
264
265 NPObject *myAllocate ()
266 {
267         MyObject *newInstance = (MyObject *)malloc (sizeof(MyObject));
268         
269         if (!identifiersInitialized) {
270                 identifiersInitialized = true;
271                 initializeIdentifiers();
272         }
273         
274         
275         newInstance->doubleValue = 666.666;
276         newInstance->intValue = 1234;
277         newInstance->boolValue = true;
278         newInstance->stringValue.value.stringValue.UTF8Length = strlen ("Hello world");
279         newInstance->stringValue.value.stringValue.UTF8Characters = strdup ("Hello world");
280         
281         return (NPObject *)newInstance;
282 }
283
284 void myInvalidate ()
285 {
286         // Make sure we've released any remainging references to JavaScript
287         // objects.
288 }
289
290 void myDeallocate (MyObject *obj) 
291 {
292         free ((void *)obj);
293 }
294
295 static NPClass _myFunctionPtrs = { 
296         kNPClassStructVersionCurrent,
297         (NPAllocateFunctionPtr) myAllocate, 
298         (NPDeallocateFunctionPtr) myDeallocate, 
299         (NPInvalidateFunctionPtr) myInvalidate,
300         (NPHasMethodFunctionPtr) myHasMethod,
301         (NPInvokeFunctionPtr) myInvoke,
302         (NPHasPropertyFunctionPtr) myHasProperty,
303         (NPGetPropertyFunctionPtr) myGetProperty,
304         (NPSetPropertyFunctionPtr) mySetProperty,
305 };
306 static NPClass *myFunctionPtrs = &_myFunctionPtrs;
307
308 // --------------------------------------------------------
309
310 using namespace KJS;
311 using namespace KJS::Bindings;
312
313 class GlobalImp : public ObjectImp {
314 public:
315   virtual UString className() const { return "global"; }
316 };
317
318 #define BufferSize 200000
319 static char code[BufferSize];
320
321 const char *readJavaScriptFromFile (const char *file)
322 {
323     FILE *f = fopen(file, "r");
324     if (!f) {
325         fprintf(stderr, "Error opening %s.\n", file);
326         return 0;
327     }
328     
329     int num = fread(code, 1, BufferSize, f);
330     code[num] = '\0';
331     if(num >= BufferSize)
332         fprintf(stderr, "Warning: File may have been too long.\n");
333
334     fclose(f);
335     
336     return code;
337 }
338
339 int main(int argc, char **argv)
340 {
341     // expecting a filename
342     if (argc < 2) {
343         fprintf(stderr, "You have to specify at least one filename\n");
344         return -1;
345     }
346     
347     bool ret = true;
348     {
349         Interpreter::lock();
350         
351         // create interpreter w/ global object
352         Object global(new GlobalImp());
353         Interpreter interp(global);
354         ExecState *exec = interp.globalExec();
355         
356         MyObject *myObject = (MyObject *)NPN_CreateObject (myFunctionPtrs);
357         
358         global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage, (void *)myObject));
359         
360         for (int i = 1; i < argc; i++) {
361             const char *code = readJavaScriptFromFile(argv[i]);
362             
363             if (code) {
364                 // run
365                 Completion comp(interp.evaluate(code));
366                 
367                 if (comp.complType() == Throw) {
368                     Value exVal = comp.value();
369                     char *msg = exVal.toString(exec).ascii();
370                     int lineno = -1;
371                     if (exVal.type() == ObjectType) {
372                         Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
373                         if (lineVal.type() == NumberType)
374                             lineno = int(lineVal.toNumber(exec));
375                     }
376                     if (lineno != -1)
377                         fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
378                     else
379                         fprintf(stderr,"Exception: %s\n",msg);
380                     ret = false;
381                 }
382                 else if (comp.complType() == ReturnValue) {
383                     char *msg = comp.value().toString(interp.globalExec()).ascii();
384                     fprintf(stderr,"Return value: %s\n",msg);
385                 }
386             }
387         }
388                 
389         NPN_ReleaseObject ((NPObject *)myObject);
390         
391         Interpreter::unlock();
392         
393     } // end block, so that Interpreter and global get deleted
394     
395     return ret ? 0 : 3;
396 }