Fixed bad GC roots in OOJSFunction. Avoid extra allocation in JS Timer constructor.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@3472 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2010-06-06 12:31:51 +00:00
parent deee594006
commit dcd183bae9
6 changed files with 34 additions and 28 deletions

View File

@ -213,6 +213,7 @@ JSObject *DebugMonitorToJSConsole(JSContext *context, OODebugMonitor *monitor)
JSObject *settingsObject = NULL; JSObject *settingsObject = NULL;
jsval value; jsval value;
NSCAssert(JS_EnterLocalRootScope(context), @"Failed to create JS GC root scope");
engine = [OOJavaScriptEngine sharedEngine]; engine = [OOJavaScriptEngine sharedEngine];
if (sConsolePrototype == NULL) if (sConsolePrototype == NULL)
@ -247,6 +248,8 @@ JSObject *DebugMonitorToJSConsole(JSContext *context, OODebugMonitor *monitor)
if (settingsObject == NULL) object = NULL; if (settingsObject == NULL) object = NULL;
} }
JS_LeaveLocalRootScope(context);
return object; return object;
// Analyzer: object leaked. (x2) [Expected, objects are retained by JS object.] // Analyzer: object leaked. (x2) [Expected, objects are retained by JS object.]
} }

View File

@ -37,7 +37,7 @@ MA 02110-1301, USA.
JSFunction *_function; JSFunction *_function;
} }
- (id) initWithFunction:(JSFunction *)function; - (id) initWithFunction:(JSFunction *)function context:(JSContext *)context;
- (id) initWithName:(NSString *)name - (id) initWithName:(NSString *)name
scope:(JSObject *)scope // may be NULL, in which case global object is used. scope:(JSObject *)scope // may be NULL, in which case global object is used.
code:(NSString *)code // full JS code for function, including function declaration. code:(NSString *)code // full JS code for function, including function declaration.

View File

@ -29,8 +29,10 @@ MA 02110-1301, USA.
@implementation OOJSFunction @implementation OOJSFunction
- (id) initWithFunction:(JSFunction *)function - (id) initWithFunction:(JSFunction *)function context:(JSContext *)context
{ {
NSParameterAssert(context != NULL);
if (function == NULL) if (function == NULL)
{ {
[self release]; [self release];
@ -40,7 +42,7 @@ MA 02110-1301, USA.
if ((self = [super init])) if ((self = [super init]))
{ {
_function = function; _function = function;
[[OOJavaScriptEngine sharedEngine] addGCRoot:&function named:"OOJSFunction._function"]; OO_AddJSGCRoot(context, _function, "OOJSFunction._function");
} }
return self; return self;
@ -92,7 +94,7 @@ MA 02110-1301, USA.
if (OK) if (OK)
{ {
self = [self initWithFunction:function]; self = [self initWithFunction:function context:context];
} }
else else
{ {
@ -157,8 +159,8 @@ MA 02110-1301, USA.
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
OO_AddJSGCRoot(context, &argv[i], "OOJSFunction argv");
argv[i] = [[arguments objectAtIndex:i] javaScriptValueInContext:context]; argv[i] = [[arguments objectAtIndex:i] javaScriptValueInContext:context];
OO_AddJSGCRoot(context, &argv[i], "OOJSFunction argv");
} }
JSObject *scopeObj = NULL; JSObject *scopeObj = NULL;

View File

@ -41,7 +41,8 @@ static JSClass sTimerClass;
- (id) initWithDelay:(OOTimeAbsolute)delay - (id) initWithDelay:(OOTimeAbsolute)delay
interval:(OOTimeDelta)interval interval:(OOTimeDelta)interval
function:(jsval)function function:(jsval)function
this:(JSObject *)jsThis; this:(JSObject *)jsThis
jsSelf:(JSObject *)jsSelf;
@end @end
@ -52,6 +53,7 @@ static JSClass sTimerClass;
interval:(OOTimeDelta)interval interval:(OOTimeDelta)interval
function:(jsval)function function:(jsval)function
this:(JSObject *)jsThis this:(JSObject *)jsThis
jsSelf:(JSObject *)jsSelf
{ {
JSContext *context = NULL; JSContext *context = NULL;
@ -68,7 +70,7 @@ static JSClass sTimerClass;
_function = function; _function = function;
OO_AddJSGCRoot(context, &_function, "OOJSTimer function"); OO_AddJSGCRoot(context, &_function, "OOJSTimer function");
_jsSelf = JS_NewObject(context, &sTimerClass, sTimerPrototype, NULL); _jsSelf = jsSelf;
if (_jsSelf != NULL) if (_jsSelf != NULL)
{ {
if (!JS_SetPrivate(context, _jsSelf, [self retain])) _jsSelf = NULL; if (!JS_SetPrivate(context, _jsSelf, [self retain])) _jsSelf = NULL;
@ -76,7 +78,7 @@ static JSClass sTimerClass;
if (_jsSelf == NULL) if (_jsSelf == NULL)
{ {
[self release]; [self release];
self = nil; return nil;
} }
_owningScript = [[OOJSScript currentlyRunningScript] weakRetain]; _owningScript = [[OOJSScript currentlyRunningScript] weakRetain];
@ -339,6 +341,12 @@ static JSBool TimerConstruct(JSContext *context, JSObject *inThis, uintN argc, j
double interval = -1.0; double interval = -1.0;
OOJSTimer *timer = nil; OOJSTimer *timer = nil;
if (!JS_IsConstructing(context))
{
OOReportJSError(context, @"Timer() cannot be called as a function, it must be used as a constructor (as in new Timer(...)).");
return NO;
}
if (argc < 3) if (argc < 3)
{ {
OOReportJSBadArguments(context, nil, @"Timer", argc, argv, @"Invalid arguments in constructor", @"(object, function, number [, number])"); OOReportJSBadArguments(context, nil, @"Timer", argc, argv, @"Invalid arguments in constructor", @"(object, function, number [, number])");
@ -376,13 +384,21 @@ static JSBool TimerConstruct(JSContext *context, JSObject *inThis, uintN argc, j
timer = [[OOJSTimer alloc] initWithDelay:delay timer = [[OOJSTimer alloc] initWithDelay:delay
interval:interval interval:interval
function:function function:function
this:this]; this:this
*outResult = [timer javaScriptValueInContext:context]; jsSelf:JSVAL_TO_OBJECT(*outResult)];
if (delay >= 0) // Leave in stopped state if delay is negative if (timer != nil)
{ {
[timer scheduleTimer]; if (delay >= 0) // Leave in stopped state if delay is negative
{
[timer scheduleTimer];
}
[timer release]; // The JS object retains the ObjC object.
} }
[timer release]; // The JS object retains the ObjC object. else
{
*outResult = JSVAL_NULL;
}
return YES; return YES;
} }

View File

@ -79,8 +79,6 @@ enum
- (JSContext *)acquireContext; - (JSContext *)acquireContext;
- (void)releaseContext:(JSContext *)context; - (void)releaseContext:(JSContext *)context;
- (BOOL) addGCRoot:(void *)rootPtr
named:(const char *)name;
- (void) removeGCRoot:(void *)rootPtr; - (void) removeGCRoot:(void *)rootPtr;
@end @end

View File

@ -413,19 +413,6 @@ static void ReportJSError(JSContext *context, const char *message, JSErrorReport
} }
- (BOOL) addGCRoot:(void *)rootPtr
named:(const char *)name
{
BOOL result;
JSContext *context = NULL;
context = [self acquireContext];
result = JS_AddNamedRoot(context, rootPtr, name);
[self releaseContext:context];
return result;
}
- (void) removeGCRoot:(void *)rootPtr - (void) removeGCRoot:(void *)rootPtr
{ {
JSContext *context = NULL; JSContext *context = NULL;