Opal 1.5: binding.irb in a web browser

We are happy to announce that Opal 1.5 is out!

Opal is a Ruby (3.1) to JavaScript (ES5) compiler allowing you to write frontend code in pure Ruby and have it translated to clean and efficient JavaScript. It also includes a highly compatible core library that includes all the methods you've come to love.

This release is mostly focused on performance improvements. In fact, in our tests, we got a 2x performance bump for the Opal Ruby compiler running in V8! As always, we have some new features (binding.irb), some compatibility improvements and a bunch of bugfixes.

Try it now on opalrb.com/try.

Enter binding.irb

This release was focused on getting binding.irb work in Opal. We decided to include this feature by default, so you can start debugging issues without needing to do anything. This barely has a performance or load time impact, since most of the logic is loaded dynamically from Opal CDN only when needed (including the Ruby parser and Opal compiler). In fact, because of the other improvements in this release, your bundle size may be even smaller than in Opal 1.4.

Under the hood, in browser we use a prompt JavaScript function (which is what IO#gets does) and we reuse a lot of the code that was written for opal-repl. So in general, we didn't port irb per se, but rather a tool that is more in line with what Opal developers need (for example it has some facilities to handle the native JavaScript values). Sadly, while irb has recently progressed very much and due to the limited interface, we don't support all the features you may think of, but a well known ls function is supported!

In addition, if you are using your browser debugger (for example in a breakpoint), you can always run Opal.irb(s => eval(s)) in your Web Inspector to launch a Ruby console. The passed eval function automatically creates a view where you can reference things like self, local variables, instance variables, etc.

It is very simple to take a sneak peek at this feature. All you need to do is to install Opal with your gem install opal and run the following command:

opal -Rserver -e 'def hello; foo = 5; bar = "a"; binding.irb; end; hello'

This will launch a server on http://localhost:3000/. When you open a browser, it will run a function hello that will launch an irb session.

This automatic load doesn't work outside of the browser, so to run in Node, you need to explicitly require opal-parser and opal-replutils. To test this feature in Node, you will obviously need to install opal (and Node!) and run the following command:

opal -ropal/platform -e 'require "opal-replutils"; require "opal-parser"; def hello; foo = 5; bar = "a"; binding.irb; end; hello'

Of course if your intention is to just run an interactive Opal console, you can simply run opal-repl which has been supported for a couple of releases already.

We hope this feature will bring the frontend and backend development even closer than it already was with Opal!

Performance

As for the last few releases we kept hitting hard on performance. This time argument coercion and Array#[]= got faster, along with writer methods (e.g. def foo=(v) @foo = v end) that had a 4% gain. Whenever possible we also now compile case/when statements to the JavaScript native switch() {case: …} instead of using a list of if / else if whenever possible.

Date, Time, and Timezone

With Opal 1.5 you can finally enjoy basic support for timezones. The DateTime class was also added for better compatibility with MRI, along with a bunch of refactoring to all the time classes.

Conclusion

As always this version brings a lot of other bug fixes and small improvements, please have a look at the full changelog. If you want to know more, have questions, or want to start contributing, please join the Slack channel and ask around, we're always happy to welcome new people to the community!

Happy Easter to everyone!


Resources