diff --git a/Gemfile b/Gemfile index 56ef68a..10d901e 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,11 @@ source :rubygems gemspec :name => "therubyrhino" -# NOTE: some specs might be excluded @see #spec/spec_helper.rb -gem 'redjs', :git => 'git://github.com/cowboyd/redjs.git', :group => :test, - :ref => "0d844f066666f967a78b20beb164c52d9ac3f5ca" -#gem 'redjs', :path => '../redjs', :group => :test \ No newline at end of file +group :test do + # NOTE: some specs might be excluded @see #spec/spec_helper.rb + gem 'redjs', :git => 'git://github.com/cowboyd/redjs.git', :group => :test, + :ref => "0d844f066666f967a78b20beb164c52d9ac3f5ca" + #gem 'redjs', :path => '../redjs', :group => :test + + gem 'therubyrhino_jar', '1.7.4' +end \ No newline at end of file diff --git a/spec/rhino/integration/bar.js b/spec/rhino/integration/bar.js new file mode 100644 index 0000000..af8513b --- /dev/null +++ b/spec/rhino/integration/bar.js @@ -0,0 +1,11 @@ +//console.log('bar.js 1'); +var util = require('util'); +//console.log('bar.js 2'); +var Bar = {}; +Bar.puts = function (message) { + util.puts(message); + return message; +}; +//console.log('bar.js 3'); +exports.Bar = Bar; +//console.log('bar.js 4'); \ No newline at end of file diff --git a/spec/rhino/integration/foo.js b/spec/rhino/integration/foo.js new file mode 100644 index 0000000..8934644 --- /dev/null +++ b/spec/rhino/integration/foo.js @@ -0,0 +1,7 @@ +//console.log('foo.js 1'); +var Bar = require('./bar').Bar; +//console.log('foo.js 2 ' + Bar + " : " + Bar.puts); +Bar.puts('Hello Bar!'); +//console.log('foo.js 3'); +exports.foo = { 'Bar': Bar }; +//console.log('foo.js 4'); \ No newline at end of file diff --git a/spec/rhino/integration_spec.rb b/spec/rhino/integration_spec.rb new file mode 100644 index 0000000..5853bec --- /dev/null +++ b/spec/rhino/integration_spec.rb @@ -0,0 +1,127 @@ +require 'bundler/setup' + +require 'rhino' +require 'pathname' +require 'stringio' + +describe 'integration' do + + it "requires (CommonJS)" do + context = Rhino::Context.new + #context.optimization_level = -1 + context['console'] = Console + path = Pathname(__FILE__).dirname.join('integration') + environment = Env.new(context, :path => path.to_s) + environment.native 'util', Util.new(out = StringIO.new) + exports = environment.require 'foo' + out.string.should == "Hello Bar!\n" + + exports.should_not be nil + exports.foo.should respond_to(:'[]') + exports.foo['Bar'].should respond_to(:'[]') + exports.foo['Bar'][:puts].should be_a Rhino::JS::Function + end + + class Env # a CommonJS like environment (inspired by commonjs.rb) + + def initialize(context, options = {}) + @context = context + @paths = [ options[:path] ].flatten.map { |path| Pathname(path) } + @modules = {} + end + + def require(module_id) + unless mod = @modules[module_id] + filepath = find(module_id) or fail LoadError, "no such module '#{module_id}'" + js = "( function(module, require, exports) {\n#{File.read(filepath)}\n} )" + load = @context.eval(js, filepath.expand_path.to_s) + @modules[module_id] = mod = Module.new(module_id, self) + load.call(mod, mod.require_function, mod.exports) + end + return mod.exports + end + + def native(module_id, impl) + @modules[module_id] = Module::Native.new(impl) + end + + def new_object + @context['Object'].new + end + + private + + def find(module_id) + if loadpath = @paths.find { |path| path.join("#{module_id}.js").exist? } + loadpath.join("#{module_id}.js") + end + end + + class Module + + attr_reader :exports + + def initialize(id, env) + @id = id + @env = env + @exports = env.new_object + @segments = id.split('/') + end + + def require_function + @require_function ||= lambda do |*args| + this, module_id = *args + module_id ||= this #backwards compatibility with TRR < 0.10 + @env.require(expand(module_id)) + end + end + + private + + def expand(module_id) + return module_id unless module_id =~ /(\.|\..)/ + module_id.split('/').inject(@segments[0..-2]) do |path, element| + path.tap do + if element == '.' + #do nothing + elsif element == '..' + path.pop + else + path.push element + end + end + end.join('/') + end + + class Native + + def initialize(impl); @impl = impl; end + def exports; @impl; end + + end + + end + + end + + class Util + + def initialize(io = STDOUT) + @io = io + end + + def puts(*args) + args.each { |arg| @io.puts(arg) } + end + + end + + class Console + + def self.log(*msgs) + puts msgs.join(', ') + end + + end + +end \ No newline at end of file