home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / js / jsj / jsStubs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  15.4 KB  |  590 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* ** */
  19. /* FIXME remove when pure JRI if possible */
  20. #include "oobj.h"
  21. #include "interpreter.h"
  22. #include "tree.h"
  23.  
  24. #include "jsapi.h"
  25. #include "jsjava.h"
  26. #include "jscntxt.h"    /* for cx->savedErrors */
  27.  
  28. #include "jri.h"
  29.  
  30. #include "prmon.h"    /* for PR_XLock and PR_XUnlock */
  31. #include "prprf.h"    /* for PR_snprintf */
  32. #include "prthread.h"
  33. #include "prlog.h"
  34.  
  35. #define IMPLEMENT_netscape_javascript_JSObject
  36. #include "netscape_javascript_JSObject.h"
  37. #ifndef XP_MAC
  38. #include "netscape_javascript_JSException.h"
  39. #else
  40. #include "n_javascript_JSException.h"
  41. #endif
  42.  
  43.  
  44. #ifdef NSPR20
  45. extern PRLogModuleInfo* Moja;
  46. #define debug    PR_LOG_DEBUG
  47. #endif /* NSPR20 */
  48.  
  49. #define JAVA_JS_STACK_SIZE 8192
  50.  
  51. typedef struct {
  52.     JSErrorReporter errReporter;
  53. } JSSavedState;
  54.  
  55. static void
  56. js_throwJSException(JRIEnv *env, char *detail)
  57. {
  58. #ifdef JAVA
  59.     struct java_lang_String* message =
  60.     JRI_NewStringPlatform(env,
  61.                   (const jbyte *) detail,
  62.                   (jint) strlen(detail),
  63.                   (const jbyte *) NULL,
  64.                   (jint) 0);
  65.     struct netscape_javascript_JSException* exc =
  66.       netscape_javascript_JSException_new_1(env,
  67.                          class_netscape_javascript_JSException(env),
  68.                          /*Java_getGlobalRef(env, js_JSExceptionClass),*/
  69.                          message);
  70.  
  71.     JRI_Throw(env, (struct java_lang_Throwable*)exc);
  72. #endif /* JAVA */
  73. }
  74.  
  75. /***********************************************************************/
  76.  
  77. static bool_t
  78. enterJS(JRIEnv *env,
  79.         struct netscape_javascript_JSObject* self,
  80.         JSContext **cxp, JSObject **jsop, JSSavedState *saved)
  81. {
  82. #ifndef JAVA
  83.     return JS_FALSE;
  84. #else
  85.     char *err;
  86.  
  87.     JSJ_EnterJS();
  88.  
  89.     /* check the internal pointer for null while holding the
  90.      * js lock to deal with shutdown issues */
  91.     if (jsop &&
  92.         (! self ||
  93.          ! (*jsop = (JSObject *)
  94.             get_netscape_javascript_JSObject_internal(env, self)))) {
  95.  
  96.         /* FIXME use a better exception */
  97.         JRI_ThrowNew(env, JRI_FindClass(env, "java/lang/Exception"),
  98.                      "not a JavaScript object");
  99.         JSJ_ExitJS();
  100.         return FALSE;
  101.     }
  102.  
  103.     /* PR_LOG(Moja, debug, ("clearing exceptions in ee=0x%x", env)); */
  104.  
  105.     exceptionClear((ExecEnv *)env);
  106.  
  107.     if (! (*cxp = JSJ_CurrentContext(env, &err))) {
  108.         JSJ_ExitJS();
  109.         if (err) {
  110.             js_throwJSException(env, err);
  111.             free(err);
  112.         }
  113.         return FALSE;
  114.     }
  115.  
  116.     jsj_ClearSavedErrors(*cxp);
  117.  
  118.     saved->errReporter = JS_SetErrorReporter(*cxp, js_JavaErrorReporter);
  119.     return TRUE;
  120. #endif
  121. }
  122.  
  123. static bool_t
  124. exitJS(JRIEnv *env,
  125.        struct netscape_javascript_JSObject* self,
  126.        JSContext *cx, JSObject *jso, JSSavedState *saved)
  127. {
  128. #ifndef JAVA
  129.     return JS_FALSE;
  130. #else
  131.     /* restore saved info */
  132.     JS_SetErrorReporter(cx, saved->errReporter);
  133.  
  134.     js_JSErrorToJException(cx, (ExecEnv*)env);
  135.  
  136.     JSJ_ExitJS();
  137.  
  138.     if (exceptionOccurred((ExecEnv*)env))
  139.         return FALSE;
  140.  
  141.     return TRUE;
  142. #endif
  143. }
  144.  
  145. /***********************************************************************/
  146.  
  147. JRI_PUBLIC_API(struct java_lang_Object *)
  148. native_netscape_javascript_JSObject_getMember(
  149.     JRIEnv* env,
  150.     struct netscape_javascript_JSObject* self,
  151.     struct java_lang_String *name)
  152. {
  153. #ifndef JAVA
  154.     return NULL;
  155. #else
  156.     JSContext *cx;
  157.     JSObject *jso;
  158.     JSSavedState saved;
  159.     const char *cstr;
  160.     struct java_lang_Object *member;
  161.     jsval val;
  162.     int cost = 0;
  163.  
  164.     if (!enterJS(env, self, &cx, &jso, &saved))
  165.         return NULL;
  166.  
  167.     if (! name ||
  168.         ! (cstr = JRI_GetStringPlatformChars(env, name,
  169.                          (const jbyte *) cx->charSetName,
  170.                          (jint) cx->charSetNameLength))) {
  171.         /* FIXME this should be an error of some sort */
  172.         js_throwJSException(env, "illegal member name");
  173.         member = NULL;
  174.     goto do_exit;
  175.     }
  176.  
  177.     if (! JS_GetProperty(cx, jso, cstr, &val) ||
  178.         ! js_convertJSValueToJObject(/*FIXME*/(HObject**)&member, cx, val,
  179.                                     0, 0, JS_FALSE, &cost))
  180.         member = NULL;
  181.  
  182.   do_exit:
  183.     if (!exitJS(env, self, cx, jso, &saved))
  184.         return NULL;
  185.  
  186.     return member;
  187. #endif
  188. }
  189.  
  190. /***********************************************************************/
  191.  
  192. /* public native getSlot(I)Ljava/lang/Object; */
  193. JRI_PUBLIC_API(struct java_lang_Object *)
  194. native_netscape_javascript_JSObject_getSlot(
  195.     JRIEnv* env,
  196.     struct netscape_javascript_JSObject* self,
  197.     jint slot)
  198. {
  199. #ifndef JAVA
  200.     return NULL;
  201. #else
  202.     JSContext *cx;
  203.     JSObject *jso;
  204.     JSSavedState saved;
  205.     struct java_lang_Object *member;
  206.     jsval val;
  207.     int cost = 0;
  208.  
  209.     if (!enterJS(env, self, &cx, &jso, &saved))
  210.         return NULL;
  211.  
  212.     if (! JS_GetElement(cx, jso, slot, &val) ||
  213.         ! js_convertJSValueToJObject(/*FIXME*/(HObject**)&member, cx, val,
  214.                                      0, 0, JS_FALSE, &cost))
  215.         member = NULL;
  216.  
  217.     if (!exitJS(env, self, cx, jso, &saved))
  218.         return NULL;
  219.  
  220.     return member;
  221. #endif
  222. }
  223.  
  224. /***********************************************************************/
  225.  
  226. JRI_PUBLIC_API(void)
  227. native_netscape_javascript_JSObject_setMember(
  228.     JRIEnv* env,
  229.     struct netscape_javascript_JSObject* self,
  230.     struct java_lang_String *name,
  231.     struct java_lang_Object *value)
  232. {
  233. #ifdef JAVA
  234.     JSContext *cx;
  235.     JSObject *jso;
  236.     JSSavedState saved;
  237.     const char *cstr;
  238.     jsval val;
  239.  
  240.     if (!enterJS(env, self, &cx, &jso, &saved))
  241.         return;
  242.  
  243.     if (! name ||
  244.         ! (cstr = JRI_GetStringPlatformChars(env, name,
  245.                          (const jbyte *) cx->charSetName,
  246.                          (jint) cx->charSetNameLength))) {
  247.         js_throwJSException(env, "illegal member name");
  248.         goto do_exit;
  249.     }
  250.  
  251.     if (js_convertJObjectToJSValue(cx, &val, (HObject *)value) &&
  252.         JS_SetProperty(cx, jso, cstr, &val)) {
  253.     }
  254.  
  255.     /* PR_LOG(Moja, debug,
  256.        ("JSObject.setMember(%s, 0x%x)\n", cstr, value)); */
  257.  
  258.   do_exit:
  259.     exitJS(env, self, cx, jso, &saved);
  260.     return;
  261. #endif
  262. }
  263.  
  264. /***********************************************************************/
  265.  
  266. JRI_PUBLIC_API(void)
  267. native_netscape_javascript_JSObject_setSlot(
  268.     JRIEnv* env,
  269.     struct netscape_javascript_JSObject* self,
  270.     jint slot,
  271.     struct java_lang_Object *value)
  272. {
  273. #ifdef JAVA
  274.     JSContext *cx;
  275.     JSObject *jso;
  276.     JSSavedState saved;
  277.     jsval val;
  278.  
  279.     if (!enterJS(env, self, &cx, &jso, &saved))
  280.         return;
  281.  
  282.     if (js_convertJObjectToJSValue(cx, &val, (HObject *)value) &&
  283.         JS_SetElement(cx, jso, slot, &val)) {
  284.     }
  285.  
  286.     /* PR_LOG(Moja, debug,
  287.            ("JSObject.setSlot(%d, 0x%x)\n", slot, value)); */
  288.  
  289.     exitJS(env, self, cx, jso, &saved);
  290.     return;
  291. #endif
  292. }
  293.  
  294. /***********************************************************************/
  295.  
  296. JRI_PUBLIC_API(void)
  297. native_netscape_javascript_JSObject_removeMember(
  298.     JRIEnv* env,
  299.     struct netscape_javascript_JSObject* self,
  300.     struct java_lang_String * name)
  301. {
  302.     JSContext *cx;
  303.     JSObject *jso;
  304.     JSSavedState saved;
  305.     const char *cstr;
  306.  
  307.     if (!enterJS(env, self, &cx, &jso, &saved))
  308.         return;
  309. #ifdef JAVA
  310.     if (! name ||
  311.         ! (cstr = JRI_GetStringPlatformChars(env, name,
  312.                          (const jbyte *) cx->charSetName,
  313.                          (jint) cx->charSetNameLength))) {
  314.         /* FIXME this should be an error of some sort */
  315.         js_throwJSException(env, "illegal member name");
  316.         goto do_exit;
  317.     }
  318.  
  319.     JS_DeleteProperty(cx, jso, cstr);
  320. #endif
  321.  
  322.     /* PR_LOG(Moja, debug,
  323.            ("JSObject.removeMember(%s)\n", cstr)); */
  324.  
  325.   do_exit:
  326.     exitJS(env, self, cx, jso, &saved);
  327.     return;
  328. }
  329.  
  330. /***********************************************************************/
  331.  
  332. JRI_PUBLIC_API(struct java_lang_Object *)
  333. native_netscape_javascript_JSObject_call(
  334.     JRIEnv* env,
  335.     struct netscape_javascript_JSObject* self,
  336.     struct java_lang_String *method,
  337.     jobjectArray args)
  338. {
  339. #ifndef JAVA
  340.     return NULL;
  341. #else
  342.     JSContext *cx;
  343.     JSObject *jso;
  344.     JSSavedState saved;
  345.     const char *cstr;
  346.     struct java_lang_Object *ret;
  347.     int total_argc, argc, i;
  348.     jsval *argv;
  349.     jsval rval;
  350.     int cost = 0;
  351.  
  352.     if (!enterJS(env, self, &cx, &jso, &saved))
  353.         return NULL;
  354.  
  355.     if (! method ||
  356.         ! (cstr = JRI_GetStringPlatformChars(env, method,
  357.                          (const jbyte *) cx->charSetName,
  358.                          (jint) cx->charSetNameLength))) {
  359.         /* FIXME this should be an error of some sort */
  360.         js_throwJSException(env, "illegal member name");
  361.         ret = NULL;
  362.     goto do_exit;
  363.     }
  364.  
  365.     if (args) {
  366.         total_argc = JRI_GetObjectArrayLength(env, args);
  367.         argv = sysMalloc(total_argc * sizeof(jsval));
  368.     } else {
  369.         total_argc = 0;
  370.         argv = 0;
  371.     }
  372.  
  373.     for (argc = 0; argc < total_argc; argc++) {
  374.         jref arg = JRI_GetObjectArrayElement(env, args, argc);
  375.  
  376.         if (!js_convertJObjectToJSValue(cx, argv+argc, (HObject*)arg))
  377.             goto cleanup_argv;
  378.         JS_AddRoot(cx, argv+argc);
  379.     }
  380.  
  381.     if (! JS_CallFunctionName(cx, jso, cstr, argc, argv, &rval) ||
  382.         ! js_convertJSValueToJObject((HObject **) &ret, cx, rval,
  383.                                      0, 0, JS_FALSE, &cost)) {
  384.         ret = NULL;
  385.     }
  386.  
  387.   cleanup_argv:
  388.     for (i = 0; i < argc; i++)
  389.         JS_RemoveRoot(cx, argv+i);
  390.     sysFree(argv);
  391.  
  392.   do_exit:
  393.     if (!exitJS(env, self, cx, jso, &saved))
  394.         return NULL;
  395.  
  396.     return ret;
  397. #endif
  398. }
  399.  
  400. /***********************************************************************/
  401.  
  402. JRI_PUBLIC_API(struct java_lang_Object *)
  403. native_netscape_javascript_JSObject_eval(
  404.     JRIEnv* env,
  405.     struct netscape_javascript_JSObject* self,
  406.     struct java_lang_String *s)
  407. {
  408. #ifndef JAVA
  409.     return NULL;
  410. #else
  411.     JSContext *cx;
  412.     JSObject *jso;
  413.     JSSavedState saved;
  414.     const char *cstr;
  415.     int cstrlen;
  416.     struct java_lang_Object *ret;
  417.     jsval rval;
  418.     int cost = 0;
  419.     JSPrincipals *principals;
  420.     char *codebase;
  421.  
  422.     if (!enterJS(env, self, &cx, &jso, &saved))
  423.         return NULL;
  424.  
  425.     if (! s ||
  426.         ! (cstr = JRI_GetStringPlatformChars(env, s,
  427.                          (const jbyte *) cx->charSetName,
  428.                          (jint) cx->charSetNameLength))) {
  429.         /* FIXME this should be an error of some sort */
  430.         js_throwJSException(env, "illegal eval string");
  431.         ret = NULL;
  432.     goto do_exit;
  433.     }
  434.  
  435.     /* subtract 1 for the NUL */
  436.     /*
  437.      * FIXME There is no JRI_GetStringPlatformLength (what a misnomer, if there
  438.      * were!), but JRI_GetStringPlatformChars does NUL-terminate the encoded
  439.      * string, so we trust that no charset encoding ever uses a NUL byte as
  440.      * part of a multibyte sequence and just call strlen.
  441.      */
  442.     cstrlen = strlen(cstr);
  443.  
  444.     principals = js_GetJSPrincipalsFromJavaCaller(cx, 0);
  445.     codebase = principals ? principals->codebase : NULL;
  446.     if (! JS_EvaluateScriptForPrincipals(cx, jso, principals, cstr, cstrlen,
  447.                                          codebase, 0, &rval) ||
  448.         ! js_convertJSValueToJObject((HObject**)&ret, cx, rval,
  449.                                      0, 0, JS_FALSE, &cost)) {
  450.         ret = NULL;
  451.     }
  452.  
  453.   do_exit:
  454.     if (!exitJS(env, self, cx, jso, &saved))
  455.         return NULL;
  456.  
  457.     return ret;
  458. #endif
  459. }
  460.  
  461. /***********************************************************************/
  462.  
  463. JRI_PUBLIC_API(void)
  464. native_netscape_javascript_JSObject_finalize(
  465.     JRIEnv* env,
  466.     struct netscape_javascript_JSObject* self)
  467. {
  468. #ifdef JAVA
  469.     JSContext *cx;
  470.     JSObject *jso;
  471.     JSSavedState saved;
  472.  
  473.     /* FIXME if enterJS fails here we have a memory leak! */
  474.  
  475.     if (!enterJS(env, self, &cx, &jso, &saved))
  476.         return;
  477.  
  478.     js_RemoveReflection(cx, jso);
  479.  
  480.     if (!exitJS(env, self, cx, jso, &saved))
  481.         return;
  482.  
  483.     return;
  484. #endif
  485. }
  486.  
  487. /***********************************************************************/
  488.  
  489. JRI_PUBLIC_API(struct java_lang_String *)
  490. native_netscape_javascript_JSObject_toString(
  491.     JRIEnv* env,
  492.     struct netscape_javascript_JSObject* self)
  493. {
  494.     JSContext *cx;
  495.     JSObject *jso;
  496.     JSSavedState saved;
  497.     JSString *jsstr;
  498.     char *cstr;
  499.     struct java_lang_String *ret;
  500.  
  501.     if (!enterJS(env, self, &cx, &jso, &saved))
  502.         return NULL;
  503.  
  504. #ifdef JAVA
  505.     if ((jsstr = JS_ValueToString(cx, OBJECT_TO_JSVAL(jso))) &&
  506.         (cstr = JS_GetStringBytes(jsstr))) {
  507.         ret = JRI_NewStringPlatform(env,
  508.                     (const jbyte *) cstr,
  509.                     (jint) JS_GetStringLength(jsstr),
  510.                     (const jbyte *) cx->charSetName,
  511.                     (jint) cx->charSetNameLength);
  512.     } else {
  513.         /* FIXME could grab the clazz name from the JSObject */
  514.         ret = JRI_NewStringPlatform(env,
  515.                     (const jbyte *) "*JSObject*",
  516.                     (jint) strlen("*JSObject*"),
  517.                     (const jbyte *) cx->charSetName,
  518.                     (jint) cx->charSetNameLength);
  519.     }
  520. #endif
  521.  
  522.     if (!exitJS(env, self, cx, jso, &saved))
  523.         return NULL;
  524.  
  525.     return ret;
  526. }
  527.  
  528. /***********************************************************************/
  529.  
  530. JRI_PUBLIC_API(struct netscape_javascript_JSObject*)
  531. native_netscape_javascript_JSObject_getWindow(
  532.     JRIEnv* env,
  533.     struct java_lang_Class* clazz,
  534.     struct java_applet_Applet* hint)
  535. {
  536. #ifndef JAVA
  537.     return NULL;
  538. #else
  539.     struct netscape_javascript_JSObject *ret = NULL;
  540.     JSContext *cx;
  541.     JSSavedState saved;
  542.     JSObject *jso;
  543.  
  544.     if (!JSJ_IsEnabled()) {
  545.         js_throwJSException(env, "Java/JavaScript communication is disabled");
  546.         return 0;
  547.     }
  548.  
  549.     if (!enterJS(env, NULL, &cx, NULL, &saved))
  550.         return NULL;
  551.  
  552.     jso = JSJ_GetDefaultObject(env, (jobject) hint);
  553.     if (exceptionOccurred((ExecEnv *)env))
  554.         goto out;
  555.  
  556.     ret = (struct netscape_javascript_JSObject *)
  557.         js_ReflectJSObjectToJObject(cx, jso);
  558.  
  559.   out:
  560.     if (!exitJS(env, NULL, cx, NULL, &saved))
  561.         return NULL;
  562.     return ret;
  563. #endif
  564. }
  565.  
  566. /***********************************************************************/
  567.  
  568. JRI_PUBLIC_API(void)
  569. native_netscape_javascript_JSObject_initClass(
  570.     JRIEnv* env,
  571.     struct java_lang_Class* myClazz)
  572. {
  573. #ifdef JAVA
  574.     struct java_lang_Class* clazz;
  575.     /* this is to initialize the field lookup indices, and protect
  576.      * the classes from gc.  */
  577.  
  578.     clazz = use_netscape_javascript_JSObject(env);
  579.     MakeClassSticky((struct Hjava_lang_Class*)clazz);
  580.  
  581.     clazz = use_netscape_javascript_JSException(env);
  582.     MakeClassSticky((struct Hjava_lang_Class*)clazz);
  583.  
  584.     /* this does nothing if somebody else has already set
  585.      * stuff up (i.e. client or server) */
  586.     JSJ_InitStandalone();
  587. #endif
  588. }
  589.  
  590.