mirror of
				https://github.com/rubyjs/therubyracer
				synced 2023-03-27 23:21:42 -04:00 
			
		
		
		
	begin internal rewrite.
This commit is contained in:
		
							parent
							
								
									490002aad7
								
							
						
					
					
						commit
						9cb4f1c7d2
					
				
					 87 changed files with 0 additions and 4613 deletions
				
			
		
							
								
								
									
										13
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,13 +0,0 @@
 | 
			
		|||
.bundle
 | 
			
		||||
.rvmrc
 | 
			
		||||
Gemfile.lock
 | 
			
		||||
v8.bundle
 | 
			
		||||
v8.so
 | 
			
		||||
*.o
 | 
			
		||||
*.gem
 | 
			
		||||
*.rbc
 | 
			
		||||
*.log
 | 
			
		||||
*~
 | 
			
		||||
pkg/
 | 
			
		||||
tmp/
 | 
			
		||||
.yardoc/
 | 
			
		||||
							
								
								
									
										1
									
								
								.rspec
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								.rspec
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
--colour
 | 
			
		||||
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
 lib/**/*.rb ext/**/*.cpp
 | 
			
		||||
							
								
								
									
										3
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								Gemfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
source 'http://rubygems.org'
 | 
			
		||||
gemspec
 | 
			
		||||
gem 'redjs', :git => 'git://github.com/cowboyd/redjs.git', :tag => "v0.6.0", :group => :test
 | 
			
		||||
							
								
								
									
										167
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										167
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,167 +0,0 @@
 | 
			
		|||
# therubyracer
 | 
			
		||||
 | 
			
		||||
* [http://github.com/cowboyd/therubyracer](http://github.com/cowboyd/therubyracer)
 | 
			
		||||
* [http://groups.google.com/group/therubyracer](http://groups.google.com/group/therubyracer)
 | 
			
		||||
* [irc://irc.freenode.net/therubyracer](http://groups.google.com/group/therubyracer)
 | 
			
		||||
* [Documentation](https://github.com/cowboyd/therubyracer/wiki)
 | 
			
		||||
 | 
			
		||||
## DESCRIPTION
 | 
			
		||||
 | 
			
		||||
Embed the V8 Javascript interpreter into Ruby.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## FEATURES
 | 
			
		||||
 | 
			
		||||
* Evaluate Javascript from with in Ruby
 | 
			
		||||
* Embed your Ruby objects into the Javascript world
 | 
			
		||||
* Manipulate JavaScript objects and call JavaScript functions from Ruby
 | 
			
		||||
* API compatible with the The Ruby Rhino (for JRuby: http://github.com/cowboyd/therubyrhino)
 | 
			
		||||
 | 
			
		||||
## SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    gem install therubyracer         ;: stable
 | 
			
		||||
    gem install therubyracer --pre   ;: bleeding edge
 | 
			
		||||
 | 
			
		||||
then in your ruby code
 | 
			
		||||
 | 
			
		||||
    require 'v8'
 | 
			
		||||
 | 
			
		||||
evaluate some simple javascript
 | 
			
		||||
 | 
			
		||||
    cxt = V8::Context.new
 | 
			
		||||
    cxt.eval('7 * 6') #=> 42
 | 
			
		||||
 | 
			
		||||
embed values into the scope of your context
 | 
			
		||||
 | 
			
		||||
    cxt['foo'] = "bar"
 | 
			
		||||
    cxt.eval('foo') # => "bar"
 | 
			
		||||
 | 
			
		||||
embed ruby code into your scope and call it from javascript
 | 
			
		||||
 | 
			
		||||
    cxt["say"] = lambda {|word, times| word * times}
 | 
			
		||||
    cxt.eval("say('Hello', 3)") #=> HelloHelloHello
 | 
			
		||||
 | 
			
		||||
embed a ruby object into your scope and access its properties/methods from javascript
 | 
			
		||||
 | 
			
		||||
    class MyMath
 | 
			
		||||
      def plus(lhs, rhs)
 | 
			
		||||
        lhs + rhs
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    cxt['math'] = MyMath.new
 | 
			
		||||
    cxt.eval("math.plus(20,22)") #=> 42
 | 
			
		||||
 | 
			
		||||
make a ruby object *be* your global javascript scope.
 | 
			
		||||
 | 
			
		||||
    math = MyMath.new
 | 
			
		||||
    V8::Context.new(:with => math) do |cxt|
 | 
			
		||||
      cxt.eval("plus(20,22)") #=> 42
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
you can do the same thing with Object#eval_js
 | 
			
		||||
 | 
			
		||||
    math.eval_js("plus(20,22)")
 | 
			
		||||
 | 
			
		||||
## Different ways of loading javascript source
 | 
			
		||||
 | 
			
		||||
In addition to just evaluating strings, you can also use streams such as files.
 | 
			
		||||
 | 
			
		||||
evaluate bytes read from any File/IO object:
 | 
			
		||||
 | 
			
		||||
    File.open("mysource.js") do |file|
 | 
			
		||||
      cxt.eval(file, "mysource.js")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
or load it by filename
 | 
			
		||||
 | 
			
		||||
    cxt.load("mysource.js")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Safe by default, dangerous by demand
 | 
			
		||||
 | 
			
		||||
The Ruby Racer is designed to let you evaluate javascript as safely as possible unless you tell it to do something more
 | 
			
		||||
dangerous. The default context is a hermetically sealed javascript environment with only the standard javascript objects
 | 
			
		||||
and functions. Nothing from the ruby world is accessible at all.
 | 
			
		||||
 | 
			
		||||
For ruby objects that you explicitly embed into javascript, by default only the _public_ methods _below_ `Object` are
 | 
			
		||||
exposed by default. E.g.
 | 
			
		||||
 | 
			
		||||
    class A
 | 
			
		||||
      def a
 | 
			
		||||
        "a"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_s
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class B < A
 | 
			
		||||
      def b
 | 
			
		||||
        "b"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    V8::Context.new do |cxt|
 | 
			
		||||
      cxt['a'] = A.new
 | 
			
		||||
      cxt['b'] = B.new
 | 
			
		||||
      cxt.eval("a.a") # => 'a'
 | 
			
		||||
      cxt.eval("b.b") # => 'b'
 | 
			
		||||
      cxt.eval("b.a") # => 'a'
 | 
			
		||||
      cxt.eval("b.to_s") # => #<B:0x101776be8> (because A explicitly defined it)
 | 
			
		||||
      cxt.eval("b.object_id") #=> undefined, object_id is on Object
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
If needed, you can override the [Ruby Access](https://github.com/cowboyd/therubyracer/blob/master/lib/v8/access.rb)
 | 
			
		||||
to allow whatever behavior you'd like
 | 
			
		||||
 | 
			
		||||
More documentation can be found on the [github wiki](https://github.com/cowboyd/therubyracer/wiki)
 | 
			
		||||
 | 
			
		||||
## REQUIREMENTS:
 | 
			
		||||
 | 
			
		||||
* python >= 2.5 (required to compile v8)
 | 
			
		||||
* C++ compiler
 | 
			
		||||
 | 
			
		||||
## Rails/Bundler
 | 
			
		||||
 | 
			
		||||
To use the ruby racer in rails, or any application using Bundler to manage gems, add the following to your Gemfile
 | 
			
		||||
 | 
			
		||||
    gem "therubyracer", :require => 'v8'
 | 
			
		||||
    gem "therubyracer", "~> 0.8.2.pre" #bleeding edge.
 | 
			
		||||
 | 
			
		||||
## DEVELOP
 | 
			
		||||
    git clone git://github.com/cowboyd/therubyracer.git
 | 
			
		||||
    cd therubyracer
 | 
			
		||||
    git submodule update --init
 | 
			
		||||
    bundle install
 | 
			
		||||
    rake compile
 | 
			
		||||
 | 
			
		||||
## Sponsored by
 | 
			
		||||
<a href="http://thefrontside.net"></a>
 | 
			
		||||
 | 
			
		||||
## LICENSE:
 | 
			
		||||
 | 
			
		||||
(The MIT License)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2009,2010,2011 Charles Lowell
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
a copy of this software and associated documentation files (the
 | 
			
		||||
'Software'), to deal in the Software without restriction, including
 | 
			
		||||
without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be
 | 
			
		||||
included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | 
			
		||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | 
			
		||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 | 
			
		||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 | 
			
		||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										26
									
								
								Rakefile
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								Rakefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
require 'bundler'
 | 
			
		||||
require 'bundler/setup'
 | 
			
		||||
require "rake/extensiontask"
 | 
			
		||||
require "rspec/core/rake_task"
 | 
			
		||||
Bundler::GemHelper.install_tasks
 | 
			
		||||
 | 
			
		||||
task :default => :spec
 | 
			
		||||
 | 
			
		||||
desc "remove all generated artifacts except built v8 objects"
 | 
			
		||||
task :clean do
 | 
			
		||||
  sh "rm -rf pkg"
 | 
			
		||||
  sh "rm -rf ext/v8/*.bundle ext/v8/*.so"
 | 
			
		||||
  sh "rm -rf lib/v8/*.bundle lib/v8/*.so"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Rake::ExtensionTask.new("v8", eval(File.read("therubyracer.gemspec"))) do |ext|
 | 
			
		||||
  ext.lib_dir = "lib/v8"
 | 
			
		||||
  ext.source_pattern = "*.{cpp,h}"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RSpec::Core::RakeTask.new(:spec) do |spec|
 | 
			
		||||
  spec.rspec_opts = ['--color', "--format documentation"]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
#!/usr/bin/env ruby
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
  require 'v8'
 | 
			
		||||
rescue LoadError
 | 
			
		||||
  require 'rubygems'
 | 
			
		||||
  require 'v8'
 | 
			
		||||
end
 | 
			
		||||
require 'v8/cli'
 | 
			
		||||
 | 
			
		||||
V8::CLI.run(File.basename(__FILE__), ARGV)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
require 'mkmf'
 | 
			
		||||
require 'set'
 | 
			
		||||
begin
 | 
			
		||||
  require 'libv8'
 | 
			
		||||
rescue LoadError
 | 
			
		||||
  require 'rubygems'
 | 
			
		||||
  require 'libv8'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
have_library('objc') if RUBY_PLATFORM =~ /darwin/
 | 
			
		||||
 | 
			
		||||
#we have to manually prepend the libv8 include path to INCFLAGS
 | 
			
		||||
#since find_header() does not actually work as advertized.
 | 
			
		||||
#see https://github.com/cowboyd/therubyracer/issues/91
 | 
			
		||||
$INCFLAGS.insert 0, "-I#{Libv8.include_path} "
 | 
			
		||||
 | 
			
		||||
$CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
 | 
			
		||||
$CPPFLAGS += " -g" unless $CPPFLAGS.split.include? "-g"
 | 
			
		||||
$CPPFLAGS += " -rdynamic" unless $CPPFLAGS.split.include? "-rdynamic"
 | 
			
		||||
 | 
			
		||||
$LDFLAGS.insert 0, "#{Libv8.library_path}/libv8.#{$LIBEXT} "
 | 
			
		||||
$LIBS << ' -lpthread'
 | 
			
		||||
 | 
			
		||||
CONFIG['LDSHARED'] = '$(CXX) -shared' unless RUBY_PLATFORM =~ /darwin/
 | 
			
		||||
 | 
			
		||||
create_makefile('v8')
 | 
			
		||||
							
								
								
									
										189
									
								
								ext/v8/rr.cpp
									
										
									
									
									
								
							
							
						
						
									
										189
									
								
								ext/v8/rr.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,189 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_context.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
#include "v8_object.h"
 | 
			
		||||
#include "v8_function.h"
 | 
			
		||||
#include "v8_array.h"
 | 
			
		||||
#include "v8_string.h"
 | 
			
		||||
#include "v8_date.h"
 | 
			
		||||
#include "v8_message.h"
 | 
			
		||||
#include "v8_external.h"
 | 
			
		||||
#include "v8_exception.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
VALUE rr_define_class(const char *name, VALUE superclass) {
 | 
			
		||||
  VALUE V8 = rb_define_module("V8");
 | 
			
		||||
  VALUE V8_C = rb_define_module_under(V8, "C");
 | 
			
		||||
  VALUE klass = rb_define_class_under(V8_C, name, superclass);
 | 
			
		||||
  rb_funcall(klass, rb_intern("private_class_method"), 1, rb_str_new2("new"));
 | 
			
		||||
  return klass;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_define_module(const char *name) {
 | 
			
		||||
  VALUE V8 = rb_define_module("V8");
 | 
			
		||||
  VALUE V8_C = rb_define_module_under(V8, "C");
 | 
			
		||||
  return rb_define_module_under(V8_C, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_define_const(const char *name, VALUE value) {
 | 
			
		||||
  VALUE V8 = rb_define_module("V8");
 | 
			
		||||
  VALUE V8_C = rb_define_module_under(V8, "C");
 | 
			
		||||
  rb_define_const(V8_C, name, value);
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_const_get(const char *name) {
 | 
			
		||||
  VALUE V8 = rb_define_module("V8");
 | 
			
		||||
  VALUE V8_C = rb_define_module_under(V8, "C");
 | 
			
		||||
  return rb_const_get(V8_C, rb_intern(name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_define_finalizer(VALUE object, void* finalizer, VALUE data) {
 | 
			
		||||
  VALUE finalizer_proc = rb_proc_new((VALUE (*)(...))finalizer, data);
 | 
			
		||||
  rb_iv_set(finalizer_proc, "data", data);
 | 
			
		||||
  VALUE ospace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
 | 
			
		||||
  rb_funcall(ospace, rb_intern("define_finalizer"), 2, object, finalizer_proc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v82rb(Handle<Value> value) {
 | 
			
		||||
  if (value.IsEmpty()) {
 | 
			
		||||
    return rr_v8_value_empty();
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsUndefined() || value->IsNull()) {
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsExternal()) {
 | 
			
		||||
    return rr_reflect_v8_external(value);
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsUint32()) {
 | 
			
		||||
    return UINT2NUM(value->Uint32Value());
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsInt32()) {
 | 
			
		||||
    return INT2FIX(value->Int32Value());
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsBoolean()) {
 | 
			
		||||
    return value->BooleanValue() ? Qtrue : Qfalse;
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsNumber()) {
 | 
			
		||||
    return rb_float_new(value->NumberValue());
 | 
			
		||||
  }  
 | 
			
		||||
  if (value->IsString()) {
 | 
			
		||||
    return rr_reflect_v8_string(value);
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsFunction()) {
 | 
			
		||||
    return rr_reflect_v8_function(value);
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsArray()) {
 | 
			
		||||
    return rr_reflect_v8_array(value);
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsDate()) {
 | 
			
		||||
    return rr_reflect_v8_date(value);
 | 
			
		||||
  }
 | 
			
		||||
  if (value->IsObject()) {
 | 
			
		||||
    return rr_reflect_v8_object(value);
 | 
			
		||||
  }
 | 
			
		||||
  return rr_wrap_v8_value(value);  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v82rb(Handle<Message> value) {
 | 
			
		||||
  return rr_reflect_v8_message(value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<StackTrace> value) {
 | 
			
		||||
  return rr_reflect_v8_stacktrace(value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<StackFrame> value) {
 | 
			
		||||
  return rr_reflect_v8_stackframe(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v82rb(Handle<Boolean> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<Number> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<String> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<Object> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<Array> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Function> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<Integer> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<Uint32> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(Handle<Int32> value) {
 | 
			
		||||
  return rr_v82rb((Handle<Value>)value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(bool value) {
 | 
			
		||||
  return value ? Qtrue : Qfalse;
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(double value) {
 | 
			
		||||
  return rb_float_new(value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(int64_t value) {
 | 
			
		||||
  return LONG2NUM(value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(uint32_t value) {
 | 
			
		||||
  return UINT2NUM(value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(int32_t value) {
 | 
			
		||||
  return INT2FIX(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Handle<Value> rr_rb2v8(VALUE value) {
 | 
			
		||||
  switch (TYPE(value)) {
 | 
			
		||||
  case T_FIXNUM:
 | 
			
		||||
    // TODO: use this conversion if value will fit in 32 bits.
 | 
			
		||||
    // return Integer::New(FIX2LONG(value));
 | 
			
		||||
  case T_FLOAT:
 | 
			
		||||
    return Number::New(NUM2DBL(value));    
 | 
			
		||||
  case T_STRING:
 | 
			
		||||
    return String::New(RSTRING_PTR(value), RSTRING_LEN(value));
 | 
			
		||||
  case T_NIL:
 | 
			
		||||
    return Null();
 | 
			
		||||
  case T_TRUE:
 | 
			
		||||
    return True();
 | 
			
		||||
  case T_FALSE:
 | 
			
		||||
    return False();
 | 
			
		||||
  case T_DATA:
 | 
			
		||||
    return rr_v8_handle<Value>(value);
 | 
			
		||||
  case T_OBJECT:
 | 
			
		||||
  case T_CLASS:
 | 
			
		||||
  case T_ICLASS:
 | 
			
		||||
  case T_MODULE:
 | 
			
		||||
  case T_REGEXP:
 | 
			
		||||
  case T_MATCH:
 | 
			
		||||
  case T_ARRAY:
 | 
			
		||||
  case T_HASH:
 | 
			
		||||
  case T_STRUCT:
 | 
			
		||||
  case T_BIGNUM:
 | 
			
		||||
  case T_FILE:
 | 
			
		||||
  case T_SYMBOL:
 | 
			
		||||
//  case T_BLKTAG: (not in 1.9)
 | 
			
		||||
  case T_UNDEF:
 | 
			
		||||
//  case T_VARMAP: (not in 1.9)
 | 
			
		||||
//  case T_SCOPE: (not in 1.9)
 | 
			
		||||
  case T_NODE:  
 | 
			
		||||
  default:
 | 
			
		||||
    rb_warn("unknown conversion to V8 for: %s", RSTRING_PTR(rb_inspect(value)));
 | 
			
		||||
    return String::New("Undefined Conversion");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return Undefined();
 | 
			
		||||
}
 | 
			
		||||
// VALUE rr_v82rb(v8::ScriptData *data) {
 | 
			
		||||
//   return rr_thunk(rr_wrap_script_data(data));
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								ext/v8/rr.h
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								ext/v8/rr.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
#ifndef _THE_RUBY_RACER_
 | 
			
		||||
#define _THE_RUBY_RACER_ 
 | 
			
		||||
 | 
			
		||||
#include <ruby.h>
 | 
			
		||||
#include <v8.h>
 | 
			
		||||
 | 
			
		||||
#define rr_define_method(klass, name, impl, argc) rb_define_method(klass, name, (VALUE(*)(...))impl, argc)
 | 
			
		||||
#define rr_define_singleton_method(object, name, impl, argc) rb_define_singleton_method(object, name, (VALUE(*)(...))impl, argc)
 | 
			
		||||
 | 
			
		||||
VALUE rr_define_class(const char *name, VALUE superclass = rb_cObject);
 | 
			
		||||
VALUE rr_define_module(const char *name);
 | 
			
		||||
VALUE rr_define_const(const char *name, VALUE value);
 | 
			
		||||
VALUE rr_const_get(const char *name);
 | 
			
		||||
VALUE rr_define_finalizer(VALUE object, void* finalizer, VALUE data);
 | 
			
		||||
 | 
			
		||||
extern "C" VALUE rb_proc_new(VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Value> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Boolean> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Number> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::String> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Object> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Array> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Function> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Integer> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Uint32> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Int32> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::Message> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::StackTrace> value);
 | 
			
		||||
VALUE rr_v82rb(v8::Handle<v8::StackFrame> value);
 | 
			
		||||
 | 
			
		||||
VALUE rr_v82rb(bool value);
 | 
			
		||||
VALUE rr_v82rb(double value);
 | 
			
		||||
VALUE rr_v82rb(int64_t value);
 | 
			
		||||
VALUE rr_v82rb(uint32_t value);
 | 
			
		||||
VALUE rr_v82rb(int32_t value);
 | 
			
		||||
 | 
			
		||||
v8::Handle<v8::Value> rr_rb2v8(VALUE value);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,48 +0,0 @@
 | 
			
		|||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_context.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
#include "v8_string.h"
 | 
			
		||||
#include "v8_object.h"
 | 
			
		||||
#include "v8_array.h"
 | 
			
		||||
#include "v8_message.h"
 | 
			
		||||
#include "v8_function.h"
 | 
			
		||||
#include "v8_date.h"
 | 
			
		||||
#include "v8_script.h"
 | 
			
		||||
#include "v8_template.h"
 | 
			
		||||
#include "v8_try_catch.h"
 | 
			
		||||
#include "v8_callbacks.h"
 | 
			
		||||
#include "v8_external.h"
 | 
			
		||||
#include "v8_exception.h"
 | 
			
		||||
#include "v8_locker.h"
 | 
			
		||||
#include "v8_debug.h"
 | 
			
		||||
#include "v8_v8.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
  void Init_v8();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
  void Init_v8() {
 | 
			
		||||
    v8::Locker locker;
 | 
			
		||||
    rr_init_handle();
 | 
			
		||||
    rr_init_context();
 | 
			
		||||
    rr_init_value();
 | 
			
		||||
    rr_init_string();
 | 
			
		||||
    rr_init_script();
 | 
			
		||||
    rr_init_template();
 | 
			
		||||
    rr_init_object();
 | 
			
		||||
    rr_init_function();
 | 
			
		||||
    rr_init_v8_array();
 | 
			
		||||
    rr_init_v8_date();
 | 
			
		||||
    rr_init_message();
 | 
			
		||||
    rr_init_v8_try_catch();
 | 
			
		||||
    rr_init_v8_callbacks();
 | 
			
		||||
    rr_init_v8_external();
 | 
			
		||||
    rr_init_v8_exception();
 | 
			
		||||
    rr_init_v8_locker();
 | 
			
		||||
    rr_init_v8_debug();
 | 
			
		||||
    rr_init_v8_v8();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,48 +0,0 @@
 | 
			
		|||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_array.h"
 | 
			
		||||
#include "v8_object.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  
 | 
			
		||||
  VALUE ArrayClass;
 | 
			
		||||
  
 | 
			
		||||
  Persistent<Array>& unwrap(VALUE self) {
 | 
			
		||||
    return rr_v8_handle<Array>(self);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE New(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
    if (!Context::InContext()) {
 | 
			
		||||
      rb_raise(rb_eScriptError, "must be in a context to call Array::New()");
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE length;
 | 
			
		||||
    rb_scan_args(argc, argv, "01", &length);
 | 
			
		||||
    if (NIL_P(length)) {
 | 
			
		||||
      length = INT2FIX(0);
 | 
			
		||||
    }
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v8_handle_new(self, Array::New(NUM2INT(length)));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE Length(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->Length());
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE CloneElementAt(VALUE self, VALUE index) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->CloneElementAt(NUM2UINT(index)));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_array() {
 | 
			
		||||
  ArrayClass = rr_define_class("Array", rr_v8_object_class());
 | 
			
		||||
  rr_define_singleton_method(ArrayClass, "New", New, -1);
 | 
			
		||||
  rr_define_method(ArrayClass, "Length", Length, 0);
 | 
			
		||||
  rr_define_method(ArrayClass, "CloneElementAt", CloneElementAt, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_array(Handle<Value> value) {
 | 
			
		||||
  return rr_reflect_v8_object_as(value, ArrayClass);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_ARRAY_
 | 
			
		||||
#define _RR_V8_ARRAY_ 
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_array();
 | 
			
		||||
VALUE rr_reflect_v8_array(v8::Handle<v8::Value> value);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,81 +0,0 @@
 | 
			
		|||
#include "v8_callbacks.h"
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  VALUE ArgumentsClass;
 | 
			
		||||
  VALUE AccessorInfoClass;
 | 
			
		||||
  
 | 
			
		||||
  VALUE _Data(VALUE self) {
 | 
			
		||||
    return rb_iv_get(self, "data");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  namespace Accessor {
 | 
			
		||||
    AccessorInfo *info(VALUE value) {
 | 
			
		||||
      AccessorInfo* i = 0;
 | 
			
		||||
      Data_Get_Struct(value, class AccessorInfo, i);
 | 
			
		||||
      return i;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE This(VALUE self) {
 | 
			
		||||
      return rr_v82rb(info(self)->This());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE Holder(VALUE self) {
 | 
			
		||||
      return rr_v82rb(info(self)->Holder());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  namespace Args {
 | 
			
		||||
    Arguments* args(VALUE value) {
 | 
			
		||||
      Arguments *arguments = 0;
 | 
			
		||||
      Data_Get_Struct(value, class Arguments, arguments);
 | 
			
		||||
      return arguments;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE This(VALUE self) {
 | 
			
		||||
      return rr_v82rb(args(self)->This());    
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VALUE Holder(VALUE self) {
 | 
			
		||||
      return rr_v82rb(args(self)->Holder());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VALUE Length(VALUE self) {
 | 
			
		||||
      return rr_v82rb(args(self)->Length());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE Get(VALUE self, VALUE index) {
 | 
			
		||||
      int i = NUM2INT(index);
 | 
			
		||||
      return rr_v82rb((*args(self))[i]);
 | 
			
		||||
    }
 | 
			
		||||
    VALUE Callee(VALUE self) {
 | 
			
		||||
      return rr_v82rb(args(self)->Callee());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE IsConstructCall(VALUE self) {
 | 
			
		||||
      return rr_v82rb(args(self)->IsConstructCall());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_callbacks() {
 | 
			
		||||
  AccessorInfoClass = rr_define_class("AccessorInfo");
 | 
			
		||||
  rr_define_method(AccessorInfoClass, "This", Accessor::This, 0);
 | 
			
		||||
  rr_define_method(AccessorInfoClass, "Holder", Accessor::Holder, 0);
 | 
			
		||||
  rr_define_method(AccessorInfoClass, "Data", _Data, 0);
 | 
			
		||||
  
 | 
			
		||||
  ArgumentsClass = rr_define_class("Arguments");
 | 
			
		||||
  rr_define_method(ArgumentsClass, "This", Args::This, 0);
 | 
			
		||||
  rr_define_method(ArgumentsClass, "Holder", Args::Holder, 0);
 | 
			
		||||
  rr_define_method(ArgumentsClass, "Data", _Data, 0);
 | 
			
		||||
  rr_define_method(ArgumentsClass, "Length", Args::Length, 0);
 | 
			
		||||
  rr_define_method(ArgumentsClass, "Callee", Args::Callee, 0);
 | 
			
		||||
  rr_define_method(ArgumentsClass, "IsConstructCall", Args::IsConstructCall, 0);
 | 
			
		||||
  rr_define_method(ArgumentsClass, "[]", Args::Get, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v82rb(const AccessorInfo& info) {
 | 
			
		||||
  return Data_Wrap_Struct(AccessorInfoClass, 0, 0, (void*)&info);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v82rb(const Arguments& arguments) {
 | 
			
		||||
  return Data_Wrap_Struct(ArgumentsClass, 0, 0, (void*)&arguments);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_CALLBACKS_
 | 
			
		||||
#define _RR_V8_CALLBACKS_
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
void rr_init_v8_callbacks();
 | 
			
		||||
VALUE rr_v82rb(const v8::AccessorInfo& info);
 | 
			
		||||
VALUE rr_v82rb(const v8::Arguments& arguments);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,92 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_context.h"
 | 
			
		||||
#include "v8_message.h"
 | 
			
		||||
#include "v8_template.h"
 | 
			
		||||
#include "v8_external.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE ContextClass;
 | 
			
		||||
 | 
			
		||||
  Persistent<Context>& unwrap(VALUE value) {
 | 
			
		||||
    return rr_v8_handle<Context>(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE New(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    VALUE global_template; VALUE global_object;
 | 
			
		||||
    rb_scan_args(argc,argv, "02", &global_template, &global_object);
 | 
			
		||||
    Handle<ObjectTemplate> v8_global_template(NIL_P(global_template) ? Handle<ObjectTemplate>() : rr_v8_handle<ObjectTemplate>(global_template));
 | 
			
		||||
    Handle<Value> v8_global_object(NIL_P(global_object) ? Handle<Value>() : rr_v8_handle<Value>(global_object));
 | 
			
		||||
    Persistent<Context> cxt(Context::New(0, v8_global_template, v8_global_object));
 | 
			
		||||
    VALUE ref = rr_v8_handle_new(self, cxt);
 | 
			
		||||
    cxt.Dispose();
 | 
			
		||||
    return ref;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE InContext(VALUE self) {
 | 
			
		||||
    return Context::InContext() ? Qtrue : Qfalse;  
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetEntered(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    if (Context::InContext()) {
 | 
			
		||||
      Local<Context> current = Context::GetEntered();
 | 
			
		||||
      return rr_v8_handle_new(self, current);    
 | 
			
		||||
    } else {
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Global(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->Global());
 | 
			
		||||
  }  
 | 
			
		||||
 | 
			
		||||
  VALUE Enter(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    unwrap(self)->Enter();
 | 
			
		||||
    return self;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Exit(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    unwrap(self)->Exit();
 | 
			
		||||
    return self;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE IsEntered(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    if (Context::InContext()) {
 | 
			
		||||
      return rr_v82rb(unwrap(self) == Context::GetEntered());
 | 
			
		||||
    } else {
 | 
			
		||||
      return Qfalse;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  VALUE GetData(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetData());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE SetData(VALUE self, VALUE data) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    unwrap(self)->SetData(rr_rb2v8(data)->ToString());
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_context() {
 | 
			
		||||
  ContextClass = rr_define_class("Context", rr_v8_handle_class());
 | 
			
		||||
  rr_define_singleton_method(ContextClass, "New", New, -1);
 | 
			
		||||
  rr_define_singleton_method(ContextClass, "InContext", InContext, 0);
 | 
			
		||||
  rr_define_singleton_method(ContextClass, "GetEntered", GetEntered, 0);
 | 
			
		||||
  rr_define_method(ContextClass, "Global", Global, 0);
 | 
			
		||||
  rr_define_method(ContextClass, "Enter", Enter, 0);
 | 
			
		||||
  rr_define_method(ContextClass, "Exit", Exit, 0);
 | 
			
		||||
  rr_define_method(ContextClass, "IsEntered", IsEntered, 0);
 | 
			
		||||
  rr_define_method(ContextClass, "GetData", GetData, 0);
 | 
			
		||||
  rr_define_method(ContextClass, "SetData", SetData, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_CXT_
 | 
			
		||||
#define _RUBY_V8_CXT_ 
 | 
			
		||||
 | 
			
		||||
void rr_init_context();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_date.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_object.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE DateClass;
 | 
			
		||||
 | 
			
		||||
  VALUE New(VALUE self, VALUE time) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v8_handle_new(self, Date::New(NUM2DBL(time)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Override Value::NumberValue in order to ensure that we call the more specific and optimized
 | 
			
		||||
  // Number Value in v8::Date
 | 
			
		||||
  VALUE NumberValue(VALUE self) {
 | 
			
		||||
    Persistent<Date> date = rr_v8_handle<Date>(self);
 | 
			
		||||
    return rr_v82rb(date->NumberValue());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_date() {
 | 
			
		||||
  DateClass = rr_define_class("Date", rr_v8_value_class());
 | 
			
		||||
  rr_define_singleton_method(DateClass, "New", New, 1);
 | 
			
		||||
  rr_define_method(DateClass, "NumberValue", NumberValue, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_date(Handle<Value> value) {
 | 
			
		||||
  return rr_reflect_v8_object_as(Handle<Object>::Cast(value), DateClass);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_DATE_
 | 
			
		||||
#define _RR_V8_DATE_
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_date();
 | 
			
		||||
VALUE rr_reflect_v8_date(v8::Handle<v8::Value> value);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_debug.h"
 | 
			
		||||
#include "v8-debug.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE EnableAgent(VALUE self, VALUE application_name, VALUE port) {
 | 
			
		||||
    return rr_v82rb(v8::Debug::EnableAgent(RSTRING_PTR(application_name), NUM2INT(port), false));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_debug() {
 | 
			
		||||
  VALUE DebugModule = rr_define_module("Debug");
 | 
			
		||||
  rr_define_singleton_method(DebugModule, "EnableAgent", EnableAgent, 2);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_DEBUG_
 | 
			
		||||
#define _RR_V8_DEBUG_
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_debug();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,133 +0,0 @@
 | 
			
		|||
#include "v8_exception.h"
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
// #include "execinfo.h"
 | 
			
		||||
// #include "signal.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  static void* stack[20];
 | 
			
		||||
 | 
			
		||||
  void fatal(const char* location, const char* message) {
 | 
			
		||||
    rb_raise(rb_eFatal, "%s: %s", location, message);
 | 
			
		||||
  }
 | 
			
		||||
  // void segfault(int sig) {
 | 
			
		||||
  //   fprintf(stderr, "segfault: game over.\n");
 | 
			
		||||
  //   int size = backtrace(stack, 20);
 | 
			
		||||
  //   backtrace_symbols_fd(stack, size, 2);
 | 
			
		||||
  //   exit(1);
 | 
			
		||||
  // }
 | 
			
		||||
  VALUE _ThrowException(VALUE rbmod, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Handle<Value> err = rr_rb2v8(value);
 | 
			
		||||
    return rr_v82rb(ThrowException(err));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE RangeError(VALUE rbclass, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(Exception::RangeError(rr_rb2v8(value)->ToString()));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ReferenceError(VALUE rbclass, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(Exception::ReferenceError(rr_rb2v8(value)->ToString()));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE SyntaxError(VALUE rbclass, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(Exception::SyntaxError(rr_rb2v8(value)->ToString()));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE Error(VALUE rbclass, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(Exception::Error(rr_rb2v8(value)->ToString()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE StackTraceClass;
 | 
			
		||||
  VALUE StackFrameClass;
 | 
			
		||||
  namespace Trace {
 | 
			
		||||
 | 
			
		||||
    Persistent<StackTrace>& trace(VALUE value) {
 | 
			
		||||
      return rr_v8_handle<StackTrace>(value);
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetFrame(VALUE self, VALUE index) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(trace(self)->GetFrame(NUM2UINT(index)));
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetFrameCount(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(trace(self)->GetFrameCount());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE AsArray(VALUE self) {
 | 
			
		||||
      return rr_v82rb(trace(self)->AsArray());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE CurrentStackTrace(VALUE self, VALUE frame_limit) {
 | 
			
		||||
      return rr_v82rb(StackTrace::CurrentStackTrace(NUM2INT(frame_limit)));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  namespace Frame {
 | 
			
		||||
    Persistent<StackFrame>& frame(VALUE value) {
 | 
			
		||||
     return rr_v8_handle<StackFrame>(value);
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetLineNumber(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(frame(self)->GetLineNumber());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetColumn(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(frame(self)->GetColumn());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetScriptName(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(frame(self)->GetScriptName());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetFunctionName(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(frame(self)->GetFunctionName());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE IsEval(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(frame(self)->IsEval());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE IsConstructor(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v82rb(frame(self)->IsConstructor());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_exception() {
 | 
			
		||||
  VALUE V8 = rb_define_module("V8");
 | 
			
		||||
  VALUE V8_C = rb_define_module_under(V8, "C");
 | 
			
		||||
  rr_define_singleton_method(V8_C, "ThrowException", _ThrowException, 1);
 | 
			
		||||
 | 
			
		||||
  VALUE ExceptionClass = rr_define_class("Exception");
 | 
			
		||||
  rr_define_singleton_method(ExceptionClass, "RangeError", RangeError, 1);
 | 
			
		||||
  rr_define_singleton_method(ExceptionClass, "ReferenceError", ReferenceError, 1);
 | 
			
		||||
  rr_define_singleton_method(ExceptionClass, "SyntaxError", SyntaxError, 1);
 | 
			
		||||
  rr_define_singleton_method(ExceptionClass, "Error", Error, 1);
 | 
			
		||||
 | 
			
		||||
  StackTraceClass = rr_define_class("StackTrace", rr_v8_handle_class());
 | 
			
		||||
  rr_define_singleton_method(StackTraceClass, "CurrentStackTrace", Trace::CurrentStackTrace, 1);
 | 
			
		||||
  rr_define_method(StackTraceClass, "GetFrame", Trace::GetFrame, 1);
 | 
			
		||||
  rr_define_method(StackTraceClass, "GetFrameCount", Trace::GetFrameCount, 0);
 | 
			
		||||
  rr_define_method(StackTraceClass, "AsArray", Trace::AsArray, 0);
 | 
			
		||||
 | 
			
		||||
  StackFrameClass = rr_define_class("StackFrame", rr_v8_handle_class());
 | 
			
		||||
  rr_define_method(StackFrameClass, "GetLineNumber", Frame::GetLineNumber, 0);
 | 
			
		||||
  rr_define_method(StackFrameClass, "GetColumn", Frame::GetColumn, 0);
 | 
			
		||||
  rr_define_method(StackFrameClass, "GetScriptName", Frame::GetScriptName, 0);
 | 
			
		||||
  rr_define_method(StackFrameClass, "GetFunctionName", Frame::GetFunctionName, 0);
 | 
			
		||||
  rr_define_method(StackFrameClass, "IsEval", Frame::IsEval, 0);
 | 
			
		||||
  rr_define_method(StackFrameClass, "IsConstructor", Frame::IsConstructor, 0);
 | 
			
		||||
 | 
			
		||||
  v8::V8::SetFatalErrorHandler(fatal);
 | 
			
		||||
  //comment this in for debugging.
 | 
			
		||||
  // signal(SIGSEGV, segfault);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_stacktrace(Handle<StackTrace> value) {
 | 
			
		||||
  return rr_v8_handle_new(StackTraceClass, value);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_reflect_v8_stackframe(Handle<StackFrame> value) {
 | 
			
		||||
  return rr_v8_handle_new(StackFrameClass, value);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_EXCEPTION_
 | 
			
		||||
#define _RR_V8_EXCEPTION_
 | 
			
		||||
 | 
			
		||||
#include "v8.h"
 | 
			
		||||
#include "ruby.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_exception();
 | 
			
		||||
VALUE rr_reflect_v8_stacktrace(v8::Handle<v8::StackTrace> value);
 | 
			
		||||
VALUE rr_reflect_v8_stackframe(v8::Handle<v8::StackFrame> value);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,70 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_external.h"
 | 
			
		||||
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  VALUE ExternalClass;
 | 
			
		||||
  VALUE references;
 | 
			
		||||
 | 
			
		||||
  struct Weaklink {
 | 
			
		||||
    bool finalized_from_rb;
 | 
			
		||||
    bool finalized_from_v8;
 | 
			
		||||
    VALUE target;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  VALUE Weaklink_finalized_from_ruby(VALUE object_id, VALUE data) {
 | 
			
		||||
    Weaklink* link = 0;
 | 
			
		||||
    Data_Get_Struct(data, struct Weaklink, link);
 | 
			
		||||
    link->finalized_from_rb = true;
 | 
			
		||||
    if (link->finalized_from_v8) {
 | 
			
		||||
      delete link;
 | 
			
		||||
    }
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  void Weaklink_finalized_from_v8(Persistent<Value> value, void* data) {
 | 
			
		||||
    Weaklink* link = (Weaklink*)data;
 | 
			
		||||
    link->finalized_from_v8 = true;
 | 
			
		||||
    if (link->finalized_from_rb) {
 | 
			
		||||
      delete link;
 | 
			
		||||
    }
 | 
			
		||||
    value.Dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE New(VALUE self, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Weaklink* link = new Weaklink();
 | 
			
		||||
    link->finalized_from_v8 = false;
 | 
			
		||||
    link->finalized_from_rb = false;
 | 
			
		||||
    link->target = value;
 | 
			
		||||
    Persistent<External> external = Persistent<External>::New(External::New((void*)link));
 | 
			
		||||
    external.MakeWeak(link,Weaklink_finalized_from_v8);
 | 
			
		||||
    VALUE finalizer_data = Data_Wrap_Struct(rb_cObject, 0, 0, link);
 | 
			
		||||
    rr_define_finalizer(value, (void*)Weaklink_finalized_from_ruby, finalizer_data);
 | 
			
		||||
    return rr_v8_handle_new(self, external);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE _Value(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Weaklink* link = (Weaklink*)rr_v8_handle<External>(self)->Value();
 | 
			
		||||
    if (link->finalized_from_rb) {
 | 
			
		||||
      rb_warn("an active v8::External wraps a VALUE that has already been finalized! This is not good.\n");
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    } else {
 | 
			
		||||
      return link->target;
 | 
			
		||||
    }
 | 
			
		||||
    return (VALUE)rr_v8_handle<External>(self)->Value();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_external() {
 | 
			
		||||
  ExternalClass = rr_define_class("External", rr_v8_value_class());
 | 
			
		||||
  rr_define_singleton_method(ExternalClass, "New", New, 1);
 | 
			
		||||
  rr_define_method(ExternalClass, "Value", _Value, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_external(Handle<Value> external) {
 | 
			
		||||
  return rr_v8_handle_new(ExternalClass, external);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_EXTERNAL_
 | 
			
		||||
#define _RR_V8_EXTERNAL_
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_external();
 | 
			
		||||
VALUE rr_reflect_v8_external(v8::Handle<v8::Value> value);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,69 +0,0 @@
 | 
			
		|||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "v8_function.h"
 | 
			
		||||
#include "v8_object.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  VALUE FunctionClass;
 | 
			
		||||
  
 | 
			
		||||
  Persistent<Function>& unwrap(VALUE value) {
 | 
			
		||||
    return rr_v8_handle<Function>(value);
 | 
			
		||||
  }  
 | 
			
		||||
  VALUE Call(VALUE self, VALUE recv, VALUE arguments) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    if (!Context::InContext()) {
 | 
			
		||||
      rb_raise(rb_eScriptError, "no open V8 Context in V8::C::Function::Call()");
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    Handle<Function> function = unwrap(self);
 | 
			
		||||
    Local<Object> thisObj = rr_rb2v8(recv)->ToObject();
 | 
			
		||||
    Handle<Array> args = rr_v8_handle<Array>(arguments);
 | 
			
		||||
    int argc = args->Length();
 | 
			
		||||
    std::vector< Handle<Value> > argv (argc);
 | 
			
		||||
    for (int i = 0; i < argc; i++) {
 | 
			
		||||
      argv[i] = args->Get(i);
 | 
			
		||||
    }
 | 
			
		||||
    return rr_v82rb(function->Call(thisObj, argc, &argv[0]));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE NewInstance(VALUE self, VALUE arguments) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Handle<Function> function = unwrap(self);
 | 
			
		||||
    Handle<Array> args = rr_v8_handle<Array>(arguments);
 | 
			
		||||
    int argc = args->Length();
 | 
			
		||||
    std::vector< Handle<Value> > argv (argc);
 | 
			
		||||
    for (int i = 0; i < argc; i++) {
 | 
			
		||||
      argv[i] = args->Get(i);
 | 
			
		||||
    }
 | 
			
		||||
    return rr_v82rb(function->NewInstance(argc, &argv[0]));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE GetName(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetName());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE SetName(VALUE self, VALUE name) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Handle<String> str = rr_v8_handle<String>(name);
 | 
			
		||||
    unwrap(self)->SetName(str);
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }  
 | 
			
		||||
  // VALUE GetScriptOrigin(VALUE self) {
 | 
			
		||||
  //   return rr_v82rb(unwrap(self)->GetScriptOrigin());
 | 
			
		||||
  // }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_function() {
 | 
			
		||||
  FunctionClass = rr_define_class("Function", rr_v8_object_class());
 | 
			
		||||
  rr_define_method(FunctionClass, "Call", Call, 2);
 | 
			
		||||
  rr_define_method(FunctionClass, "NewInstance", NewInstance, 1);
 | 
			
		||||
  rr_define_method(FunctionClass, "GetName", GetName, 0);
 | 
			
		||||
  rr_define_method(FunctionClass, "SetName", SetName, 1);
 | 
			
		||||
  // rr_define_method(FunctionClass, "GetScriptOrigin", GetScriptOrigin, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_function(Handle<Value> value) {
 | 
			
		||||
  return rr_reflect_v8_object_as(value, FunctionClass);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_FUNCTION_
 | 
			
		||||
#define _RUBY_V8_FUNCTION_
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
#include "v8.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_function();
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_function(v8::Handle<v8::Value> value);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,186 +0,0 @@
 | 
			
		|||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* Creates a new Persistent storage cell for `handle`
 | 
			
		||||
* so that we can reference it from Ruby. Ruby metadat
 | 
			
		||||
* is contained on the handle object, and then the actual
 | 
			
		||||
* v8 references are contain in an instance of `Payload`
 | 
			
		||||
*/
 | 
			
		||||
v8_handle::v8_handle(Handle<void> object) {
 | 
			
		||||
  this->weakref_callback = Qnil;
 | 
			
		||||
  this->weakref_callback_parameters = Qnil;
 | 
			
		||||
  this->dead = false;
 | 
			
		||||
  this->payload = new Payload(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8_handle::~v8_handle() {}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* Construct a new handle payload.
 | 
			
		||||
*
 | 
			
		||||
* Each payload contains a Ruby object wrapper so that it
 | 
			
		||||
* can be enqueued for V8 GC (the GC queue is a ruby Array)
 | 
			
		||||
* the wrapper is pre-allocated at payload creation time
 | 
			
		||||
* so that no Ruby objects are allocated during Ruby GC.
 | 
			
		||||
*/
 | 
			
		||||
v8_handle::Payload::Payload(Handle<void> object) {
 | 
			
		||||
  rb_gc_register_address(&wrapper);
 | 
			
		||||
  handle = Persistent<void>::New(object);
 | 
			
		||||
  wrapper = Data_Wrap_Struct(rb_cObject, 0, destroy, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8_handle::Payload::~Payload() {
 | 
			
		||||
  rb_gc_unregister_address(&wrapper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void v8_handle::Payload::release() {
 | 
			
		||||
  handle.Dispose();
 | 
			
		||||
  handle.Clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void v8_handle::Payload::destroy(v8_handle::Payload* payload) {
 | 
			
		||||
  delete payload;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  /**
 | 
			
		||||
  * Holds dead references, that are no longer being held in Ruby, so that they can be garbage collected
 | 
			
		||||
  * inside of V8
 | 
			
		||||
  */
 | 
			
		||||
  VALUE handle_queue;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Invoked by the Ruby garbage collector whenever it determines that this handle is
 | 
			
		||||
  * still reachable. We in turn, mark our weak callback parameters, so that it knows
 | 
			
		||||
  * they are reachable too.
 | 
			
		||||
  */
 | 
			
		||||
  void v8_handle_mark(v8_handle* handle) {
 | 
			
		||||
    rb_gc_mark(handle->weakref_callback);
 | 
			
		||||
    rb_gc_mark(handle->weakref_callback_parameters);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Whenver a V8::C::Handle becomes garbage collected, we do not free it immediately.
 | 
			
		||||
  * instead, we put them into a "zombie" queue, where its corresponding V8 storage cell
 | 
			
		||||
  * can be released safely while the V8 engine is running. A zombie Ruby object is
 | 
			
		||||
  * created to wrap it so that it can be stored in the queue.
 | 
			
		||||
  */
 | 
			
		||||
  void v8_handle_enqueue(v8_handle* handle) {
 | 
			
		||||
    handle->dead = true;
 | 
			
		||||
    rb_ary_unshift(handle_queue, handle->payload->wrapper);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Drains the dead handle queue, and releases them from V8
 | 
			
		||||
  *
 | 
			
		||||
  * This implements the V8 `GCPrologueCallback` and is registered to run before
 | 
			
		||||
  * each invocation of the V8 garbage collector. It empties the queue of dead handles
 | 
			
		||||
  * and disposes of them. It is important to do this operations inside V8 so that
 | 
			
		||||
  * Ruby garbage collection is never locked, and never touches V8.
 | 
			
		||||
  */
 | 
			
		||||
  void v8_handle_dequeue(GCType type, GCCallbackFlags flags) {
 | 
			
		||||
    for (VALUE handle = rb_ary_pop(handle_queue); RTEST(handle); handle = rb_ary_pop(handle_queue)) {
 | 
			
		||||
      v8_handle::Payload* payload = NULL;
 | 
			
		||||
      Data_Get_Struct(handle, struct v8_handle::Payload, payload);
 | 
			
		||||
      payload->release();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE New(VALUE self, VALUE handle) {
 | 
			
		||||
    if (RTEST(handle)) {
 | 
			
		||||
      Persistent<void> that = rr_v8_handle<void>(handle);
 | 
			
		||||
      return rr_v8_handle_new(self, that);
 | 
			
		||||
    } else {
 | 
			
		||||
      return rr_v8_handle_new(self, Handle<void>());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE IsEmpty(VALUE self) {
 | 
			
		||||
    return rr_v82rb(rr_v8_handle<void>(self).IsEmpty());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Clear(VALUE self) {
 | 
			
		||||
    rr_v8_handle<void>(self).Clear();
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Dispose(VALUE self) {
 | 
			
		||||
    rr_v8_handle<void>(self).Dispose();
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void RubyWeakReferenceCallback(Persistent<Value> value, void* parameter) {
 | 
			
		||||
    VALUE self = (VALUE)parameter;
 | 
			
		||||
    v8_handle* handle = rr_v8_handle_raw(self);
 | 
			
		||||
    VALUE callback = handle->weakref_callback;
 | 
			
		||||
    VALUE parameters = handle->weakref_callback_parameters;
 | 
			
		||||
    if (RTEST(callback)) {
 | 
			
		||||
      rb_funcall(callback, rb_intern("call"), 2, self, parameters);
 | 
			
		||||
    }
 | 
			
		||||
    value.Dispose();
 | 
			
		||||
    handle->payload->release();
 | 
			
		||||
    handle->dead = true;
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE MakeWeak(VALUE self, VALUE parameters, VALUE callback) {
 | 
			
		||||
    v8_handle* handle = rr_v8_handle_raw(self);
 | 
			
		||||
    handle->weakref_callback = callback;
 | 
			
		||||
    handle->weakref_callback_parameters = parameters;
 | 
			
		||||
    rr_v8_handle<void>(self).MakeWeak((void*)self, RubyWeakReferenceCallback);
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE ClearWeak(VALUE self) {
 | 
			
		||||
    rr_v8_handle<void>(self).ClearWeak();
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE IsNearDeath(VALUE self) {
 | 
			
		||||
    return rr_v82rb(rr_v8_handle<void>(self).IsNearDeath());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE IsWeak(VALUE self) {
 | 
			
		||||
    return rr_v82rb(rr_v8_handle<void>(self).IsWeak());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE dead_p(VALUE self) {
 | 
			
		||||
    return rr_v8_handle_raw(self)->dead ? Qtrue : Qfalse;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_handle() {
 | 
			
		||||
  VALUE HandleClass = rr_define_class("Handle");
 | 
			
		||||
  rr_define_method(HandleClass, "dead?", dead_p, 0);
 | 
			
		||||
  rr_define_singleton_method(HandleClass, "New", New, 1);
 | 
			
		||||
  rr_define_method(HandleClass, "IsEmpty", IsEmpty, 0);
 | 
			
		||||
  rr_define_method(HandleClass, "Clear", Clear, 0);
 | 
			
		||||
  rr_define_method(HandleClass, "Dispose", Dispose, 0);
 | 
			
		||||
  rr_define_method(HandleClass, "MakeWeak", MakeWeak, 2);
 | 
			
		||||
  rr_define_method(HandleClass, "ClearWeak", ClearWeak, 0);
 | 
			
		||||
  rr_define_method(HandleClass, "IsNearDeath", IsNearDeath, 0);
 | 
			
		||||
  rr_define_method(HandleClass, "IsWeak", IsWeak, 0);
 | 
			
		||||
 | 
			
		||||
  rb_gc_register_address(&handle_queue);
 | 
			
		||||
  handle_queue = rb_ary_new();
 | 
			
		||||
  V8::AddGCPrologueCallback(v8_handle_dequeue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v8_handle_new(VALUE klass, v8::Handle<void> handle) {
 | 
			
		||||
  v8_handle* new_handle = new v8_handle(handle);
 | 
			
		||||
  return Data_Wrap_Struct(klass, v8_handle_mark, v8_handle_enqueue, new_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v8_handle_class() {
 | 
			
		||||
  return rr_define_class("Handle");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8_handle* rr_v8_handle_raw(VALUE value) {
 | 
			
		||||
  v8_handle* handle = 0;
 | 
			
		||||
  Data_Get_Struct(value, struct v8_handle, handle);
 | 
			
		||||
  return handle;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,48 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_HANDLE_
 | 
			
		||||
#define _RR_V8_HANDLE_
 | 
			
		||||
 | 
			
		||||
#include <v8.h>
 | 
			
		||||
#include "ruby.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* Holds a reference to a V8 heap object. This serves as the base
 | 
			
		||||
* class for all of the low-level proxies that reference into V8.
 | 
			
		||||
*/
 | 
			
		||||
struct v8_handle  {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Contains the *actual* V8 references. This object is kept
 | 
			
		||||
  * separate so that it can be "detached" from the handle when
 | 
			
		||||
  * it is garbage collected, and enqueued separately and
 | 
			
		||||
  * collected in the context of a V8 thread.
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  struct Payload {
 | 
			
		||||
    Payload(v8::Handle<void> object);
 | 
			
		||||
    virtual ~Payload();
 | 
			
		||||
    void release();
 | 
			
		||||
    static void destroy(v8_handle::Payload* payload);
 | 
			
		||||
    v8::Persistent<void> handle;
 | 
			
		||||
    VALUE wrapper;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  v8_handle(v8::Handle<void> object);
 | 
			
		||||
  virtual ~v8_handle();
 | 
			
		||||
 | 
			
		||||
  Payload* payload;
 | 
			
		||||
  bool dead;
 | 
			
		||||
  VALUE weakref_callback;
 | 
			
		||||
  VALUE weakref_callback_parameters;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void rr_init_handle();
 | 
			
		||||
 | 
			
		||||
v8_handle* rr_v8_handle_raw(VALUE value);
 | 
			
		||||
 | 
			
		||||
template <class T> v8::Persistent<T>& rr_v8_handle(VALUE value) {
 | 
			
		||||
  return (v8::Persistent<T>&)(rr_v8_handle_raw(value)->payload->handle);
 | 
			
		||||
}
 | 
			
		||||
VALUE rr_v8_handle_new(VALUE rbclass, v8::Handle<void> handle);
 | 
			
		||||
VALUE rr_v8_handle_class();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,139 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_locker.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  namespace Lock {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Document-method: V8::C::Locker#new
 | 
			
		||||
    *
 | 
			
		||||
    * Allocates and returns a new `v8::Locker` object. The thread that instantiated
 | 
			
		||||
    * this object will hold the V8 interpreter lock until it is released with a
 | 
			
		||||
    * corresponding call to {#delete}.
 | 
			
		||||
    *
 | 
			
		||||
    * It critical that you call {#delete} to deallocate it, preferably within the same method.
 | 
			
		||||
    * If you don't, two bad things will happen:
 | 
			
		||||
    *
 | 
			
		||||
    * 1. You'll leak the underlying C++ object
 | 
			
		||||
    * 1. Worse, you'll leave the V8 vm locked to this thread forever
 | 
			
		||||
    *
 | 
			
		||||
    * It's dangerous! Be sure to `ensure`.
 | 
			
		||||
    *
 | 
			
		||||
    * for detailed semantics see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
 | 
			
		||||
    *
 | 
			
		||||
    * @return [V8::C::Locker] the new locker
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    VALUE New(VALUE LockerClass) {
 | 
			
		||||
      Locker* locker = new Locker();
 | 
			
		||||
      return Data_Wrap_Struct(LockerClass, 0, 0, (void*)locker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Document-method: V8::C::Locker#delete
 | 
			
		||||
    *
 | 
			
		||||
    * Pop this lock off the stack for this thread. For a full run down of V8 locking
 | 
			
		||||
    * semantics see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
 | 
			
		||||
    * @return nil
 | 
			
		||||
    */
 | 
			
		||||
    VALUE Delete(VALUE self) {
 | 
			
		||||
      Locker* locker = 0;
 | 
			
		||||
      Data_Get_Struct(self, class Locker, locker);
 | 
			
		||||
      delete locker;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  namespace Unlock {
 | 
			
		||||
    /**
 | 
			
		||||
    * Document-method: V8::C::Unlocker#new
 | 
			
		||||
    *
 | 
			
		||||
    * Allocates and returns a new `v8::UnLocker` object, temporarily releasing any locks that
 | 
			
		||||
    * this thread is holding. It will reaquire all of the locksto {#delete}.
 | 
			
		||||
    *
 | 
			
		||||
    * This is a great thing to do when you want to call out to some code that might do some
 | 
			
		||||
    * waiting, sleeping, and you want to politely let other threads use this VM.
 | 
			
		||||
    *
 | 
			
		||||
    * It critical that you call {#delete} to deallocate it, preferably within the same method.
 | 
			
		||||
    * If you don't, two bad things will happen:
 | 
			
		||||
    *
 | 
			
		||||
    * 1. You'll leak the underlying C++ object
 | 
			
		||||
    * 1. You won't restore the locks to your current thread, and will mess things up horribly
 | 
			
		||||
    *
 | 
			
		||||
    * It's dangerous! Be sure to `ensure`.
 | 
			
		||||
    *
 | 
			
		||||
    * For details on V8 locking semantics, see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
 | 
			
		||||
    * @return [V8::C::Unocker] the new locker
 | 
			
		||||
    */
 | 
			
		||||
    VALUE New(VALUE UnlockerClass) {
 | 
			
		||||
      Unlocker* unlocker = new Unlocker();
 | 
			
		||||
      return Data_Wrap_Struct(UnlockerClass, 0, 0, (void*)unlocker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Document-method: V8::C::Unlocker#delete
 | 
			
		||||
    *
 | 
			
		||||
    * Restore any locks to the stack that were temporarily removed by this `Unlocker`.
 | 
			
		||||
    * For a full run down, see semantics see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
 | 
			
		||||
    * @return nil
 | 
			
		||||
    */
 | 
			
		||||
    VALUE Delete(VALUE self) {
 | 
			
		||||
      Unlocker* unlocker;
 | 
			
		||||
      Data_Get_Struct(self, class Unlocker, unlocker);
 | 
			
		||||
      delete unlocker;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Document-method: V8::C::Locker#StartPreemption
 | 
			
		||||
  * Start preemption.
 | 
			
		||||
  * When preemption is started, a timer is fired every n milli seconds that will switch between
 | 
			
		||||
  * multiple threads that are in contention for the V8 lock.
 | 
			
		||||
  *
 | 
			
		||||
  * @param [Integer] every_n_ms
 | 
			
		||||
  * @return nil
 | 
			
		||||
  */
 | 
			
		||||
  VALUE StartPreemption(VALUE self, VALUE every_n_ms) {
 | 
			
		||||
    Locker::StartPreemption(NUM2INT(rb_to_int(every_n_ms)));
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Document-method: V8::C::Locker#StartPreemption
 | 
			
		||||
  * Stop preemption
 | 
			
		||||
  */
 | 
			
		||||
  VALUE StopPreemption(VALUE self) {
 | 
			
		||||
    Locker::StopPreemption();
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Document-method: V8::C::Locker#IsLocked
 | 
			
		||||
  * Returns whether or not the locker is locked by the current thread.
 | 
			
		||||
  */
 | 
			
		||||
  VALUE IsLocked(VALUE self) {
 | 
			
		||||
    return rr_v82rb(Locker::IsLocked());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Document-method: V8::C::Locker#IsActive
 | 
			
		||||
  * Returns whether v8::Locker is being used by this V8 instance.
 | 
			
		||||
  */
 | 
			
		||||
  VALUE IsActive(VALUE self) {
 | 
			
		||||
    return rr_v82rb(Locker::IsActive());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_locker() {
 | 
			
		||||
  VALUE LockerClass = rr_define_class("Locker");
 | 
			
		||||
  VALUE UnlockerClass = rr_define_class("Unlocker");
 | 
			
		||||
  rr_define_singleton_method(LockerClass, "new", Lock::New, 0);
 | 
			
		||||
  rr_define_method(LockerClass, "delete", Lock::Delete, 0);
 | 
			
		||||
  rr_define_singleton_method(UnlockerClass, "new", Unlock::New, 0);
 | 
			
		||||
  rr_define_method(UnlockerClass, "delete", Unlock::Delete, 0);
 | 
			
		||||
  rr_define_singleton_method(LockerClass, "StartPreemption", StartPreemption, 1);
 | 
			
		||||
  rr_define_singleton_method(LockerClass, "StopPreemption", StopPreemption, 0);
 | 
			
		||||
  rr_define_singleton_method(LockerClass, "IsLocked", IsLocked, 0);
 | 
			
		||||
  rr_define_singleton_method(LockerClass, "IsActive", IsActive, 0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_LOCKER
 | 
			
		||||
#define _RUBY_V8_LOCKER
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_locker();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,67 +0,0 @@
 | 
			
		|||
#include "v8_message.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  VALUE MessageClass;
 | 
			
		||||
  
 | 
			
		||||
  Persistent<Message>& unwrap(VALUE self) {
 | 
			
		||||
    return rr_v8_handle<Message>(self);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE Get(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->Get());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetSourceLine(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetSourceLine());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetScriptResourceName(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetScriptResourceName());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetStackTrace(VALUE self) {
 | 
			
		||||
    Handle<StackTrace> trace = unwrap(self)->GetStackTrace();
 | 
			
		||||
    return trace.IsEmpty() ? Qnil : rr_v82rb(trace);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetLineNumber(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetLineNumber());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetStartPosition(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetStartPosition());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetEndPosition(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetEndPosition());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetStartColumn(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetStartColumn());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetEndColumn(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetEndColumn());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_message() {
 | 
			
		||||
  MessageClass = rr_define_class("Message", rr_v8_handle_class());
 | 
			
		||||
  rr_define_method(MessageClass, "Get", Get, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetSourceLine", GetSourceLine, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetScriptResourceName", GetScriptResourceName, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetStackTrace", GetStackTrace, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetLineNumber", GetLineNumber, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetStartPosition", GetStartPosition, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetEndPosition", GetEndPosition, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetStartColumn", GetStartColumn, 0);
 | 
			
		||||
  rr_define_method(MessageClass, "GetEndColumn", GetEndColumn, 0);  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_message(Handle<Message> value) {
 | 
			
		||||
  return rr_v8_handle_new(MessageClass, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_MESSAGE_
 | 
			
		||||
#define _RUBY_V8_MESSAGE_ 
 | 
			
		||||
 | 
			
		||||
#include "v8.h"
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_message();
 | 
			
		||||
VALUE rr_reflect_v8_message(v8::Handle<v8::Message> value);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,122 +0,0 @@
 | 
			
		|||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_weakref.h"
 | 
			
		||||
#include "v8_object.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
#include "v8_template.h"
 | 
			
		||||
#include "v8_external.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE ObjectClass;
 | 
			
		||||
 | 
			
		||||
  Persistent<Object>& unwrap(VALUE object) {
 | 
			
		||||
    return rr_v8_handle<Object>(object);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Get(VALUE self, VALUE key) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    Persistent<Object> obj(unwrap(self));
 | 
			
		||||
    if (rb_obj_is_kind_of(key, rb_cNumeric)) {
 | 
			
		||||
      return rr_v82rb(obj->Get(NUM2UINT(key)));
 | 
			
		||||
    } else {
 | 
			
		||||
      return rr_v82rb(obj->Get(rr_rb2v8(key)->ToString()));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE New(VALUE rbclass) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    if (!Context::InContext()) {
 | 
			
		||||
      rb_raise(rb_eScriptError, "Object::New() called without an entered Context");
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    return rr_v8_handle_new(rbclass, Object::New());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Set(VALUE self, VALUE key, VALUE value) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    Persistent<Object> obj = unwrap(self);
 | 
			
		||||
    if (rb_obj_is_kind_of(key, rb_cNumeric)) {
 | 
			
		||||
      return rr_v82rb(obj->Set(NUM2UINT(key), rr_rb2v8(value)));
 | 
			
		||||
    } else {
 | 
			
		||||
      return rr_v82rb(obj->Set(rr_rb2v8(key), rr_rb2v8(value)));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE GetPropertyNames(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    Persistent<Object> object = unwrap(self);
 | 
			
		||||
    Local<Value> names = object->GetPropertyNames();
 | 
			
		||||
    return rr_v82rb(names);
 | 
			
		||||
  }
 | 
			
		||||
  VALUE GetIdentityHash(VALUE self) {
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetIdentityHash());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE SetHiddenValue(VALUE self, VALUE key, VALUE value) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    if (Context::InContext()) {
 | 
			
		||||
      unwrap(self)->SetHiddenValue(rr_rb2v8(key)->ToString(), rr_rb2v8(value));
 | 
			
		||||
    } else {
 | 
			
		||||
      rb_raise(rb_eScriptError, "Object::SetHiddenValue() called without an entered Context");
 | 
			
		||||
    }
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  VALUE GetHiddenValue(VALUE self, VALUE key) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetHiddenValue(rr_rb2v8(key)->ToString()));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE GetPrototype(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->GetPrototype());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE SetPrototype(VALUE self, VALUE prototype) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Handle<Value> proto(rr_rb2v8(prototype));
 | 
			
		||||
    return rr_v82rb(unwrap(self)->SetPrototype(rr_rb2v8(prototype)));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v8_object_class() {
 | 
			
		||||
  return ObjectClass;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_object() {
 | 
			
		||||
  ObjectClass = rr_define_class("Object", rr_v8_value_class());
 | 
			
		||||
  rr_define_singleton_method(ObjectClass, "New", New, 0);
 | 
			
		||||
  rr_define_method(ObjectClass, "Get", Get, 1);
 | 
			
		||||
  rr_define_method(ObjectClass, "Set", Set, 2);
 | 
			
		||||
  rr_define_method(ObjectClass, "GetPropertyNames", GetPropertyNames, 0);
 | 
			
		||||
  rr_define_method(ObjectClass, "GetIdentityHash", GetIdentityHash, 0);
 | 
			
		||||
  rr_define_method(ObjectClass, "GetHiddenValue", GetHiddenValue, 1);
 | 
			
		||||
  rr_define_method(ObjectClass, "SetHiddenValue", SetHiddenValue, 2);
 | 
			
		||||
  rr_define_method(ObjectClass, "GetPrototype", GetPrototype, 0);
 | 
			
		||||
  rr_define_method(ObjectClass, "SetPrototype", SetPrototype, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_object_as(Handle<Value> value, VALUE ruby_class) {
 | 
			
		||||
  Handle<Object> object = Handle<Object>::Cast(value);
 | 
			
		||||
  VALUE handle;
 | 
			
		||||
  v8_weakref* backref;
 | 
			
		||||
  Local<Value> holder = object->GetHiddenValue(String::NewSymbol("TheRubyRacer::Backref"));
 | 
			
		||||
  if (holder.IsEmpty()) {
 | 
			
		||||
    handle = rr_v8_handle_new(ruby_class, object);
 | 
			
		||||
    backref = new v8_weakref(handle);
 | 
			
		||||
    object->SetHiddenValue(String::NewSymbol("TheRubyRacer::Backref"), backref->external);
 | 
			
		||||
  } else {
 | 
			
		||||
    backref = (v8_weakref*)External::Unwrap(holder);
 | 
			
		||||
    handle = backref->get();
 | 
			
		||||
    if (!RTEST(handle)) {
 | 
			
		||||
      handle = rr_v8_handle_new(ruby_class, object);
 | 
			
		||||
      backref->set(handle);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_object(Handle<Value> value) {
 | 
			
		||||
  return rr_reflect_v8_object_as(value, ObjectClass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_OBJECT_
 | 
			
		||||
#define _RUBY_V8_OBJECT_ 
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_object();
 | 
			
		||||
VALUE rr_v8_object_class();
 | 
			
		||||
VALUE rr_reflect_v8_object(v8::Handle<v8::Value> value);
 | 
			
		||||
VALUE rr_reflect_v8_object_as(v8::Handle<v8::Value> object, VALUE ruby_class);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,36 +0,0 @@
 | 
			
		|||
#include "v8.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_script.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE New(VALUE self, VALUE source, VALUE source_name) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Local<String> src(rr_rb2v8(source)->ToString());
 | 
			
		||||
    Local<String> src_name(rr_rb2v8(source_name)->ToString());
 | 
			
		||||
    return rr_v8_handle_new(self, Script::Compile(src, src_name));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Compile(VALUE self, VALUE source, VALUE source_name) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Local<String> src(rr_rb2v8(source)->ToString());
 | 
			
		||||
    Local<String> src_name(rr_rb2v8(source_name)->ToString());
 | 
			
		||||
    return rr_v8_handle_new(self, Script::Compile(src, src_name));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Run(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    Persistent<Script> script(rr_v8_handle<Script>(self));
 | 
			
		||||
    Local<Value> result(script->Run());
 | 
			
		||||
    return result.IsEmpty() ? Qnil : rr_v82rb(result);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_script() {
 | 
			
		||||
  VALUE ScriptClass = rr_define_class("Script", rr_v8_handle_class());
 | 
			
		||||
  rr_define_singleton_method(ScriptClass, "New", New, 2);
 | 
			
		||||
  rr_define_singleton_method(ScriptClass, "Compile", Compile, 2);
 | 
			
		||||
  rr_define_method(ScriptClass, "Run", Run, 0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_SCRIPT_
 | 
			
		||||
#define _RUBY_V8_SCRIPT_ 
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_script();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,52 +0,0 @@
 | 
			
		|||
 | 
			
		||||
#include "v8.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
#include "v8_string.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {  
 | 
			
		||||
  VALUE StringClass;
 | 
			
		||||
  
 | 
			
		||||
  Persistent<String>& unwrap(VALUE value) {
 | 
			
		||||
    return rr_v8_handle<String>(value);
 | 
			
		||||
  }
 | 
			
		||||
  VALUE New(VALUE string_class, VALUE data) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    VALUE str = rb_funcall(data, rb_intern("to_s"), 0);
 | 
			
		||||
    return rr_v8_handle_new(string_class, String::New(RSTRING_PTR(str), RSTRING_LEN(str)));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE NewSymbol(VALUE string_class, VALUE data) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    VALUE str = rb_funcall(data, rb_intern("to_s"), 0);
 | 
			
		||||
    return rr_v8_handle_new(string_class, String::NewSymbol(RSTRING_PTR(str), RSTRING_LEN(str)));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE Utf8Value(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    Handle<String> str = unwrap(self);
 | 
			
		||||
    return rb_str_new(*String::Utf8Value(str), str->Utf8Length());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE Utf16Value(VALUE self) {
 | 
			
		||||
    //How are UTF16 strings represented in ruby 1.8, 1.9
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  VALUE AsciiValue(VALUE self) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    Handle<String> str = unwrap(self);
 | 
			
		||||
    return rb_str_new(*String::AsciiValue(str), str->Length());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_string(Handle<Value> value) {
 | 
			
		||||
  return rr_v8_handle_new(StringClass, Handle<String>::Cast(value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_string() {
 | 
			
		||||
  StringClass = rr_define_class("String", rr_v8_value_class());
 | 
			
		||||
  rr_define_singleton_method(StringClass, "New", New, 1);
 | 
			
		||||
  rr_define_singleton_method(StringClass, "NewSymbol", NewSymbol, 1);
 | 
			
		||||
  rr_define_method(StringClass, "Utf8Value", Utf8Value, 0);
 | 
			
		||||
  rr_define_method(StringClass, "Utf16Value", Utf16Value, 0);
 | 
			
		||||
  rr_define_method(StringClass, "AsciiValue", AsciiValue, 0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_STR_
 | 
			
		||||
#define _RUBY_V8_STR_
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_string();
 | 
			
		||||
 | 
			
		||||
VALUE rr_reflect_v8_string(v8::Handle<v8::Value> value);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,344 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_function.h"
 | 
			
		||||
#include "v8_template.h"
 | 
			
		||||
#include "v8_external.h"
 | 
			
		||||
#include "v8_callbacks.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE ObjectTemplateClass;
 | 
			
		||||
  VALUE FunctionTemplateClass;
 | 
			
		||||
 | 
			
		||||
  struct v8_callback_data {
 | 
			
		||||
    VALUE handler;
 | 
			
		||||
    VALUE getter;
 | 
			
		||||
    VALUE setter;
 | 
			
		||||
    VALUE query;
 | 
			
		||||
    VALUE deleter;
 | 
			
		||||
    VALUE enumerator;
 | 
			
		||||
    VALUE data;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  void delete_v8_data(Persistent<Value> value, void* parameter) {
 | 
			
		||||
    value.Dispose();
 | 
			
		||||
    delete (v8_callback_data*)parameter;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Local<External> make_v8_data(int argc, VALUE *argv, const char* argf) {
 | 
			
		||||
    VALUE handler; VALUE data;
 | 
			
		||||
    rb_scan_args(argc, argv, argf, &handler, &data);
 | 
			
		||||
    v8_callback_data* v8_data = new v8_callback_data();
 | 
			
		||||
    v8_data->handler = handler;
 | 
			
		||||
    v8_data->data = data;
 | 
			
		||||
    Local<External> external = External::New((void*)v8_data);
 | 
			
		||||
    Persistent<External>::New(external).MakeWeak((void*)v8_data, delete_v8_data);
 | 
			
		||||
    return external;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Persistent<Template> tmpl(VALUE self) {
 | 
			
		||||
    return rr_v8_handle<Template>(self);
 | 
			
		||||
  }
 | 
			
		||||
  Persistent<ObjectTemplate> obj(VALUE self) {
 | 
			
		||||
    return rr_v8_handle<ObjectTemplate>(self);
 | 
			
		||||
  }
 | 
			
		||||
  Persistent<FunctionTemplate> func(VALUE self) {
 | 
			
		||||
    return rr_v8_handle<FunctionTemplate>(self);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Set(VALUE self, VALUE name, VALUE value) {
 | 
			
		||||
    HandleScope handles;
 | 
			
		||||
    Local<String> key = rr_rb2v8(name)->ToString();
 | 
			
		||||
    Persistent<Data> data = rr_v8_handle<Data>(value);
 | 
			
		||||
    tmpl(self)->Set(key, data);
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Handle<Value> RubyInvocationCallback(const Arguments& args) {
 | 
			
		||||
    Handle<External> v8_data_wrapper = Handle<External>::Cast(args.Data());
 | 
			
		||||
    v8_callback_data* v8_data = (v8_callback_data*)v8_data_wrapper->Value();
 | 
			
		||||
    if (RTEST(v8_data->handler)) {
 | 
			
		||||
    VALUE rb_args = rr_v82rb(args);
 | 
			
		||||
      rb_iv_set(rb_args, "data", v8_data->data);
 | 
			
		||||
      VALUE result = rb_funcall(v8_data->handler, rb_intern("call"), 1, rb_args);
 | 
			
		||||
      return rr_rb2v8(result);
 | 
			
		||||
    } else {
 | 
			
		||||
      return Handle<Value>();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  namespace Obj {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    v8_callback_data* accessor_info_data(const AccessorInfo& info) {
 | 
			
		||||
      Handle<External> v8_data_wrapper = Handle<External>::Cast(info.Data());
 | 
			
		||||
      return (v8_callback_data*)v8_data_wrapper->Value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VALUE accessor_info_rb(const AccessorInfo& info) {
 | 
			
		||||
      VALUE rb_data = accessor_info_data(info)->data;
 | 
			
		||||
      VALUE rb_info = rr_v82rb(info);
 | 
			
		||||
      rb_iv_set(rb_info, "data", rb_data);
 | 
			
		||||
      return rb_info;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Local<External> accessor_info_data(VALUE getter, VALUE setter, VALUE query, VALUE deleter, VALUE enumerator, VALUE data) {
 | 
			
		||||
      v8_callback_data* v8_data = new v8_callback_data();
 | 
			
		||||
      v8_data->getter = getter;
 | 
			
		||||
      v8_data->setter = setter;
 | 
			
		||||
      v8_data->query = query;
 | 
			
		||||
      v8_data->deleter = deleter;
 | 
			
		||||
      v8_data->enumerator = enumerator;
 | 
			
		||||
      v8_data->data = data;
 | 
			
		||||
      Local<External> external = External::New((void*)v8_data);
 | 
			
		||||
      Persistent<External>::New(external).MakeWeak((void*)v8_data, delete_v8_data);
 | 
			
		||||
      return external;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * NamedProperty[Getter|Setter] are used as interceptors on object.
 | 
			
		||||
     * See ObjectTemplate::SetNamedPropertyHandler.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Value> RubyNamedPropertyGetter(Local<String> property, const AccessorInfo& info) {
 | 
			
		||||
      VALUE getter = accessor_info_data(info)->getter;
 | 
			
		||||
      return rr_rb2v8(rb_funcall(getter, rb_intern("call"), 2, rr_v82rb(property), accessor_info_rb(info)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the value if the setter intercepts the request.
 | 
			
		||||
     * Otherwise, returns an empty handle.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Value> RubyNamedPropertySetter(Local<String> property, Local<Value> value, const AccessorInfo& info) {
 | 
			
		||||
      VALUE setter = accessor_info_data(info)->setter;
 | 
			
		||||
      VALUE result = rb_funcall(setter, rb_intern("call"), 3, rr_v82rb(property), rr_v82rb(value), accessor_info_rb(info));
 | 
			
		||||
      return rr_rb2v8(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a non-empty handle if the interceptor intercepts the request.
 | 
			
		||||
     * The result is true if the property exists and false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Integer> RubyNamedPropertyQuery(Local<String> property, const AccessorInfo& info) {
 | 
			
		||||
      VALUE query = accessor_info_data(info)->query;
 | 
			
		||||
      VALUE result = rb_funcall(query, rb_intern("call"), 2, rr_v82rb(property), accessor_info_rb(info));
 | 
			
		||||
      Handle<Value> intercepts = rr_rb2v8(result);
 | 
			
		||||
      return intercepts.IsEmpty() ? Handle<Integer>() : Integer::New(None);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a non-empty handle if the deleter intercepts the request.
 | 
			
		||||
     * The return value is true if the property could be deleted and false
 | 
			
		||||
     * otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Boolean> RubyNamedPropertyDeleter(Local<String> property, const AccessorInfo& info) {
 | 
			
		||||
      VALUE deleter = accessor_info_data(info)->deleter;
 | 
			
		||||
      VALUE result = rb_funcall(deleter, rb_intern("call"), 2, rr_v82rb(property), accessor_info_rb(info));
 | 
			
		||||
      Handle<Value> intercepts = rr_rb2v8(result);
 | 
			
		||||
      return intercepts.IsEmpty() ? Handle<Boolean>() : intercepts->ToBoolean();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns an array containing the names of the properties the named
 | 
			
		||||
     * property getter intercepts.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Array> RubyNamedPropertyEnumerator(const AccessorInfo& info) {
 | 
			
		||||
      VALUE enumerator = accessor_info_data(info)->enumerator;
 | 
			
		||||
      VALUE result = rb_funcall(enumerator, rb_intern("call"), 1, accessor_info_rb(info));
 | 
			
		||||
      Handle<Value> v(rr_rb2v8(result));
 | 
			
		||||
      if (v.IsEmpty()) {
 | 
			
		||||
        return Array::New();
 | 
			
		||||
      } else if (!v->IsArray()) {
 | 
			
		||||
        Local<Array> a = Array::New();
 | 
			
		||||
        a->Set(Integer::New(0), v->ToString());
 | 
			
		||||
        return a;
 | 
			
		||||
      } else {
 | 
			
		||||
        return (Handle<Array>)Array::Cast(*v);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the value of the property if the getter intercepts the
 | 
			
		||||
     * request.  Otherwise, returns an empty handle.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Value> RubyIndexedPropertyGetter(uint32_t index, const AccessorInfo& info) {
 | 
			
		||||
      VALUE getter = accessor_info_data(info)->getter;
 | 
			
		||||
      VALUE result = rb_funcall(getter, rb_intern("call"), 2, UINT2NUM(index), accessor_info_rb(info));
 | 
			
		||||
      return rr_rb2v8(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the value if the setter intercepts the request.
 | 
			
		||||
     * Otherwise, returns an empty handle.
 | 
			
		||||
     */
 | 
			
		||||
    Handle<Value> RubyIndexedPropertySetter(uint32_t index, Local<Value> value, const AccessorInfo& info) {
 | 
			
		||||
      VALUE setter = accessor_info_data(info)->setter;
 | 
			
		||||
      VALUE result = rb_funcall(setter, rb_intern("call"), 3, UINT2NUM(index), rr_v82rb(value), accessor_info_rb(info));
 | 
			
		||||
      return rr_rb2v8(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a non-empty handle if the interceptor intercepts the request.
 | 
			
		||||
     * The result is true if the property exists and false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
     Handle<Integer> RubyIndexedPropertyQuery(uint32_t index, const AccessorInfo& info) {
 | 
			
		||||
       VALUE query = accessor_info_data(info)->query;
 | 
			
		||||
       VALUE result = rb_funcall(query, rb_intern("call"), 2, UINT2NUM(index), accessor_info_rb(info));
 | 
			
		||||
       Handle<Value> intercepts = rr_rb2v8(result);
 | 
			
		||||
       return intercepts.IsEmpty() ? Handle<Integer>() : Integer::New(None);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a non-empty handle if the deleter intercepts the request.
 | 
			
		||||
     * The return value is true if the property could be deleted and false
 | 
			
		||||
     * otherwise.
 | 
			
		||||
     */
 | 
			
		||||
     Handle<Boolean> RubyIndexedPropertyDeleter(uint32_t index, const AccessorInfo& info) {
 | 
			
		||||
       VALUE deleter = accessor_info_data(info)->deleter;
 | 
			
		||||
       VALUE result = rb_funcall(deleter, rb_intern("call"), 2, UINT2NUM(index), accessor_info_rb(info));
 | 
			
		||||
       Handle<Value> intercepts = rr_rb2v8(result);
 | 
			
		||||
       return intercepts.IsEmpty() ? Handle<Boolean>() : intercepts->ToBoolean();
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns an array containing the indices of the properties the
 | 
			
		||||
     * indexed property getter intercepts.
 | 
			
		||||
     */
 | 
			
		||||
     Handle<Array> RubyIndexedPropertyEnumerator(const AccessorInfo& info) {
 | 
			
		||||
       VALUE enumerator = accessor_info_data(info)->enumerator;
 | 
			
		||||
       VALUE result = rb_funcall(enumerator, rb_intern("call"), 1, accessor_info_rb(info));
 | 
			
		||||
       Handle<Value> v(rr_rb2v8(result));
 | 
			
		||||
       if (v.IsEmpty()) {
 | 
			
		||||
         return Array::New();
 | 
			
		||||
       } else if (!v->IsArray()) {
 | 
			
		||||
         Local<Array> a = Array::New();
 | 
			
		||||
         a->Set(Integer::New(0), v->ToString());
 | 
			
		||||
         return a;
 | 
			
		||||
       } else {
 | 
			
		||||
         return (Handle<Array>)Array::Cast(*v);
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
    VALUE New(VALUE rbclass) {
 | 
			
		||||
      HandleScope handles;
 | 
			
		||||
      return rr_v8_handle_new(rbclass, ObjectTemplate::New());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE NewInstance(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      if (!Context::InContext()) {
 | 
			
		||||
        rb_raise(rb_eScriptError, "ObjectTemplate::NewInstance() called without an entered Context");
 | 
			
		||||
        return Qnil;
 | 
			
		||||
      }
 | 
			
		||||
      Local<Object> object(obj(self)->NewInstance());
 | 
			
		||||
      if (object.IsEmpty()) {
 | 
			
		||||
        rb_raise(rb_eFatal, "V8 returned empty handle on call to ObjectTemplate::NewInstance()");
 | 
			
		||||
        return Qnil;
 | 
			
		||||
      }
 | 
			
		||||
      return rr_v82rb(object);
 | 
			
		||||
    }
 | 
			
		||||
    VALUE SetNamedPropertyHandler(VALUE self, VALUE getter, VALUE setter, VALUE query, VALUE deleter, VALUE enumerator, VALUE data) {
 | 
			
		||||
      HandleScope handles;
 | 
			
		||||
      if (!RTEST(getter)) {
 | 
			
		||||
        rb_raise(rb_eArgError, "you must supply at least a getter to V8::C::ObjectTemplate#SetNamedPropertyHandler()");
 | 
			
		||||
        return Qnil;
 | 
			
		||||
      }
 | 
			
		||||
      obj(self)->SetNamedPropertyHandler(
 | 
			
		||||
        RubyNamedPropertyGetter,
 | 
			
		||||
        RTEST(setter) ? RubyNamedPropertySetter : 0,
 | 
			
		||||
        RTEST(query) ? RubyNamedPropertyQuery : 0,
 | 
			
		||||
        RTEST(deleter) ? RubyNamedPropertyDeleter : 0,
 | 
			
		||||
        RTEST(enumerator) ? RubyNamedPropertyEnumerator : 0,
 | 
			
		||||
        accessor_info_data(getter, setter, query, deleter, enumerator, data)
 | 
			
		||||
      );
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VALUE SetIndexedPropertyHandler(VALUE self, VALUE getter, VALUE setter, VALUE query, VALUE deleter, VALUE enumerator, VALUE data) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      if (!RTEST(getter)) {
 | 
			
		||||
        rb_raise(rb_eArgError, "you must supply at least a getter to V8::C::ObjectTemplate#SetNamedPropertyHandler()");
 | 
			
		||||
        return Qnil;
 | 
			
		||||
      }
 | 
			
		||||
      obj(self)->SetIndexedPropertyHandler(
 | 
			
		||||
        RubyIndexedPropertyGetter,
 | 
			
		||||
        RTEST(setter) ? RubyIndexedPropertySetter : 0,
 | 
			
		||||
        RTEST(query) ? RubyIndexedPropertyQuery : 0,
 | 
			
		||||
        RTEST(deleter) ? RubyIndexedPropertyDeleter : 0,
 | 
			
		||||
        RTEST(enumerator) ? RubyIndexedPropertyEnumerator : 0,
 | 
			
		||||
        accessor_info_data(getter, setter, query, deleter, enumerator, data)
 | 
			
		||||
      );
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE SetCallAsFunctionHandler(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
      Handle<Value> v8_data = make_v8_data(argc, argv, "11");
 | 
			
		||||
      obj(self)->SetCallAsFunctionHandler(RubyInvocationCallback, v8_data);
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  namespace Func {
 | 
			
		||||
 | 
			
		||||
    VALUE New(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
      HandleScope h;
 | 
			
		||||
      Handle<External> v8_data = make_v8_data(argc, argv, "02");
 | 
			
		||||
      Local<FunctionTemplate> t = FunctionTemplate::New(RubyInvocationCallback, v8_data);
 | 
			
		||||
      VALUE handle = rr_v8_handle_new(self,t);
 | 
			
		||||
      return handle;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE SetCallHandler(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
      HandleScope h;
 | 
			
		||||
      Handle<Value> v8_data = make_v8_data(argc, argv, "11");
 | 
			
		||||
      func(self)->SetCallHandler(RubyInvocationCallback, v8_data);
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE PrototypeTemplate(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v8_handle_new(ObjectTemplateClass, func(self)->PrototypeTemplate());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE InstanceTemplate(VALUE self) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      return rr_v8_handle_new(ObjectTemplateClass, func(self)->InstanceTemplate());
 | 
			
		||||
    }
 | 
			
		||||
    VALUE Inherit(VALUE self, VALUE function_template) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      func(self)->Inherit(func(function_template));
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE SetClassName(VALUE self, VALUE name) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      func(self)->SetClassName(rr_rb2v8(name)->ToString());
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    VALUE GetFunction(VALUE self) {
 | 
			
		||||
      HandleScope handles;
 | 
			
		||||
      if (!Context::InContext()) {
 | 
			
		||||
        rb_raise(rb_eScriptError, "calls to FunctionTemplate::GetFunction() require a Context to be entered");
 | 
			
		||||
        return Qnil;
 | 
			
		||||
      }
 | 
			
		||||
      return rr_v82rb(func(self)->GetFunction());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_template() {
 | 
			
		||||
  VALUE Template = rr_define_class("Template", rr_v8_handle_class());
 | 
			
		||||
  rr_define_method(Template, "Set", Set, 2);
 | 
			
		||||
 | 
			
		||||
  ObjectTemplateClass = rr_define_class("ObjectTemplate", Template);
 | 
			
		||||
  rr_define_singleton_method(ObjectTemplateClass, "New", Obj::New, 0);
 | 
			
		||||
  rr_define_method(ObjectTemplateClass, "NewInstance", Obj::NewInstance, 0);
 | 
			
		||||
  rr_define_method(ObjectTemplateClass, "SetNamedPropertyHandler", Obj::SetNamedPropertyHandler, 6);
 | 
			
		||||
  rr_define_method(ObjectTemplateClass, "SetIndexedPropertyHandler", Obj::SetIndexedPropertyHandler, 6);
 | 
			
		||||
  rr_define_method(ObjectTemplateClass, "SetCallAsFunctionHandler", Obj::SetCallAsFunctionHandler, -1);
 | 
			
		||||
 | 
			
		||||
  FunctionTemplateClass = rr_define_class("FunctionTemplate", Template);
 | 
			
		||||
  rr_define_singleton_method(FunctionTemplateClass, "New", Func::New, -1);
 | 
			
		||||
  rr_define_method(FunctionTemplateClass, "SetCallHandler", Func::SetCallHandler, -1);
 | 
			
		||||
  rr_define_method(FunctionTemplateClass, "PrototypeTemplate", Func::PrototypeTemplate, 0);
 | 
			
		||||
  rr_define_method(FunctionTemplateClass, "InstanceTemplate", Func::InstanceTemplate, 0);
 | 
			
		||||
  rr_define_method(FunctionTemplateClass, "Inherit", Func::Inherit, 1);
 | 
			
		||||
  rr_define_method(FunctionTemplateClass, "SetClassName", Func::SetClassName, 1);
 | 
			
		||||
  rr_define_method(FunctionTemplateClass, "GetFunction", Func::GetFunction, 0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
#ifndef _RUBY_V8_TEMPLATE_
 | 
			
		||||
#define _RUBY_V8_TEMPLATE_ 
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_template();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,70 +0,0 @@
 | 
			
		|||
#include "rr.h"
 | 
			
		||||
#include "v8_try_catch.h"
 | 
			
		||||
#include "v8_message.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  VALUE TryCatchClass;
 | 
			
		||||
 | 
			
		||||
  TryCatch *unwrap(VALUE self) {
 | 
			
		||||
    TryCatch *tc = 0;
 | 
			
		||||
    Data_Get_Struct(self, class TryCatch, tc);
 | 
			
		||||
    if (RTEST(rb_iv_get(self, "dead"))) {
 | 
			
		||||
      rb_raise(rb_eScriptError, "out of scope access of %s", RSTRING_PTR(rb_inspect(self)));
 | 
			
		||||
      return false;
 | 
			
		||||
    } else {
 | 
			
		||||
      return tc;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE Try(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
    if (rb_block_given_p()) {
 | 
			
		||||
      HandleScope scope;
 | 
			
		||||
      TryCatch tc;
 | 
			
		||||
      VALUE try_catch = Data_Wrap_Struct(TryCatchClass, 0, 0, &tc);
 | 
			
		||||
      rb_iv_set(try_catch, "dead", Qfalse);
 | 
			
		||||
      VALUE result = rb_yield(try_catch);
 | 
			
		||||
      rb_iv_set(try_catch, "dead", Qtrue);
 | 
			
		||||
      tc.Reset();
 | 
			
		||||
      return result;
 | 
			
		||||
    } else {
 | 
			
		||||
      return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE HasCaught(VALUE self) {
 | 
			
		||||
    TryCatch *tc = unwrap(self);
 | 
			
		||||
    return tc ? rr_v82rb(tc->HasCaught()) : Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE _Exception(VALUE self) {
 | 
			
		||||
    TryCatch *tc = unwrap(self);
 | 
			
		||||
    return tc ? rr_v82rb(tc->Exception()) : Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE _StackTrace(VALUE self) {
 | 
			
		||||
    TryCatch *tc = unwrap(self);
 | 
			
		||||
    return tc ? rr_v82rb(tc->StackTrace()) : Qnil;
 | 
			
		||||
  }    
 | 
			
		||||
  
 | 
			
		||||
  VALUE _Message(VALUE self) {
 | 
			
		||||
    TryCatch *tc = unwrap(self);
 | 
			
		||||
    return tc ? rr_v82rb(tc->Message()) : Qnil;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  VALUE CanContinue(VALUE self) {
 | 
			
		||||
    TryCatch *tc = unwrap(self);
 | 
			
		||||
    return tc ? rr_v82rb(tc->CanContinue()) : Qnil;    
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_try_catch() {
 | 
			
		||||
  TryCatchClass = rr_define_class("TryCatch");
 | 
			
		||||
  rr_define_singleton_method(TryCatchClass, "try", Try, -1);
 | 
			
		||||
  rr_define_method(TryCatchClass, "HasCaught", HasCaught, 0);
 | 
			
		||||
  rr_define_method(TryCatchClass, "Exception", _Exception, 0);
 | 
			
		||||
  rr_define_method(TryCatchClass, "StackTrace", _StackTrace, 0);
 | 
			
		||||
  rr_define_method(TryCatchClass, "Message", _Message, 0);
 | 
			
		||||
  rr_define_method(TryCatchClass, "CanContinue", CanContinue, 0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_TRY_CATCH_
 | 
			
		||||
#define _RR_V8_TRY_CATCH_
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_try_catch();
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,35 +0,0 @@
 | 
			
		|||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE IsDead(VALUE self) {
 | 
			
		||||
    return rr_v82rb(V8::IsDead());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE AdjustAmountOfExternalAllocatedMemory(VALUE self, VALUE bytes) {
 | 
			
		||||
    V8::AdjustAmountOfExternalAllocatedMemory(NUM2INT(bytes));
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
   VALUE IdleNotification(VALUE self) {
 | 
			
		||||
     return rr_v82rb(V8::IdleNotification());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  VALUE SetFlagsFromString(VALUE self, VALUE string) {
 | 
			
		||||
    V8::SetFlagsFromString(RSTRING_PTR(string), RSTRING_LEN(string));
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_v8() {
 | 
			
		||||
  VALUE V8Module = rr_define_module("V8");
 | 
			
		||||
  rr_define_singleton_method(V8Module, "IsDead", IsDead, 0);
 | 
			
		||||
  rr_define_singleton_method(V8Module, "AdjustAmountOfExternalAllocatedMemory", AdjustAmountOfExternalAllocatedMemory, 1);
 | 
			
		||||
  rr_define_singleton_method(V8Module, "IdleNotification", IdleNotification, 0);
 | 
			
		||||
  rr_define_singleton_method(V8Module, "SetFlagsFromString", SetFlagsFromString, 1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_V8_
 | 
			
		||||
#define _RR_V8_V8_
 | 
			
		||||
 | 
			
		||||
void rr_init_v8_v8();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,175 +0,0 @@
 | 
			
		|||
#include "v8_handle.h"
 | 
			
		||||
#include "v8_value.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
  VALUE ValueClass;
 | 
			
		||||
 | 
			
		||||
  Persistent<Value>& unwrap(VALUE value) {
 | 
			
		||||
    return rr_v8_handle<Value>(value);
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsEmpty(VALUE value) {
 | 
			
		||||
    return value == rr_v8_value_empty() ? Qtrue : Qfalse;
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsUndefined(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsUndefined());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsNull(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsNull());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsTrue(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsTrue());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsFalse(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsFalse());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsString(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsString());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsFunction(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsFunction());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsArray(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsArray());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsObject(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsObject());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsBoolean(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsBoolean());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsNumber(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsNumber());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsExternal(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsExternal());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsInt32(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsInt32());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsUint32(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsUint32());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE IsDate(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->IsDate());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE ToBoolean(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToBoolean());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToNumber(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToNumber());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToString(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToString());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToDetailString(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToDetailString());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToObject(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToObject());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToInteger(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToInteger());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToUint32(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToUint32());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToInt32(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToInt32());
 | 
			
		||||
  }
 | 
			
		||||
  VALUE ToArrayIndex(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->ToArrayIndex());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE Equals(VALUE self, VALUE that) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->Equals(unwrap(that)));
 | 
			
		||||
  }
 | 
			
		||||
  VALUE StrictEquals(VALUE self, VALUE that) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->StrictEquals(unwrap(that)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE BooleanValue(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->BooleanValue());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VALUE NumberValue(VALUE self) {
 | 
			
		||||
    HandleScope scope;
 | 
			
		||||
    return rr_v82rb(unwrap(self)->NumberValue());
 | 
			
		||||
  }  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v8_value_class() {
 | 
			
		||||
  return ValueClass;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_v8_value_empty() {
 | 
			
		||||
  return rr_const_get("Empty");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rr_init_value() {
 | 
			
		||||
  ValueClass = rr_define_class("Value", rr_v8_handle_class());
 | 
			
		||||
  rr_define_const("Empty", rr_v8_handle_new(ValueClass, Handle<Value>()));
 | 
			
		||||
 | 
			
		||||
  rr_define_method(ValueClass, "IsEmpty", IsEmpty, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsUndefined", IsUndefined, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsNull", IsNull, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsTrue", IsTrue, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsFalse", IsFalse, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsString", IsString, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsFunction", IsFunction, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsArray", IsArray, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsObject", IsObject, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsBoolean", IsBoolean, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsNumber", IsNumber, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsExternal", IsExternal, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsInt32", IsInt32, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsUint32", IsUint32, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "IsDate", IsDate, 0);
 | 
			
		||||
 | 
			
		||||
  rr_define_method(ValueClass, "ToBoolean", ToBoolean, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToNumber", ToNumber, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToString", ToString, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToDetailString", ToDetailString, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToObject", ToObject, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToInteger", ToInteger, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToUint32", ToUint32, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "ToArrayIndex", ToArrayIndex, 0);
 | 
			
		||||
 | 
			
		||||
  rr_define_method(ValueClass, "Equals", Equals, 1);
 | 
			
		||||
  rr_define_method(ValueClass, "StrictEquals", StrictEquals, 1);
 | 
			
		||||
 | 
			
		||||
  rr_define_method(ValueClass, "BooleanValue", BooleanValue, 0);
 | 
			
		||||
  rr_define_method(ValueClass, "NumberValue", NumberValue, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE rr_wrap_v8_value(Handle<Value>& value) {
 | 
			
		||||
  return rr_v8_handle_new(ValueClass, value);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_VALUE_
 | 
			
		||||
#define _RR_V8_VALUE_ 
 | 
			
		||||
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
void rr_init_value();
 | 
			
		||||
VALUE rr_wrap_v8_value(v8::Handle<v8::Value>& value);
 | 
			
		||||
VALUE rr_v8_value_class();
 | 
			
		||||
VALUE rr_v8_value_empty();
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,61 +0,0 @@
 | 
			
		|||
#include "v8.h"
 | 
			
		||||
#include "v8_weakref.h"
 | 
			
		||||
 | 
			
		||||
using namespace v8;
 | 
			
		||||
 | 
			
		||||
v8_weakref::v8_weakref(VALUE object) {
 | 
			
		||||
  this->v8_active = true;
 | 
			
		||||
  this->rb_active = true;
 | 
			
		||||
  this->external = Persistent<External>::New(External::New((void *)this));
 | 
			
		||||
  this->external.MakeWeak(this, v8_weakref_dispose);
 | 
			
		||||
  this->set(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void v8_weakref::set(VALUE value) {
 | 
			
		||||
  this->object_id = rb_obj_id(value);
 | 
			
		||||
  this->rb_active = true;
 | 
			
		||||
  VALUE data = Data_Wrap_Struct(rb_cObject, 0, 0, this);
 | 
			
		||||
  rr_define_finalizer(value,(void*)v8_weakref_finalize, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE v8_weakref::get() {
 | 
			
		||||
  if (this->object_id) {
 | 
			
		||||
    return rb_rescue((VALUE (*)(...))v8_weakref_id2ref, this->object_id, (VALUE (*)(...))v8_weakref_nil, Qnil);
 | 
			
		||||
  } else {
 | 
			
		||||
    return Qnil;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE v8_weakref_finalize(VALUE object_id, VALUE data) {
 | 
			
		||||
  v8_weakref* weakref = 0;
 | 
			
		||||
  Data_Get_Struct(data, struct v8_weakref, weakref);
 | 
			
		||||
  weakref->object_id = Qnil;
 | 
			
		||||
  weakref->rb_active = false;
 | 
			
		||||
  if (!weakref->v8_active) {
 | 
			
		||||
    delete weakref;
 | 
			
		||||
  }
 | 
			
		||||
  return Qnil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void v8_weakref_dispose(Persistent<Value> value, void* data) {
 | 
			
		||||
  value.Dispose();
 | 
			
		||||
  value.Clear();
 | 
			
		||||
  v8_weakref* weakref = (v8_weakref*)data;
 | 
			
		||||
  weakref->v8_active = false;
 | 
			
		||||
  if (!weakref->rb_active) {
 | 
			
		||||
    delete weakref;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE v8_weakref_nil(VALUE nil, VALUE exception) {
 | 
			
		||||
  return nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE v8_weakref_objectspace() {
 | 
			
		||||
  return rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE v8_weakref_id2ref(VALUE id) {
 | 
			
		||||
  return rb_funcall(v8_weakref_objectspace(), rb_intern("_id2ref"), 1, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,29 +0,0 @@
 | 
			
		|||
#ifndef _RR_V8_WEAKREF_
 | 
			
		||||
#define _RR_V8_WEAKREF_ 
 | 
			
		||||
 | 
			
		||||
#include <v8.h>
 | 
			
		||||
#include "ruby.h"
 | 
			
		||||
#include "rr.h"
 | 
			
		||||
 | 
			
		||||
struct v8_weakref  {
 | 
			
		||||
  v8_weakref(VALUE object);
 | 
			
		||||
  VALUE get();
 | 
			
		||||
  void set(VALUE object);
 | 
			
		||||
  void retain();
 | 
			
		||||
  void release();
 | 
			
		||||
 | 
			
		||||
  VALUE object_id;
 | 
			
		||||
  bool v8_active;
 | 
			
		||||
  bool rb_active;
 | 
			
		||||
  v8::Persistent<v8::External> external;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void  v8_weakref_dispose(v8::Persistent<v8::Value> value, void* weakref);
 | 
			
		||||
VALUE v8_weakref_finalize(VALUE self, VALUE object_id);
 | 
			
		||||
VALUE v8_weakref_objectspace();
 | 
			
		||||
VALUE v8_weakref_nil(VALUE nil, VALUE exception);
 | 
			
		||||
VALUE v8_weakref_id2ref(VALUE id);
 | 
			
		||||
 | 
			
		||||
// extern "C" VALUE rb_proc_new(VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										23
									
								
								lib/v8.rb
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								lib/v8.rb
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,23 +0,0 @@
 | 
			
		|||
$:.unshift(File.dirname(__FILE__)) unless
 | 
			
		||||
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
 | 
			
		||||
 | 
			
		||||
module V8
 | 
			
		||||
  require 'v8/version'
 | 
			
		||||
  require 'v8/v8' #native glue
 | 
			
		||||
  require 'v8/c/locker'
 | 
			
		||||
  require 'v8/portal'
 | 
			
		||||
  require 'v8/portal/caller'
 | 
			
		||||
  require 'v8/portal/proxies'
 | 
			
		||||
  require 'v8/portal/templates'
 | 
			
		||||
  require 'v8/portal/function'
 | 
			
		||||
  require 'v8/portal/constructor'
 | 
			
		||||
  require 'v8/portal/interceptors'
 | 
			
		||||
  require 'v8/context'
 | 
			
		||||
  require 'v8/object'
 | 
			
		||||
  require 'v8/array'
 | 
			
		||||
  require 'v8/function'
 | 
			
		||||
  require 'v8/tap'
 | 
			
		||||
  require 'v8/access'
 | 
			
		||||
  require 'v8/error'
 | 
			
		||||
  require 'v8/stack'
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,92 +0,0 @@
 | 
			
		|||
require 'set'
 | 
			
		||||
module V8
 | 
			
		||||
  class Access
 | 
			
		||||
    def get(obj, name, &dontintercept)
 | 
			
		||||
      methods = accessible_methods(obj)
 | 
			
		||||
      if methods.include?(name)
 | 
			
		||||
        method = obj.method(name)
 | 
			
		||||
        method.arity == 0 ? method.call : method.unbind
 | 
			
		||||
      elsif obj.respond_to?(:[]) && !special?(name)
 | 
			
		||||
        obj.send(:[], name, &dontintercept)
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def iget(obj, index, &dontintercept)
 | 
			
		||||
      if obj.respond_to?(:[])
 | 
			
		||||
        obj.send(:[], index, &dontintercept)
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def set(obj, name, value, &dontintercept)
 | 
			
		||||
      setter = name + "="
 | 
			
		||||
      methods = accessible_methods(obj, true)
 | 
			
		||||
      if methods.include?(setter)
 | 
			
		||||
        obj.send(setter, value)
 | 
			
		||||
      elsif obj.respond_to?(:[]=) && !special?(name)
 | 
			
		||||
        obj.send(:[]=, name, value, &dontintercept)
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def iset(obj, index, value, &dontintercept)
 | 
			
		||||
      if obj.respond_to?(:[]=)
 | 
			
		||||
        obj.send(:[]=, index, value, &dontintercept)
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def query(obj, name, attributes)
 | 
			
		||||
      if obj.respond_to?(name)
 | 
			
		||||
        attributes.dont_delete
 | 
			
		||||
        unless obj.respond_to?(name + "=")
 | 
			
		||||
          attributes.read_only
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def iquery(obj, index, attributes)
 | 
			
		||||
      if obj.respond_to?(:[])
 | 
			
		||||
        attributes.dont_delete
 | 
			
		||||
        unless obj.respond_to?(:[]=)
 | 
			
		||||
          attributes.read_only
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def names(obj)
 | 
			
		||||
      accessible_methods(obj)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def indices(obj)
 | 
			
		||||
      obj.respond_to?(:length) ? (0..obj.length).to_a : yield
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def accessible_methods(obj, special_methods = false)
 | 
			
		||||
      obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods|
 | 
			
		||||
        ancestors = obj.class.ancestors.dup
 | 
			
		||||
        while ancestor = ancestors.shift
 | 
			
		||||
          break if ancestor == ::Object
 | 
			
		||||
          methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
 | 
			
		||||
        end
 | 
			
		||||
        methods.reject!(&special?) unless special_methods
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def special?(name = nil)
 | 
			
		||||
      @special ||= lambda {|m| m == "[]" || m == "[]=" || m =~ /=$/}
 | 
			
		||||
      name.nil? ? @special : @special[name]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class Array < V8::Object
 | 
			
		||||
    
 | 
			
		||||
    def each
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        for i in 0..(@native.Length() - 1)
 | 
			
		||||
          yield to.rb(@native.Get(i))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def length
 | 
			
		||||
      @native.Length()
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
module V8
 | 
			
		||||
  module C
 | 
			
		||||
    # Shim to support the old style locking syntax. We don't currently
 | 
			
		||||
    # deprecate this because it might make a comeback at some point.
 | 
			
		||||
    #
 | 
			
		||||
    # to synchronize access to V8, and to associate V8 with this thread:
 | 
			
		||||
    #
 | 
			
		||||
    #     Locker() do
 | 
			
		||||
    #       #... interact with v8
 | 
			
		||||
    #     end
 | 
			
		||||
    def self.Locker
 | 
			
		||||
      lock = Locker.new
 | 
			
		||||
      yield
 | 
			
		||||
    ensure
 | 
			
		||||
      lock.delete
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										133
									
								
								lib/v8/cli.rb
									
										
									
									
									
								
							
							
						
						
									
										133
									
								
								lib/v8/cli.rb
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,133 +0,0 @@
 | 
			
		|||
require 'optparse'
 | 
			
		||||
require 'ostruct'
 | 
			
		||||
 | 
			
		||||
module V8
 | 
			
		||||
  module CLI
 | 
			
		||||
    def self.run(exename = 'v8', args = [])
 | 
			
		||||
      options = OpenStruct.new
 | 
			
		||||
      options.libs = []
 | 
			
		||||
      options.libdirs = []
 | 
			
		||||
      parser = OptionParser.new
 | 
			
		||||
      parser.banner = "Usage: #{exename} [options]"
 | 
			
		||||
      parser.on("-r", "--require FILE", "load and execute FILE as JavaScript source") {|r| options.libs << r}
 | 
			
		||||
      parser.on("-i", "--interactive", "interactive mode") {options.interactive = true}
 | 
			
		||||
      parser.on("-e", "--execute JAVASCRIPT", String, "evaluate JAVASCRIPT and exit") {|src| options.execute = src}
 | 
			
		||||
      parser.on("--selftest", "check that therubyracer is functioning properly") {options.selftest = true}
 | 
			
		||||
      parser.on_tail("-v", "--version", "Show version and exit") {options.version_info = true}
 | 
			
		||||
      parser.on_tail("-h", "--help", "Show this message") do
 | 
			
		||||
        puts parser
 | 
			
		||||
        exit
 | 
			
		||||
      end
 | 
			
		||||
      begin
 | 
			
		||||
        parser.parse!(args.dup)
 | 
			
		||||
      rescue OptionParser::InvalidOption => e
 | 
			
		||||
        puts "#{exename}: #{e.message}"
 | 
			
		||||
        exit(1)
 | 
			
		||||
      end
 | 
			
		||||
      if options.version_info
 | 
			
		||||
        require 'libv8'
 | 
			
		||||
        puts "The Ruby Racer #{V8::VERSION}"
 | 
			
		||||
        puts "V8 Version #{Libv8::V8_VERSION}"
 | 
			
		||||
        exit
 | 
			
		||||
      elsif options.selftest
 | 
			
		||||
        self.test
 | 
			
		||||
      end
 | 
			
		||||
      Context.new(:with => Shell.new) do |cxt|
 | 
			
		||||
        for libfile in options.libs do
 | 
			
		||||
          load(cxt,libfile)
 | 
			
		||||
        end
 | 
			
		||||
        if options.interactive
 | 
			
		||||
          repl(cxt, exename)
 | 
			
		||||
        elsif options.execute
 | 
			
		||||
          cxt.eval(options.execute, '<execute>')
 | 
			
		||||
        else
 | 
			
		||||
          begin
 | 
			
		||||
            cxt.eval($stdin, '<stdin>')
 | 
			
		||||
          rescue Interrupt => e
 | 
			
		||||
            puts; exit
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.load(cxt, libfile)
 | 
			
		||||
      begin
 | 
			
		||||
        cxt.load(libfile)
 | 
			
		||||
      rescue V8::JSError => e
 | 
			
		||||
        puts e.message
 | 
			
		||||
        puts e.backtrace(:javascript)
 | 
			
		||||
      rescue StandardError => e
 | 
			
		||||
        puts e
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.test
 | 
			
		||||
      begin
 | 
			
		||||
        require 'rspec'
 | 
			
		||||
        specs = File.expand_path('../../../spec', __FILE__)
 | 
			
		||||
        $:.unshift specs
 | 
			
		||||
        ARGV.clear
 | 
			
		||||
        ARGV << specs
 | 
			
		||||
        ::RSpec::Core::Runner.autorun
 | 
			
		||||
        exit(0)
 | 
			
		||||
      rescue LoadError => e
 | 
			
		||||
        puts "selftest requires rspec to be installed (gem install rspec)"
 | 
			
		||||
        exit(1)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.repl(cxt, exename)
 | 
			
		||||
      require 'readline'
 | 
			
		||||
      puts "help() for help. quit() to quit."
 | 
			
		||||
      puts "The Ruby Racer #{V8::VERSION}"
 | 
			
		||||
      puts "Vroom Vroom!"
 | 
			
		||||
      trap("SIGINT") do
 | 
			
		||||
        puts "^C"
 | 
			
		||||
      end
 | 
			
		||||
      loop do
 | 
			
		||||
        line = Readline.readline("#{exename}> ", true)
 | 
			
		||||
        begin
 | 
			
		||||
          result = cxt.eval(line, '<shell>')
 | 
			
		||||
          puts(result) unless result.nil?
 | 
			
		||||
        rescue V8::JSError => e
 | 
			
		||||
          puts e.message
 | 
			
		||||
          puts e.backtrace(:javascript)
 | 
			
		||||
        rescue StandardError => e
 | 
			
		||||
          puts e
 | 
			
		||||
          puts e.backtrace.join("\n")
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class Shell
 | 
			
		||||
      def to_s
 | 
			
		||||
        "[object Shell]"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def print(string)
 | 
			
		||||
        puts string
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def exit(status = 0)
 | 
			
		||||
        Kernel.exit(status)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      alias_method :quit, :exit
 | 
			
		||||
 | 
			
		||||
      def help(*args)
 | 
			
		||||
        <<-HELP
 | 
			
		||||
    print(msg)
 | 
			
		||||
      print msg to STDOUT
 | 
			
		||||
 | 
			
		||||
    exit(status = 0)
 | 
			
		||||
      exit the shell
 | 
			
		||||
      also: quit()
 | 
			
		||||
 | 
			
		||||
    evalrb(source)
 | 
			
		||||
      evaluate some ruby source
 | 
			
		||||
    HELP
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,111 +0,0 @@
 | 
			
		|||
require 'stringio'
 | 
			
		||||
 | 
			
		||||
module V8
 | 
			
		||||
  class Context
 | 
			
		||||
    attr_reader :native, :scope, :access
 | 
			
		||||
 | 
			
		||||
    def initialize(opts = {})
 | 
			
		||||
      @access = Access.new
 | 
			
		||||
      @to = Portal.new(self, @access)
 | 
			
		||||
      @to.lock do
 | 
			
		||||
        with = opts[:with]
 | 
			
		||||
        constructor = nil
 | 
			
		||||
        template = if with
 | 
			
		||||
          constructor = @to.templates.to_constructor(with.class)
 | 
			
		||||
          constructor.disable()
 | 
			
		||||
          constructor.template.InstanceTemplate()
 | 
			
		||||
        else
 | 
			
		||||
          C::ObjectTemplate::New()
 | 
			
		||||
        end
 | 
			
		||||
        @native = opts[:with] ? C::Context::New(template) : C::Context::New()
 | 
			
		||||
        @native.enter do
 | 
			
		||||
          @global = @native.Global()
 | 
			
		||||
          @to.proxies.register_javascript_proxy @global, :for => with if with
 | 
			
		||||
          constructor.enable() if constructor
 | 
			
		||||
          @scope = @to.rb(@global)
 | 
			
		||||
          @global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
 | 
			
		||||
        end
 | 
			
		||||
        yield(self) if block_given?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def eval(javascript, filename = "<eval>", line = 1)
 | 
			
		||||
      if IO === javascript || StringIO === javascript
 | 
			
		||||
        javascript = javascript.read()
 | 
			
		||||
      end
 | 
			
		||||
      err = nil
 | 
			
		||||
      value = nil
 | 
			
		||||
      @to.lock do
 | 
			
		||||
        C::TryCatch.try do |try|
 | 
			
		||||
          @native.enter do
 | 
			
		||||
            script = C::Script::Compile(@to.v8(javascript.to_s), @to.v8(filename.to_s))
 | 
			
		||||
            if try.HasCaught()
 | 
			
		||||
              err = JSError.new(try, @to)
 | 
			
		||||
            else
 | 
			
		||||
              result = script.Run()
 | 
			
		||||
              if try.HasCaught()
 | 
			
		||||
                err = JSError.new(try, @to)
 | 
			
		||||
              else
 | 
			
		||||
                value = @to.rb(result)
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      raise err if err
 | 
			
		||||
      return value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def load(filename)
 | 
			
		||||
      File.open(filename) do |file|
 | 
			
		||||
        self.eval file, filename, 1
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [](key)
 | 
			
		||||
      @to.open do
 | 
			
		||||
        @to.rb @global.Get(@to.v8(key))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def []=(key, value)
 | 
			
		||||
      @to.open do
 | 
			
		||||
        @global.Set(@to.v8(key), @to.v8(value))
 | 
			
		||||
      end
 | 
			
		||||
      return value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.stack(limit = 99)
 | 
			
		||||
      if native = C::Context::GetEntered()
 | 
			
		||||
        global = native.Global()
 | 
			
		||||
        cxt = global.GetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext")).Value()
 | 
			
		||||
        cxt.instance_eval {@to.rb(C::StackTrace::CurrentStackTrace(limit))}
 | 
			
		||||
      else
 | 
			
		||||
        []
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    def self.passes_this_argument?
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  module C
 | 
			
		||||
    class Context
 | 
			
		||||
      def enter
 | 
			
		||||
        if block_given?
 | 
			
		||||
          if IsEntered()
 | 
			
		||||
            yield(self)
 | 
			
		||||
          else
 | 
			
		||||
            Enter()
 | 
			
		||||
            begin
 | 
			
		||||
              yield(self)
 | 
			
		||||
            ensure
 | 
			
		||||
              Exit()
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										130
									
								
								lib/v8/error.rb
									
										
									
									
									
								
							
							
						
						
									
										130
									
								
								lib/v8/error.rb
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,130 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class JSError < StandardError
 | 
			
		||||
    attr_reader :value, :boundaries
 | 
			
		||||
 | 
			
		||||
    def initialize(try, to)
 | 
			
		||||
      @to = to
 | 
			
		||||
      super(initialize_unsafe(try))
 | 
			
		||||
    rescue Exception => e
 | 
			
		||||
      @boundaries = [Boundary.new(:rbframes => e.backtrace)]
 | 
			
		||||
      @value = e
 | 
			
		||||
      super(<<-EOMSG)
 | 
			
		||||
You have uncovered what is probably a BUG in therubyracer exception code. An error report would be very helpful.
 | 
			
		||||
JSError#initialize failed!: #{e.message}"
 | 
			
		||||
EOMSG
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_unsafe(try)
 | 
			
		||||
      message = nil
 | 
			
		||||
      ex = @to.rb(try.Exception())
 | 
			
		||||
      @boundaries = [Boundary.new(:rbframes => caller(3), :jsframes => parse_js_frames(try))]
 | 
			
		||||
      if V8::Object === ex
 | 
			
		||||
        if msg = ex['message']
 | 
			
		||||
          message = msg
 | 
			
		||||
        else
 | 
			
		||||
          message = ex.to_s
 | 
			
		||||
        end
 | 
			
		||||
        if cause = ex.instance_variable_get(:@native).GetHiddenValue("TheRubyRacer::Cause")
 | 
			
		||||
          if !cause.IsEmpty()
 | 
			
		||||
            prev = cause.Value()
 | 
			
		||||
            if prev.kind_of?(JSError)
 | 
			
		||||
              @boundaries.concat prev.boundaries
 | 
			
		||||
              @value = prev.value
 | 
			
		||||
            else
 | 
			
		||||
              @value = prev
 | 
			
		||||
              @boundaries.concat [Boundary.new(:rbframes => prev.backtrace)]
 | 
			
		||||
            end
 | 
			
		||||
          else
 | 
			
		||||
            @value = ex
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        @value = ex
 | 
			
		||||
        message = ex.to_s
 | 
			
		||||
      end
 | 
			
		||||
      return message
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def in_ruby?
 | 
			
		||||
      @value.kind_of?(Exception)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def in_javascript?
 | 
			
		||||
      !in_ruby?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def backtrace(*modifiers)
 | 
			
		||||
      trace_framework = modifiers.include?(:framework)
 | 
			
		||||
      trace_ruby = modifiers.length == 0 || modifiers.include?(:ruby)
 | 
			
		||||
      trace_javascript = modifiers.length == 0 || modifiers.include?(:javascript)
 | 
			
		||||
      mixed = []
 | 
			
		||||
      rbcontext = []
 | 
			
		||||
      jscontext = []
 | 
			
		||||
      @boundaries.each do |b|
 | 
			
		||||
        rbframes = b.rbframes.dup
 | 
			
		||||
        rbcontext.reverse_each do |frame|
 | 
			
		||||
          if frame == rbframes.last
 | 
			
		||||
            rbframes.pop
 | 
			
		||||
          else
 | 
			
		||||
            break
 | 
			
		||||
          end
 | 
			
		||||
        end if trace_ruby
 | 
			
		||||
        jsframes = b.jsframes.dup
 | 
			
		||||
        jscontext.reverse_each do |frame|
 | 
			
		||||
          if frame == jsframes.last
 | 
			
		||||
            jsframes.pop
 | 
			
		||||
          else
 | 
			
		||||
            break
 | 
			
		||||
          end
 | 
			
		||||
        end if trace_javascript
 | 
			
		||||
        rbcontext = b.rbframes
 | 
			
		||||
        jscontext = b.jsframes
 | 
			
		||||
        rbframes.reject! {|f| f =~ /lib\/v8\/.*\.rb/} unless trace_framework
 | 
			
		||||
        mixed.unshift(*rbframes) if trace_ruby
 | 
			
		||||
        mixed.unshift(*jsframes) if trace_javascript
 | 
			
		||||
      end
 | 
			
		||||
      return mixed
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def parse_js_frames(try)
 | 
			
		||||
      #I can't figure out why V8 is not capturing the stacktrace here
 | 
			
		||||
      #in terms of StackTrace and StackFrame objects, so we have to
 | 
			
		||||
      #parse the string.
 | 
			
		||||
      raw = @to.rb(try.StackTrace())
 | 
			
		||||
      if raw && !raw.empty? && !syntax_error?(try)
 | 
			
		||||
        raw.split("\n")[1..-1].tap do |frames|
 | 
			
		||||
          frames.each {|frame| frame.strip!; frame.chomp!(",")}
 | 
			
		||||
        end.reject(&:empty?)
 | 
			
		||||
      else
 | 
			
		||||
        msg = try.Message()
 | 
			
		||||
        ["at #{@to.rb(msg.GetScriptResourceName())}:#{msg.GetLineNumber()}:#{msg.GetStartColumn() + 1}"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #Syntax errors are weird in that they have a non-empty stack trace
 | 
			
		||||
    #but it does not contain any source location information, so
 | 
			
		||||
    #in these instances, we have to pull it out of the Message object
 | 
			
		||||
    #in the TryCatch. Is there a better way to detect a syntax error
 | 
			
		||||
    def syntax_error?(try)
 | 
			
		||||
      ex = @to.rb(try.Exception())
 | 
			
		||||
      if ex && ex.kind_of?(V8::Object)
 | 
			
		||||
        type = ex["constructor"]
 | 
			
		||||
        type && type.kind_of?(V8::Function) && type.name == "SyntaxError"
 | 
			
		||||
      else
 | 
			
		||||
        false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class Boundary
 | 
			
		||||
      attr_reader :rbframes, :jsframes
 | 
			
		||||
 | 
			
		||||
      def initialize(frames = {})
 | 
			
		||||
        @rbframes = frames[:rbframes] || []
 | 
			
		||||
        @jsframes = frames[:jsframes] || []
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #deprecated -- use JSError
 | 
			
		||||
  JavasriptError = JSError
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,44 +0,0 @@
 | 
			
		|||
module V8
 | 
			
		||||
  class Function < V8::Object
 | 
			
		||||
 | 
			
		||||
    def methodcall(thisObject, *args)
 | 
			
		||||
      err = nil
 | 
			
		||||
      return_value = nil
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        C::TryCatch.try do |try|
 | 
			
		||||
          this = to.v8(thisObject)
 | 
			
		||||
          return_value = to.rb(@native.Call(this, to.v8(args)))
 | 
			
		||||
          err = JSError.new(try, to) if try.HasCaught()
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      raise err if err
 | 
			
		||||
      return return_value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def call(*args)
 | 
			
		||||
      @portal.open do
 | 
			
		||||
        self.methodcall(@portal.context.native.Global(), *args)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def new(*args)
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        to.rb(@native.NewInstance(to.v8(args)))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def name
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        to.rb(@native.GetName())
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def name=(name)
 | 
			
		||||
      name.tap do
 | 
			
		||||
        @portal.open do |to|
 | 
			
		||||
          @native.SetName(to.v8(name))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,69 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class Object
 | 
			
		||||
    include Enumerable
 | 
			
		||||
 | 
			
		||||
    def initialize(native, portal)
 | 
			
		||||
      @native, @portal = native, portal
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [](key)
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        to.rb(@native.Get(to.v8(key)))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def []=(key, value)
 | 
			
		||||
      value.tap do
 | 
			
		||||
        @portal.open do |to|
 | 
			
		||||
          @native.Set(to.v8(key), to.v8(value))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_s
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        to.rb(@native.ToString())
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def each
 | 
			
		||||
      @portal.open do |to|
 | 
			
		||||
        for prop in to.rb(@native.GetPropertyNames())
 | 
			
		||||
          yield prop, self[prop]
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def respond_to?(method)
 | 
			
		||||
      super or self[method] != nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(name, *args, &block)
 | 
			
		||||
      if name.to_s =~ /(.*)=$/
 | 
			
		||||
        if args.length > 1
 | 
			
		||||
          self[$1] = args
 | 
			
		||||
          return args
 | 
			
		||||
        else
 | 
			
		||||
          self[$1] = args.first
 | 
			
		||||
          return args
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      return super(name, *args, &block) unless self.respond_to?(name)
 | 
			
		||||
      property = self[name]
 | 
			
		||||
      if property.kind_of?(V8::Function)
 | 
			
		||||
        property.methodcall(self, *args)
 | 
			
		||||
      elsif args.empty?
 | 
			
		||||
        property
 | 
			
		||||
      else
 | 
			
		||||
        raise ArgumentError, "wrong number of arguments (#{args.length} for 0)" unless args.empty?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Object  
 | 
			
		||||
  def eval_js(javascript)
 | 
			
		||||
    V8::Context.new(:with => self).eval(javascript)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,86 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    attr_reader :context, :access, :proxies, :templates, :interceptors, :caller
 | 
			
		||||
 | 
			
		||||
    def initialize(context, access)
 | 
			
		||||
      @context, @access = context, access
 | 
			
		||||
      @proxies = Proxies.new
 | 
			
		||||
      @templates = Templates.new(self)
 | 
			
		||||
      @interceptors = Interceptors.new(self)
 | 
			
		||||
      @caller = Caller.new(self)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def lock
 | 
			
		||||
      lock = V8::C::Locker.new
 | 
			
		||||
      yield
 | 
			
		||||
    ensure
 | 
			
		||||
      lock.delete
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def open
 | 
			
		||||
      lock do
 | 
			
		||||
        @context.native.enter do
 | 
			
		||||
          yield(self)
 | 
			
		||||
        end if block_given?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def rb(value)
 | 
			
		||||
      @proxies.js2rb(value) do
 | 
			
		||||
        case value
 | 
			
		||||
          when V8::C::Function    then V8::Function.new(value, self)
 | 
			
		||||
          when V8::C::Array       then V8::Array.new(value, self)
 | 
			
		||||
          when V8::C::Object      then V8::Object.new(value, self)
 | 
			
		||||
          when V8::C::String      then value.Utf8Value.tap {|s| return s.respond_to?(:force_encoding) ? s.force_encoding("UTF-8") : s}
 | 
			
		||||
          when V8::C::Date        then Time.at(value.NumberValue() / 1000)
 | 
			
		||||
          when V8::C::StackTrace  then V8::StackTrace.new(self, value)
 | 
			
		||||
          when V8::C::Value       then nil if value.IsEmpty()
 | 
			
		||||
        else
 | 
			
		||||
          value
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def v8(value)
 | 
			
		||||
      case value
 | 
			
		||||
      when V8::Object
 | 
			
		||||
        value.instance_eval {@native}
 | 
			
		||||
      when String
 | 
			
		||||
        C::String::New(value)
 | 
			
		||||
      when Symbol
 | 
			
		||||
        C::String::NewSymbol(value.to_s)
 | 
			
		||||
      when Proc,Method,UnboundMethod
 | 
			
		||||
        @proxies.rb2js(value) do
 | 
			
		||||
          @templates.to_function(value).function
 | 
			
		||||
        end
 | 
			
		||||
      when ::Array
 | 
			
		||||
        C::Array::New(value.length).tap do |a|
 | 
			
		||||
          value.each_with_index do |item, i|
 | 
			
		||||
            a.Set(i, v8(item))
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      when ::Hash
 | 
			
		||||
        C::Object::New().tap do |o|
 | 
			
		||||
          value.each do |key, val|
 | 
			
		||||
            o.Set(v8(key), v8(val))
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      when ::Time
 | 
			
		||||
        C::Date::New(value.to_f * 1000)
 | 
			
		||||
      when ::Class
 | 
			
		||||
        @proxies.rb2js(value) do
 | 
			
		||||
          constructor = @templates.to_constructor(value)
 | 
			
		||||
          constructor.exposed = true
 | 
			
		||||
          constructor.function
 | 
			
		||||
        end
 | 
			
		||||
      when nil,Numeric,TrueClass,FalseClass, C::Value
 | 
			
		||||
        value
 | 
			
		||||
      else
 | 
			
		||||
        @proxies.rb2js(value) do
 | 
			
		||||
          @templates.to_constructor(value.class).allocate(value)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,37 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    class Caller
 | 
			
		||||
 | 
			
		||||
      def initialize(portal)
 | 
			
		||||
        @portal = portal
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def raw
 | 
			
		||||
        yield
 | 
			
		||||
      rescue Exception => e
 | 
			
		||||
        case e
 | 
			
		||||
        when SystemExit, NoMemoryError
 | 
			
		||||
          raise e
 | 
			
		||||
        else
 | 
			
		||||
          error = V8::C::Exception::Error(V8::C::String::New(e.message))
 | 
			
		||||
          #TODO: This is almost certainly a crash here.
 | 
			
		||||
          #we need to hold onto `error` while it bubbles up the javascript stack.
 | 
			
		||||
          error.SetHiddenValue("TheRubyRacer::Cause", C::External::New(e))
 | 
			
		||||
          V8::C::ThrowException(error)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def protect(*args, &block)
 | 
			
		||||
        @portal.v8 raw(*args, &block)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def invoke(code, *args, &block)
 | 
			
		||||
        protect do
 | 
			
		||||
          args = args.slice(0, code.arity) if code.arity >= 0
 | 
			
		||||
          code.call(*args, &block)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,98 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    class ConstructorAdapter
 | 
			
		||||
      attr_reader :template, :exposed
 | 
			
		||||
      alias_method :exposed?, :exposed
 | 
			
		||||
 | 
			
		||||
      def initialize(templates, class_id)
 | 
			
		||||
        @exposed = false
 | 
			
		||||
        @class_id = class_id
 | 
			
		||||
        @templates = templates
 | 
			
		||||
        @invoke = method(:invoke)
 | 
			
		||||
        @template = C::FunctionTemplate::New(@invoke)
 | 
			
		||||
        portal.interceptors.setup(@template.InstanceTemplate())
 | 
			
		||||
        cls = self.ruby_class
 | 
			
		||||
        superclass = cls.superclass
 | 
			
		||||
        if cls != ::Object && superclass != ::Object && superclass != ::Class
 | 
			
		||||
          @template.Inherit(templates.to_constructor(superclass).template)
 | 
			
		||||
        end
 | 
			
		||||
        if cls.name && cls.name =~ /(::)?(\w+?)$/
 | 
			
		||||
          template.SetClassName(C::String::NewSymbol("rb::" + $2))
 | 
			
		||||
        else
 | 
			
		||||
          template.SetClassName("Ruby")
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def function
 | 
			
		||||
        @template.GetFunction()
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def allocate(object)
 | 
			
		||||
        arguments = C::Array::New(1)
 | 
			
		||||
        arguments.Set(0, C::External::New(object))
 | 
			
		||||
        function.NewInstance(arguments)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def disable
 | 
			
		||||
        @disabled = true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def enable
 | 
			
		||||
        @disabled = nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def invoke(arguments)
 | 
			
		||||
        return if @disabled
 | 
			
		||||
        if !@exposed
 | 
			
		||||
          unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
 | 
			
		||||
            C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
 | 
			
		||||
          else
 | 
			
		||||
            object = arguments[0].Value()
 | 
			
		||||
            proxies.register_javascript_proxy arguments.This(), :for => object
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          instance = nil
 | 
			
		||||
          if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
 | 
			
		||||
            instance = arguments[0].Value()
 | 
			
		||||
          else
 | 
			
		||||
            rbargs = []
 | 
			
		||||
            for i in 0..arguments.Length() - 1
 | 
			
		||||
              rbargs << @templates.portal.rb(arguments[i])
 | 
			
		||||
            end
 | 
			
		||||
            instance = portal.caller.raw do
 | 
			
		||||
              self.ruby_class.new(*rbargs)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          proxies.register_javascript_proxy arguments.This(), :for => instance
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def exposed=(exposed)
 | 
			
		||||
        if exposed && !@augmented
 | 
			
		||||
          #create a prototype so that this constructor also acts like a ruby object
 | 
			
		||||
          prototype_template = C::ObjectTemplate::New()
 | 
			
		||||
          portal.interceptors.setup(prototype_template)
 | 
			
		||||
          prototype = prototype_template.NewInstance()
 | 
			
		||||
          #set *that* object's prototype to an empty function so that it will look and behave like a function.
 | 
			
		||||
          prototype.SetPrototype(C::FunctionTemplate::New().GetFunction())
 | 
			
		||||
          template.GetFunction().SetPrototype(prototype)
 | 
			
		||||
          @augmented = true
 | 
			
		||||
        end
 | 
			
		||||
        @exposed = exposed
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def ruby_class
 | 
			
		||||
        ObjectSpace._id2ref(@class_id)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def proxies
 | 
			
		||||
        @templates.proxies
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def portal
 | 
			
		||||
        @templates.portal
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,63 +0,0 @@
 | 
			
		|||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    class FunctionAdapter
 | 
			
		||||
 | 
			
		||||
      attr_reader :template
 | 
			
		||||
 | 
			
		||||
      def initialize(portal, code)
 | 
			
		||||
        @portal = portal
 | 
			
		||||
        @caller = case code
 | 
			
		||||
        when Method then BoundCall.new(portal)
 | 
			
		||||
        when UnboundMethod then BindAndCall.new(portal)
 | 
			
		||||
        else Call.new(portal)
 | 
			
		||||
        end
 | 
			
		||||
        @code = code
 | 
			
		||||
        @template = V8::C::FunctionTemplate::New(@caller, @code)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def function
 | 
			
		||||
        @template.GetFunction()
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class Call
 | 
			
		||||
        def initialize(portal)
 | 
			
		||||
          @portal = portal
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def call(arguments)
 | 
			
		||||
          proc = arguments.Data()
 | 
			
		||||
          rbargs = [@portal.rb(arguments.This())]
 | 
			
		||||
          for i in 0..arguments.Length() - 1
 | 
			
		||||
            rbargs << @portal.rb(arguments[i])
 | 
			
		||||
          end
 | 
			
		||||
          @portal.caller.invoke(proc, *rbargs)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class BoundCall < Call
 | 
			
		||||
        def call(arguments)
 | 
			
		||||
          proc = arguments.Data()
 | 
			
		||||
          rbargs = []
 | 
			
		||||
          for i in 0..arguments.Length() - 1
 | 
			
		||||
            rbargs << @portal.rb(arguments[i])
 | 
			
		||||
          end
 | 
			
		||||
          @portal.caller.invoke(proc, *rbargs)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class BindAndCall < Call
 | 
			
		||||
        def call(arguments)
 | 
			
		||||
          method = arguments.Data()
 | 
			
		||||
          rbargs = []
 | 
			
		||||
          for i in 0..arguments.Length() - 1
 | 
			
		||||
            rbargs << @portal.rb(arguments[i])
 | 
			
		||||
          end
 | 
			
		||||
          this = @portal.rb(arguments.This())
 | 
			
		||||
          @portal.caller.protect do
 | 
			
		||||
            method.bind(this).call(*rbargs)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,152 +0,0 @@
 | 
			
		|||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    class Interceptors
 | 
			
		||||
      def initialize(portal)
 | 
			
		||||
        @getter = NamedPropertyGetter.new(portal)
 | 
			
		||||
        @setter = NamedPropertySetter.new(portal)
 | 
			
		||||
        @query = nil
 | 
			
		||||
        @deleter = nil
 | 
			
		||||
        @enumerator = NamedPropertyEnumerator.new(portal)
 | 
			
		||||
        @igetter = IndexedPropertyGetter.new(portal)
 | 
			
		||||
        @isetter = IndexedPropertySetter.new(portal)
 | 
			
		||||
        @iquery = nil
 | 
			
		||||
        @ideleter = nil
 | 
			
		||||
        @ienumerator = IndexedPropertyEnumerator.new(portal)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def setup(template)
 | 
			
		||||
        template.SetNamedPropertyHandler(@getter,@setter,@query,@deleter,@enumerator, nil)
 | 
			
		||||
        template.SetIndexedPropertyHandler(@igetter,@isetter,@iquery,@ideleter,@ienumerator, nil)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class PropertyAttributes
 | 
			
		||||
        attr_reader :flags
 | 
			
		||||
        def initialize
 | 
			
		||||
          @flags = 0
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def read_only
 | 
			
		||||
          tap do
 | 
			
		||||
            @flags |= V8::C::ReadOnly
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def dont_enum
 | 
			
		||||
          tap do
 | 
			
		||||
            @flags |= V8::C::DontEnum
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def dont_delete
 | 
			
		||||
          tap do
 | 
			
		||||
            @flags |= V8::C::DontDelete
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class Interceptor
 | 
			
		||||
 | 
			
		||||
        def initialize(portal)
 | 
			
		||||
          @to, @access = portal, portal.access
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def intercept(info, retval = nil, &code)
 | 
			
		||||
          obj = @to.rb(info.This())
 | 
			
		||||
          intercepts = true
 | 
			
		||||
          result = @to.caller.protect do
 | 
			
		||||
            dontintercept = proc do
 | 
			
		||||
              intercepts = false
 | 
			
		||||
            end
 | 
			
		||||
            code.call(obj, dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
          intercepts ? (retval || result) : C::Empty
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class NamedPropertyGetter < Interceptor
 | 
			
		||||
        def call(property, info)
 | 
			
		||||
          intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.get(obj, @to.rb(property), &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class NamedPropertySetter < Interceptor
 | 
			
		||||
        def call(property, value, info)
 | 
			
		||||
          intercept(info, value) do |obj, dontintercept|
 | 
			
		||||
            @access.set(obj, @to.rb(property), @to.rb(value), &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class NamedPropertyQuery
 | 
			
		||||
        def call(property, info)
 | 
			
		||||
          attributes = PropertyAttributes.new
 | 
			
		||||
          result = intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.query(obj, @to.rb(property), attributes, &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
          return result == C::Empty ? result : C::Integer::New(attributes.flags)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class NamedPropertyEnumerator < Interceptor
 | 
			
		||||
        def call(info)
 | 
			
		||||
          intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.names(obj, &dontintercept).to_a
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class NamedPropertyDeleter < Interceptor
 | 
			
		||||
        def call(property, info)
 | 
			
		||||
          intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.delete(obj, property, &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class IndexedPropertyGetter < Interceptor
 | 
			
		||||
        def call(index, info)
 | 
			
		||||
          intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.iget(obj, index, &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class IndexedPropertySetter < Interceptor
 | 
			
		||||
        def call(index, value, info)
 | 
			
		||||
          intercept(info, value) do |obj, dontintercept|
 | 
			
		||||
            @access.iset(obj, index, @to.rb(value), &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class IndexedPropertyQuery < Interceptor
 | 
			
		||||
        def call(property, info)
 | 
			
		||||
          attributes = PropertyAttributes.new
 | 
			
		||||
          result = intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.indices(obj, &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
          result == C::Empty ? C::Empty : C::Integer::New(attributes.flags)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class IndexedPropertyDeleter < Interceptor
 | 
			
		||||
        def call(index, info)
 | 
			
		||||
          intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.idelete(obj, index, &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class IndexedPropertyEnumerator < Interceptor
 | 
			
		||||
        def call(info)
 | 
			
		||||
          intercept(info) do |obj, dontintercept|
 | 
			
		||||
            @access.indices(obj, &dontintercept)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,151 +0,0 @@
 | 
			
		|||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    class Proxies
 | 
			
		||||
 | 
			
		||||
      def initialize
 | 
			
		||||
        @js_proxies_rb2js = {}
 | 
			
		||||
        @js_proxies_js2rb = {}
 | 
			
		||||
        @rb_proxies_rb2js = {}
 | 
			
		||||
        @rb_proxies_js2rb = {}
 | 
			
		||||
        @clear_js_proxy = ClearJSProxy.new(@js_proxies_rb2js, @js_proxies_js2rb)
 | 
			
		||||
        @clear_rb_proxy = ClearRubyProxy.new(@rb_proxies_rb2js, @rb_proxies_js2rb)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def js2rb(js)
 | 
			
		||||
        if rb = js_proxy_2_rb_object(js)
 | 
			
		||||
          return rb
 | 
			
		||||
        elsif rb = js_object_2_rb_proxy(js)
 | 
			
		||||
          return rb
 | 
			
		||||
        else
 | 
			
		||||
          proxy = block_given? ? yield(js) : Object.new
 | 
			
		||||
          register_ruby_proxy proxy, :for => js if proxy && js && js.kind_of?(V8::C::Handle)
 | 
			
		||||
          return proxy
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def rb2js(rb)
 | 
			
		||||
        if js = rb_proxy_2_js_object(rb)
 | 
			
		||||
          return js
 | 
			
		||||
        elsif js = rb_object_2_js_proxy(rb)
 | 
			
		||||
          return js
 | 
			
		||||
        else
 | 
			
		||||
          proxy = block_given? ? yield(rb) : V8::C::Object::New()
 | 
			
		||||
          register_javascript_proxy proxy, :for => rb unless @js_proxies_rb2js[rb]
 | 
			
		||||
          return proxy
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def register_javascript_proxy(proxy, options = {})
 | 
			
		||||
        target = options[:for] or fail ArgumentError, "must specify the object that you're proxying with the :for => param"
 | 
			
		||||
        fail ArgumentError, "javascript proxy must be a V8::C::Handle, not #{proxy.class}" unless proxy.kind_of?(V8::C::Handle)
 | 
			
		||||
        fail DoubleProxyError, "target already has a registered proxy" if @js_proxies_rb2js[target]
 | 
			
		||||
 | 
			
		||||
        @js_proxies_js2rb[proxy] = target
 | 
			
		||||
        @js_proxies_rb2js[target] = proxy
 | 
			
		||||
        proxy.MakeWeak(nil, @clear_js_proxy)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Lookup the JavaScript proxy for a natively Ruby object
 | 
			
		||||
      # @param [Object] object the Ruby object
 | 
			
		||||
      # @return [V8::C::Handle] the JavaScript proxy representing `object`
 | 
			
		||||
      def rb_object_2_js_proxy(object)
 | 
			
		||||
        @js_proxies_rb2js[object]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Look up a natively Ruby object given its JavaScript proxy
 | 
			
		||||
      # @param [V8::C::Handle] proxy the JavaScript proxy
 | 
			
		||||
      # @return [Object] the Ruby object represented by `proxy`
 | 
			
		||||
      def js_proxy_2_rb_object(proxy)
 | 
			
		||||
        @js_proxies_js2rb[proxy]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def register_ruby_proxy(proxy, options = {})
 | 
			
		||||
        target = options[:for] or fail ArgumentError, "must specify the object that you're proxying with the :for => param"
 | 
			
		||||
        fail ArgumentError, "'#{proxy.inspect}' is not a Handle to an actual V8 object" unless target.kind_of?(V8::C::Handle)
 | 
			
		||||
        @rb_proxies_rb2js[proxy.object_id] = target
 | 
			
		||||
        @rb_proxies_js2rb[target] = proxy.object_id
 | 
			
		||||
        ObjectSpace.define_finalizer(proxy, @clear_rb_proxy)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Looks up the Ruby proxy for an object that is natively JavaScript
 | 
			
		||||
      # @param [V8::C::Handle] object the JavaScript whose proxy we want
 | 
			
		||||
      # @return [Object] the Ruby proxy for `object`
 | 
			
		||||
      def js_object_2_rb_proxy(object)
 | 
			
		||||
        if id = @rb_proxies_js2rb[object]
 | 
			
		||||
          ObjectSpace._id2ref id
 | 
			
		||||
        end
 | 
			
		||||
      rescue RangeError
 | 
			
		||||
        # sometimes, the Ruby proxy has been garbage collected, but
 | 
			
		||||
        # the finalizer which runs has not been called. That's OK
 | 
			
		||||
        # we just clear out the entry, and return nil so that a new
 | 
			
		||||
        # proxy can be created.
 | 
			
		||||
        @clear_rb_proxy.call(id)
 | 
			
		||||
        return nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Looks up a native JavaScript object by its Ruby proxy
 | 
			
		||||
      # @param [Object] proxy the Ruby proxy
 | 
			
		||||
      # @return [V8::C::Handle] the native JavaScript object
 | 
			
		||||
      def rb_proxy_2_js_object(proxy)
 | 
			
		||||
        @rb_proxies_rb2js[proxy.object_id]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def js_empty?
 | 
			
		||||
        @js_proxies_rb2js.empty? && @js_proxies_js2rb.empty?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def rb_empty?
 | 
			
		||||
        @rb_proxies_rb2js.empty? && @rb_proxies_js2rb.empty?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def empty?
 | 
			
		||||
        js_empty? && rb_empty?
 | 
			
		||||
      end
 | 
			
		||||
      DoubleProxyError = Class.new(StandardError)
 | 
			
		||||
 | 
			
		||||
      class ClearJSProxy
 | 
			
		||||
 | 
			
		||||
        def initialize(rb2js, js2rb)
 | 
			
		||||
          @rb2js, @js2rb = rb2js, js2rb
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def call(proxy, parameter)
 | 
			
		||||
          rb = @js2rb[proxy]
 | 
			
		||||
          @js2rb.delete(proxy)
 | 
			
		||||
          @rb2js.delete(rb)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # @Private
 | 
			
		||||
      # Remove the linkage between a Ruby proxy and a native
 | 
			
		||||
      # JavaScript object. In general, this object is registered
 | 
			
		||||
      # as a finalizer on the Ruby proxy itself, so that when it is
 | 
			
		||||
      # garbage collected, it releases the back reference to the
 | 
			
		||||
      # native JavaScript object.
 | 
			
		||||
      #
 | 
			
		||||
      # It is important to do this as soon as is reasonably possible
 | 
			
		||||
      # so that the native JavaScript object can itself be garbage 
 | 
			
		||||
      # collected (provided there are no other references to it)
 | 
			
		||||
      class ClearRubyProxy
 | 
			
		||||
        def initialize(rb2js, js2rb)
 | 
			
		||||
          @rb2js, @js2rb = rb2js, js2rb
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # takes the object id of a Ruby proxy that has been garbage collected
 | 
			
		||||
        # and releases the reference to the native JavaScript object that
 | 
			
		||||
        # it was bound to.
 | 
			
		||||
        # @param[Fixnum] proxy_id the proxy id of the garbage collected Ruby proxy
 | 
			
		||||
        def call(proxy_id)
 | 
			
		||||
          # TODO: this if-check should be synchronized, so that if called manually
 | 
			
		||||
          # it will not conflict with the finalization thread. It's not so heinous
 | 
			
		||||
          # if the refererence gets cleared twice, but we definiteily dont't want
 | 
			
		||||
          # to double-decrement the v8 GC hint.
 | 
			
		||||
          if js = @rb2js[proxy_id]
 | 
			
		||||
            @rb2js.delete(proxy_id)
 | 
			
		||||
            @js2rb.delete(js)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,73 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
  class Portal
 | 
			
		||||
    class Templates
 | 
			
		||||
 | 
			
		||||
      attr_reader :portal
 | 
			
		||||
 | 
			
		||||
      def initialize(portal)
 | 
			
		||||
        @portal = portal
 | 
			
		||||
        @constructors = {}
 | 
			
		||||
        @methods = {}
 | 
			
		||||
        @procs = {}
 | 
			
		||||
        @releases = {}
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_constructor(ruby_class)
 | 
			
		||||
        class_id = ruby_class.object_id
 | 
			
		||||
        if constructor = @constructors[class_id]
 | 
			
		||||
          return constructor
 | 
			
		||||
        else
 | 
			
		||||
          constructor = @constructors[class_id] = ConstructorAdapter.new(self, class_id)
 | 
			
		||||
          ObjectSpace.define_finalizer(ruby_class, release(@constructors, class_id))
 | 
			
		||||
          return constructor
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_function(code)
 | 
			
		||||
        case code
 | 
			
		||||
        when Method, UnboundMethod
 | 
			
		||||
          if fn = @methods[code.to_s]
 | 
			
		||||
            return fn
 | 
			
		||||
          else
 | 
			
		||||
            function = @methods[code.to_s] = FunctionAdapter.new(@portal, code)
 | 
			
		||||
            #TODO: test this weak behavior
 | 
			
		||||
            function.template.MakeWeak(0, release(@methods, code.to_s))
 | 
			
		||||
            return function
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          if fn = @procs[code]
 | 
			
		||||
            return fn
 | 
			
		||||
          else
 | 
			
		||||
            function = @procs[code] = FunctionAdapter.new(@portal, code)
 | 
			
		||||
            #TODO: test this weak behavior
 | 
			
		||||
            function.template.MakeWeak(0, release(@procs, code))
 | 
			
		||||
            return function
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def proxies
 | 
			
		||||
        @portal.proxies
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def release(refs, id)
 | 
			
		||||
        release = Release.new(@releases, refs, id)
 | 
			
		||||
        @releases[release] = true
 | 
			
		||||
        return release
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class Release
 | 
			
		||||
        def initialize(releases, refs, id)
 | 
			
		||||
          @releases, @refs, @id = releases, refs, id
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def call(*args)
 | 
			
		||||
          @refs.delete(@id)
 | 
			
		||||
          @releases.delete(self)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,66 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8
 | 
			
		||||
 | 
			
		||||
  class StackTrace
 | 
			
		||||
    include Enumerable
 | 
			
		||||
 | 
			
		||||
    def initialize(to, native)
 | 
			
		||||
      @to = to
 | 
			
		||||
      @native = native
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def length
 | 
			
		||||
      @native.GetFrameCount()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def each
 | 
			
		||||
      for i in 0..length - 1
 | 
			
		||||
        yield V8::StackFrame.new(@to, @native.GetFrame(i))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_s
 | 
			
		||||
      map {|f|"at #{f}"}.join("\n")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class StackFrame
 | 
			
		||||
 | 
			
		||||
    def initialize(portal, native)
 | 
			
		||||
      @to = portal
 | 
			
		||||
      @native = native
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def script_name
 | 
			
		||||
      @to.rb(@native.GetScriptName())
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def function_name
 | 
			
		||||
      @to.rb(@native.GetFunctionName())
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def line_number
 | 
			
		||||
      @native.GetLineNumber()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def column
 | 
			
		||||
      @native.GetColumn()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def eval?
 | 
			
		||||
      @native.IsEval()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def constructor?
 | 
			
		||||
      @native.IsConstructor()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_s
 | 
			
		||||
      if @native.GetFunctionName()
 | 
			
		||||
        "#{function_name} (#{script_name}:#{line_number}:#{column})"
 | 
			
		||||
      else
 | 
			
		||||
        "#{script_name}:#{line_number}:#{column}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
 | 
			
		||||
unless Object.method_defined?(:tap)
 | 
			
		||||
  class Object
 | 
			
		||||
    def tap
 | 
			
		||||
      yield self
 | 
			
		||||
      return self
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
module V8
 | 
			
		||||
  VERSION = "0.10.1"
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
require "spec_helper"
 | 
			
		||||
 | 
			
		||||
describe V8::C::Array do
 | 
			
		||||
  include V8::ExtSpec
 | 
			
		||||
  
 | 
			
		||||
  it "can be instantiated" do
 | 
			
		||||
    a = c::Array::New()
 | 
			
		||||
    a.Length().should eql(0)
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  it "maintains referential integrity" do
 | 
			
		||||
    v8_eval('a = []')
 | 
			
		||||
    v8_eval('a').should be(v8_eval('a'))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,57 +0,0 @@
 | 
			
		|||
 | 
			
		||||
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
 | 
			
		||||
 | 
			
		||||
include V8
 | 
			
		||||
 | 
			
		||||
describe C::Context do
 | 
			
		||||
 | 
			
		||||
  before {@lock = C::Locker.new}
 | 
			
		||||
  after {@lock.delete}
 | 
			
		||||
 | 
			
		||||
  it "should not have a current context if no context is open" do
 | 
			
		||||
    C::Context::GetEntered().should be_nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can javascript properties on the global scope via ruby when the default scope is a ruby object" do
 | 
			
		||||
    V8::Context.new(:with => Object.new) do |cxt|
 | 
			
		||||
      cxt['foo'] = 'bar'
 | 
			
		||||
      cxt.eval('foo').should eql('bar')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can get the current javascript execution stack" do
 | 
			
		||||
    V8::Context.new do |cxt|
 | 
			
		||||
      trace = nil
 | 
			
		||||
      cxt['getTrace'] = lambda do
 | 
			
		||||
        trace = V8::Context.stack
 | 
			
		||||
      end
 | 
			
		||||
      cxt.eval(<<-JS, 'trace.js')
 | 
			
		||||
      function one() {
 | 
			
		||||
        return two();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function two() {
 | 
			
		||||
        return three();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function three() {
 | 
			
		||||
        return getTrace()
 | 
			
		||||
      }
 | 
			
		||||
      one();
 | 
			
		||||
JS
 | 
			
		||||
      trace.length.should be(4)
 | 
			
		||||
      trace.to_a[0].tap do |frame|
 | 
			
		||||
        frame.line_number.should == 10
 | 
			
		||||
        frame.column.should == 16
 | 
			
		||||
        frame.script_name.should == 'trace.js'
 | 
			
		||||
        frame.function_name.should == 'three'
 | 
			
		||||
        frame.should_not be_eval
 | 
			
		||||
        frame.should_not be_constructor
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "has an empty stack if there is no enterned context" do
 | 
			
		||||
    V8::Context.stack.should be_empty
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,27 +0,0 @@
 | 
			
		|||
 | 
			
		||||
module V8::ExtSpec
 | 
			
		||||
 | 
			
		||||
  def self.included(object)
 | 
			
		||||
    object.class_eval do
 | 
			
		||||
      before do
 | 
			
		||||
        @lock = c::Locker.new
 | 
			
		||||
        @cxt = c::Context::New()
 | 
			
		||||
        @cxt.Enter()
 | 
			
		||||
      end
 | 
			
		||||
      after do
 | 
			
		||||
        @cxt.Exit()
 | 
			
		||||
        @cxt.Dispose()
 | 
			
		||||
        @lock.delete
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def v8_eval(script, sourcename = "<eval>")
 | 
			
		||||
    c::Script::New(c::String::New(script), c::String::New(sourcename)).Run()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def c
 | 
			
		||||
    V8::C
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,64 +0,0 @@
 | 
			
		|||
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
 | 
			
		||||
 | 
			
		||||
include V8
 | 
			
		||||
 | 
			
		||||
describe C::Function do
 | 
			
		||||
  it "is callable" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      f = cxt.eval('(function() {return "Hello World"})', '<eval>');
 | 
			
		||||
      f.call().should == "Hello World"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "receives proper argument length from ruby" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      f = cxt.eval('(function() {return arguments.length})', 'eval')
 | 
			
		||||
      f.call(1, 2, 3).should == 3
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "maps all arguments from ruby" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      f = cxt.eval('(function(one, two, three) {return one + two + three})', 'eval')
 | 
			
		||||
      f.call(1,2,3).should == 6
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "properly maps ruby objects back and forth from arguments to return value" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      Object.new.tap do |this|
 | 
			
		||||
         f = cxt.eval('(function() {return this})', 'eval')
 | 
			
		||||
         f.methodcall(this).should be(this)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called outside of a context" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      @f = cxt.eval('(function() {return "Call Me"})', 'eval')
 | 
			
		||||
    end
 | 
			
		||||
    @f.call().should == "Call Me"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "is reflected properly" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      cxt['say'] = lambda {|this, word, times| word * times}
 | 
			
		||||
      cxt.eval('say("Hello", 3)').should == "HelloHelloHello"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "has a name" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      f = cxt.eval('(function hi() {return "Hello World"})', '<eval>')
 | 
			
		||||
      f.name.should == "hi"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can have its name set" do
 | 
			
		||||
    Context.new do |cxt|
 | 
			
		||||
      f = cxt.eval('(function () {return "Goodbye World"})', '<eval>')
 | 
			
		||||
      f.name = 'bye'
 | 
			
		||||
      f.name.should == 'bye'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe V8::C::Object do
 | 
			
		||||
  include V8::ExtSpec
 | 
			
		||||
 | 
			
		||||
  it "always returns a copy of the same object if it is the same object" do
 | 
			
		||||
    v8_eval('var o = new Object()')
 | 
			
		||||
    v8_eval('o').should be(v8_eval('o'))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
 | 
			
		||||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe V8::C::String do
 | 
			
		||||
  include V8::ExtSpec
 | 
			
		||||
  
 | 
			
		||||
  describe "a string with null bytes" do
 | 
			
		||||
    subject {c::String::New("foo\0bar")}
 | 
			
		||||
    its(:Utf8Value) {should eql "foo\0bar"}
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,60 +0,0 @@
 | 
			
		|||
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
 | 
			
		||||
 | 
			
		||||
include V8
 | 
			
		||||
 | 
			
		||||
describe C::TryCatch do
 | 
			
		||||
 | 
			
		||||
  before {@lock = C::Locker.new;@cxt = C::Context::New();}
 | 
			
		||||
  after {@cxt.Dispose(); @lock.delete}
 | 
			
		||||
 | 
			
		||||
  it "does not allow instance creation by default" do
 | 
			
		||||
    lambda {
 | 
			
		||||
     C::TryCatch.new
 | 
			
		||||
    }.should raise_error
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "will do nothing if not passed a block" do
 | 
			
		||||
    C::TryCatch.try.should == nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "executes a block in the context of a C++ stack frame" do
 | 
			
		||||
    C::TryCatch.try do |catch|
 | 
			
		||||
      catch.HasCaught().should be(false)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "raises an erro if you try to access it outside of its scope" do
 | 
			
		||||
    tc = C::TryCatch.try do |catch|
 | 
			
		||||
      catch.tap {}
 | 
			
		||||
    end
 | 
			
		||||
    lambda {
 | 
			
		||||
      tc.HasCaught()
 | 
			
		||||
    }.should raise_error(ScriptError)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
    it "doesn't segfault when an error is raised in a javascript function on a native prototype" do
 | 
			
		||||
      constructor = Class.new
 | 
			
		||||
      constructor.class_eval do
 | 
			
		||||
        def detonate(*a)
 | 
			
		||||
          raise "BOOM!"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      V8::Context.new do |cxt|
 | 
			
		||||
        cxt['Boom'] = constructor
 | 
			
		||||
        cxt['puts'] = method(:puts)
 | 
			
		||||
        danger = <<-JS
 | 
			
		||||
  Boom.prototype.boom = function() {
 | 
			
		||||
    this.detonate()
 | 
			
		||||
  }
 | 
			
		||||
  var go = new(Boom)()
 | 
			
		||||
  try {
 | 
			
		||||
    go.boom()
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
  }
 | 
			
		||||
  go.boom()
 | 
			
		||||
  JS
 | 
			
		||||
        expect {cxt.eval(danger, 'danger.js')}.should raise_error(V8::JSError)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
require 'spec_helper'
 | 
			
		||||
require 'redjs/load_specs'
 | 
			
		||||
module RedJS
 | 
			
		||||
  Context = V8::Context
 | 
			
		||||
  Error = V8::JSError
 | 
			
		||||
end
 | 
			
		||||
describe V8::Context do
 | 
			
		||||
  it_behaves_like 'RedJS::Context'
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
 | 
			
		||||
require 'v8'
 | 
			
		||||
require 'erb'
 | 
			
		||||
require Pathname(__FILE__).dirname.join('ext/ext_spec_helper')
 | 
			
		||||
require Pathname(__FILE__).dirname.join('../specmem/spec_helper')
 | 
			
		||||
def rputs(msg)
 | 
			
		||||
  puts "<pre>#{ERB::Util.h(msg)}</pre>"
 | 
			
		||||
  $stdout.flush
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,131 +0,0 @@
 | 
			
		|||
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
 | 
			
		||||
 | 
			
		||||
describe V8::JSError do
 | 
			
		||||
 | 
			
		||||
  before(:each) do
 | 
			
		||||
    @cxt = V8::Context.new
 | 
			
		||||
    @cxt['one'] = lambda do
 | 
			
		||||
      @cxt.eval('two()', 'one.js')
 | 
			
		||||
    end
 | 
			
		||||
    @cxt['two'] = lambda do
 | 
			
		||||
      @cxt.eval('three()', 'two.js')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "captures a message without over nesting when the error is an error" do
 | 
			
		||||
    throw! do |e|
 | 
			
		||||
      e.message.should == "BOOM!"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "captures the js message without over nesting when the error is a normal object" do
 | 
			
		||||
    throw!('{foo: "bar"}') do |e|
 | 
			
		||||
      e.message.should == "[object Object]"
 | 
			
		||||
    end
 | 
			
		||||
    throw!('{message: "bar"}') do |e|
 | 
			
		||||
      e.message.should == "bar"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "captures a thrown value as the message" do
 | 
			
		||||
    throw!('"BOOM!"') do |e|
 | 
			
		||||
      e.message.should == "BOOM!"
 | 
			
		||||
    end
 | 
			
		||||
    throw!('6') do |e|
 | 
			
		||||
      e.message.should == '6'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "has a reference to the root javascript cause" do
 | 
			
		||||
    throw!('"I am a String"') do |e|
 | 
			
		||||
      e.should_not be_in_ruby
 | 
			
		||||
      e.should be_in_javascript 
 | 
			
		||||
      e.value.should == "I am a String"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "has a reference to the root ruby cause if one exists" do
 | 
			
		||||
    StandardError.new("BOOM!").tap do |bomb|
 | 
			
		||||
      @cxt['boom'] = lambda do
 | 
			
		||||
        raise bomb
 | 
			
		||||
      end
 | 
			
		||||
      lambda {
 | 
			
		||||
        @cxt.eval('boom()', 'boom.js')
 | 
			
		||||
      }.should(raise_error do |raised|
 | 
			
		||||
        raised.should be_in_ruby 
 | 
			
		||||
        raised.should_not be_in_javascript 
 | 
			
		||||
        raised.value.should be(bomb)
 | 
			
		||||
      end)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "backtrace" do
 | 
			
		||||
 | 
			
		||||
    it "is mixed with ruby and javascript" do
 | 
			
		||||
      throw! do |e|
 | 
			
		||||
        e.backtrace.first.should == "at three.js:1:7"
 | 
			
		||||
        e.backtrace[1].should =~ /error_spec.rb/
 | 
			
		||||
        e.backtrace[2].should == "at two.js:1:1"
 | 
			
		||||
        e.backtrace[3].should =~ /error_spec.rb/
 | 
			
		||||
        e.backtrace[4].should == "at one.js:1:1"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    it "can be set to show only ruby frames" do
 | 
			
		||||
      throw! do |e|
 | 
			
		||||
        e.backtrace(:ruby).each do |frame|
 | 
			
		||||
          frame.should =~ /(\.rb|):\d+/
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    it "can be set to show only javascript frames" do
 | 
			
		||||
      throw! do |e|
 | 
			
		||||
        e.backtrace(:javascript).each do |frame|
 | 
			
		||||
          frame.should =~ /\.js:\d:\d/
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    it "includes a mystery marker when the original frame is unavailable because what got thrown wasn't an error" do
 | 
			
		||||
      throw!("6") do |e|
 | 
			
		||||
        e.backtrace.first.should == 'at three.js:1:1'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    it "has a source name and line number when there is a javascript SyntaxError" do
 | 
			
		||||
      lambda do
 | 
			
		||||
        @cxt.eval(<<-INVALID, 'source.js')
 | 
			
		||||
"this line is okay";
 | 
			
		||||
"this line has a syntax error because it ends with a colon":
 | 
			
		||||
"this line is also okay";
 | 
			
		||||
"how do I find out that line 2 has the syntax error?";
 | 
			
		||||
INVALID
 | 
			
		||||
      end.should raise_error(V8::JSError) {|error|
 | 
			
		||||
        error.backtrace.first.should == 'at source.js:2:60'
 | 
			
		||||
      }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can start with ruby at the bottom" do
 | 
			
		||||
      @cxt['boom'] = lambda do
 | 
			
		||||
        raise StandardError, "Bif!"
 | 
			
		||||
      end
 | 
			
		||||
      lambda {
 | 
			
		||||
        @cxt.eval('boom()', "boom.js")
 | 
			
		||||
      }.should(raise_error {|e|
 | 
			
		||||
        e.backtrace.first.should =~ /error_spec\.rb/
 | 
			
		||||
        e.backtrace[1].should =~ /boom.js/
 | 
			
		||||
      })
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  def throw!(js = "new Error('BOOM!')", &block)
 | 
			
		||||
    @cxt['three'] = lambda do
 | 
			
		||||
      @cxt.eval("throw #{js}", 'three.js')
 | 
			
		||||
    end
 | 
			
		||||
    lambda do
 | 
			
		||||
      @cxt['one'].call()
 | 
			
		||||
    end.should(raise_error(V8::JSError, &block))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,106 +0,0 @@
 | 
			
		|||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe V8::Portal::Proxies do
 | 
			
		||||
  include V8::ExtSpec
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  context "for Ruby objects which are embedded into javascript" do
 | 
			
		||||
 | 
			
		||||
    it "allows you to resolve the Ruby object's JavaScript proxy" do
 | 
			
		||||
      js_proxy = c::Object::New()
 | 
			
		||||
      rb_object = Object.new
 | 
			
		||||
      subject.register_javascript_proxy js_proxy, :for => rb_object
 | 
			
		||||
      subject.rb_object_2_js_proxy(rb_object).should be(js_proxy)
 | 
			
		||||
      subject.js_proxy_2_rb_object(js_proxy).should be(rb_object)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "requires a Ruby object which is the actual object that is proxied" do
 | 
			
		||||
      expect {subject.register_javascript_proxy c::Object::New()}.should raise_error(ArgumentError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can only register proxies which are low-level JavaScript objects" do
 | 
			
		||||
      expect {subject.register_javascript_proxy Object.new, :for => Object.new}.should raise_error(ArgumentError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "is only allowed to have a single JavaScript proxy" do
 | 
			
		||||
      rb_object = Object.new
 | 
			
		||||
      subject.register_javascript_proxy c::Object::New(), :for => rb_object
 | 
			
		||||
      expect {subject.register_javascript_proxy c::Object::New(), :for => rb_object}.should raise_error(V8::Portal::Proxies::DoubleProxyError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context "for a JavaScript objects which are embedded into Ruby" do
 | 
			
		||||
 | 
			
		||||
    it "allows you to resolve the JavaScript object's Ruby proxy" do
 | 
			
		||||
      rb_proxy = Object.new
 | 
			
		||||
      js_object = c::Object::New()
 | 
			
		||||
      subject.register_ruby_proxy rb_proxy, :for => js_object
 | 
			
		||||
      subject.js_object_2_rb_proxy(js_object).should be(rb_proxy)
 | 
			
		||||
      subject.rb_proxy_2_js_object(rb_proxy).should be(js_object)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "requires a JavaScript low level javascript object as the actual object that is proxied" do
 | 
			
		||||
      expect {subject.register_javascript_proxy Object.new, :for => c::Object::New()}.should raise_error(ArgumentError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "will not a proxy twice if the proxy creator block actually registers the proxy inside it" do
 | 
			
		||||
      target = Object.new
 | 
			
		||||
      proxy = c::Object::New()
 | 
			
		||||
      expect {subject.rb2js(target) do |object|
 | 
			
		||||
        subject.register_javascript_proxy(proxy, :for => object)
 | 
			
		||||
        c::Object::New()
 | 
			
		||||
      end}.should_not raise_error
 | 
			
		||||
      subject.rb2js(target).should be(proxy)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context "looking up a Ruby object from a random JavaScript object" do
 | 
			
		||||
      it "checks first if it's a native Ruby object with a javascript proxy" do
 | 
			
		||||
        target = Object.new
 | 
			
		||||
        proxy = c::Object::New()
 | 
			
		||||
        subject.register_javascript_proxy proxy, :for => target
 | 
			
		||||
        subject.js2rb(proxy).should be(target)
 | 
			
		||||
      end
 | 
			
		||||
      it "then sees if maybe it's a native JavaScript that has a Ruby proxy" do
 | 
			
		||||
        target = c::Object::New()
 | 
			
		||||
        proxy = Object.new
 | 
			
		||||
        subject.register_ruby_proxy proxy, :for => target
 | 
			
		||||
        subject.js2rb(target).should be(proxy)
 | 
			
		||||
      end
 | 
			
		||||
      it "will assume that it is a native JavaScript object that needs a Ruby proxy if no corresponding Ruby object can be found" do
 | 
			
		||||
        js = c::Object::New()
 | 
			
		||||
        proxy = subject.js2rb(js) do |target|
 | 
			
		||||
          {:target => target}
 | 
			
		||||
        end
 | 
			
		||||
        subject.js2rb(js).should be(proxy)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context "looking up a JavaScript object from a random Ruby object" do
 | 
			
		||||
      it "checks first if it's a native JavaScript object with a Ruby proxy" do
 | 
			
		||||
        target = c::Object::New()
 | 
			
		||||
        proxy = Object.new
 | 
			
		||||
        subject.register_ruby_proxy proxy, :for => target
 | 
			
		||||
        subject.rb2js(proxy).should be(target)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it "then sees if maybe it's a native Ruby object that has a JavaScript proxy" do
 | 
			
		||||
        target = Object.new
 | 
			
		||||
        proxy = c::Object::New()
 | 
			
		||||
        subject.register_javascript_proxy proxy, :for => target
 | 
			
		||||
        subject.rb2js(target).should be(proxy)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it "assumes that it is a native Ruby object that needs a JavaScript proxy if no corresponding JavaScript object can be found" do
 | 
			
		||||
        rb = Object.new
 | 
			
		||||
        proxy = nil
 | 
			
		||||
        js = subject.rb2js(rb) do |target|
 | 
			
		||||
          target.should be(rb)
 | 
			
		||||
          proxy = c::Object::New()
 | 
			
		||||
        end
 | 
			
		||||
        proxy.should_not be_nil
 | 
			
		||||
        js.should be(proxy)
 | 
			
		||||
        subject.rb2js(rb).should be(proxy)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
 | 
			
		||||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe V8::C::Handle do
 | 
			
		||||
  include V8::MemSpec
 | 
			
		||||
  context "A JavaScript Object reflected into Ruby" do
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      @weakref_callback = WeakrefCallback.new
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "has a strong reference from the ruby side, which is not released until the Ruby reference goes away" do
 | 
			
		||||
      handle = c::Handle::New(object = c::Object::New())
 | 
			
		||||
      handle.MakeWeak(nil, @weakref_callback)
 | 
			
		||||
      ruby_gc do
 | 
			
		||||
        v8_gc
 | 
			
		||||
        @weakref_callback.should_not have_been_invoked
 | 
			
		||||
        handle.should_not be_dead
 | 
			
		||||
      end
 | 
			
		||||
      ruby_gc do
 | 
			
		||||
        object = nil
 | 
			
		||||
        v8_gc
 | 
			
		||||
        @weakref_callback.should have_been_invoked
 | 
			
		||||
        handle.should be_dead
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    class WeakrefCallback
 | 
			
		||||
 | 
			
		||||
      def call(value, parameters)
 | 
			
		||||
        @invoked = true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def has_been_invoked?
 | 
			
		||||
        @invoked
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,14 +0,0 @@
 | 
			
		|||
 | 
			
		||||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe V8::C::Object do
 | 
			
		||||
  include V8::MemSpec
 | 
			
		||||
  it "will return a new peer and not barf if the old peer has been garbage collected" do
 | 
			
		||||
    v8_eval('var o = {foo: "bar"}')
 | 
			
		||||
    old_id = v8_eval('o').object_id
 | 
			
		||||
    ruby_gc do
 | 
			
		||||
      v8_eval('o').Get(c::String::New("foo")).Utf8Value().should == "bar"
 | 
			
		||||
      v8_eval('o').object_id.should_not be(old_id)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe V8::Portal::Proxies do
 | 
			
		||||
  include V8::MemSpec
 | 
			
		||||
  
 | 
			
		||||
  context "A Ruby object embedded into JavaScript" do
 | 
			
		||||
    it "holds a hard reference to any ruby object which is linked to a javascript proxy" do
 | 
			
		||||
      subject.register_javascript_proxy c::Object::New(), :for => Object.new
 | 
			
		||||
      ruby_gc do
 | 
			
		||||
        subject.should_not be_empty
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "releases the hard reference if its corresponding javascript object has been garbage collected" do
 | 
			
		||||
      ruby_gc do
 | 
			
		||||
        rb_object = Object.new
 | 
			
		||||
        js_proxy = c::Object::New()
 | 
			
		||||
        subject.should be_empty
 | 
			
		||||
        subject.register_javascript_proxy js_proxy, :for => rb_object
 | 
			
		||||
        rb_object = nil
 | 
			
		||||
        subject.should_not be_empty
 | 
			
		||||
        v8_gc()
 | 
			
		||||
      end
 | 
			
		||||
      subject.should be_empty
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context "A JavaScript object embedded into Ruby" do
 | 
			
		||||
    it "holds a hard reference to any JavaScript object which is linked to a Ruby proxy" do
 | 
			
		||||
      proxy = Object.new
 | 
			
		||||
      subject.register_ruby_proxy proxy, :for => c::Object::New()
 | 
			
		||||
      ruby_gc do
 | 
			
		||||
        subject.should_not be_empty
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "clears any strong references to the JavaScript object when it's Ruby proxy is garbage collected" do
 | 
			
		||||
      subject.register_ruby_proxy Object.new, :for => c::Object::New()
 | 
			
		||||
      subject.should_not be_empty
 | 
			
		||||
      ruby_gc do
 | 
			
		||||
        v8_gc
 | 
			
		||||
        GC.start
 | 
			
		||||
        v8_gc
 | 
			
		||||
      end
 | 
			
		||||
      subject.should be_empty
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
require Pathname(__FILE__).dirname.join('../spec/spec_helper')
 | 
			
		||||
 | 
			
		||||
module V8::MemSpec
 | 
			
		||||
  
 | 
			
		||||
  def self.included(cls)
 | 
			
		||||
    cls.class_eval do
 | 
			
		||||
      include V8::ExtSpec
 | 
			
		||||
      before(:all) {V8::C::V8::SetFlagsFromString("--expose-gc")}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  def ruby_gc
 | 
			
		||||
    current = GC.stress
 | 
			
		||||
    GC.stress = true
 | 
			
		||||
    yield
 | 
			
		||||
  ensure
 | 
			
		||||
    GC.stress = current
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def v8_gc
 | 
			
		||||
    while !c::V8::IdleNotification();end
 | 
			
		||||
    v8_eval('gc()', 'gc.js')
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require Pathname(__FILE__).dirname.join('../spec/spec_helper')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +0,0 @@
 | 
			
		|||
 | 
			
		||||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe "using v8 from multiple threads" do
 | 
			
		||||
  
 | 
			
		||||
  it "is possible" do
 | 
			
		||||
    Thread.new do
 | 
			
		||||
      require 'v8'
 | 
			
		||||
      V8::Context.new
 | 
			
		||||
    end.join
 | 
			
		||||
    V8::Context.new
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								thefrontside.png
									
										
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								thefrontside.png
									
										
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 7.5 KiB  | 
| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
# -*- encoding: utf-8 -*-
 | 
			
		||||
$:.push File.expand_path("../lib", __FILE__)
 | 
			
		||||
require "v8/version"
 | 
			
		||||
require 'pathname'
 | 
			
		||||
 | 
			
		||||
Gem::Specification.new do |s|
 | 
			
		||||
  s.name = s.rubyforge_project = "therubyracer"
 | 
			
		||||
  s.summary = "Embed the V8 Javascript interpreter into Ruby"
 | 
			
		||||
  s.version = V8::VERSION
 | 
			
		||||
  s.authors = ["Charles Lowell", "Bill Robertson"]
 | 
			
		||||
  s.description = "Call javascript code and manipulate javascript objects from ruby. Call ruby code and manipulate ruby objects from javascript."
 | 
			
		||||
  s.homepage = "http://github.com/cowboyd/therubyracer"
 | 
			
		||||
  s.email = "cowboyd@thefrontside.net"
 | 
			
		||||
 | 
			
		||||
  root = Pathname(__FILE__).dirname
 | 
			
		||||
  s.files = `git ls-files`.split("\n")
 | 
			
		||||
  s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
 | 
			
		||||
  s.extensions = ["ext/v8/extconf.rb"]
 | 
			
		||||
  s.require_paths = ["lib", "ext"]
 | 
			
		||||
 | 
			
		||||
  s.add_dependency "libv8", "~> 3.3.10"
 | 
			
		||||
 | 
			
		||||
  s.add_development_dependency "rake"
 | 
			
		||||
  s.add_development_dependency "rspec", "~> 2.0"
 | 
			
		||||
  s.add_development_dependency "rake-compiler"
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue