1 /* 2 * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "jni_jsobject.h" 28 29 #if ENABLE(JAVA_BRIDGE) 30 31 #include "Frame.h" 32 #include "JNIUtility.h" 33 #include "JNIUtilityPrivate.h" 34 #include "JSDOMBinding.h" 35 #include "JavaRuntimeObject.h" 36 #include "JavaString.h" 37 #include "Logging.h" 38 #include "ScriptController.h" 39 #include "StringSourceProvider.h" 40 #include "WebCoreFrameView.h" 41 #include "runtime_object.h" 42 #include "runtime_root.h" 43 #include <interpreter/CallFrame.h> 44 #include <runtime/Completion.h> 45 #include <runtime/JSGlobalObject.h> 46 #include <runtime/JSLock.h> 47 48 using WebCore::Frame; 49 50 using namespace JSC::Bindings; 51 using namespace JSC; 52 using namespace WebCore; 53 54 #define UndefinedHandle 1 55 56 static CFRunLoopSourceRef _performJavaScriptSource; 57 static CFRunLoopRef _performJavaScriptRunLoop; 58 59 // May only be set by dispatchToJavaScriptThread(). 60 static CFRunLoopSourceRef completionSource; 61 62 static void completedJavaScriptAccess (void *i) 63 { 64 ASSERT(CFRunLoopGetCurrent() != _performJavaScriptRunLoop); 65 66 JSObjectCallContext *callContext = (JSObjectCallContext *)i; 67 CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop; 68 69 ASSERT(CFRunLoopGetCurrent() == runLoop); 70 71 CFRunLoopStop(runLoop); 72 } 73 74 static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT; 75 static pthread_mutex_t javaScriptAccessLock; 76 static int javaScriptAccessLockCount = 0; 77 78 static void initializeJavaScriptAccessLock() 79 { 80 pthread_mutexattr_t attr; 81 82 pthread_mutexattr_init(&attr); 83 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); 84 85 pthread_mutex_init(&javaScriptAccessLock, &attr); 86 } 87 88 static inline void lockJavaScriptAccess() 89 { 90 // Perhaps add deadlock detection? 91 pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock); 92 pthread_mutex_lock(&javaScriptAccessLock); 93 javaScriptAccessLockCount++; 94 } 95 96 static inline void unlockJavaScriptAccess() 97 { 98 javaScriptAccessLockCount--; 99 pthread_mutex_unlock(&javaScriptAccessLock); 100 } 101 102 static void dispatchToJavaScriptThread(JSObjectCallContext *context) 103 { 104 // This lock guarantees that only one thread can invoke 105 // at a time, and also guarantees that completionSource; 106 // won't get clobbered. 107 lockJavaScriptAccess(); 108 109 CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent(); 110 111 ASSERT(currentRunLoop != _performJavaScriptRunLoop); 112 113 // Setup a source to signal once the invocation of the JavaScript 114 // call completes. 115 // 116 // FIXME: This could be a potential performance issue. Creating and 117 // adding run loop sources is expensive. We could create one source 118 // per thread, as needed, instead. 119 context->originatingLoop = currentRunLoop; 120 CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess}; 121 completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext); 122 CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode); 123 124 // Wakeup JavaScript access thread and make it do its work. 125 CFRunLoopSourceSignal(_performJavaScriptSource); 126 if (CFRunLoopIsWaiting(_performJavaScriptRunLoop)) 127 CFRunLoopWakeUp(_performJavaScriptRunLoop); 128 129 // Wait until the JavaScript access thread is done. 130 CFRunLoopRun (); 131 132 CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode); 133 CFRelease (completionSource); 134 135 unlockJavaScriptAccess(); 136 } 137 138 static void performJavaScriptAccess(void*) 139 { 140 ASSERT(CFRunLoopGetCurrent() == _performJavaScriptRunLoop); 141 142 // Dispatch JavaScript calls here. 143 CFRunLoopSourceContext sourceContext; 144 CFRunLoopSourceGetContext (completionSource, &sourceContext); 145 JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info; 146 CFRunLoopRef originatingLoop = callContext->originatingLoop; 147 148 JavaJSObject::invoke (callContext); 149 150 // Signal the originating thread that we're done. 151 CFRunLoopSourceSignal (completionSource); 152 if (CFRunLoopIsWaiting(originatingLoop)) 153 CFRunLoopWakeUp(originatingLoop); 154 } 155 156 // Must be called from the thread that will be used to access JavaScript. 157 void JavaJSObject::initializeJNIThreading() { 158 // Should only be called once. 159 ASSERT(!_performJavaScriptRunLoop); 160 161 // Assume that we can retain this run loop forever. It'll most 162 // likely (always?) be the main loop. 163 _performJavaScriptRunLoop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent()); 164 165 // Setup a source the other threads can use to signal the _runLoop 166 // thread that a JavaScript call needs to be invoked. 167 CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess}; 168 _performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext); 169 CFRunLoopAddSource(_performJavaScriptRunLoop, _performJavaScriptSource, kCFRunLoopDefaultMode); 170 } 171 172 static bool isJavaScriptThread() 173 { 174 return (_performJavaScriptRunLoop == CFRunLoopGetCurrent()); 175 } 176 177 jvalue JavaJSObject::invoke(JSObjectCallContext *context) 178 { 179 jvalue result; 180 181 bzero ((void *)&result, sizeof(jvalue)); 182 183 if (!isJavaScriptThread()) { 184 // Send the call context to the thread that is allowed to 185 // call JavaScript. 186 dispatchToJavaScriptThread(context); 187 result = context->result; 188 } 189 else { 190 jlong nativeHandle = context->nativeHandle; 191 if (nativeHandle == UndefinedHandle || nativeHandle == 0) { 192 return result; 193 } 194 195 if (context->type == CreateNative) { 196 result.j = JavaJSObject::createNative(nativeHandle); 197 } 198 else { 199 JSObject *imp = jlong_to_impptr(nativeHandle); 200 if (!findProtectingRootObject(imp)) { 201 LOG_ERROR("Attempt to access JavaScript from destroyed applet, type %d.", context->type); 202 return result; 203 } 204 205 switch (context->type){ 206 case Call: { 207 result.l = JavaJSObject(nativeHandle).call(context->string, context->args); 208 break; 209 } 210 211 case Eval: { 212 result.l = JavaJSObject(nativeHandle).eval(context->string); 213 break; 214 } 215 216 case GetMember: { 217 result.l = JavaJSObject(nativeHandle).getMember(context->string); 218 break; 219 } 220 221 case SetMember: { 222 JavaJSObject(nativeHandle).setMember(context->string, context->value); 223 break; 224 } 225 226 case RemoveMember: { 227 JavaJSObject(nativeHandle).removeMember(context->string); 228 break; 229 } 230 231 case GetSlot: { 232 result.l = JavaJSObject(nativeHandle).getSlot(context->index); 233 break; 234 } 235 236 case SetSlot: { 237 JavaJSObject(nativeHandle).setSlot(context->index, context->value); 238 break; 239 } 240 241 case ToString: { 242 result.l = (jobject) JavaJSObject(nativeHandle).toString(); 243 break; 244 } 245 246 case Finalize: { 247 JavaJSObject(nativeHandle).finalize(); 248 break; 249 } 250 251 default: { 252 LOG_ERROR("invalid JavaScript call"); 253 } 254 } 255 } 256 context->result = result; 257 } 258 259 return result; 260 } 261 262 263 JavaJSObject::JavaJSObject(jlong nativeJSObject) 264 { 265 _imp = jlong_to_impptr(nativeJSObject); 266 267 ASSERT(_imp); 268 _rootObject = findProtectingRootObject(_imp); 269 ASSERT(_rootObject); 270 } 271 272 RootObject* JavaJSObject::rootObject() const 273 { 274 return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; 275 } 276 277 jobject JavaJSObject::call(jstring methodName, jobjectArray args) const 278 { 279 LOG(LiveConnect, "JavaJSObject::call methodName = %s", JavaString(methodName).utf8()); 280 281 RootObject* rootObject = this->rootObject(); 282 if (!rootObject) 283 return 0; 284 285 // Lookup the function object. 286 ExecState* exec = rootObject->globalObject()->globalExec(); 287 JSLock lock(SilenceAssertionsOnly); 288 289 Identifier identifier(exec, JavaString(methodName).impl()); 290 JSValue function = _imp->get(exec, identifier); 291 CallData callData; 292 CallType callType = getCallData(function, callData); 293 if (callType == CallTypeNone) 294 return 0; 295 296 // Call the function object. 297 MarkedArgumentBuffer argList; 298 getListFromJArray(exec, args, argList); 299 rootObject->globalObject()->globalData().timeoutChecker.start(); 300 JSValue result = JSC::call(exec, function, callType, callData, _imp, argList); 301 rootObject->globalObject()->globalData().timeoutChecker.stop(); 302 303 return convertValueToJObject(result); 304 } 305 306 jobject JavaJSObject::eval(jstring script) const 307 { 308 LOG(LiveConnect, "JavaJSObject::eval script = %s", JavaString(script).utf8()); 309 310 JSValue result; 311 312 JSLock lock(SilenceAssertionsOnly); 313 314 RootObject* rootObject = this->rootObject(); 315 if (!rootObject) 316 return 0; 317 318 rootObject->globalObject()->globalData().timeoutChecker.start(); 319 Completion completion = JSC::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script).impl()), JSC::JSValue()); 320 rootObject->globalObject()->globalData().timeoutChecker.stop(); 321 ComplType type = completion.complType(); 322 323 if (type == Normal) { 324 result = completion.value(); 325 if (!result) 326 result = jsUndefined(); 327 } else 328 result = jsUndefined(); 329 330 return convertValueToJObject (result); 331 } 332 333 jobject JavaJSObject::getMember(jstring memberName) const 334 { 335 LOG(LiveConnect, "JavaJSObject::getMember (%p) memberName = %s", _imp, JavaString(memberName).utf8()); 336 337 RootObject* rootObject = this->rootObject(); 338 if (!rootObject) 339 return 0; 340 341 ExecState* exec = rootObject->globalObject()->globalExec(); 342 343 JSLock lock(SilenceAssertionsOnly); 344 JSValue result = _imp->get(exec, Identifier(exec, JavaString(memberName).impl())); 345 346 return convertValueToJObject(result); 347 } 348 349 void JavaJSObject::setMember(jstring memberName, jobject value) const 350 { 351 LOG(LiveConnect, "JavaJSObject::setMember memberName = %s, value = %p", JavaString(memberName).utf8(), value); 352 353 RootObject* rootObject = this->rootObject(); 354 if (!rootObject) 355 return; 356 357 ExecState* exec = rootObject->globalObject()->globalExec(); 358 359 JSLock lock(SilenceAssertionsOnly); 360 PutPropertySlot slot; 361 _imp->put(exec, Identifier(exec, JavaString(memberName).impl()), convertJObjectToValue(exec, value), slot); 362 } 363 364 365 void JavaJSObject::removeMember(jstring memberName) const 366 { 367 LOG(LiveConnect, "JavaJSObject::removeMember memberName = %s", JavaString(memberName).utf8()); 368 369 RootObject* rootObject = this->rootObject(); 370 if (!rootObject) 371 return; 372 373 ExecState* exec = rootObject->globalObject()->globalExec(); 374 JSLock lock(SilenceAssertionsOnly); 375 _imp->deleteProperty(exec, Identifier(exec, JavaString(memberName).impl())); 376 } 377 378 379 jobject JavaJSObject::getSlot(jint index) const 380 { 381 LOG(LiveConnect, "JavaJSObject::getSlot index = %ld", static_cast<long>(index)); 382 383 RootObject* rootObject = this->rootObject(); 384 if (!rootObject) 385 return 0; 386 387 ExecState* exec = rootObject->globalObject()->globalExec(); 388 389 JSLock lock(SilenceAssertionsOnly); 390 JSValue result = _imp->get(exec, index); 391 392 return convertValueToJObject(result); 393 } 394 395 396 void JavaJSObject::setSlot(jint index, jobject value) const 397 { 398 LOG(LiveConnect, "JavaJSObject::setSlot index = %ld, value = %p", static_cast<long>(index), value); 399 400 RootObject* rootObject = this->rootObject(); 401 if (!rootObject) 402 return; 403 404 ExecState* exec = rootObject->globalObject()->globalExec(); 405 JSLock lock(SilenceAssertionsOnly); 406 _imp->put(exec, (unsigned)index, convertJObjectToValue(exec, value)); 407 } 408 409 410 jstring JavaJSObject::toString() const 411 { 412 LOG(LiveConnect, "JavaJSObject::toString"); 413 414 RootObject* rootObject = this->rootObject(); 415 if (!rootObject) 416 return 0; 417 418 JSLock lock(SilenceAssertionsOnly); 419 JSObject *thisObj = const_cast<JSObject*>(_imp); 420 ExecState* exec = rootObject->globalObject()->globalExec(); 421 422 return static_cast<jstring>(convertValueToJValue(exec, rootObject, thisObj, JavaTypeObject, "java.lang.String").l); 423 } 424 425 void JavaJSObject::finalize() const 426 { 427 if (RootObject* rootObject = this->rootObject()) 428 rootObject->gcUnprotect(_imp); 429 } 430 431 static PassRefPtr<RootObject> createRootObject(void* nativeHandle) 432 { 433 Frame* frame = 0; 434 for (NSView *view = (NSView *)nativeHandle; view; view = [view superview]) { 435 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { 436 NSView<WebCoreFrameView> *webCoreFrameView = static_cast<NSView<WebCoreFrameView>*>(view); 437 frame = [webCoreFrameView _web_frame]; 438 break; 439 } 440 } 441 if (!frame) 442 return 0; 443 return frame->script()->createRootObject(nativeHandle); 444 } 445 446 // We're either creating a 'Root' object (via a call to JavaJSObject.getWindow()), or 447 // another JavaJSObject. 448 jlong JavaJSObject::createNative(jlong nativeHandle) 449 { 450 LOG(LiveConnect, "JavaJSObject::createNative nativeHandle = %d", static_cast<int>(nativeHandle)); 451 452 if (nativeHandle == UndefinedHandle) 453 return nativeHandle; 454 455 if (findProtectingRootObject(jlong_to_impptr(nativeHandle))) 456 return nativeHandle; 457 458 RefPtr<RootObject> rootObject = createRootObject(jlong_to_ptr(nativeHandle)); 459 460 // If rootObject is !NULL We must have been called via netscape.javascript.JavaJSObject.getWindow(), 461 // otherwise we are being called after creating a JavaJSObject in 462 // JavaJSObject::convertValueToJObject(). 463 if (rootObject) { 464 JSObject* globalObject = rootObject->globalObject(); 465 // We call gcProtect here to get the object into the root object's "protect set" which 466 // is used to test if a native handle is valid as well as getting the root object given the handle. 467 rootObject->gcProtect(globalObject); 468 return ptr_to_jlong(globalObject); 469 } 470 471 return nativeHandle; 472 } 473 474 jobject JavaJSObject::convertValueToJObject(JSValue value) const 475 { 476 JSLock lock(SilenceAssertionsOnly); 477 478 RootObject* rootObject = this->rootObject(); 479 if (!rootObject) 480 return 0; 481 482 ExecState* exec = rootObject->globalObject()->globalExec(); 483 JNIEnv *env = getJNIEnv(); 484 jobject result = 0; 485 486 // See section 22.7 of 'JavaScript: The Definitive Guide, 4th Edition', 487 // figure 22-5. 488 // number -> java.lang.Double 489 // string -> java.lang.String 490 // boolean -> java.lang.Boolean 491 // Java instance -> Java instance 492 // Everything else -> JavaJSObject 493 494 if (value.isNumber()) { 495 jclass JSObjectClass = env->FindClass ("java/lang/Double"); 496 jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(D)V"); 497 if (constructorID != NULL) { 498 result = env->NewObject (JSObjectClass, constructorID, (jdouble)value.toNumber(exec)); 499 } 500 } else if (value.isString()) { 501 UString stringValue = value.toString(exec); 502 JNIEnv *env = getJNIEnv(); 503 result = env->NewString ((const jchar *)stringValue.characters(), stringValue.length()); 504 } else if (value.isBoolean()) { 505 jclass JSObjectClass = env->FindClass ("java/lang/Boolean"); 506 jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(Z)V"); 507 if (constructorID != NULL) { 508 result = env->NewObject (JSObjectClass, constructorID, (jboolean)value.toBoolean(exec)); 509 } 510 } 511 else { 512 // Create a JavaJSObject. 513 jlong nativeHandle; 514 515 if (value.isObject()) { 516 JSObject* object = asObject(value); 517 518 // We either have a wrapper around a Java instance or a JavaScript 519 // object. If we have a wrapper around a Java instance, return that 520 // instance, otherwise create a new Java JavaJSObject with the JSObject* 521 // as its nativeHandle. 522 if (object->inherits(&JavaRuntimeObject::s_info)) { 523 JavaRuntimeObject* runtimeObject = static_cast<JavaRuntimeObject*>(object); 524 JavaInstance* runtimeInstance = runtimeObject->getInternalJavaInstance(); 525 if (!runtimeInstance) 526 return 0; 527 528 return runtimeInstance->javaInstance(); 529 } else { 530 nativeHandle = ptr_to_jlong(object); 531 rootObject->gcProtect(object); 532 } 533 } else { 534 // All other types will result in an undefined object. 535 nativeHandle = UndefinedHandle; 536 } 537 538 // Now create the Java JavaJSObject. Look for the JavaJSObject in its new (Tiger) 539 // location and in the original Java 1.4.2 location. 540 jclass JSObjectClass; 541 542 JSObjectClass = env->FindClass ("sun/plugin/javascript/webkit/JSObject"); 543 if (!JSObjectClass) { 544 env->ExceptionDescribe(); 545 env->ExceptionClear(); 546 JSObjectClass = env->FindClass ("apple/applet/JSObject"); 547 } 548 549 jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(J)V"); 550 if (constructorID != NULL) { 551 result = env->NewObject (JSObjectClass, constructorID, nativeHandle); 552 } 553 } 554 555 return result; 556 } 557 558 JSValue JavaJSObject::convertJObjectToValue(ExecState* exec, jobject theObject) const 559 { 560 // Instances of netscape.javascript.JSObject get converted back to 561 // JavaScript objects. All other objects are wrapped. It's not 562 // possible to pass primitive types from the Java to JavaScript. 563 // See section 22.7 of 'JavaScript: The Definitive Guide, 4th Edition', 564 // figure 22-4. 565 jobject classOfInstance = callJNIMethod<jobject>(theObject, "getClass", "()Ljava/lang/Class;"); 566 if (!classOfInstance) { 567 JSLock lock(SilenceAssertionsOnly); 568 return JavaInstance::create(theObject, _rootObject)->createRuntimeObject(exec); 569 } 570 571 // Only the sun.plugin.javascript.webkit.JSObject has a member called nativeJSObject. This class is 572 // created above to wrap internal browser objects. The constructor of this class takes the native 573 // pointer and stores it in this object, so that it can be retrieved below. 574 jstring className = (jstring)callJNIMethod<jobject>(classOfInstance, "getName", "()Ljava/lang/String;"); 575 if (!className || (strcmp(JavaString(className).utf8(), "sun.plugin.javascript.webkit.JSObject") != 0)) { 576 JSLock lock(SilenceAssertionsOnly); 577 return JavaInstance::create(theObject, _rootObject)->createRuntimeObject(exec); 578 } 579 580 // Pull the nativeJSObject value from the Java instance. This is a 581 // pointer to the JSObject. 582 JNIEnv *env = getJNIEnv(); 583 jfieldID fieldID = env->GetFieldID((jclass)classOfInstance, "nativeJSObject", "J"); 584 if (fieldID == NULL) 585 return jsUndefined(); 586 jlong nativeHandle = env->GetLongField(theObject, fieldID); 587 if (nativeHandle == UndefinedHandle) 588 return jsUndefined(); 589 JSObject *imp = static_cast<JSObject*>(jlong_to_impptr(nativeHandle)); 590 return imp; 591 } 592 593 void JavaJSObject::getListFromJArray(ExecState* exec, jobjectArray jArray, MarkedArgumentBuffer& list) const 594 { 595 JNIEnv *env = getJNIEnv(); 596 int numObjects = jArray ? env->GetArrayLength(jArray) : 0; 597 598 for (int i = 0; i < numObjects; i++) { 599 jobject anObject = env->GetObjectArrayElement ((jobjectArray)jArray, i); 600 if (anObject) { 601 list.append(convertJObjectToValue(exec, anObject)); 602 env->DeleteLocalRef (anObject); 603 } 604 else { 605 env->ExceptionDescribe(); 606 env->ExceptionClear(); 607 } 608 } 609 } 610 611 extern "C" { 612 613 jlong KJS_JSCreateNativeJSObject (JNIEnv*, jclass, jstring, jlong nativeHandle, jboolean) 614 { 615 JSObjectCallContext context; 616 context.type = CreateNative; 617 context.nativeHandle = nativeHandle; 618 return JavaJSObject::invoke (&context).j; 619 } 620 621 void KJS_JSObject_JSFinalize (JNIEnv*, jclass, jlong nativeHandle) 622 { 623 JSObjectCallContext context; 624 context.type = Finalize; 625 context.nativeHandle = nativeHandle; 626 JavaJSObject::invoke (&context); 627 } 628 629 jobject KJS_JSObject_JSObjectCall (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring methodName, jobjectArray args, jboolean) 630 { 631 JSObjectCallContext context; 632 context.type = Call; 633 context.nativeHandle = nativeHandle; 634 context.string = methodName; 635 context.args = args; 636 return JavaJSObject::invoke (&context).l; 637 } 638 639 jobject KJS_JSObject_JSObjectEval (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jscript, jboolean) 640 { 641 JSObjectCallContext context; 642 context.type = Eval; 643 context.nativeHandle = nativeHandle; 644 context.string = jscript; 645 return JavaJSObject::invoke (&context).l; 646 } 647 648 jobject KJS_JSObject_JSObjectGetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean) 649 { 650 JSObjectCallContext context; 651 context.type = GetMember; 652 context.nativeHandle = nativeHandle; 653 context.string = jname; 654 return JavaJSObject::invoke (&context).l; 655 } 656 657 void KJS_JSObject_JSObjectSetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jobject value, jboolean) 658 { 659 JSObjectCallContext context; 660 context.type = SetMember; 661 context.nativeHandle = nativeHandle; 662 context.string = jname; 663 context.value = value; 664 JavaJSObject::invoke (&context); 665 } 666 667 void KJS_JSObject_JSObjectRemoveMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean) 668 { 669 JSObjectCallContext context; 670 context.type = RemoveMember; 671 context.nativeHandle = nativeHandle; 672 context.string = jname; 673 JavaJSObject::invoke (&context); 674 } 675 676 jobject KJS_JSObject_JSObjectGetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jboolean) 677 { 678 JSObjectCallContext context; 679 context.type = GetSlot; 680 context.nativeHandle = nativeHandle; 681 context.index = jindex; 682 return JavaJSObject::invoke (&context).l; 683 } 684 685 void KJS_JSObject_JSObjectSetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jobject value, jboolean) 686 { 687 JSObjectCallContext context; 688 context.type = SetSlot; 689 context.nativeHandle = nativeHandle; 690 context.index = jindex; 691 context.value = value; 692 JavaJSObject::invoke (&context); 693 } 694 695 jstring KJS_JSObject_JSObjectToString (JNIEnv*, jclass, jlong nativeHandle) 696 { 697 JSObjectCallContext context; 698 context.type = ToString; 699 context.nativeHandle = nativeHandle; 700 return (jstring)JavaJSObject::invoke (&context).l; 701 } 702 703 } 704 705 #endif // ENABLE(JAVA_BRIDGE) 706