2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
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.
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.
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.
29 #include "interpreter.h"
31 #include "npruntime_internal.h"
34 #include "runtime_object.h"
37 #define LOG(formatAndArgs...) { \
38 fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
39 fprintf(stderr, formatAndArgs); \
43 // ------------------ NP Interface definition --------------------
49 NPVariant stringValue
;
54 static bool identifiersInitialized
= false;
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
64 static NPIdentifier myPropertyIdentifiers
[NUM_PROPERTY_IDENTIFIERS
];
65 static const NPUTF8
*myPropertyIdentifierNames
[NUM_PROPERTY_IDENTIFIERS
] = {
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
85 static NPIdentifier myMethodIdentifiers
[NUM_METHOD_IDENTIFIERS
];
86 static const NPUTF8
*myMethodIdentifierNames
[NUM_METHOD_IDENTIFIERS
] = {
98 static void initializeIdentifiers()
100 NPN_GetStringIdentifiers (myPropertyIdentifierNames
, NUM_PROPERTY_IDENTIFIERS
, myPropertyIdentifiers
);
101 NPN_GetStringIdentifiers (myMethodIdentifierNames
, NUM_METHOD_IDENTIFIERS
, myMethodIdentifiers
);
104 bool myHasProperty (NPClass
*theClass
, NPIdentifier name
)
107 for (i
= 0; i
< NUM_PROPERTY_IDENTIFIERS
; i
++) {
108 if (name
== myPropertyIdentifiers
[i
]){
115 bool myHasMethod (NPClass
*theClass
, NPIdentifier name
)
118 for (i
= 0; i
< NUM_METHOD_IDENTIFIERS
; i
++) {
119 if (name
== myMethodIdentifiers
[i
]){
127 void logMessage (const NPVariant
*message
)
129 if (message
->type
== NPVariantStringType
) {
131 strncpy (msgBuf
, message
->value
.stringValue
.UTF8Characters
, message
->value
.stringValue
.UTF8Length
);
132 msgBuf
[message
->value
.stringValue
.UTF8Length
] = 0;
133 printf ("%s\n", msgBuf
);
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
);
143 void setDoubleValue (MyObject
*obj
, const NPVariant
*variant
)
145 if (!NPN_VariantToDouble (variant
, &obj
->doubleValue
)) {
146 NPUTF8
*msg
= "Attempt to set double value with invalid type.";
148 aString
.UTF8Characters
= msg
;
149 aString
.UTF8Length
= strlen (msg
);
150 NPN_SetException ((NPObject
*)obj
, &aString
);
154 void setIntValue (MyObject
*obj
, const NPVariant
*variant
)
156 if (!NPN_VariantToInt32 (variant
, &obj
->intValue
)) {
157 NPUTF8
*msg
= "Attempt to set int value with invalid type.";
159 aString
.UTF8Characters
= msg
;
160 aString
.UTF8Length
= strlen (msg
);
161 NPN_SetException ((NPObject
*)obj
, &aString
);
165 void setStringValue (MyObject
*obj
, const NPVariant
*variant
)
167 NPN_ReleaseVariantValue (&obj
->stringValue
);
168 NPN_InitializeVariantWithVariant (&obj
->stringValue
, variant
);
171 void setBooleanValue (MyObject
*obj
, const NPVariant
*variant
)
173 if (!NPN_VariantToBool (variant
, (NPBool
*)&obj
->boolValue
)) {
174 NPUTF8
*msg
= "Attempt to set bool value with invalid type.";
176 aString
.UTF8Characters
= msg
;
177 aString
.UTF8Length
= strlen (msg
);
178 NPN_SetException ((NPObject
*)obj
, &aString
);
182 void getDoubleValue (MyObject
*obj
, NPVariant
*variant
)
184 NPN_InitializeVariantWithDouble (variant
, obj
->doubleValue
);
187 void getIntValue (MyObject
*obj
, NPVariant
*variant
)
189 NPN_InitializeVariantWithInt32 (variant
, obj
->intValue
);
192 void getStringValue (MyObject
*obj
, NPVariant
*variant
)
194 NPN_InitializeVariantWithVariant (variant
, &obj
->stringValue
);
197 void getBooleanValue (MyObject
*obj
, NPVariant
*variant
)
199 NPN_InitializeVariantWithBool (variant
, obj
->boolValue
);
202 void myGetProperty (MyObject
*obj
, NPIdentifier name
, NPVariant
*variant
)
204 if (name
== myPropertyIdentifiers
[ID_DOUBLE_VALUE
]){
205 getDoubleValue (obj
, variant
);
207 else if (name
== myPropertyIdentifiers
[ID_INT_VALUE
]){
208 getIntValue (obj
, variant
);
210 else if (name
== myPropertyIdentifiers
[ID_STRING_VALUE
]){
211 getStringValue (obj
, variant
);
213 else if (name
== myPropertyIdentifiers
[ID_BOOLEAN_VALUE
]){
214 getBooleanValue (obj
, variant
);
216 else if (name
== myPropertyIdentifiers
[ID_NULL_VALUE
]){
217 return NPN_InitializeVariantAsNull (variant
);
219 else if (name
== myPropertyIdentifiers
[ID_UNDEFINED_VALUE
]){
220 return NPN_InitializeVariantAsUndefined (variant
);
223 NPN_InitializeVariantAsUndefined(variant
);
226 void mySetProperty (MyObject
*obj
, NPIdentifier name
, const NPVariant
*variant
)
228 if (name
== myPropertyIdentifiers
[ID_DOUBLE_VALUE
]) {
229 setDoubleValue (obj
, variant
);
231 else if (name
== myPropertyIdentifiers
[ID_INT_VALUE
]) {
232 setIntValue (obj
, variant
);
234 else if (name
== myPropertyIdentifiers
[ID_STRING_VALUE
]) {
235 setStringValue (obj
, variant
);
237 else if (name
== myPropertyIdentifiers
[ID_BOOLEAN_VALUE
]) {
238 setBooleanValue (obj
, variant
);
240 else if (name
== myPropertyIdentifiers
[ID_NULL_VALUE
]) {
243 else if (name
== myPropertyIdentifiers
[ID_UNDEFINED_VALUE
]) {
248 void myInvoke (MyObject
*obj
, NPIdentifier name
, NPVariant
*args
, unsigned argCount
, NPVariant
*result
)
250 if (name
== myMethodIdentifiers
[ID_LOG_MESSAGE
]) {
251 if (argCount
== 1 && NPN_VariantIsString(&args
[0]))
252 logMessage (&args
[0]);
253 NPN_InitializeVariantAsVoid (result
);
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
);
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
);
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
);
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
);
275 else if (name
== myMethodIdentifiers
[ID_GET_DOUBLE_VALUE
]) {
276 getDoubleValue (obj
, result
);
278 else if (name
== myMethodIdentifiers
[ID_GET_INT_VALUE
]) {
279 getIntValue (obj
, result
);
281 else if (name
== myMethodIdentifiers
[ID_GET_STRING_VALUE
]) {
282 getStringValue (obj
, result
);
284 else if (name
== myMethodIdentifiers
[ID_GET_BOOLEAN_VALUE
]) {
285 getBooleanValue (obj
, result
);
288 NPN_InitializeVariantAsUndefined (result
);
291 NPObject
*myAllocate ()
293 MyObject
*newInstance
= (MyObject
*)malloc (sizeof(MyObject
));
295 if (!identifiersInitialized
) {
296 identifiersInitialized
= true;
297 initializeIdentifiers();
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");
308 return (NPObject
*)newInstance
;
313 // Make sure we've released any remaining references to JavaScript objects.
316 void myDeallocate (MyObject
*obj
)
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
,
332 static NPClass
*myFunctionPtrs
= &_myFunctionPtrs
;
334 // --------------------------------------------------------
337 using namespace JSC::Bindings
;
339 class GlobalImp
: public ObjectImp
{
341 virtual UString
className() const { return "global"; }
344 #define BufferSize 200000
345 static char code
[BufferSize
];
347 const char *readJavaScriptFromFile (const char *file
)
349 FILE *f
= fopen(file
, "r");
351 fprintf(stderr
, "Error opening %s.\n", file
);
355 int num
= fread(code
, 1, BufferSize
, f
);
357 if(num
>= BufferSize
)
358 fprintf(stderr
, "Warning: File may have been too long.\n");
365 int main(int argc
, char **argv
)
367 // expecting a filename
369 fprintf(stderr
, "You have to specify at least one filename\n");
377 // create interpreter w/ global object
378 Object
global(new GlobalImp());
380 interp
.setGlobalObject(global
);
381 ExecState
*exec
= interp
.globalExec();
383 MyObject
*myObject
= (MyObject
*)NPN_CreateObject (myFunctionPtrs
);
385 global
.put(exec
, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage
, (void *)myObject
));
387 for (int i
= 1; i
< argc
; i
++) {
388 const char *code
= readJavaScriptFromFile(argv
[i
]);
392 Completion
comp(interp
.evaluate(code
));
394 if (comp
.complType() == Throw
) {
395 Value exVal
= comp
.value();
396 char *msg
= exVal
.toString(exec
).ascii();
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
));
404 fprintf(stderr
,"Exception, line %d: %s\n",lineno
,msg
);
406 fprintf(stderr
,"Exception: %s\n",msg
);
409 else if (comp
.complType() == ReturnValue
) {
410 char *msg
= comp
.value().toString(interp
.globalExec()).ascii();
411 fprintf(stderr
,"Return value: %s\n",msg
);
416 NPN_ReleaseObject ((NPObject
*)myObject
);
418 } // end block, so that Interpreter and global get deleted