home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
- /* ** */
- /* FIXME remove when pure JRI if possible */
- #include "oobj.h"
- #include "interpreter.h"
- #include "tree.h"
-
- #include "jsapi.h"
- #include "jsjava.h"
- #include "jscntxt.h" /* for cx->savedErrors */
-
- #include "jri.h"
-
- #include "prmon.h" /* for PR_XLock and PR_XUnlock */
- #include "prprf.h" /* for PR_snprintf */
- #include "prthread.h"
- #include "prlog.h"
-
- #define IMPLEMENT_netscape_javascript_JSObject
- #include "netscape_javascript_JSObject.h"
- #ifndef XP_MAC
- #include "netscape_javascript_JSException.h"
- #else
- #include "n_javascript_JSException.h"
- #endif
-
-
- #ifdef NSPR20
- extern PRLogModuleInfo* Moja;
- #define debug PR_LOG_DEBUG
- #endif /* NSPR20 */
-
- #define JAVA_JS_STACK_SIZE 8192
-
- typedef struct {
- JSErrorReporter errReporter;
- } JSSavedState;
-
- static void
- js_throwJSException(JRIEnv *env, char *detail)
- {
- #ifdef JAVA
- struct java_lang_String* message =
- JRI_NewStringPlatform(env,
- (const jbyte *) detail,
- (jint) strlen(detail),
- (const jbyte *) NULL,
- (jint) 0);
- struct netscape_javascript_JSException* exc =
- netscape_javascript_JSException_new_1(env,
- class_netscape_javascript_JSException(env),
- /*Java_getGlobalRef(env, js_JSExceptionClass),*/
- message);
-
- JRI_Throw(env, (struct java_lang_Throwable*)exc);
- #endif /* JAVA */
- }
-
- /***********************************************************************/
-
- static bool_t
- enterJS(JRIEnv *env,
- struct netscape_javascript_JSObject* self,
- JSContext **cxp, JSObject **jsop, JSSavedState *saved)
- {
- #ifndef JAVA
- return JS_FALSE;
- #else
- char *err;
-
- JSJ_EnterJS();
-
- /* check the internal pointer for null while holding the
- * js lock to deal with shutdown issues */
- if (jsop &&
- (! self ||
- ! (*jsop = (JSObject *)
- get_netscape_javascript_JSObject_internal(env, self)))) {
-
- /* FIXME use a better exception */
- JRI_ThrowNew(env, JRI_FindClass(env, "java/lang/Exception"),
- "not a JavaScript object");
- JSJ_ExitJS();
- return FALSE;
- }
-
- /* PR_LOG(Moja, debug, ("clearing exceptions in ee=0x%x", env)); */
-
- exceptionClear((ExecEnv *)env);
-
- if (! (*cxp = JSJ_CurrentContext(env, &err))) {
- JSJ_ExitJS();
- if (err) {
- js_throwJSException(env, err);
- free(err);
- }
- return FALSE;
- }
-
- jsj_ClearSavedErrors(*cxp);
-
- saved->errReporter = JS_SetErrorReporter(*cxp, js_JavaErrorReporter);
- return TRUE;
- #endif
- }
-
- static bool_t
- exitJS(JRIEnv *env,
- struct netscape_javascript_JSObject* self,
- JSContext *cx, JSObject *jso, JSSavedState *saved)
- {
- #ifndef JAVA
- return JS_FALSE;
- #else
- /* restore saved info */
- JS_SetErrorReporter(cx, saved->errReporter);
-
- js_JSErrorToJException(cx, (ExecEnv*)env);
-
- JSJ_ExitJS();
-
- if (exceptionOccurred((ExecEnv*)env))
- return FALSE;
-
- return TRUE;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(struct java_lang_Object *)
- native_netscape_javascript_JSObject_getMember(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- struct java_lang_String *name)
- {
- #ifndef JAVA
- return NULL;
- #else
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- const char *cstr;
- struct java_lang_Object *member;
- jsval val;
- int cost = 0;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return NULL;
-
- if (! name ||
- ! (cstr = JRI_GetStringPlatformChars(env, name,
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength))) {
- /* FIXME this should be an error of some sort */
- js_throwJSException(env, "illegal member name");
- member = NULL;
- goto do_exit;
- }
-
- if (! JS_GetProperty(cx, jso, cstr, &val) ||
- ! js_convertJSValueToJObject(/*FIXME*/(HObject**)&member, cx, val,
- 0, 0, JS_FALSE, &cost))
- member = NULL;
-
- do_exit:
- if (!exitJS(env, self, cx, jso, &saved))
- return NULL;
-
- return member;
- #endif
- }
-
- /***********************************************************************/
-
- /* public native getSlot(I)Ljava/lang/Object; */
- JRI_PUBLIC_API(struct java_lang_Object *)
- native_netscape_javascript_JSObject_getSlot(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- jint slot)
- {
- #ifndef JAVA
- return NULL;
- #else
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- struct java_lang_Object *member;
- jsval val;
- int cost = 0;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return NULL;
-
- if (! JS_GetElement(cx, jso, slot, &val) ||
- ! js_convertJSValueToJObject(/*FIXME*/(HObject**)&member, cx, val,
- 0, 0, JS_FALSE, &cost))
- member = NULL;
-
- if (!exitJS(env, self, cx, jso, &saved))
- return NULL;
-
- return member;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(void)
- native_netscape_javascript_JSObject_setMember(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- struct java_lang_String *name,
- struct java_lang_Object *value)
- {
- #ifdef JAVA
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- const char *cstr;
- jsval val;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return;
-
- if (! name ||
- ! (cstr = JRI_GetStringPlatformChars(env, name,
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength))) {
- js_throwJSException(env, "illegal member name");
- goto do_exit;
- }
-
- if (js_convertJObjectToJSValue(cx, &val, (HObject *)value) &&
- JS_SetProperty(cx, jso, cstr, &val)) {
- }
-
- /* PR_LOG(Moja, debug,
- ("JSObject.setMember(%s, 0x%x)\n", cstr, value)); */
-
- do_exit:
- exitJS(env, self, cx, jso, &saved);
- return;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(void)
- native_netscape_javascript_JSObject_setSlot(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- jint slot,
- struct java_lang_Object *value)
- {
- #ifdef JAVA
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- jsval val;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return;
-
- if (js_convertJObjectToJSValue(cx, &val, (HObject *)value) &&
- JS_SetElement(cx, jso, slot, &val)) {
- }
-
- /* PR_LOG(Moja, debug,
- ("JSObject.setSlot(%d, 0x%x)\n", slot, value)); */
-
- exitJS(env, self, cx, jso, &saved);
- return;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(void)
- native_netscape_javascript_JSObject_removeMember(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- struct java_lang_String * name)
- {
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- const char *cstr;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return;
- #ifdef JAVA
- if (! name ||
- ! (cstr = JRI_GetStringPlatformChars(env, name,
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength))) {
- /* FIXME this should be an error of some sort */
- js_throwJSException(env, "illegal member name");
- goto do_exit;
- }
-
- JS_DeleteProperty(cx, jso, cstr);
- #endif
-
- /* PR_LOG(Moja, debug,
- ("JSObject.removeMember(%s)\n", cstr)); */
-
- do_exit:
- exitJS(env, self, cx, jso, &saved);
- return;
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(struct java_lang_Object *)
- native_netscape_javascript_JSObject_call(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- struct java_lang_String *method,
- jobjectArray args)
- {
- #ifndef JAVA
- return NULL;
- #else
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- const char *cstr;
- struct java_lang_Object *ret;
- int total_argc, argc, i;
- jsval *argv;
- jsval rval;
- int cost = 0;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return NULL;
-
- if (! method ||
- ! (cstr = JRI_GetStringPlatformChars(env, method,
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength))) {
- /* FIXME this should be an error of some sort */
- js_throwJSException(env, "illegal member name");
- ret = NULL;
- goto do_exit;
- }
-
- if (args) {
- total_argc = JRI_GetObjectArrayLength(env, args);
- argv = sysMalloc(total_argc * sizeof(jsval));
- } else {
- total_argc = 0;
- argv = 0;
- }
-
- for (argc = 0; argc < total_argc; argc++) {
- jref arg = JRI_GetObjectArrayElement(env, args, argc);
-
- if (!js_convertJObjectToJSValue(cx, argv+argc, (HObject*)arg))
- goto cleanup_argv;
- JS_AddRoot(cx, argv+argc);
- }
-
- if (! JS_CallFunctionName(cx, jso, cstr, argc, argv, &rval) ||
- ! js_convertJSValueToJObject((HObject **) &ret, cx, rval,
- 0, 0, JS_FALSE, &cost)) {
- ret = NULL;
- }
-
- cleanup_argv:
- for (i = 0; i < argc; i++)
- JS_RemoveRoot(cx, argv+i);
- sysFree(argv);
-
- do_exit:
- if (!exitJS(env, self, cx, jso, &saved))
- return NULL;
-
- return ret;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(struct java_lang_Object *)
- native_netscape_javascript_JSObject_eval(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self,
- struct java_lang_String *s)
- {
- #ifndef JAVA
- return NULL;
- #else
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- const char *cstr;
- int cstrlen;
- struct java_lang_Object *ret;
- jsval rval;
- int cost = 0;
- JSPrincipals *principals;
- char *codebase;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return NULL;
-
- if (! s ||
- ! (cstr = JRI_GetStringPlatformChars(env, s,
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength))) {
- /* FIXME this should be an error of some sort */
- js_throwJSException(env, "illegal eval string");
- ret = NULL;
- goto do_exit;
- }
-
- /* subtract 1 for the NUL */
- /*
- * FIXME There is no JRI_GetStringPlatformLength (what a misnomer, if there
- * were!), but JRI_GetStringPlatformChars does NUL-terminate the encoded
- * string, so we trust that no charset encoding ever uses a NUL byte as
- * part of a multibyte sequence and just call strlen.
- */
- cstrlen = strlen(cstr);
-
- principals = js_GetJSPrincipalsFromJavaCaller(cx, 0);
- codebase = principals ? principals->codebase : NULL;
- if (! JS_EvaluateScriptForPrincipals(cx, jso, principals, cstr, cstrlen,
- codebase, 0, &rval) ||
- ! js_convertJSValueToJObject((HObject**)&ret, cx, rval,
- 0, 0, JS_FALSE, &cost)) {
- ret = NULL;
- }
-
- do_exit:
- if (!exitJS(env, self, cx, jso, &saved))
- return NULL;
-
- return ret;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(void)
- native_netscape_javascript_JSObject_finalize(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self)
- {
- #ifdef JAVA
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
-
- /* FIXME if enterJS fails here we have a memory leak! */
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return;
-
- js_RemoveReflection(cx, jso);
-
- if (!exitJS(env, self, cx, jso, &saved))
- return;
-
- return;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(struct java_lang_String *)
- native_netscape_javascript_JSObject_toString(
- JRIEnv* env,
- struct netscape_javascript_JSObject* self)
- {
- JSContext *cx;
- JSObject *jso;
- JSSavedState saved;
- JSString *jsstr;
- char *cstr;
- struct java_lang_String *ret;
-
- if (!enterJS(env, self, &cx, &jso, &saved))
- return NULL;
-
- #ifdef JAVA
- if ((jsstr = JS_ValueToString(cx, OBJECT_TO_JSVAL(jso))) &&
- (cstr = JS_GetStringBytes(jsstr))) {
- ret = JRI_NewStringPlatform(env,
- (const jbyte *) cstr,
- (jint) JS_GetStringLength(jsstr),
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength);
- } else {
- /* FIXME could grab the clazz name from the JSObject */
- ret = JRI_NewStringPlatform(env,
- (const jbyte *) "*JSObject*",
- (jint) strlen("*JSObject*"),
- (const jbyte *) cx->charSetName,
- (jint) cx->charSetNameLength);
- }
- #endif
-
- if (!exitJS(env, self, cx, jso, &saved))
- return NULL;
-
- return ret;
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(struct netscape_javascript_JSObject*)
- native_netscape_javascript_JSObject_getWindow(
- JRIEnv* env,
- struct java_lang_Class* clazz,
- struct java_applet_Applet* hint)
- {
- #ifndef JAVA
- return NULL;
- #else
- struct netscape_javascript_JSObject *ret = NULL;
- JSContext *cx;
- JSSavedState saved;
- JSObject *jso;
-
- if (!JSJ_IsEnabled()) {
- js_throwJSException(env, "Java/JavaScript communication is disabled");
- return 0;
- }
-
- if (!enterJS(env, NULL, &cx, NULL, &saved))
- return NULL;
-
- jso = JSJ_GetDefaultObject(env, (jobject) hint);
- if (exceptionOccurred((ExecEnv *)env))
- goto out;
-
- ret = (struct netscape_javascript_JSObject *)
- js_ReflectJSObjectToJObject(cx, jso);
-
- out:
- if (!exitJS(env, NULL, cx, NULL, &saved))
- return NULL;
- return ret;
- #endif
- }
-
- /***********************************************************************/
-
- JRI_PUBLIC_API(void)
- native_netscape_javascript_JSObject_initClass(
- JRIEnv* env,
- struct java_lang_Class* myClazz)
- {
- #ifdef JAVA
- struct java_lang_Class* clazz;
- /* this is to initialize the field lookup indices, and protect
- * the classes from gc. */
-
- clazz = use_netscape_javascript_JSObject(env);
- MakeClassSticky((struct Hjava_lang_Class*)clazz);
-
- clazz = use_netscape_javascript_JSException(env);
- MakeClassSticky((struct Hjava_lang_Class*)clazz);
-
- /* this does nothing if somebody else has already set
- * stuff up (i.e. client or server) */
- JSJ_InitStandalone();
- #endif
- }
-
-