1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten (at) 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 "BridgeJSC.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 96 static void initializeIdentifiers() 97 { 98 NPN_GetStringIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers); 99 NPN_GetStringIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers); 100 }; 101 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 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 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 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 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 163 void setStringValue (MyObject *obj, const NPVariant *variant) 164 { 165 NPN_ReleaseVariantValue (&obj->stringValue); 166 NPN_InitializeVariantWithVariant (&obj->stringValue, variant); 167 } 168 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 180 void getDoubleValue (MyObject *obj, NPVariant *variant) 181 { 182 NPN_InitializeVariantWithDouble (variant, obj->doubleValue); 183 } 184 185 void getIntValue (MyObject *obj, NPVariant *variant) 186 { 187 NPN_InitializeVariantWithInt32 (variant, obj->intValue); 188 } 189 190 void getStringValue (MyObject *obj, NPVariant *variant) 191 { 192 NPN_InitializeVariantWithVariant (variant, &obj->stringValue); 193 } 194 195 void getBooleanValue (MyObject *obj, NPVariant *variant) 196 { 197 NPN_InitializeVariantWithBool (variant, obj->boolValue); 198 } 199 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 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 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 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 309 void myInvalidate () 310 { 311 // Make sure we've released any remaining references to JavaScript objects. 312 } 313 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: 339 virtual UString className() const { return "global"; } 340 }; 341 342 #define BufferSize 200000 343 static char code[BufferSize]; 344 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 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