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 "NGJavaScriptObjCClassInfo.h"
24 #include "NGJavaScriptObjectHandler.h"
25 #include <NGExtensions/NGObjCRuntime.h>
30 # warning needs to be rewritten for tinyIds
33 @interface NGJavaScriptObjectHandler(Misc)
34 + (void *)jsStaticFuncDispatcher;
39 # define PROP_READONLY_FLAGS (JSPROP_READONLY | JSPROP_SHARED)
40 # define PROP_READWRITE_FLAGS (JSPROP_SHARED)
42 // special version of 1.5 rc
43 # define PROP_READONLY_FLAGS (JSPROP_READONLY | JSPROP_NOSLOT)
44 # define PROP_READWRITE_FLAGS (JSPROP_NOSLOT)
46 //#define PROP_READONLY_FLAGS (JSPROP_READONLY | JSPROP_PERMANENT)
48 @implementation NGJavaScriptObjCClassInfo
50 - (id)initWithClass:(Class)_clazz
51 setter:(JSPropertyOp)_setter
52 getter:(JSPropertyOp)_getter
53 caller:(JSNative)_caller
57 NSMutableArray *funcs;
58 NSMutableArray *props;
59 NSMutableArray *roProps;
62 self->setter = _setter;
63 self->getter = _getter;
64 self->caller = _caller;
66 funcs = props = roProps = nil;
68 self->idToKey = NSCreateMapTable(NSIntMapKeyCallBacks,
69 NSOwnedPointerMapValueCallBacks,
72 e = [_clazz hierachyMethodNameEnumerator];
73 while ((mname = [e nextObject])) {
74 if ([mname hasPrefix:@"_jsfunc_"]) {
78 funcs = [NSMutableArray arrayWithCapacity:64];
80 f = [mname substringFromIndex:8];
81 f = [f substringToIndex:([f length] - 1)];
85 else if ([mname hasPrefix:@"_jsprop_"] && ![mname hasSuffix:@":"]) {
92 buf = malloc(len + 3);
93 [mname getCString:buf];
95 propName = [NSString stringWithCString:&(buf[8])];
97 /* get set-selector */
100 #if NeXT_RUNTIME || APPLE_RUNTIME
101 setSel = sel_getUid(buf);
103 setSel = sel_get_uid(buf);
106 if ((setSel != NULL) && [_clazz instancesRespondToSelector:setSel]) {
108 props = [NSMutableArray arrayWithCapacity:64];
109 [props addObject:propName];
113 roProps = [NSMutableArray arrayWithCapacity:64];
114 [roProps addObject:propName];
119 self->jsFuncNames = [funcs copy];
120 self->jsPropNames = [props copy];
121 self->jsReadOnlyPropNames = [roProps copy];
127 //NSLog(@"DEALLOC ClassInfo ..");
129 #if 0 // BUGGY, need to leak
130 if (self->funcSpecs) {
133 while (self->funcSpecs[i].name)
134 free((void *)self->funcSpecs[i].name);
136 free(self->funcSpecs);
139 NSFreeMapTable(self->idToKey);
140 self->idToKey = NULL;
143 [self->jsFuncNames release];
144 [self->jsReadOnlyPropNames release];
145 [self->jsPropNames release];
149 - (NSArray *)jsFuncNames {
150 return self->jsFuncNames;
152 - (NSArray *)jsPropNames {
153 return self->jsPropNames;
155 - (NSArray *)jsReadOnlyPropNames {
156 return self->jsReadOnlyPropNames;
159 - (JSFunctionSpec *)functionSpecs {
163 return self->funcSpecs;
165 if ((count = [self->jsFuncNames count]) == 0)
168 self->funcSpecs = calloc(count + 1, sizeof(JSFunctionSpec));
169 for (i = 0; i < count; i++) {
173 oname = [self->jsFuncNames objectAtIndex:i];
174 clen = [oname cStringLength];
176 self->funcSpecs[i].name = malloc(clen + 4);
177 [oname getCString:(char *)self->funcSpecs[i].name];
179 //NSLog(@" def JS func '%s'\n", self->funcSpecs[i].name);
182 // TODO: explain the comment below
183 //***BUG: copy 'name'!
184 NSMapInsert(self->idToKey, (void*)(int)self->tinyId,
185 self->funcSpecs[i].name);
187 self->funcSpecs[i].call = self->caller;
188 self->funcSpecs[i].nargs = 0;
189 self->funcSpecs[i].flags = 0;
190 self->funcSpecs[i].extra = 0;
192 return self->funcSpecs;
195 - (BOOL)isStaticProperty:(NSString *)_prop {
196 if ([self->jsFuncNames containsObject:_prop])
198 if ([self->jsReadOnlyPropNames containsObject:_prop])
200 if ([self->jsPropNames containsObject:_prop])
207 - (SEL)getSelectorForPropertyId:(void *)_idval inJSContext:(void *)_cx {
208 jsval _id = *(jsval *)_idval;
209 const char *propName = NULL;
212 if (JSVAL_IS_STRING(_id)) {
213 if ((propName = JS_GetStringBytes(JS_ValueToString(_cx, _id))) == NULL)
214 NSLog(@"%s: got no string for string id val ..", __PRETTY_FUNCTION__);
216 else if (JSVAL_IS_INT(_id)) {
219 ttid = JSVAL_TO_INT(_id);
220 if ((propName = NSMapGet(self->idToKey, (void*)(int)ttid)) == NULL)
221 NSLog(@"%s: got no INT id val %i ..", __PRETTY_FUNCTION__, ttid);
225 NSLog(@"%s: GOT invalid id value ..", __PRETTY_FUNCTION__);
228 NSLog(@"%s: GOT invalid id value ..", __PRETTY_FUNCTION__);
236 msgname = malloc(strlen(propName) + 12);
237 strcpy(msgname, "_jsprop_");
238 strcat(msgname, propName);
240 sel = sel_getUid(msgname);
242 sel = sel_get_any_uid(msgname);
245 NSLog(@"%s: got no selector for msg '%s'", __PRETTY_FUNCTION__, msgname);
250 - (SEL)setSelectorForPropertyId:(void *)_idval inJSContext:(void *)_cx {
251 jsval _id = *(jsval *)_idval;
252 const char *propName = NULL;
255 if (JSVAL_IS_STRING(_id)) {
256 if ((propName = JS_GetStringBytes(JS_ValueToString(_cx, _id))) == NULL)
257 NSLog(@"%s: got no string for string id val ..", __PRETTY_FUNCTION__);
259 else if (JSVAL_IS_INT(_id)) {
262 ttid = JSVAL_TO_INT(_id);
263 if ((propName = NSMapGet(self->idToKey, (void*)(int)ttid)) == NULL)
264 NSLog(@"%s: got no INT id val %i ..", __PRETTY_FUNCTION__, ttid);
268 NSLog(@"%s: GOT invalid id value ..", __PRETTY_FUNCTION__);
271 NSLog(@"%s: GOT invalid id value ..", __PRETTY_FUNCTION__);
279 msgname = malloc(strlen(propName) + 12);
280 strcpy(msgname, "_jsprop_");
281 strcat(msgname, propName);
282 strcat(msgname, ":");
285 sel = sel_getUid(msgname);
287 sel = sel_get_any_uid(msgname);
290 NSLog(@"%s: got no selector for msg '%s'", __PRETTY_FUNCTION__, msgname);
297 /* apply on JSObject */
299 - (unsigned char)tinyIdForKey:(NSString *)_key {
303 ckey = malloc([_key cStringLength] + 1);
304 [_key getCString:ckey];
305 NSMapInsert(self->idToKey, (void*)(int)self->tinyId, ckey);
310 - (JSBool)defineProperty:(NSString *)mname readOnly:(BOOL)_ro
311 onObject:(void *)_jso inJSContext:(void *)_cx
315 if (NGJavaScriptBridge_LOG_PROP_DEFINITION) {
316 NSLog(@"%s: definition of %@ property '%@' on j0x%08X",
317 __PRETTY_FUNCTION__, _ro ? @"ro/noslot" : @"rw/noslot",
322 ret = JS_DefinePropertyWithTinyId(_cx, _jso,
324 [self tinyIdForKey:mname],
326 self->getter, ro ? NULL : self->setter,
327 _ro ? PROP_READONLY_FLAGS : PROP_READWRITE_FLAGS);
329 ret = JS_DefineProperty(_cx, _jso,
332 self->getter, _ro ? NULL : self->setter,
333 _ro ? PROP_READONLY_FLAGS : PROP_READWRITE_FLAGS);
338 - (BOOL)applyOnJSObject:(void *)_jso inJSContext:(void *)_cx {
339 NSEnumerator *mnames;
341 JSFunctionSpec *fspecs;
343 if ((fspecs = [self functionSpecs])) {
344 if (!JS_DefineFunctions(_cx, _jso, fspecs)) {
345 NSLog(@"ERROR(%s): couldn't define static JS functions (0x%08X) on "
346 @"JSObject 0x%08X in JSContext 0x%08X ..",
347 __PRETTY_FUNCTION__, fspecs, _jso, _cx);
352 mnames = [[self jsPropNames] objectEnumerator];
353 while ((mname = [mnames nextObject])) {
356 ret = [self defineProperty:mname readOnly:NO
357 onObject:_jso inJSContext:_cx];
359 NSLog(@"ERROR(%s): couldn't define property '%@' on "
360 @"JSObject 0x%08X in JSContext 0x%08X",
361 __PRETTY_FUNCTION__, mname, _jso, _cx);
366 mnames = [[self jsReadOnlyPropNames] objectEnumerator];
367 while ((mname = [mnames nextObject])) {
370 ret = [self defineProperty:mname readOnly:YES
371 onObject:_jso inJSContext:_cx];
379 @end /* NGJavaScriptObjCClassInfo */