Back to index

lightning-sunbird  0.9+nobinonly
jsj_JavaMember.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  * 
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  * 
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  * 
00022  * Contributor(s):
00023  * 
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038  /* -*- Mode: C; tab-width: 8 -*-
00039  * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved.
00040  */
00041 
00042 /*
00043  * This file is part of the Java-vendor-neutral implementation of LiveConnect
00044  *
00045  * It contains the native code implementation of JS's JavaMember class.
00046  * JavaMember's are a strange beast required only to handle the special case
00047  * of a public field and a public method that appear in the same class and
00048  * have the same name.  When such a field/method is used in Java, the compiler
00049  * can statically determine from context whether the field or the method is
00050  * being referenced, but that is not possible with JavaScript.  For example:
00051  *
00052  * ambiguousVal = javaObj.fieldOrMethod; // ambiguousVal is a JavaMember object
00053  * a = ambiguousVal();                   // ambiguousVal used as a method value
00054  * b = ambiguousVal + 4;                 // ambiguousVal used as a field value
00055  *
00056  * A JavaMember instance carries both the captured value of the Java field and
00057  * the method value until the context that the value is to be used in is known,
00058  * at which point conversion forces the use of one or the other.
00059  */
00060 
00061 #include <stdlib.h>
00062 #include <string.h>
00063 
00064 #include "jsj_private.h"      /* LiveConnect internals */
00065 
00066 /* Private, native portion of a JavaMember */
00067 typedef struct JavaMethodOrFieldValue {
00068     jsval method_val;
00069     jsval field_val;
00070 } JavaMethodOrFieldValue;
00071 
00072 JSObject *
00073 jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val)
00074 {
00075     JavaMethodOrFieldValue *member_val;
00076     JSObject *JavaMember_obj;
00077     
00078     member_val = (JavaMethodOrFieldValue *)JS_malloc(cx, sizeof(*member_val));
00079     if (!member_val)
00080         return NULL;
00081     
00082     JavaMember_obj = JS_NewObject(cx, &JavaMember_class, 0, 0);
00083     if (!JavaMember_obj) {
00084         JS_free(cx, member_val);
00085         return NULL;
00086     }
00087 
00088     JS_SetPrivate(cx, JavaMember_obj, (void *)member_val);
00089     member_val->method_val = method_val;
00090     JS_AddNamedRoot(cx, &member_val->method_val, "&member_val->method_val");
00091     member_val->field_val = field_val;
00092     if (JSVAL_IS_GCTHING(field_val))
00093         JS_AddNamedRoot(cx, &member_val->field_val, "&member_val->field_val");
00094 
00095     return JavaMember_obj;
00096 }
00097 
00098 JS_STATIC_DLL_CALLBACK(void)
00099 JavaMember_finalize(JSContext *cx, JSObject *obj)
00100 {
00101     JavaMethodOrFieldValue *member_val;
00102 
00103     member_val = JS_GetPrivate(cx, obj);
00104     if (!member_val)
00105         return;
00106 
00107     JS_RemoveRoot(cx, &member_val->method_val);
00108     if (JSVAL_IS_GCTHING(member_val->field_val))
00109         JS_RemoveRoot(cx, &member_val->field_val);
00110     JS_free(cx, member_val);
00111 }
00112 
00113 JS_STATIC_DLL_CALLBACK(JSBool)
00114 JavaMember_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
00115 {
00116     JavaMethodOrFieldValue *member_val;
00117         
00118     member_val = JS_GetPrivate(cx, obj);
00119     if (!member_val) {
00120         if (type == JSTYPE_OBJECT) {
00121             *vp = OBJECT_TO_JSVAL(obj);
00122             return JS_TRUE;
00123         }
00124         
00125         JS_ReportError(cx, "illegal operation on JavaObject prototype object");
00126         return JS_FALSE;
00127     }
00128 
00129     switch (type) {
00130     case JSTYPE_VOID:
00131     case JSTYPE_STRING:
00132     case JSTYPE_NUMBER:
00133     case JSTYPE_BOOLEAN:
00134     case JSTYPE_OBJECT:
00135         *vp = member_val->field_val;
00136         return JS_TRUE;
00137 
00138     case JSTYPE_FUNCTION:
00139         *vp = member_val->method_val;
00140         return JS_TRUE;
00141 
00142     default:
00143         JS_ASSERT(0);
00144         return JS_FALSE;
00145     }
00146 }
00147 
00148 /*
00149  * This function exists only to make JavaMember's Call'able.  The way the JS
00150  * engine is written now, it's never actually called because when a JavaMember
00151  * is invoked, it's converted to a JS function via JavaMember_convert().
00152  */
00153 JS_STATIC_DLL_CALLBACK(JSBool)
00154 JavaMember_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00155 {
00156     JS_ASSERT(0);
00157     return JS_TRUE;
00158 }
00159 
00160 JSClass JavaMember_class = {
00161     "JavaMember", JSCLASS_HAS_PRIVATE,
00162     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
00163     JS_EnumerateStub, JS_ResolveStub, 
00164     JavaMember_convert, JavaMember_finalize,
00165 
00166     NULL, /* getObjectOps */
00167     NULL, /* checkAccess */
00168     JavaMember_Call,
00169     NULL, /* construct */
00170     NULL, /* xdrObject */
00171     NULL, /* hasInstance */
00172     NULL, /* mark */
00173     0,    /* spare */
00174 };
00175 
00176 JSBool
00177 jsj_init_JavaMember(JSContext *cx, JSObject *global_obj)
00178 {
00179     if (!JS_InitClass(cx, global_obj, 
00180         0, &JavaMember_class, 0, 0,
00181         0, 0,
00182         0, 0))
00183         return JS_FALSE;
00184 
00185     return JS_TRUE;
00186 }