From 1bd5c3b26e5fe84b34f15ff940be7dae7dd7e73a Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Thu, 30 Jul 2015 21:15:10 +0300 Subject: [PATCH] implement date and related conversions --- ext/v8/date.h | 18 ++++++++++++++++++ ext/v8/init.cc | 1 + ext/v8/object.cc | 7 +++---- ext/v8/rr.h | 1 + ext/v8/value.cc | 5 ----- lib/v8.rb | 3 ++- lib/v8/conversion.rb | 19 +++++++++++++++++++ lib/v8/date.rb | 7 +++++++ lib/v8/function.rb | 6 +++--- lib/v8/object.rb | 7 +++++-- spec/v8/context_spec.rb | 21 ++++++++++----------- 11 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 ext/v8/date.h create mode 100644 lib/v8/date.rb diff --git a/ext/v8/date.h b/ext/v8/date.h new file mode 100644 index 0000000..7ffcb7f --- /dev/null +++ b/ext/v8/date.h @@ -0,0 +1,18 @@ +// -*- mode: c++ -*- +#ifndef RR_DATE_H +#define RR_DATE_H + +namespace rr { + class Date : public Ref { + public: + Date(v8::Isolate* isolate, v8::Local date) : + Ref(isolate, date) {} + + static void Init() { + ClassBuilder("Date", Object::Class). + store(&Class); + }; + }; +} + +#endif /* RR_DATE_H */ diff --git a/ext/v8/init.cc b/ext/v8/init.cc index ded672f..c849806 100644 --- a/ext/v8/init.cc +++ b/ext/v8/init.cc @@ -19,6 +19,7 @@ extern "C" { Maybe::Init(); Value::Init(); Object::Init(); + Date::Init(); Primitive::Init(); Null::Init(); Undefined::Init(); diff --git a/ext/v8/object.cc b/ext/v8/object.cc index c69f3ec..e7a5807 100644 --- a/ext/v8/object.cc +++ b/ext/v8/object.cc @@ -105,16 +105,15 @@ namespace rr { if (handle->IsFunction()) { return Function(isolate, handle.As()); } - if (handle->IsArray()) { return Array(isolate, handle.As()); } + if (handle->IsDate()) { + return Date(isolate, handle.As()); + } // TODO: Enable this when the methods are implemented // - // if (handle->IsDate()) { - // // return Date(handle); - // } // // if (handle->IsBooleanObject()) { // // return BooleanObject(handle); diff --git a/ext/v8/rr.h b/ext/v8/rr.h index 2ef7fa4..aacde8a 100644 --- a/ext/v8/rr.h +++ b/ext/v8/rr.h @@ -52,6 +52,7 @@ inline VALUE not_implemented(const char* message) { #include "function.h" #include "object.h" +#include "date.h" #include "return-value.h" #include "property-callback.h" #include "property-callback-info.h" diff --git a/ext/v8/value.cc b/ext/v8/value.cc index d58a2d5..ce5061c 100644 --- a/ext/v8/value.cc +++ b/ext/v8/value.cc @@ -193,11 +193,6 @@ namespace rr { return Name(isolate, handle.As()); } - // TODO - // if (handle->IsDate()) { - // return Date((v8::Handle)v8::Date::Cast(*handle)); - // } - if (handle->IsFunction()) { return Function(isolate, v8::Handle::Cast(handle)); } diff --git a/lib/v8.rb b/lib/v8.rb index a5f271a..c2f6821 100644 --- a/lib/v8.rb +++ b/lib/v8.rb @@ -26,5 +26,6 @@ require 'v8/conversion' # require 'v8/access/invocation' # require 'v8/access' require 'v8/object' +require 'v8/date' # require 'v8/array' -# require 'v8/function' +require 'v8/function' diff --git a/lib/v8/conversion.rb b/lib/v8/conversion.rb index 656fa0b..64a1a36 100644 --- a/lib/v8/conversion.rb +++ b/lib/v8/conversion.rb @@ -37,6 +37,18 @@ module V8::C ::V8::Object.new self end end + + class Date + def to_ruby + ::V8::Date.new self + end + end + + class Function + def to_ruby + ::V8::Function.new self + end + end end class String @@ -51,6 +63,13 @@ class Fixnum end end +class Symbol + def to_v8(context) + isolate = context.isolate.native + V8::C::Symbol::For(context.isolate.native, V8::C::String::NewFromUtf8(isolate, to_s)) + end +end + # for type in [TrueClass, FalseClass, NilClass, Float] do # type.class_eval do # include V8::Conversion::Primitive diff --git a/lib/v8/date.rb b/lib/v8/date.rb new file mode 100644 index 0000000..0fc4e76 --- /dev/null +++ b/lib/v8/date.rb @@ -0,0 +1,7 @@ +module V8 + class Date < V8::Object + def value_of + @context.to_ruby @native.ValueOf() + end + end +end diff --git a/lib/v8/function.rb b/lib/v8/function.rb index c1cbbb4..b3ad665 100644 --- a/lib/v8/function.rb +++ b/lib/v8/function.rb @@ -1,5 +1,5 @@ class V8::Function < V8::Object - include V8::Error::Try + #include V8::Error::Try def initialize(native = nil) super do @@ -10,7 +10,7 @@ class V8::Function < V8::Object def methodcall(this, *args) @context.enter do this ||= @context.native.Global() - @context.to_ruby try {native.Call(@context.to_v8(this), args.map {|a| @context.to_v8 a})} + @context.to_ruby native.Call(@context.to_v8(this), args.map {|a| @context.to_v8 a}) end end @@ -25,4 +25,4 @@ class V8::Function < V8::Object @context.to_ruby try {native.NewInstance(args.map {|a| @context.to_v8 a})} end end -end \ No newline at end of file +end diff --git a/lib/v8/object.rb b/lib/v8/object.rb index 5382f16..83123e3 100644 --- a/lib/v8/object.rb +++ b/lib/v8/object.rb @@ -1,7 +1,6 @@ class V8::Object include Enumerable attr_reader :native - alias_method :to_v8, :native def initialize(native = nil) @context = V8::Context.current or fail "tried to initialize a #{self.class} without being in an entered V8::Context" @@ -11,7 +10,7 @@ class V8::Object def [](key) @context.enter do - @context.to_ruby @native.Get(@context.native, @context.to_v8(key)).FromJust() + @context.to_ruby @native.Get(@context.native, @context.to_v8(key.to_s)).FromJust() end end @@ -52,6 +51,10 @@ class V8::Object end end + def to_v8(context) + native + end + def respond_to?(method) super or self[method] != nil end diff --git a/spec/v8/context_spec.rb b/spec/v8/context_spec.rb index 3b2b7e2..732ef11 100644 --- a/spec/v8/context_spec.rb +++ b/spec/v8/context_spec.rb @@ -59,17 +59,16 @@ describe "V8::Context" do @cxt['nativeUtf8'].should == "Σὲ γνωρίζω ἀπὸ τὴν κόψη" end - # xit "translates JavaScript dates properly into ruby Time objects" do - # now = Time.now - # @cxt.eval('new Date()').tap do |time| - # time.should be_kind_of(Time) - # time.year.should == now.year - # time.day.should == now.day - # time.month.should == now.month - # time.min.should == now.min - # time.sec.should == now.sec - # end - # end + it "translates JavaScript dates objects" do + now = Time.now + @cxt.eval('new Date()').tap do |time| + expect(time.getDate().to_i).to eql now.day + expect(time.getFullYear().to_i).to eql now.year + expect(time.getMonth().to_i).to eql now.month - 1 + expect(time.getMinutes().to_i).to eql now.min + expect(time.getSeconds().to_i).to eql now.sec + end + end it "can pass objects back to ruby" do @cxt.eval("({foo: 'bar', baz: 'bang', '5': 5, embedded: {badda: 'bing'}})").tap do |object|