Having trouble with garbage collection

6 views
Skip to first unread message

Ian Beck

unread,
Jul 27, 2009, 8:54:45 PM7/27/09
to jsc...@googlegroups.com
Hey there,

I'm having trouble with one of my Objective-C objects getting garbage
collected while I still have a reference to them. I'm using Mootools
classes:

var myClass = new Class({
initialize: function() {
this.object = ObjCClass.alloc.init;
},
doSomething: function() {
this.object.someMethodCall();
}
});

var myObject = new myClass();
myObject.doSomething();

The last call throws an error that result of expression this.object is
that [undefined] is not an object. I've logged this.object
immediately after creating it, and it's indeed an Objective-C object
of the correct type in the initialize function. I'm assuming that the
problem lies with this.object, which works fine in Mootools, but
evidently isn't strong enough of a reference to preserve the object in
JSCocoa.

Is this a bug in JSCocoa, or is there a workaround/fix that I'm not
aware of that I can make on my end?

Thanks in advance for your help! If you'd like to see the actual code
that's failing instead of the super abbreviated example above, let me
know and I'll get some links to the files on GitHub (this is all part
of a new JSCocoaLoader class living in the example branch).

Ian

Patrick Geiller

unread,
Jul 27, 2009, 11:30:03 PM7/27/09
to jsc...@googlegroups.com

Hello Ian,

> doSomething: function() {
> this.object.someMethodCall();
> }


Remove the parentheses. this.object.someMethodCall is the default
syntax for calling zero-param functions, just like [object
someMethodCall]. If your function returns void (converted to
undefined), Javascript tries to call a method with undefined as this,
then fails.

If you want to enable the use of parentheses, check useAutoCall. http://code.google.com/p/jscocoa/wiki/Autocall
You'll then have a new problem : you'll need to use parentheses to
force calling in some expressions. if (object.alloc.init) won't work,
you'll have to use (object.alloc.init()). That's a limitation of
JavascriptCore which I don't know how to get around.

Additionally, I'm working on adding an ObjC syntax to JSCocoa, just
like Obj-J and JSTalk. Using an ObjC syntax will make autocall
irrelevant.

-Patrick

Ian Beck

unread,
Jul 28, 2009, 1:28:54 AM7/28/09
to jsc...@googlegroups.com
Hey Patrick,

Sorry, should have looked at my source a little closer before I wrote
the example. It's got the proper usage for parentheses with void vs.
parameter calls. Here's an actual snippet:

> initialize: function() {
> this.recipe = CETextRecipe.textRecipe; // Class method
> },
> insert: function(string, index) {
> this.recipe.addInsertedString_forIndex_(string, index); // this
> fails
> }

The exact error in my console is:

> JSException: TypeError: Result of expression
> 'this.recipe' [undefined] is not an object. on line 61 of (null)


If I do JSCocoaController.log(String(this.recipe)) at the end of
initialize and the beginning of insert, I get:

In initialize:
> <CETextRecipe: 0x1a06c720> [ ]

In insert:
> undefined

This is why I was figuring it must be a garbage collection problem;
the Objective-C calls are working fine to create the object, and it's
just when I try to access it a little later that it appears to have
been scrapped.

Here's links to the actual source on GitHub if you'd like to verify I
haven't made any other minor mistakes:

The class that's dying
http://tr.im/text_recipe

The action I'm running through Espresso that uses the class
http://tr.im/sugar_action

The bootstrapping script, if you're wondering what the heck is up with
require()
http://tr.im/require

Ian

Patrick Geiller

unread,
Jul 28, 2009, 10:08:46 AM7/28/09
to jsc...@googlegroups.com
Hello Ian,

I'm stumped. JSCocoa retains ObjC objects when boxing them, so they
live as long as they're bound to at least one Javascript variables.

I don't know Mootools, so off the top of my head you could debug these :

* When creating your object, store it in a global variable
> myGlobalVar = this.recipe = CETextRecipe.textRecipe; // Class
> method
Then check in insert if myGlobalVar is still alive.

* Store this from initialize and and insert in two global vars then
compare them -> maybe they're two different instances ?

* Log boxedObject in jsCocoaObject_finalize to see if it a
CETextRecipe is being destroyed.

-Patrick

Ian Beck

unread,
Jul 28, 2009, 10:49:10 AM7/28/09
to jsc...@googlegroups.com
Hey Patrick,

Sorry for involving you in my debugging issues, but thank you for the
excellent suggestions below. Turned out to be a "this" binding issue;
JSCocoa is working great! :-)

Ian

Patrick Geiller

unread,
Jul 28, 2009, 11:04:29 AM7/28/09
to jsc...@googlegroups.com

Hehe. Good :)
Reply all
Reply to author
Forward
0 new messages