JSCocoa Garbage Collection uses JavascriptCore's Garbage Collection engine. You can safely manipulate Objective-C objects without fear of them being deallocated as JSCocoa retains and releases them for you. But you have to be careful when allocating objects yourself and you have to know when they can be deallocated.
When are ObjC objects actually released ?
ObjC objects are released during JavascriptCore Garbage Collection when no Javascript variables are using them anymore.
Getting objects back from the runtime in the global scope (not in a function)
var myObject = anObject.getSomeObject(2, 3)
myObject
becomes collectable when you set myObject = null
.
Getting objects back from the runtime in a function
var myObject = anObject.getSomeObject(2, 3)
Provided you only use myObject
in this function, myObject
becomes collectable when you exit the function. If you return it and use it in the global scope, set it to null
Allocating objects with instance
var myObject = MyObject.instance
Set myObject
to null
if you're in the global scope. In a function, it will be collectable on function exit.
Allocating objects with alloc/init
var myObject = MyObject.alloc.init
Call myObject.release
and set myObject
to null
if you're in the global scope. If in a function, myObject.release
will suffice.
WARNING ! Forgetting the var declarator in a function will declare a variable in the global scope
In a function, assigning to an undefined variable myVar = someObjCObject
will create myVar
in the global scope. You'll need to set it to null
to make it collectable. To prevent that, always declare your variables with var myVar = someObjCObject
That's it ! To sum up, use instance
to allocate and set your variables to null
when you're not in a function.
Some behind-the-scenes info follows :
Live instance count
For JSCocoa classes only JSCocoa logs instance count. Call JSCocoaController.logInstanceStats
Manually start Garbage Collection
Call JSCocoaController.garbageCollect
. You need to do that only if you want an object to be released NOW.
Javascript name binding
Javascript does not copy objects when evaluating myVar = someObject; myVar2 = someObject
— a new name is bound to the object, therefore both variables myVar
and myVar2
point to someObject
. JavascriptCore's Garbage Collector handles that itself, there's no extra retaining or releasing happening here.
JSCocoa boxes ObjC objects
When evaluating NSWorkspace.sharedWorkspace.activeApplication
, JSCocoa gets called back by Javascript and has to give back Javascript objects to Javascript. In that case, JSCocoa will :
- be called a first time by JavascriptCore asking for
NSWorkspace
. JSCocoa finds the matching ObjC class and boxes it back to Javascript - be called a second time by JavascriptCore asking for the property
sharedWorkspace
ofNSWorkspace
— JSCocoa calls the matching method and boxes it back to Javascript - be called a third time by JavascriptCore asking for the property
activeApplication
ofsharedWorkspace
— JSCocoa calls the matching method and boxes it back to Javascript
That's how the bridge works : JavascriptCore can only manipulate Javascript objects so JSCocoa boxes ObjC objects in Javascript objects. Each time this happens the boxed object is retained, each time the Javascript object is destroyed the boxed object is released. That's why you can use any object you get from any method call safely as it will be released automatically when Garbage Collection happens.
Boxing is done with JSCocoaPrivateObject. More in SampleBridgeEvaluation.