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 "BridgeJSC.h" 24#include "JSCJSValue.h" 25#include "JSObject.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 -------------------- 42typedef struct 43{ 44 NPObject object; 45 double doubleValue; 46 int intValue; 47 NPVariant stringValue; 48 bool boolValue; 49} MyObject; 50 51 52static 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 62static NPIdentifier myPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS]; 63static 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 83static NPIdentifier myMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; 84static 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 96static void initializeIdentifiers() 97{ 98 NPN_GetStringIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers); 99 NPN_GetStringIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers); 100}; 101 102bool 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 113bool 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 125void 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 141void 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 152void 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 163void setStringValue (MyObject *obj, const NPVariant *variant) 164{ 165 NPN_ReleaseVariantValue (&obj->stringValue); 166 NPN_InitializeVariantWithVariant (&obj->stringValue, variant); 167} 168 169void 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 180void getDoubleValue (MyObject *obj, NPVariant *variant) 181{ 182 NPN_InitializeVariantWithDouble (variant, obj->doubleValue); 183} 184 185void getIntValue (MyObject *obj, NPVariant *variant) 186{ 187 NPN_InitializeVariantWithInt32 (variant, obj->intValue); 188} 189 190void getStringValue (MyObject *obj, NPVariant *variant) 191{ 192 NPN_InitializeVariantWithVariant (variant, &obj->stringValue); 193} 194 195void getBooleanValue (MyObject *obj, NPVariant *variant) 196{ 197 NPN_InitializeVariantWithBool (variant, obj->boolValue); 198} 199 200void 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 224void 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 246void 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 289NPObject *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 309void myInvalidate () 310{ 311 // Make sure we've released any remaining references to JavaScript objects. 312} 313 314void myDeallocate (MyObject *obj) 315{ 316 free ((void *)obj); 317} 318 319static 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}; 330static NPClass *myFunctionPtrs = &_myFunctionPtrs; 331 332// -------------------------------------------------------- 333 334using namespace JSC; 335using namespace JSC::Bindings; 336 337class GlobalImp : public ObjectImp { 338public: 339 virtual String className() const { return "global"; } 340}; 341 342#define BufferSize 200000 343static char code[BufferSize]; 344 345const 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 363int 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)->value(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