How to use source files and call their exposed objects?

272 views
Skip to first unread message

David Pelaez

unread,
Nov 1, 2013, 2:24:20 AM11/1/13
to therub...@googlegroups.com
I'm trying to find a way to compile jade without having node install by using the ruby racer. I have this file: https://github.com/visionmedia/jade/blob/master/jade.js which when loaded in a single html like this:

<html>
<head>
<script src='jade.js'></script>
</head>
<body>
jade is loaded.
</body>
</html>

Would let me do something like jade.compile('h1') This works perfectly in the browser (Chrome) and with ExecJS using node. But when I try this script:

#!/usr/bin/env ruby
puts "Compiling hellow world"
require 'rubygems'
require 'v8' #therubyracer
require 'execjs'
def jade_path
File.expand_path '../jade.js', __FILE__
end
def context
ExecJS.compile File.read(jade_path)
end
def hello
context.call "jade.compile('h1 Hola mundo')"
end
 
puts hello

All I get is 'V8::Error: jade is not defined'. 

But I just don't understand why it doesn't work in V8, if I remove the v8 require and it falls back to node, then this ruby code works. So I don't know how to interact with this kind of files or what I'm missing from the docs. The Ruby Racer is the right way to go, because what I'm trying to solve is ruby developers avoiding jade because of the node dependency, but Jade is simply awesome and should be more widely used, even in Ruby.

Any help to understand how to use this kind of 'browserified' source files is appreciated. Thanks beforehand.

Charles Lowell

unread,
Nov 1, 2013, 10:16:44 AM11/1/13
to therub...@googlegroups.com
David,

What happens if you just use the V8 context directly?

  V8::Context.new do |cxt|
    cxt.load File.expand_path('../jade.js', __FILE__)
    puts cxt.jade.compile "h1 hola mundo"
  end

cheers,
Charles

David Pelaez

unread,
Nov 1, 2013, 11:48:52 AM11/1/13
to therub...@googlegroups.com
Hi Charles,

same error:

./test_compile.rb:26:in `block in <main>': undefined method `jade' for #<V8::Context:0x007fd32ac31f68> (NoMethodError)
from /opt/boxen/rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/therubyracer-0.12.0/lib/v8/context.rb:70:in `initialize'
from ./test_compile.rb:24:in `new'
from ./test_compile.rb:24:in `<main>'

I'm assuming there are limitations to V8 that I don't understand, maybe do you know what constraints the javascript should adhere to in order to run with Therubyracer. Maybe this js has that? But it runs perfectly on the browser, should something running on the browser (chrome) work with V8 in Ruby?

Cheers,

DPT

Charles Lowell

unread,
Nov 1, 2013, 1:36:12 PM11/1/13
to therub...@googlegroups.com
David,

If you post a gist or a repo with the full jade source, then perhaps I can help you debug it.

cheers,
Charles

--
You received this message because you are subscribed to the Google Groups "The Ruby Racer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to therubyracer...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

David Pelaez

unread,
Nov 1, 2013, 2:10:59 PM11/1/13
to therub...@googlegroups.com
Charles,


thanks for the help!

On Friday, November 1, 2013 1:24:20 AM UTC-5, David Pelaez wrote:

Charles Lowell

unread,
Nov 5, 2013, 9:24:36 AM11/5/13
to The Ruby Racer
David,

Yes, the problem is that jade.js assumes the existence of either a browser or a module system that provides an `exports` object and a `require` function. Node provides these, but therubyracer does not. It really is “just javascript” and doesn’t give you anything extra. You should be able to use commonjs.rb however, which is a ruby gem that provides a commonjs environment for therubyracer and therubyrhino.

I would suggest having a look at the handlebars gem to see how this is done.

cheers,
Charles

David Pelaez

unread,
Nov 10, 2013, 4:51:26 PM11/10/13
to therub...@googlegroups.com
Hi charles,

I understand that. But Browserify takes care of defining those require methos. It works perfectly on the browser, which has exactly the same constraints as v8. So this isn't exactly why it fails. :(

Charles Lowell

unread,
Nov 10, 2013, 10:33:43 PM11/10/13
to therub...@googlegroups.com, therub...@googlegroups.com
Remember that therubyracer really is "just v8" there is no browser environment like in a real browser, no "window" object, no "document" or anything else but the JavaScript objects. My guess is that browserify leans on some artifact of the browser, either to detect a code path, or to provide some functionality that does not exist it a pure JavaScript environment like therubyracer's.

I'm not familiar with browserify internals, but you might want to check if is doing things like:

  If (this.window) //...

  If (typeof document != 'undefined')

If so you can fool it by injecting those objects into the global scope.

I can have a look at the browserify code on Monday. Cheers!

Sent from my iPhone

David Pelaez

unread,
Nov 11, 2013, 10:25:11 PM11/11/13
to therub...@googlegroups.com
Charles,

thank you so much. I knew I was missing something and because v8 is used in Chrome, then I misunderstood that window would exist. Simply injecting window to an empty objet literal made it, here's the working version:

#!/usr/bin/env ruby

puts "Compiling hellow world, expected output is <h1>Hellow world</h1>"

require 'rubygems'
require 'v8' #therubyracer

cxt = V8::Context.new
cxt.eval 'var window = {}'

cxt.load File.expand_path '../jade.js', __FILE__
puts cxt.eval 'window.jade.compile("h1 Hello World")()'


Thanks again. I'll now go an finally build a jade gem for ruby that doesn't depend on node, it's been long missing.

Cheers,

DPT 
Reply all
Reply to author
Forward
0 new messages