Tag: implementation

In this post we’ll learn how Ruby objects are mapped in JavaScript-land by the Opal compiler, how to call methods on them and how object instantiation works for both Ruby and JavaScript.

The basics: constants, methods and instance variables

The rule by which Ruby objects are compiled into JavaScript by Opal is quite simple. Constants are registered with their regular name under the window.Opal (i.e. the Opal property on the JavaScript window object). Methods are mapped to properties prefixed by a $ (dollar sign). Instance variables are just regular properties.

As a Ruby developer you may be surprised that obj.baz returns undefined and not nil (actually window.Opal.nil) as that’s the value that you would expect to find while reading an instance variable for the first time.

What happens is that the Opal compiler will do just that, as long as you access those instance variables from Ruby code. In fact it statically analyzes the class’ code and pre-initializes to nil any instance variable for which it can find a reference.

Now that we have the basics let’s go further and put Foo.new under the microscope for both Opal and CRuby.

The birth of an object in 3 steps

By looking in detail how object instantiation is done in JavaScript by the Opal compiled code we’ll have a chance to learn how it actually works in CRuby.

The implementation of .new

At the cost of oversimplifying here’s the rough implementation of the #new method available to all classes in Ruby:

As you can see the the only notable difference is in how the block is passed. Opal will store any block call on the method itself under the $$p property. This way blocks can’t be confused with regular arguments. Apart from that it’s clear that it’s fundamentally the same code.

Uncovering Class#allocate

The curious reader at this point is wondering what the allocate method does in JavaScript because surely it can’t manage memory. Let’s see the implementation: