Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit 30dc90d

Browse files
committed
implement JavaScript numeric types
1 parent 75823c1 commit 30dc90d

11 files changed

Lines changed: 174 additions & 18 deletions

File tree

ext/v8/array.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ namespace rr {
2727
Array array(self);
2828
Locker lock(array.getIsolate());
2929

30-
return UInt32(array->Length());
30+
return Uint32_t(array->Length());
3131
}
3232

3333
VALUE Array::CloneElementAt(VALUE self, VALUE index) {
3434
Array array(self);
3535
Locker lock(array.getIsolate());
3636

37-
return Object(array.getIsolate(), array->CloneElementAt(UInt32(index)));
37+
return Object(array.getIsolate(), array->CloneElementAt(Uint32_t(index)));
3838
}
3939

4040
}

ext/v8/init.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ extern "C" {
1818
Object::Init();
1919
Primitive::Init();
2020
Name::Init();
21+
Number::Init();
2122
String::Init();
2223
Symbol::Init();
2324
Function::Init();

ext/v8/number.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "rr.h"
2+
3+
namespace rr {
4+
void Number::Init() {
5+
ClassBuilder("Number", Primitive::Class).
6+
7+
defineSingletonMethod("New", [] (VALUE self, VALUE r_isolate, VALUE value) -> VALUE {
8+
Isolate isolate(r_isolate);
9+
Locker lock(isolate);
10+
11+
return Number(isolate, NUM2DBL(value));
12+
}).
13+
14+
defineMethod("Value", [] (VALUE self) -> VALUE {
15+
Number number(self);
16+
Locker lock(number);
17+
18+
return DBL2NUM(number->Value());
19+
}).
20+
21+
store(&Class);
22+
23+
ClassBuilder("Integer", Number::Class).
24+
25+
defineSingletonMethod("New", [] (VALUE self, VALUE r_isolate, VALUE value) -> VALUE {
26+
Isolate isolate(r_isolate);
27+
Locker lock(isolate);
28+
29+
auto integer = v8::Integer::New(isolate, NUM2INT(value));
30+
return Value::handleToRubyObject(isolate, integer);
31+
}).
32+
33+
defineSingletonMethod("NewFromUnsigned", [] (VALUE self, VALUE r_isolate, VALUE value) -> VALUE {
34+
Isolate isolate(r_isolate);
35+
Locker lock(isolate);
36+
37+
auto uint = v8::Integer::NewFromUnsigned(isolate, NUM2UINT(value));
38+
return Value::handleToRubyObject(isolate, uint);
39+
}).
40+
41+
defineMethod("Value", [] (VALUE self) -> VALUE {
42+
Integer integer(self);
43+
Locker lock(integer);
44+
45+
return INT2NUM(integer->Value());
46+
}).
47+
48+
store(&Integer::Class);
49+
50+
ClassBuilder("Int32", Integer::Class).
51+
52+
defineMethod("Value", [] (VALUE self) -> VALUE {
53+
Int32 int32(self);
54+
Locker lock(int32);
55+
56+
return INT2NUM(int32->Value());
57+
}).
58+
store(&Int32::Class);
59+
60+
ClassBuilder("Uint32", Integer::Class).
61+
defineMethod("Value", [] (VALUE self) -> VALUE {
62+
Uint32 uint32(self);
63+
Locker lock(uint32);
64+
65+
return UINT2NUM(uint32->Value());
66+
}).
67+
store(&Uint32::Class);
68+
}
69+
}

ext/v8/number.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// -*- mode: c++ -*-
2+
#ifndef NUMBER_H
3+
#define NUMBER_H
4+
5+
namespace rr {
6+
class Number : public Ref<v8::Number> {
7+
public:
8+
Number(v8::Isolate* isolate, double value) :
9+
Ref<v8::Number>(isolate, v8::Number::New(isolate, value)) {}
10+
Number(v8::Isolate* isolate, v8::Handle<v8::Value> value) :
11+
Ref<v8::Number>(isolate, value.As<v8::Number>()) {}
12+
Number(VALUE self) :
13+
Ref<v8::Number>(self) {}
14+
15+
static void Init();
16+
};
17+
18+
class Integer : public Ref<v8::Integer> {
19+
public:
20+
Integer(v8::Isolate* isolate, int32_t value) :
21+
Ref<v8::Integer>(isolate, v8::Integer::New(isolate, value)) {}
22+
Integer(v8::Isolate* isolate, uint32_t value) :
23+
Ref<v8::Integer>(isolate, v8::Integer::NewFromUnsigned(isolate, value)) {}
24+
Integer(VALUE self) :
25+
Ref<v8::Integer>(self) {}
26+
};
27+
28+
class Int32 : public Ref<v8::Int32> {
29+
public:
30+
Int32(VALUE self) :
31+
Ref<v8::Int32>(self) {}
32+
Int32(v8::Isolate* isolate, v8::Handle<v8::Value> value) :
33+
Ref<v8::Int32>(isolate, value.As<v8::Int32>()) {}
34+
};
35+
36+
class Uint32 : public Ref<v8::Uint32> {
37+
public:
38+
Uint32(VALUE self) :
39+
Ref<v8::Uint32>(self) {}
40+
Uint32(v8::Isolate* isolate, v8::Handle<v8::Value> value) :
41+
Ref<v8::Uint32>(isolate, value.As<v8::Uint32>()) {}
42+
};
43+
}
44+
45+
46+
#endif /* NUMBER_H */

ext/v8/object.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace rr {
2727
Locker lock(isolate);
2828

2929
if (rb_obj_is_kind_of(key, rb_cNumeric)) {
30-
return Bool::Maybe(object->Set(context, UInt32(key), Value::rubyObjectToHandle(isolate, value)));
30+
return Bool::Maybe(object->Set(context, UInt32_t(key), Value::rubyObjectToHandle(isolate, value)));
3131
} else {
3232
return Bool::Maybe(object->Set(context, *Value(key), Value::rubyObjectToHandle(isolate, value)));
3333
}
@@ -40,7 +40,7 @@ namespace rr {
4040
Locker lock(isolate);
4141

4242
if (rb_obj_is_kind_of(key, rb_cNumeric)) {
43-
return Value::Maybe(isolate, object->Get(context, UInt32(key)));
43+
return Value::Maybe(isolate, object->Get(context, UInt32_t(key)));
4444
} else {
4545
return Value::Maybe(isolate, object->Get(context, *Value(key)));
4646
}

ext/v8/rr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ inline VALUE not_implemented(const char* message) {
3737
#include "object.h"
3838
#include "array.h"
3939
#include "primitive.h"
40+
#include "number.h"
4041
#include "external.h"
4142
// This one is named v8_string to avoid name collisions with C's string.h
4243
#include "name.h"

ext/v8/script-origin.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "rr.h"
22

33
namespace rr {
4-
VALUE ScriptOrigin::Class;
4+
VALUE ScriptOrigin::Class;
55
void ScriptOrigin::Init() {
66
ClassBuilder("ScriptOrigin").
77
defineSingletonMethod("new", &initialize).

ext/v8/uint32.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,27 @@ namespace rr {
1111
* Ruby VALUE is expected (such as a method call) E.g.
1212
*
1313
* uint_32_t myInt = 5;
14-
* rb_funcall(UInt32(myInt), rb_intern("to_s")); //=> <String "5">
14+
* rb_funcall(Uint32_t(myInt), rb_intern("to_s")); //=> <String "5">
1515
*
1616
* It also converts a Ruby `VALUE` into its corresponding
1717
* `uint32_t`:
1818
*
19-
* uint_32_t myInt = UInt32(rb_eval_string("5")); //=> 5
19+
* uint_32_t myInt = Uint32_t(rb_eval_string("5")); //=> 5
2020
*
2121
* Like all `Equiv`s, it stores itself internally as a Ruby `VALUE`
2222
*/
23-
class UInt32 : public Equiv {
23+
class Uint32_t : public Equiv {
2424
public:
2525
/**
26-
* Construct a UInt32 from a Ruby `VALUE`
26+
* Construct a Uint32_t from a Ruby `VALUE`
2727
*/
28-
UInt32(VALUE val) : Equiv(val) {}
28+
Uint32_t(VALUE val) : Equiv(val) {}
2929

3030
/**
31-
* Construct a UInt32 from a `uint32_t` by converting it into its
31+
* Construct a Uint32_t from a `uint32_t` by converting it into its
3232
* corresponding `VALUE`.
3333
*/
34-
UInt32(uint32_t ui) : Equiv(UINT2NUM(ui)) {}
34+
Uint32_t(uint32_t ui) : Equiv(UINT2NUM(ui)) {}
3535

3636
/**
3737
* Coerce the Ruby `VALUE` into a `uint32_t`.

ext/v8/value.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,22 @@ namespace rr {
171171
}
172172

173173
if (handle->IsUint32()) {
174-
return UInt32(handle->Uint32Value());
174+
return Uint32(isolate, handle);
175175
}
176176

177177
if (handle->IsInt32()) {
178-
return INT2FIX(handle->Int32Value());
178+
return Int32(isolate, handle);
179+
}
180+
181+
if (handle->IsNumber()) {
182+
return Number(isolate, handle);
179183
}
180184

181185
if (handle->IsBoolean()) {
182186
return handle->BooleanValue() ? Qtrue : Qfalse;
183187
}
184188

185189
// TODO
186-
// if (handle->IsNumber()) {
187-
// return rb_float_new(handle->NumberValue());
188-
// }
189190

190191
if (handle->IsString()) {
191192
return String(isolate, handle->ToString());

spec/c/number_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
require 'c_spec_helper'
2+
3+
describe "V8::C::Number pyramid" do
4+
requires_v8_context
5+
6+
describe V8::C::Number do
7+
let(:number) { V8::C::Number::New @isolate, 25.325 }
8+
it "sees that value" do
9+
expect(number.Value()).to eql 25.325
10+
end
11+
it "is a kind of primitive" do
12+
expect(number).to be_kind_of V8::C::Primitive
13+
end
14+
end
15+
describe V8::C::Integer do
16+
let(:int) { V8::C::Integer::New @isolate, 5 }
17+
18+
it "is has a value of 5" do
19+
expect(int.Value()).to eql 5
20+
end
21+
22+
it "is a Uint32" do
23+
expect(int.IsUint32()).to be_truthy
24+
expect(int).to be_kind_of V8::C::Uint32
25+
end
26+
end
27+
describe V8::C::Int32 do
28+
let(:int32) { V8::C::Integer::New @isolate, -5 }
29+
30+
it "has a value of -5" do
31+
expect(int32.Value()).to eql -5
32+
end
33+
34+
it "is an Int32" do
35+
expect(int32).to be_kind_of V8::C::Int32
36+
end
37+
end
38+
end

0 commit comments

Comments
 (0)