From ae448321e8c264dc0cc6ca493622c0e88e17110f Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Fri, 8 Jun 2012 03:56:04 -0500 Subject: [PATCH] constants for Undefined, Null, True, False --- ext/v8/constants.cc | 34 +++++++++++++++++++++++++++++++++ ext/v8/init.cc | 2 ++ ext/v8/primitive.cc | 8 ++++++++ ext/v8/rr.h | 41 ++++++++++++++++++++++++++++++++++++++-- ext/v8/string.cc | 2 +- spec/c/constants_spec.rb | 11 +++++++++++ spec/spec_helper.rb | 3 +-- 7 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 ext/v8/constants.cc create mode 100644 ext/v8/primitive.cc create mode 100644 spec/c/constants_spec.rb diff --git a/ext/v8/constants.cc b/ext/v8/constants.cc new file mode 100644 index 0000000..65ca1b0 --- /dev/null +++ b/ext/v8/constants.cc @@ -0,0 +1,34 @@ +#include "rr.h" + +namespace rr { + VALUE Constants::_Undefined; + VALUE Constants::_Null; + VALUE Constants::_True; + VALUE Constants::_False; + void Constants::Init() { + ModuleBuilder("V8::C"). + defineSingletonMethod("Undefined", &Undefined). + defineSingletonMethod("Null", &Null). + defineSingletonMethod("True", &True). + defineSingletonMethod("False", &False); + + _Undefined = _Null = _True = _False = Qnil; + rb_gc_register_address(&_Undefined); + rb_gc_register_address(&_Null); + rb_gc_register_address(&_True); + rb_gc_register_address(&_False); + } + + VALUE Constants::Undefined(VALUE self) { + return cached(&_Undefined, v8::Undefined()); + } + VALUE Constants::Null(VALUE self) { + return cached(&_Null, v8::Null()); + } + VALUE Constants::True(VALUE self) { + return cached(&_True, v8::True()); + } + VALUE Constants::False(VALUE self) { + return cached(&_False, v8::False()); + } +} \ No newline at end of file diff --git a/ext/v8/init.cc b/ext/v8/init.cc index a598420..1a4d6a0 100644 --- a/ext/v8/init.cc +++ b/ext/v8/init.cc @@ -17,11 +17,13 @@ extern "C" { Invocation::Init(); Signature::Init(); Value::Init(); + Primitive::Init(); String::Init(); Object::Init(); Array::Init(); Function::Init(); Date::Init(); + Constants::Init(); External::Init(); Script::Init(); Template::Init(); diff --git a/ext/v8/primitive.cc b/ext/v8/primitive.cc new file mode 100644 index 0000000..6ea1186 --- /dev/null +++ b/ext/v8/primitive.cc @@ -0,0 +1,8 @@ +#include "rr.h" + +namespace rr { + void Primitive::Init() { + ClassBuilder("Primitive", Value::Class). + store(&Class); + } +} \ No newline at end of file diff --git a/ext/v8/rr.h b/ext/v8/rr.h index 5547db9..6a2af62 100644 --- a/ext/v8/rr.h +++ b/ext/v8/rr.h @@ -25,6 +25,7 @@ class Bool : public Equiv { public: Bool(VALUE val) : Equiv(val) {} Bool(bool b) : Equiv(b ? Qtrue : Qfalse) {} + Bool(v8::Handle b) : Equiv(b->Value() ? Qtrue : Qfalse) {} inline operator bool() {return RTEST(value);} }; @@ -103,7 +104,7 @@ public: Ref(VALUE value) { this->value = value; } - Ref(v8::Handle handle) { + Ref(v8::Handle handle, const char* label = "v8::Handle") { this->handle = handle; } virtual operator VALUE() const { @@ -298,6 +299,13 @@ public: virtual operator VALUE(); }; +class Primitive: public Ref { +public: + static void Init(); + inline Primitive(VALUE value) : Ref(value) {} + inline Primitive(v8::Handle primitive) : Ref(primitive) {} +}; + class String: public Ref { public: static void Init(); @@ -675,6 +683,27 @@ public: static VALUE doUnlockCall(VALUE code); }; +class Constants { +public: + static void Init(); + static VALUE Undefined(VALUE self); + static VALUE Null(VALUE self); + static VALUE True(VALUE self); + static VALUE False(VALUE self); + +private: + template static VALUE cached(VALUE* storage, v8::Handle value) { + if (!RTEST(*storage)) { + *storage = R(value); + } + return *storage; + } + static VALUE _Undefined; + static VALUE _Null; + static VALUE _True; + static VALUE _False; +}; + class V8 { public: static void Init(); @@ -684,6 +713,7 @@ public: class ClassBuilder { public: + ClassBuilder() {}; ClassBuilder(const char* name, VALUE superclass = rb_cObject); ClassBuilder(const char* name, const char* supername); ClassBuilder& defineMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE)); @@ -699,10 +729,17 @@ public: ClassBuilder& defineEnumConst(const char* name, int value); ClassBuilder& store(VALUE* storage); inline operator VALUE() {return this->value;} -private: +protected: VALUE value; }; +class ModuleBuilder : public ClassBuilder { +public: + inline ModuleBuilder(const char* name) { + this->value = rb_eval_string(name); + } +}; + } #endif diff --git a/ext/v8/string.cc b/ext/v8/string.cc index b0db7ac..6c5274f 100644 --- a/ext/v8/string.cc +++ b/ext/v8/string.cc @@ -3,7 +3,7 @@ namespace rr { void String::Init() { - ClassBuilder("String", Value::Class). + ClassBuilder("String", Primitive::Class). defineSingletonMethod("New", &New). defineSingletonMethod("Concat", &Concat). defineMethod("Utf8Value", &Utf8Value). diff --git a/spec/c/constants_spec.rb b/spec/c/constants_spec.rb new file mode 100644 index 0000000..d72d057 --- /dev/null +++ b/spec/c/constants_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe V8::C do + it "has constant methods for Undefined, Null, True and False" do + [:Undefined, :Null, :True, :False].each do |name| + constant = V8::C.send(name) + constant.should_not be_nil + V8::C.send(name).should be constant + end + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7692da7..029f905 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -29,8 +29,7 @@ module Autoscope def low_level_c_spec? return false unless described_class - name = described_class.name.split('::').last - return V8::C.const_defined?(name) && V8::C.const_get(name) == described_class + return described_class.name =~ /^V8::C/ end def explicitly_defines_scope?