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

View File

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

View File

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

View File

@ -41,7 +41,8 @@ static JSClass sTimerClass;
- (id) initWithDelay:(OOTimeAbsolute)delay
interval:(OOTimeDelta)interval
function:(jsval)function
this:(JSObject *)jsThis;
this:(JSObject *)jsThis
jsSelf:(JSObject *)jsSelf;
@end
@ -52,6 +53,7 @@ static JSClass sTimerClass;
interval:(OOTimeDelta)interval
function:(jsval)function
this:(JSObject *)jsThis
jsSelf:(JSObject *)jsSelf
{
JSContext *context = NULL;
@ -68,7 +70,7 @@ static JSClass sTimerClass;
_function = function;
OO_AddJSGCRoot(context, &_function, "OOJSTimer function");
_jsSelf = JS_NewObject(context, &sTimerClass, sTimerPrototype, NULL);
_jsSelf = jsSelf;
if (_jsSelf != NULL)
{
if (!JS_SetPrivate(context, _jsSelf, [self retain])) _jsSelf = NULL;
@ -76,7 +78,7 @@ static JSClass sTimerClass;
if (_jsSelf == NULL)
{
[self release];
self = nil;
return nil;
}
_owningScript = [[OOJSScript currentlyRunningScript] weakRetain];
@ -339,6 +341,12 @@ static JSBool TimerConstruct(JSContext *context, JSObject *inThis, uintN argc, j
double interval = -1.0;
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)
{
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
interval:interval
function:function
this:this];
*outResult = [timer javaScriptValueInContext:context];
if (delay >= 0) // Leave in stopped state if delay is negative
this:this
jsSelf:JSVAL_TO_OBJECT(*outResult)];
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;
}

View File

@ -79,8 +79,6 @@ enum
- (JSContext *)acquireContext;
- (void)releaseContext:(JSContext *)context;
- (BOOL) addGCRoot:(void *)rootPtr
named:(const char *)name;
- (void) removeGCRoot:(void *)rootPtr;
@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
{
JSContext *context = NULL;