2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "NGJavaScriptObjectHandler.h"
24 #include "NGJavaScriptObjectMappingContext.h"
26 #include "NGJavaScriptContext.h"
27 #include "NSString+JS.h"
28 #include "NSObject+JS.h"
29 #include "NGJavaScriptObjCClassInfo.h"
30 #include "NGJavaScriptRuntime.h"
31 #include <NGExtensions/NGObjCRuntime.h>
32 #import <EOControl/EONull.h>
35 //#define LOG_PROP_RESOLVE 1
37 #define PROP_READONLY_FLAGS 0
38 #define PROP_READWRITE_FLAGS 0
39 //#define PROP_READONLY_FLAGS (JSPROP_READONLY | JSPROP_PERMANENT)
41 @interface NGJavaScriptObjectHandler(Privates)
42 - (BOOL)_applyStaticDefs;
43 - (NSString *)stringValue;
46 static BOOL IsInPropDefMode = NO;
48 @interface NSObject(JSFinalization)
49 - (BOOL)isJSCombinedObject;
50 - (NSEnumerator *)jsObjectEnumerator;
55 @implementation NGJavaScriptObjectHandler
59 (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
60 static JSBool NGJavaScriptBridge_setStaticProp
61 (JSContext *cx, JSObject *obj, jsval _id, jsval *vp);
62 static JSBool NGJavaScriptBridge_getStaticProp
63 (JSContext *cx, JSObject *obj, jsval _id, jsval *vp);
65 static NSMutableDictionary *classToInfo = nil;
67 static void relInfo(void) {
69 [classToInfo release]; classToInfo = nil;
71 static NGJavaScriptObjCClassInfo *jsClassInfo(Class _class) {
72 NGJavaScriptObjCClassInfo *ci;
77 if (classToInfo == nil) {
78 classToInfo = [[NSMutableDictionary alloc] initWithCapacity:64];
82 if ((ci = [classToInfo objectForKey:_class]) == nil) {
83 ci = [[NGJavaScriptObjCClassInfo alloc]
85 setter:NGJavaScriptBridge_setStaticProp
86 getter:NGJavaScriptBridge_getStaticProp
87 caller:&staticFuncDispatcher];
88 [classToInfo setObject:ci forKey:_class];
95 static Class NSStringClass = Nil;
96 static Class ObjInfoClass = Nil;
98 static JSBool _addProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp);
99 static JSBool _delProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp);
100 static JSBool _getProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp);
101 static JSBool _setProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp);
102 static JSBool _resolve(JSContext *cx, JSObject *obj, jsval _id);
103 static JSBool _convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
104 static void _finalize(JSContext *cx, JSObject *obj);
105 //static JSBool _construct
106 //(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
110 _newEnumObj(JSContext *cx, JSObject *obj,
111 JSIterateOp op, jsval *statep, jsid *idp);
114 JSClass NGJavaScriptObjectHandler_JSClass = {
115 "NGJavaScriptObjectHandler",
117 JSCLASS_HAS_PRIVATE | JSCLASS_NEW_ENUMERATE /* flags */,
119 JSCLASS_HAS_PRIVATE /* flags */,
126 (JSEnumerateOp)_newEnumObj,
133 /* Optionally non-null members start here. */
134 NULL, //JSGetObjectOps getObjectOps;
135 NULL, //JSCheckAccessOp checkAccess;
136 NULL, //JSNative call;
137 NULL,// _construct //JSNative construct;
138 NULL, //JSXDRObjectOp xdrObject;
139 NULL, //JSHasInstanceOp hasInstance;
144 if (NSStringClass == Nil) NSStringClass = [NSString class];
145 if (ObjInfoClass == Nil) ObjInfoClass = [NGJavaScriptObjCClassInfo class];
148 + (void *)defaultJSClassHandle {
149 return &NGJavaScriptObjectHandler_JSClass;
151 - (void *)jsclassHandle {
152 return [[self class] defaultJSClassHandle];
155 - (id)initWithJSContext:(NGJavaScriptContext *)_ctx {
157 TODO: This *is* used. But where ? Document !
160 blah = [[Blah alloc] init];
161 [global setObject:blah forKey:@"blah"];
162 The setObject: triggers the initWithJSContext:.
168 self->jsObject = JS_NewObject(cx,
169 [self jsclassHandle],
170 NULL /* prototype */,
172 if (self->jsObject == NULL) {
173 NSLog(@"WARNING(%s): got no JS object ...", __PRETTY_FUNCTION__);
178 // TODO: is it correct that private is retained ?
179 JS_SetPrivate(cx, self->jsObject, [self retain]);
181 self->jsContext = [_ctx handle];
185 - (id)initWithJSContext:(NGJavaScriptContext *)_ctx handler:(id)_handler {
186 // TODO: is this actually used anywhere
187 if ((self = [self initWithJSContext:_ctx])) {
188 self->managedObject = _handler;
190 if (![self _applyStaticDefs]) {
191 NSLog(@"ERROR(%s): rejecting creation of handler for %@ in ctx %@ "
192 @"because the static defs could not be applied !",
193 __PRETTY_FUNCTION__, _handler, _ctx);
201 - (id)initWithObject:(id)_object
202 inMappingContext:(NGObjectMappingContext *)_ctx
205 this one is called by -proxyForObject: and makeObjectCombined: of
206 NGJavaScriptObjectMappingContext
208 if ((self = [self initWithJSContext:[(id)_ctx jsContext]])) {
209 self->ctx = (NGJavaScriptObjectMappingContext *)_ctx;
210 self->managedObject = _object;
212 if (![self _applyStaticDefs]) {
213 NSLog(@"ERROR(%s): rejecting creation of handler for %@ in ctx %@ "
214 @"because the static defs could not be applied !",
215 __PRETTY_FUNCTION__, _object, _ctx);
227 Note: managedObject could already be deallocated at this stage !
228 BUT: if managedObject is deallocated, the "ctx" is not retained
229 by the managedObject and therefore possibly broken !
232 if (NGJavaScriptBridge_TRACK_MEMORY) {
233 NSLog(@"%s: dealloc 0x%08X<%@> at 0x%08X on j0x%08X",
235 self, NSStringFromClass([self class]),
240 cx = self->jsContext;
242 if (self->jsObject) {
246 while (self->jsRootRC > 0)
247 JS_RemoveRoot(cx, self->jsObject);
250 priv = JS_GetPrivate(cx, self->jsObject);
252 NSLog(@"ERROR(%s): object handler 0x%08X still has a private ???",
253 __PRETTY_FUNCTION__, self);
254 JS_SetPrivate(cx, self->jsObject, NULL);
259 if (self->jsRootRC > 0) {
260 NSLog(@"WARNING(%s): jsRootRc > 0, but jsObject is missing 0x%08X",
261 __PRETTY_FUNCTION__, self);
270 - (NGJavaScriptContext *)jsContext {
271 return [NGJavaScriptContext jsContextForHandle:self->jsContext];
274 return self->jsObject;
277 - (NSString *)javaScriptClassName {
280 if (self->jsObject == nil)
283 if ((clazz = JS_GetClass(self->jsObject)))
286 return [NSStringClass stringWithCString:clazz->name];
289 - (id)managedObject {
290 return self->managedObject;
296 if ((pjso = JS_GetParent(self->jsContext, self->jsObject)) == NULL)
299 return [self->ctx objectForHandle:pjso];
302 /* JS root references */
304 - (const char *)_jsRCName {
306 /* WATCH OUT: leaks memory ! */
309 sprintf(buf, "ObjC:0x%08X", (unsigned)self);
317 if (self->jsRootRC > 0) {
325 cx = self->jsContext;
327 NSAssert(self->jsObject, @"missing JS object !");
328 NSAssert(cx, @"missing JS context !");
330 c = [self _jsRCName];
332 ? JS_AddNamedRoot(cx, &self->jsObject, c)
333 : JS_AddRoot(cx, &self->jsObject);
335 NSAssert(ret, @"couldn't add JS root !");
341 if (self->jsRootRC < 1) {
342 NSLog(@"WARNING(%s): called jsRelease on JS object which is not retained !");
347 if (self->jsRootRC == 0)
348 JS_RemoveRoot(self->jsContext, &self->jsObject);
350 - (unsigned)jsRootRetainCount {
351 return self->jsRootRC;
356 - (BOOL)hasPropertyNamed:(NSString *)_propName {
360 r = JS_LookupProperty(self->jsContext,
365 NSLog(@"WARNING: JS_LookupProperty call failed !");
368 return v == JSVAL_VOID ? NO : YES;
371 - (BOOL)hasElementAtIndex:(unsigned)_idx {
375 r = JS_LookupElement(self->jsContext,
380 return v == JSVAL_VOID ? NO : YES;
383 - (void)setValue:(id)_value ofPropertyNamed:(NSString *)_propName {
387 if (![self->ctx jsValue:&val forObject:_value]) {
388 NSLog(@"WARNING: couldn't convert ObjC value to JS: %@", _value);
392 ret = JS_SetProperty(self->jsContext,
397 NSLog(@"WARNING: couldn't set value of property %@ ", _propName);
401 - (id)valueOfPropertyNamed:(NSString *)_propName {
405 ret = JS_GetProperty(self->jsContext,
410 NSLog(@"WARNING: couldn't get value of property %@ ", _propName);
414 if (val == JSVAL_VOID)
415 /* property is not defined */
418 return [self->ctx objectForJSValue:&val];
423 - (id)callFunctionNamed:(NSString *)_funcName, ... {
434 va_start(va, _funcName);
435 for (arg = va_arg(va, id); arg; arg = va_arg(va, id))
440 argv = calloc(argc, sizeof(jsval));
441 va_start(va, _funcName);
442 for (arg = va_arg(va, id), i = 0; arg; arg = va_arg(va, id), i++) {
443 if (![self->ctx jsValue:&(argv[i]) forObject:arg])
444 NSLog(@"couldn't convert func argument !");
449 res = JS_CallFunctionName(self->jsContext,
455 if (argv) free(argv);
458 return [self->ctx objectForJSValue:&result];
460 [NSException raise:@"JavaScriptEvalException"
461 format:@"could not call function '%@' !", _funcName];
465 - (id)evaluateScript:(NSString *)_script {
469 NSAssert(self->jsObject, @"missing JS object ..");
471 res = JS_EvaluateScript(self->jsContext,
472 self->jsObject /* script obj */,
474 [_script cStringLength],
475 "<string>", /* source file */
480 return [self->ctx objectForJSValue:&lastValue];
486 ui = [NSDictionary dictionaryWithObjectsAndKeys:
488 self, @"objectHandler",
489 [NGJavaScriptContext jsContextForHandle:
490 self->jsContext], @"jscontext",
493 e = [[NSException alloc] initWithName:@"JavaScriptEvalException"
494 reason:@"couldn't evaluate script"
501 /* static definition declarations */
503 static JSBool NGJavaScriptBridge_setStaticProp
504 (JSContext *cx, JSObject *obj, jsval _id, jsval *vp)
506 NGJavaScriptObjectHandler *self;
507 NGJavaScriptObjCClassInfo *ci;
511 if ((self = JS_GetPrivate(cx, obj)) == NULL)
514 ci = jsClassInfo([self->managedObject class]);
515 sel = [ci setSelectorForPropertyId:&_id inJSContext:cx];
518 NSLog(@"%s: did not find selector for id !", __PRETTY_FUNCTION__);
522 value = [self->ctx objectForJSValue:vp];
523 [self->managedObject performSelector:sel withObject:value];
527 static JSBool NGJavaScriptBridge_getStaticProp
528 (JSContext *cx, JSObject *obj, jsval _id, jsval *vp)
530 NGJavaScriptObjCClassInfo *ci;
531 NGJavaScriptObjectHandler *self;
535 if ((self = JS_GetPrivate(cx, obj)) == NULL) {
536 NSLog(@"%s: did not get private of JS object !", __PRETTY_FUNCTION__);
540 ci = jsClassInfo([self->managedObject class]);
541 sel = [ci getSelectorForPropertyId:&_id inJSContext:cx];
544 NSLog(@"%s: did not find selector for id !", __PRETTY_FUNCTION__);
548 result = [self->managedObject performSelector:sel];
549 //NSLog(@"result is %@", result);
551 return [self->ctx jsValue:vp forObject:result]
558 (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
560 NGJavaScriptObjectHandler *self;
561 NSException *exception;
563 const char *funcName;
577 if ((clazz = JS_GetClass(obj)))
580 cname = "<no class>";
582 printf("%s: cx=0x%08X, obj=0x%08X<%s>, argc=%d\n",
584 cx, obj, cname, argc);
588 if (JS_IsConstructing(cx))
589 obj = JS_GetParent(cx, obj);
592 if (JS_GetClass(obj) != &NGJavaScriptObjectHandler_JSClass) {
593 NSLog(@"%s: invoked on invalid object class (eg using 'new' ?) !",
594 __PRETTY_FUNCTION__);
599 if ((self = JS_GetPrivate(cx, obj)) == NULL)
603 NSCAssert(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION,
604 @"expected function in argv[-2] !");
607 funobj = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2]));
608 funcName = JS_GetFunctionName(funobj);
610 msgname = malloc(strlen(funcName) + 10);
611 strcpy(msgname, "_jsfunc_");
612 strcat(msgname, funcName);
613 strcat(msgname, ":");
614 #if APPLE_RUNTIME || NeXT_RUNTIME
615 sel = sel_getUid(msgname); /* TODO: should be registerName? */
617 sel = sel_get_any_uid(msgname);
621 args = calloc(argc, sizeof(id));
622 for (i = 0; i < argc; i++) {
624 [self->ctx objectForJSValue:&(argv[i])];
626 if (args[i] == nil) args[i] = [EONull null];
628 argArray = [NSArray arrayWithObjects:args count:argc];
632 argArray = [NSArray array];
635 NSLog(@"calling function '%s'(%s), %d args %@\n",
636 funcName, msgname, argc, argArray);
641 result = [self->managedObject performSelector:sel withObject:argArray];
642 retcode = [self->ctx jsValue:rval forObject:result] ? JS_TRUE : JS_FALSE;
645 exception = [localException retain];
653 NSLog(@"%s: catched exception: %@", __PRETTY_FUNCTION__, exception);
657 if ([self->ctx jsValue:&exval forObject:exception]) {
658 JS_SetPendingException(cx, exval);
661 NSLog(@"%s: couldn't get JS value for exception: %@",
662 __PRETTY_FUNCTION__, exception);
667 NSLog(@"result is %@", result);
673 + (void *)jsStaticFuncDispatcher {
674 return &staticFuncDispatcher;
677 - (BOOL)_applyStaticDefs {
678 NGJavaScriptObjCClassInfo *ci;
681 if (self->managedObject == nil) {
682 NSLog(@"WARNING(%s): cannot apply defs on nil ...", __PRETTY_FUNCTION__);
686 ci = jsClassInfo([self->managedObject class]);
688 IsInPropDefMode = YES;
689 ok = [ci applyOnJSObject:self->jsObject inJSContext:self->jsContext];
691 NSLog(@"ERROR(%s): couldn't apply static defs !", __PRETTY_FUNCTION__);
692 IsInPropDefMode = NO;
696 - (BOOL)isStaticProperty:(NSString *)_name {
697 NGJavaScriptObjCClassInfo *ci;
698 ci = jsClassInfo([self->managedObject class]);
699 return [ci isStaticProperty:_name];
704 - (BOOL)loadStandardClasses {
705 NSLog(@"NGJavaScriptObjectHandler: load std classes ...");
706 if (!JS_InitStandardClasses(self->jsContext, self->jsObject)) {
707 NSLog(@"NGJavaScriptObjectHandler: failed to load std classes ...");
714 JS_SetGlobalObject(self->jsContext, self->jsObject);
719 - (void)failureUnknownIDType:(jsval)_id {
723 NSLog(@"SERIOUS ERROR(%s:%i): unknown id type ..",
724 __PRETTY_FUNCTION__, __LINE__);
730 - (NSString *)description {
733 ms = [NSMutableString stringWithCapacity:256];
734 [ms appendFormat:@"<%@[0x%08X]:", NSStringFromClass([self class]), self];
735 [ms appendFormat:@" handle=0x%08X", [self handle]];
736 [ms appendFormat:@" class=%@", [self javaScriptClassName]];
737 [ms appendFormat:@" parent=%@", [self parentObject]];
738 [ms appendString:@">"];
743 /* JS class methods */
753 static inline JSBool _propOp(JSContext *cx, NGPropOp op,
754 JSObject *obj, jsval _id, jsval *vp)
756 NGJavaScriptObjectHandler *self;
759 if ((self = JS_GetPrivate(cx, obj)) == nil) {
760 NSLog(@"WARNING: missing private in NGJavaScriptObjectHandler JS object !");
761 return JS_PropertyStub(cx, obj, _id, vp);
765 return JS_PropertyStub(cx, obj, _id, vp);
767 NSCAssert2(self->managedObject,
768 @"missing managed object (handler=%@, j0x%08X) !",
771 if (JSVAL_IS_INT(_id)) {
775 sel = JSVAL_TO_INT(_id);
779 if (NGJavaScriptBridge_LOG_PROP_GET)
780 NSLog(@"JS: get by sel %i", sel);
783 if ([self->managedObject respondsToSelector:
784 @selector(valueForJSPropertyAtIndex:)]) {
787 v = [self->managedObject valueForJSPropertyAtIndex:sel];
788 res = [self->ctx jsValue:vp forObject:v];
795 if (NGJavaScriptBridge_LOG_PROP_SET)
796 NSLog(@"JS: set by sel %i", sel);
799 if ([self->managedObject respondsToSelector:
800 @selector(takeValue:forJSPropertyAtIndex:)]) {
803 v = [self->ctx objectForJSValue:vp];
805 res = [self->managedObject takeValue:v forJSPropertyAtIndex:sel];
812 case NGPropOp_resolve:
814 NSLog(@"RESOLVE '%i'", idx);
820 NSLog(@"int keys are not supported for this operation (%i) !", op);
824 else if (JSVAL_IS_STRING(_id)) {
831 jsname = JS_ValueToString(cx, _id);
832 name = [NSStringClass stringWithJavaScriptString:jsname];
835 case NGPropOp_resolve: {
837 NSLog(@"RESOLVE '%@'", name);
840 res = [self resolvePropertyByName:name];
846 if ([self isStaticProperty:name])
849 if (NGJavaScriptBridge_LOG_PROP_DEL)
850 NSLog(@"JS: NOT REALLY SUPPORTED del by name %@", name);
856 if (NGJavaScriptBridge_LOG_PROP_ADD) {
857 NSLog(@"JS: add by name '%@' type %s "
858 @"j0x%08X o0x%08X<%@> on o0x%08X<%@>",
859 name, JS_GetTypeName(cx, JS_TypeOfValue(cx, *vp)),
860 obj, self, NSStringFromClass([self class]),
862 NSStringFromClass([self->managedObject class]));
865 if ([self->managedObject respondsToSelector:
866 @selector(takeValue:forJSPropertyNamed:)]) {
869 if ((v = [self->ctx objectForJSValue:vp]) == nil)
872 res = [self->managedObject takeValue:v forJSPropertyNamed:name];
879 if ([self isStaticProperty:name])
882 if (NGJavaScriptBridge_LOG_PROP_GET) {
883 NSLog(@"JS: get by name '%@' type %s "
884 @"j0x%08X o0x%08X<%@> on o0x%08X<%@>",
885 name, JS_GetTypeName(cx, JS_TypeOfValue(cx, *vp)),
886 obj, self, NSStringFromClass([self class]),
888 NSStringFromClass([self->managedObject class]));
891 if ([self->managedObject respondsToSelector:
892 @selector(valueForJSPropertyNamed:)]) {
896 v = [self->managedObject valueForJSPropertyNamed:name];
898 if (NGJavaScriptBridge_LOG_PROP_GET) {
899 NSLog(@" return value o0x%08X<%@>",
900 v, NSStringFromClass([v class]));
903 res = [self->ctx jsValue:vp forObject:v];
906 [[self->ctx jsContext] reportException:localException];
915 if ([self isStaticProperty:name])
918 if (NGJavaScriptBridge_LOG_PROP_SET) {
919 NSLog(@"JSObjectHandler: set by name '%@' type %s "
920 @"j0x%08X o0x%08X<%@> on o0x%08X<%@>",
921 name, JS_GetTypeName(cx, JS_TypeOfValue(cx, *vp)),
922 obj, self, NSStringFromClass([self class]),
924 NSStringFromClass([self->managedObject class]));
927 if ([self->managedObject respondsToSelector:
928 @selector(takeValue:forJSPropertyNamed:)]) {
931 v = [self->ctx objectForJSValue:vp];
932 res = [self->managedObject takeValue:v forJSPropertyNamed:name];
939 [self failureUnknownIDType:_id];
943 return res ? JS_TRUE : JS_FALSE;
946 static JSBool _addProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp) {
947 return _propOp(cx, NGPropOp_add, obj, _id, vp);
949 static JSBool _delProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp) {
950 return _propOp(cx, NGPropOp_del, obj, _id, vp);
952 static JSBool _getProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp) {
953 return _propOp(cx, NGPropOp_get, obj, _id, vp);
955 static JSBool _setProp(JSContext *cx, JSObject *obj, jsval _id, jsval *vp) {
956 return _propOp(cx, NGPropOp_set, obj, _id, vp);
961 _newEnumObj(JSContext *cx, JSObject *obj,
962 JSIterateOp op, jsval *statep, jsid *idp)
964 NGJavaScriptObjectHandler *self;
966 if ((self = JS_GetPrivate(cx, obj)) == nil)
971 NSCAssert(self->managedObject, @"missing managed object !");
973 if (![self->managedObject respondsToSelector:@selector(jsObjectEnumerator)])
977 case JSENUMERATE_INIT:
978 e = [[self->managedObject jsObjectEnumerator] retain];
979 *statep = PRIVATE_TO_JSVAL(e);
980 if (idp) *idp = JSVAL_ZERO;
983 case JSENUMERATE_NEXT: {
986 e = JSVAL_TO_PRIVATE(*statep);
988 if ((nextObj = [e nextObject])) {
991 // NSLog(@"next id %@ ..", nextObj);
992 #if 0 // can someone explain that ?
993 if (![self->ctx jsValue:&idval forObject:nextObject])
996 idval = INT_TO_JSVAL([nextObj intValue]);
999 if (!JS_ValueToId(cx, idval, idp))
1004 //NSLog(@"no more IDs ..");
1005 /* else fall through */
1007 case JSENUMERATE_DESTROY: {
1008 //NSLog(@"destroying enum ..");
1009 if (*statep != JSVAL_NULL) {
1010 if ((e = JSVAL_TO_PRIVATE(*statep))) {
1014 *statep = JSVAL_NULL;
1025 static JSBool _construct
1026 (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1028 NSLog(@"construct called ..");
1033 static JSBool _resolve(JSContext *cx, JSObject *obj, jsval _id) {
1034 return _propOp(cx, NGPropOp_resolve, obj, _id, NULL);
1037 static JSBool _convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) {
1038 NGJavaScriptObjectHandler *self;
1040 if ((self = JS_GetPrivate(cx, obj)) == nil)
1041 return JS_ConvertStub(cx, obj, type, vp);
1043 NSCAssert(self->managedObject, @"missing managed object !");
1047 case JSTYPE_STRING: {
1050 s = [self->managedObject stringValue];
1051 return [self->ctx jsValue:vp forObject:s];
1055 *vp = INT_TO_JSVAL([self->managedObject intValue]);
1058 case JSTYPE_BOOLEAN:
1059 *vp = [self->managedObject boolValue] ? JSVAL_TRUE : JSVAL_FALSE;
1063 case JSTYPE_FUNCTION:
1065 return JS_ConvertStub(cx, obj, type, vp);
1070 static void _finalize(JSContext *cx, JSObject *obj) {
1071 NGJavaScriptObjectHandler *self;
1073 if ((self = JS_GetPrivate(cx, obj)) == nil) {
1074 JS_FinalizeStub(cx, obj);
1076 else if (self->jsObject == obj) {
1077 /* the managed JS object is the same as the finalizing object */
1079 NSCAssert(self->managedObject, @"missing managed object !");
1081 if (NGJavaScriptBridge_TRACK_FINALIZATION) {
1082 NSLog(@"finalizing j0x%08X o0x%08X<%@>",
1084 self->managedObject,
1085 NSStringFromClass([self->managedObject class]));
1088 [self->ctx forgetObject:self->managedObject];
1091 #warning RC watch is on !
1092 if ([self retainCount] != 1) {
1093 NSLog(@"WARNING: JS object %@ was collected, "
1094 @"but handle is still live (rc=%d) "
1095 @"(could be pending autorelease refs: pending: %d) !",
1096 self, [self retainCount],
1097 [NSAutoreleasePool autoreleaseCountForObject:self]);
1101 JS_SetPrivate(self->jsContext, obj, NULL);
1102 self->jsObject = NULL;
1104 /* release private ref */
1105 NSCAssert(self, @"where got self ??");
1106 [self release]; self = nil;
1110 fprintf(stderr, "%s: finalization error ...\n", __PRETTY_FUNCTION__);
1113 fprintf(stderr, "%s: finalization error ...\n", __PRETTY_FUNCTION__);
1118 @end /* NGJavaScriptObjectHandler */