Boom.

I'm dividing this into two parts, one's a quick answer and quick fix,
and the other's an explanation on the whole thing for future
reference.


Quick Answer and Quick Fix
==========================

It's a bug in Rhino (#510504, 
https://bugzilla.mozilla.org/show_bug.cgi?id=510504).
You have 3 choices for fixes:

1. If you're using the current MooTools release and you're okay with
editing -Core, search for the Object.reset function under 'Class.js'
and remove the line `delete object[key];` inside that function. That's
it.

2. If you're not comfortable with editing -Core, download and build
the MooTools2 code on Github or the new MooTools build that has the
Moo2 -core files (also on Github), build and use that. It doesn't have
that particular line in the reset code. Done.

3. If you don't want any headaches in the future, patch Rhino with the
patch included in the Bugzilla page: 
https://bugzilla.mozilla.org/attachment.cgi?id=394500&action=edit.
Boom.

And that's it.


Explanation
===========

When you create new class instances via the `new` operator and a
constructor function, a new object is created and passed to your
function. This is the actual class instance, available via `this`.
>From the moment the class instance is created, its `prototype`
property is already set, meaning it's already inheriting from your
class.

A common misconception when using MooTools is that the `initialize`
property you put in your class declaration will become the constructor
function for your object. While this might be so, MooTools actually
wraps your `initialize` method inside another function that does some
basic housekeeping magic for your classes (and this wrapper function
is what actually becomes the constructor).

One of the functions invoked inside this wrapper function is
`Object.reset`, which does some basic cleanup for your classes. The
"offending" line that's causing the problem is that `delete object
[key];` right after the loop.

As you might have guessed, this line doesn't actually do anything.
There are certain items that can't actually be deleted by the `delete`
operator, most of which are marked in the ECMA 262 specs as
`DontDelete`. Another gotcha is that you can't delete an item that an
object inherits via its prototype. This is the reason why `delete
object[key];` doesn't do anything--the `object` there is the new
instance object created because of the `new` operator. It's a blank
object that doesn't have its own properties but instead inherits them
from your class, so deleting it won't work.

Now that's the problem with Rhino. Unlike other JavaScript engines,
Rhino *actually* deletes the property. This is because Rhino reads the
actual inheritance chain of the object until it find the property and
deletes it. And that's the big bug: it actually deletes the prototypal
item directly--which causes all other instances to lose the same
property.

And so, I offered you the three solutions above. You can either remove
the delete line from your current MooTools source to get it working,
or use the newer versions that don't have that line. But the best
solution would be to patch Rhino itself.

Hope that clears it up.


Mark
http://keetology.com/

P.S: Natives aren't affected by this because they don't use `delete`
anywhere in the Native constructor, which is why everything else seems
to  work in Rhino, except for Classes.


-------------------------------------------------------------------------------------------------

On Dec 4, 6:18 am, Matthew Beale <[email protected]> wrote:
> Hi all,
>
> Is anyone using mootools server-side with Rhino?  I was creating classes
> with base.js but wanted to move to mootools... but though mootool's
> methods are showing up fine:
>
> js> (new Array).each
> function forEach() { [native code for Array.forEach, arity=1] }
>
> My classes are "missing" their instance methods
>
> js> (new Dataset).each_datapoint
> js>
>
> The code is nothing special:
>
> var Dataset = new Class({
>
>   initialize: function( id ) {
>     // yeah
>   },
>
>   get: function( attr ) {
>     // yeah
>   },
>
>   each_datapoint: function( each_datapoint_function ) {
>     // exactly, nothing special!
>   }  
>
> });
>
> However if I add a class method with extend...
>
> Dataset.extend({
>   foo: function(a){
>     return a + 3;
>   }
>
> });
>
> I can see the method just fine:
>
> js> Dataset.foo
>
> function (a) {
>     return a + 3;
>
> }
>
> Thoughts?  This is wacky.
>
> --
> Matthew Beale :: 607 227 0871
> Resume & Portfolio @http://madhatted.com

Reply via email to