2011-01-07 Adam Barth <abarth@webkit.org>
[WebKit-https.git] / Source / WebCore / bridge / jni / jni_jsobject.mm
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 "JavaRuntimeObject.h"
33 #include "JNIBridge.h"
34 #include "JNIUtility.h"
35 #include "JNIUtilityPrivate.h"
36 #include "JSDOMBinding.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));
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)), 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)));
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)), 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)));
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, object_type, "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)