1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

get the ruby racer running on the shared specs (which fail horribly)

This commit is contained in:
Charles Lowell 2009-12-16 07:40:19 +01:00
parent 45001c6a66
commit 7912eec8cd
13 changed files with 39 additions and 377 deletions

View file

@ -3,7 +3,6 @@ History.txt
Manifest.txt
README.rdoc
Rakefile
config.sh
docs/data_conversion.txt
ext/v8/convert_ruby.cpp
ext/v8/convert_ruby.h
@ -31,10 +30,13 @@ ext/v8/v8_str.h
ext/v8/v8_template.cpp
ext/v8/v8_template.h
lib/v8.rb
lib/v8/v8.bundle
lib/v8/context.rb
script/console
script/destroy
script/generate
spec/jsapi/README.txt
spec/jsapi/spec.rb
spec/jsapi_spec.rb
spec/spec.opts
spec/spec_helper.rb
spec/therubyracer_spec.rb

View file

@ -2,7 +2,11 @@ require 'rubygems'
gem 'hoe', '>= 2.1.0'
require 'hoe'
require 'fileutils'
require './lib/v8'
begin
require './lib/v8'
rescue LoadError
#it will fail to load if we don't have the extensions compiled yet
end
gem 'rake-compiler', '>= 0.4.1'
require "rake/extensiontask"

View file

@ -1 +0,0 @@
ruby extconf.rb --with-v8-lib=$1 --with-v8-include=$1/include

View file

@ -5,7 +5,6 @@
#include <v8.h>
#include <stdio.h>
#include <string>
#include "v8_object.h"
/**
* A RubyValueSource takes a Destination class and a return
@ -95,8 +94,7 @@ class RubyValueDest {
}
VALUE pushObject(v8::Handle<v8::Object>& value) {
v8_object* wrapper = new v8_object(value);
return wrapper->ruby_value;
return Qnil;
}
};

View file

@ -1,5 +1,3 @@
#include "v8_object.h"
#include "v8_context.h"
#include "v8_cxt.h"
#include "v8_str.h"
#include "v8_script.h"
@ -27,13 +25,7 @@ extern "C" {
ruby_method_class = rb_eval_string("::Method");
rb_mModule = rb_define_module("V8");
// context setup
rb_cV8 = rb_define_class_under(rb_mModule, "Context", rb_cObject);
rb_define_alloc_func(rb_cV8, v8_context_allocate);
rb_define_method(rb_cV8, "eval", (VALUE(*)(...)) v8_context_eval, 1);
rb_define_method(rb_cV8, "[]=", (VALUE(*)(...)) v8_context_inject, 2);
//native module setup
VALUE rb_mNative = rb_define_module_under(rb_mModule, "C");
@ -59,16 +51,6 @@ extern "C" {
rb_define_singleton_method(V8__C__ObjectTemplate, "new", (VALUE(*)(...))v8_ObjectTemplate_New, 0);
VALUE V8__C__FunctionTemplate = rb_define_class_under(rb_mNative, "FunctionTemplate", V8__C__Template);
rb_define_singleton_method(V8__C__FunctionTemplate, "new", (VALUE(*)(...))v8_FunctionTemplate_New, -1);
// js object setup
rb_cV8_JSObject = rb_define_class_under(rb_mModule, "JSObject", rb_cObject);
rb_define_alloc_func(rb_cV8_JSObject, v8_object_allocate);
rb_define_method(rb_cV8_JSObject, "[]", (VALUE(*)(...)) v8_object_hash_access, 1);
rb_define_method(rb_cV8_JSObject, "[]=", (VALUE(*)(...)) v8_object_hash_assignment, 2);
rb_define_method(rb_cV8_JSObject, "call_something", (VALUE(*)(...)) v8_object_call_something, 1);
// stand alone methods
rb_define_singleton_method(rb_mModule, "what_is_this?",(VALUE(*)(...)) v8_what_is_this, 1);
rb_define_singleton_method(V8__C__FunctionTemplate, "new", (VALUE(*)(...))v8_FunctionTemplate_New, -1);
}
}

View file

@ -1,66 +0,0 @@
#include "converters.h"
#include "v8_context.h"
#include<stdio.h>
using namespace v8;
v8_context::v8_context() : handle(Context::New()) {}
v8_context::~v8_context() {
handle.Dispose();
}
VALUE v8_context_allocate(VALUE clazz) {
v8_context *cxt = new v8_context;
return Data_Wrap_Struct(clazz, v8_context_mark, v8_context_free, cxt);
}
void v8_context_free(v8_context *context) {
delete context;
}
void v8_context_mark(v8_context *context) {
//don't mark anything.
}
//methods
VALUE v8_context_eval(VALUE self, VALUE javascript) {
v8_context* cxt = 0;
Data_Get_Struct(self, struct v8_context, cxt);
Context::Scope enter(cxt->handle);
HandleScope handles;
RubyValueSource<StringDest, std::string> tostring;
const std::string source(tostring(javascript));
Local<Script> script = Script::Compile(String::New(source.c_str()));
Local<Value> result = script->Run();
convert_v8_to_rb_t toValue;
return toValue(result);
}
VALUE v8_context_inject(VALUE self, VALUE key, VALUE value) {
v8_context* context = 0;
Data_Get_Struct(self, struct v8_context, context);
Context::Scope enter(context->handle);
HandleScope handles;
convert_rb_to_string_t tostring;
convert_rb_to_v8_t toHandle;
const std::string key_string(tostring(key));
// does this need to be a persistent handle ?
Local<Value> key_handle(String::New(key_string.c_str()));
Local<Value> value_handle(toHandle(value));
Local<Object> global = context->handle->Global();
global->Set(key_handle, value_handle);
return value;
}

View file

@ -1,46 +0,0 @@
#ifndef __RUBY_V8_CONTEXT__
#define __RUBY_V8_CONTEXT__
#include <ruby.h>
#include <v8.h>
typedef struct v8_context {
v8_context();
~v8_context();
v8::Handle<v8::Value> eval(const char* javascript);
v8::Persistent<v8::Context> handle;
typedef struct ensure {
inline ensure() {
if (!v8::Context::InContext()) {
cxt = v8::Context::New();
cxt->Enter();
}
}
~ensure() {
if (!cxt.IsEmpty()) {
cxt->Exit();
}
cxt.Dispose();
}
v8::Persistent<v8::Context> cxt;
v8::HandleScope handles;
} ensure;
} v8_context;
//memory management
VALUE v8_context_allocate(VALUE clazz);
void v8_context_mark(v8_context *context);
void v8_context_free(v8_context *context);
//methods
VALUE v8_context_eval(VALUE self, VALUE javascript);
VALUE v8_context_inject(VALUE self, VALUE key, VALUE value);
#endif

View file

@ -1,67 +0,0 @@
#include "v8_object.h"
#include "v8_context.h"
#include "converters.h"
#include <stdio.h>
VALUE rb_cV8_JSObject;
using namespace v8;
v8_object::v8_object(VALUE clazz) {
v8_context::ensure context;
handle = (*Object::New());
this->make_ruby_value(clazz);
}
v8_object::v8_object(Handle<Object>& object) : handle(Persistent<Object>(*object)) {
Handle<Value> peer = object->GetHiddenValue(String::New("ruby::peer"));
if (peer.IsEmpty()) {
this->make_ruby_value(rb_cV8_JSObject);
} else {
ruby_value = (VALUE)External::Unwrap(peer);
}
}
v8_object::~v8_object() {
handle.Dispose();
}
VALUE v8_object::make_ruby_value(VALUE clazz) {
ruby_value = Data_Wrap_Struct(clazz, v8_object_mark, v8_object_free, this);
v8_context::ensure context;
handle->SetHiddenValue(String::New("ruby::peer"), External::Wrap((void *)ruby_value));
return ruby_value;
}
VALUE v8_object_hash_access(VALUE self, VALUE key) {
v8_object* object = 0;
Data_Get_Struct(self, struct v8_object, object);
convert_rb_to_string_t tostring;
const std::string cppkey(tostring(key));
HandleScope handles;
Handle<Value> result = object->handle->Get(String::New(cppkey.c_str()));
convert_v8_to_rb_t toValue;
return toValue(result);
}
VALUE v8_object_hash_assignment(VALUE self, VALUE key, VALUE value) {
}
VALUE v8_object_call_something(VALUE self, VALUE code) {
return rb_funcall(code, rb_intern("call"), 0);
}
VALUE v8_object_allocate(VALUE clazz) {
v8_object *wrapper = new v8_object(clazz);
return wrapper->ruby_value;
}
void v8_object_mark(v8_object *o) {
}
void v8_object_free(v8_object *o) {
delete o;
}

View file

@ -1,31 +0,0 @@
#ifndef __RUBY_V8_OBJECT__
#define __RUBY_V8_OBJECT__
#include <ruby.h>
#include <v8.h>
extern VALUE rb_cV8_JSObject;
typedef struct v8_object {
v8_object(VALUE clazz);
v8_object(v8::Handle<v8::Object>& object);
~v8_object();
VALUE make_ruby_value(VALUE clazz);
v8::Persistent<v8::Object> handle;
VALUE ruby_value;
} v8_object;
VALUE v8_object_hash_access(VALUE self, VALUE key);
VALUE v8_object_hash_assignment(VALUE self, VALUE key, VALUE value);
VALUE v8_object_call_something(VALUE self, VALUE code);
//memory management
VALUE v8_object_allocate(VALUE clazz);
void v8_object_mark(v8_object *object);
void v8_object_free(v8_object *object);
#endif

View file

@ -1,7 +1,6 @@
#include "v8.h"
#include "v8_ref.h"
#include "v8_script.h"
#include "v8_context.h"
#include "converters.h"
using namespace v8;

View file

@ -4,4 +4,5 @@ $:.unshift(File.dirname(__FILE__)) unless
module V8
VERSION = '0.4.0'
require 'v8/v8' #native glue
require 'v8/context'
end

View file

@ -1,6 +1,31 @@
module V8
# This doesn't do anything at the moment. But the ruby interface will go here
# The native interface is under the V8::C module.
class Context
class Context
def initialize
@native = C::Context.new
end
def open(&block)
@native.open do
block.call(self) if block
end if block_given?
end
def eval(javascript)
self.open do
source = V8::C::String.new(javascript)
script = V8::C::Script.new(source)
script.Run()
end
end
def evaluate(*args)
self.eval(*args)
end
def self.open(&block)
new.open(&block)
end
end
end

View file

@ -1,138 +0,0 @@
require File.dirname(__FILE__) + '/spec_helper.rb'
describe "The Ruby Racer" do
before(:each) do
@cxt = V8::Context.new
end
describe "Type Conversion from Ruby to Javascript" do
it "can pass nil back to ruby" do
eval("null").should be_nil
end
it "passes back undefined value as nil" do
eval("this.undefined").should be_nil
end
it "can pass strings back to ruby" do
eval("'Hello World'").should == "Hello World"
end
it "can pass large strings back to ruby" do
lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis faucibus, diam vel pellentesque aliquet, nisl sapien molestie eros, vitae vehicula libero massa vel neque. Phasellus tempor pharetra ipsum vel venenatis. Quisque vitae nisl vitae quam mattis pellentesque et in sapien. Sed at lectus quis eros pharetra feugiat non ac neque. Vivamus lacus eros, feugiat at volutpat at, viverra id nisl. Vivamus ac dolor eleifend libero venenatis pharetra ut iaculis arcu. Donec neque nibh, vehicula non porta a, consectetur eu erat. Sed eleifend, metus vel euismod placerat, lectus lectus sollicitudin nisl, ac elementum sem quam nec dolor. In hac habitasse platea dictumst. Proin vitae suscipit orci. Suspendisse a ipsum vel lorem tempus scelerisque et vitae neque. Proin sodales, tellus sit amet consequat cursus, odio massa ultricies enim, eu fermentum velit lectus in lacus. Quisque eu porttitor diam. Nunc felis purus, facilisis non tristique ac, pulvinar nec nulla. Duis dolor risus, egestas nec tristique ac, ullamcorper cras amet."
eval("'#{lorem}'").should == lorem
end
it "can pass the empty string back to ruby" do
eval("''").should == ""
end
it "can pass doubles back to ruby" do
eval("2.5").should == 2.5
end
it "can pass fixed numbers back to ruby" do
eval("1").should == 1
end
it "can pass boolean values back to ruby" do
eval("true").should be(true)
eval("false").should be(false)
end
it "can pass objects back to ruby" do
eval("({foo: 'bar', baz: 'bang', '5': 5, segfault: {}})").tap do |object|
object.should_not be_nil
object['foo'].should == 'bar'
object['baz'].should == 'bang'
object['5'].should == 5
object['segfault'].should be_kind_of(V8::JSObject)
end
end
end
describe "Calling Ruby Code from JavaScript" do
it "knows your name" do
class Foo
def call
end
end
foo = Foo.new
#V8.what_is_this? Class.new
# V8.what_is_this? Module.new
# V8.what_is_this? Object.new
# V8.what_is_this? :foo
# V8.what_is_this? V8::JSObject.new
V8.what_is_this?(proc {|foo| "string form is: #{foo}"})
V8.what_is_this?(foo.method(:bar))
# V8.what_is_this?(foo)
end
it "can embed ruby values into javascript" do
@cxt["bar"] = 9
@cxt['foo'] = "bar"
@cxt['num'] = 3.14
@cxt['trU'] = true
@cxt['falls'] = false
@cxt.eval("bar + 10").should be(19)
@cxt.eval('foo').should == "bar"
@cxt.eval('num').should == 3.14
@cxt.eval('trU').should be(true)
@cxt.eval('falls').should be(false)
end
it "can embed a ruby closure and call it from javascript" do
V8::JSObject.new.tap do |o|
o.call_something(lambda{ puts "bar"})
end
# pending
# @cxt['times'] = lambda {|lhs, rhs| lhs * rhs}
# @cxt.eval('times(5,2)').should == 10
end
it "can call a bound ruby method" do
pending
five = singleton(5) do
def initialize(lhs)
@lhs = lhs
end
def times(rhs)
@lhs * rhs
end
end
eval('timesfive(3)', :timesfive => mult.method(:times)).should == 15
end
it "can embed a ruby object and call its methods" do
pending
eval('object.times(8,8)', :object => singelton {
def times(lhs, rhs)
lhs * rhs
end
})
end
it "unwraps ruby objects returned by embedded ruby code to maintain referential integrity" do
pending
mock(:object).tap do |o|
eval('get()', :get => lambda {o}).should be(o)
end
end
end
# describe "Passing Ruby Values Back from Javascript"
def eval(str, scope = nil)
@cxt.eval(str)
end
def singleton(*args, &body)
Class.new.class_eval(&body).new(*args)
end
end