therubyracer 0.7.5 → 0.8.0.pre
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of therubyracer might be problematic. Click here for more details.
- data/History.txt +2 -2
- data/README.rdoc +1 -1
- data/Rakefile +4 -2
- data/ext/v8/rr.cpp +9 -2
- data/ext/v8/rr.h +1 -0
- data/ext/v8/v8.cpp +2 -0
- data/ext/v8/v8_cxt.cpp +11 -0
- data/ext/v8/v8_locker.cpp +41 -0
- data/ext/v8/v8_locker.h +6 -0
- data/ext/v8/v8_obj.cpp +12 -0
- data/ext/v8/v8_script.cpp +2 -0
- data/ext/v8/v8_template.cpp +17 -7
- data/lib/v8.rb +3 -2
- data/lib/v8/access.rb +53 -168
- data/lib/v8/array.rb +2 -2
- data/lib/v8/context.rb +9 -7
- data/lib/v8/error.rb +5 -4
- data/lib/v8/function.rb +7 -34
- data/lib/v8/object.rb +10 -12
- data/lib/v8/portal.rb +325 -0
- data/lib/v8/portal/functions.rb +45 -0
- data/spec/redjs/jsapi_spec.rb +154 -50
- data/therubyracer.gemspec +4 -4
- metadata +17 -13
- data/ext/v8/upstream/2.3.3/tools/v8.xcodeproj/project.pbxproj +0 -1855
- data/lib/v8/to.rb +0 -82
- data/spec/v8/to_spec.rb +0 -14
data/History.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
=== 0.7.5 1010-08-03
|
2
|
-
*
|
2
|
+
* 4 major enhancements
|
3
3
|
* upgrade to V8 2.3.3
|
4
4
|
* property interceptors from ruby via [] and []=
|
5
5
|
* indexed property access via [] and []=
|
6
6
|
* property
|
7
|
-
*
|
7
|
+
* 3 minor enhancements
|
8
8
|
* several bugfixes
|
9
9
|
* stability: eliminate many segfaults
|
10
10
|
* don't enumerate property setters such as foo= from javascript
|
data/README.rdoc
CHANGED
@@ -38,7 +38,7 @@ Embed the V8 Javascript interpreter into Ruby.
|
|
38
38
|
# embed ruby code into your scope and call it from javascript
|
39
39
|
|
40
40
|
cxt["say"] = lambda {|word, times| word * times}
|
41
|
-
|
41
|
+
cxt.eval("say('Hello', 3)") #=> HelloHelloHello
|
42
42
|
|
43
43
|
# embed a ruby object into your scope and access its properties/methods from javascript
|
44
44
|
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ manifest.exclude "lib/v8/*.bundle", "lib/v8/*.so", "ext/**/test/*", "ext/**/test
|
|
7
7
|
Gem::Specification.new do |gemspec|
|
8
8
|
$gemspec = gemspec
|
9
9
|
gemspec.name = gemspec.rubyforge_project = "therubyracer"
|
10
|
-
gemspec.version = "0.
|
10
|
+
gemspec.version = "0.8.0.pre"
|
11
11
|
gemspec.summary = "Embed the V8 Javascript interpreter into Ruby"
|
12
12
|
gemspec.description = "Call javascript code and manipulate javascript objects from ruby. Call ruby code and manipulate ruby objects from javascript."
|
13
13
|
gemspec.email = "cowboyd@thefrontside.net"
|
@@ -20,6 +20,8 @@ Gem::Specification.new do |gemspec|
|
|
20
20
|
gemspec.files = manifest.to_a
|
21
21
|
end
|
22
22
|
|
23
|
+
task :default => :spec
|
24
|
+
|
23
25
|
desc "Build gem"
|
24
26
|
task :gem => :gemspec do
|
25
27
|
Gem::Builder.new($gemspec).build
|
@@ -32,8 +34,8 @@ task :gemspec => :clean do
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
desc "remove all generated artifacts except built v8 objects"
|
35
38
|
task :clean do
|
36
|
-
sh "rm -rf pkg"
|
37
39
|
sh "rm -rf *.gem"
|
38
40
|
sh "rm -rf ext/v8/Makefile"
|
39
41
|
sh "rm -rf ext/v8/*.bundle ext/v8/*.so"
|
data/ext/v8/rr.cpp
CHANGED
@@ -19,6 +19,12 @@ VALUE rr_define_class(const char *name, VALUE superclass) {
|
|
19
19
|
return klass;
|
20
20
|
}
|
21
21
|
|
22
|
+
VALUE rr_define_module(const char *name) {
|
23
|
+
VALUE V8 = rb_define_module("V8");
|
24
|
+
VALUE V8_C = rb_define_module_under(V8, "C");
|
25
|
+
return rb_define_module_under(V8_C, name);
|
26
|
+
}
|
27
|
+
|
22
28
|
VALUE rr_define_const(const char *name, VALUE value) {
|
23
29
|
VALUE V8 = rb_define_module("V8");
|
24
30
|
VALUE V8_C = rb_define_module_under(V8, "C");
|
@@ -100,7 +106,7 @@ VALUE rr_v82rb(double value) {
|
|
100
106
|
return rb_float_new(value);
|
101
107
|
}
|
102
108
|
VALUE rr_v82rb(int64_t value) {
|
103
|
-
return
|
109
|
+
return LONG2NUM(value);
|
104
110
|
}
|
105
111
|
VALUE rr_v82rb(uint32_t value) {
|
106
112
|
return UINT2NUM(value);
|
@@ -112,7 +118,8 @@ VALUE rr_v82rb(int32_t value) {
|
|
112
118
|
Handle<Value> rr_rb2v8(VALUE value) {
|
113
119
|
switch (TYPE(value)) {
|
114
120
|
case T_FIXNUM:
|
115
|
-
|
121
|
+
// TODO: use this conversion if value will fit in 32 bits.
|
122
|
+
// return Integer::New(FIX2LONG(value));
|
116
123
|
case T_FLOAT:
|
117
124
|
return Number::New(NUM2DBL(value));
|
118
125
|
case T_STRING:
|
data/ext/v8/rr.h
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#define rr_define_singleton_method(object, name, impl, argc) rb_define_singleton_method(object, name, (VALUE(*)(...))impl, argc)
|
9
9
|
|
10
10
|
VALUE rr_define_class(const char *name, VALUE superclass = rb_cObject);
|
11
|
+
VALUE rr_define_module(const char *name);
|
11
12
|
VALUE rr_define_const(const char *name, VALUE value);
|
12
13
|
|
13
14
|
VALUE rr_v82rb(v8::Handle<v8::Value> value);
|
data/ext/v8/v8.cpp
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
#include "v8_callbacks.h"
|
13
13
|
#include "v8_external.h"
|
14
14
|
#include "v8_exception.h"
|
15
|
+
#include "v8_locker.h"
|
15
16
|
|
16
17
|
#include <stdio.h>
|
17
18
|
|
@@ -35,5 +36,6 @@ extern "C" {
|
|
35
36
|
rr_init_v8_callbacks();
|
36
37
|
rr_init_v8_external();
|
37
38
|
rr_init_v8_exception();
|
39
|
+
rr_init_v8_locker();
|
38
40
|
}
|
39
41
|
}
|
data/ext/v8/v8_cxt.cpp
CHANGED
@@ -66,6 +66,15 @@ namespace {
|
|
66
66
|
return Qfalse;
|
67
67
|
}
|
68
68
|
}
|
69
|
+
VALUE GetData(VALUE self) {
|
70
|
+
HandleScope scope;
|
71
|
+
return rr_v82rb(unwrap(self)->GetData());
|
72
|
+
}
|
73
|
+
VALUE SetData(VALUE self, VALUE data) {
|
74
|
+
HandleScope scope;
|
75
|
+
unwrap(self)->SetData(rr_rb2v8(data)->ToString());
|
76
|
+
return Qnil;
|
77
|
+
}
|
69
78
|
}
|
70
79
|
|
71
80
|
void rr_init_cxt() {
|
@@ -77,5 +86,7 @@ void rr_init_cxt() {
|
|
77
86
|
rr_define_method(ContextClass, "Enter", Enter, 0);
|
78
87
|
rr_define_method(ContextClass, "Exit", Exit, 0);
|
79
88
|
rr_define_method(ContextClass, "IsEntered", IsEntered, 0);
|
89
|
+
rr_define_method(ContextClass, "GetData", GetData, 0);
|
90
|
+
rr_define_method(ContextClass, "SetData", SetData, 1);
|
80
91
|
}
|
81
92
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
#include "v8_locker.h"
|
3
|
+
|
4
|
+
using namespace v8;
|
5
|
+
|
6
|
+
namespace {
|
7
|
+
VALUE Lock(VALUE self) {
|
8
|
+
Locker locker;
|
9
|
+
return rb_yield(Qnil);
|
10
|
+
}
|
11
|
+
VALUE Unlock(VALUE self) {
|
12
|
+
Unlocker unlocker;
|
13
|
+
return rb_yield(Qnil);
|
14
|
+
}
|
15
|
+
VALUE StartPreemption(VALUE self, VALUE thread_id) {
|
16
|
+
Locker::StartPreemption(NUM2INT(rb_to_int(thread_id)));
|
17
|
+
return Qnil;
|
18
|
+
}
|
19
|
+
VALUE StopPreemption(VALUE self) {
|
20
|
+
Locker::StopPreemption();
|
21
|
+
return Qnil;
|
22
|
+
}
|
23
|
+
VALUE IsLocked(VALUE self) {
|
24
|
+
return rr_v82rb(Locker::IsLocked());
|
25
|
+
}
|
26
|
+
VALUE IsActive(VALUE self) {
|
27
|
+
return rr_v82rb(Locker::IsActive());
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
void rr_init_v8_locker() {
|
32
|
+
VALUE V8 = rb_define_module("V8");
|
33
|
+
VALUE V8_C = rb_define_module_under(V8, "C");
|
34
|
+
VALUE LockerModule = rb_define_module_under(V8_C, "Locker");
|
35
|
+
rr_define_singleton_method(V8_C, "Locker", Lock, 0);
|
36
|
+
rr_define_singleton_method(V8_C, "Unlocker", Unlock, 0);
|
37
|
+
rr_define_singleton_method(LockerModule, "StartPreemption", StartPreemption, 1);
|
38
|
+
rr_define_singleton_method(LockerModule, "StopPreemption", StopPreemption, 0);
|
39
|
+
rr_define_singleton_method(LockerModule, "IsLocked", IsLocked, 0);
|
40
|
+
rr_define_singleton_method(LockerModule, "IsActive", IsActive, 0);
|
41
|
+
}
|
data/ext/v8/v8_locker.h
ADDED
data/ext/v8/v8_obj.cpp
CHANGED
@@ -64,6 +64,16 @@ namespace {
|
|
64
64
|
HandleScope scope;
|
65
65
|
return rr_v82rb(unwrap(self)->GetHiddenValue(rr_rb2v8(key)->ToString()));
|
66
66
|
}
|
67
|
+
VALUE GetPrototype(VALUE self) {
|
68
|
+
HandleScope scope;
|
69
|
+
return rr_v82rb(unwrap(self)->GetPrototype());
|
70
|
+
}
|
71
|
+
VALUE SetPrototype(VALUE self, VALUE prototype) {
|
72
|
+
HandleScope scope;
|
73
|
+
Handle<Value> proto = rr_rb2v8(prototype);
|
74
|
+
Local<Object> me = unwrap(self);
|
75
|
+
return rr_v82rb(unwrap(self)->SetPrototype(rr_rb2v8(prototype)));
|
76
|
+
}
|
67
77
|
}
|
68
78
|
|
69
79
|
void rr_init_obj() {
|
@@ -74,6 +84,8 @@ void rr_init_obj() {
|
|
74
84
|
rr_define_method(rr_cV8_C_Object, "GetPropertyNames", GetPropertyNames, 0);
|
75
85
|
rr_define_method(rr_cV8_C_Object, "GetHiddenValue", GetHiddenValue, 1);
|
76
86
|
rr_define_method(rr_cV8_C_Object, "SetHiddenValue", SetHiddenValue, 2);
|
87
|
+
rr_define_method(rr_cV8_C_Object, "GetPrototype", GetPrototype, 0);
|
88
|
+
rr_define_method(rr_cV8_C_Object, "SetPrototype", SetPrototype, 1);
|
77
89
|
}
|
78
90
|
|
79
91
|
VALUE rr_reflect_v8_object(Handle<Value> value) {
|
data/ext/v8/v8_script.cpp
CHANGED
@@ -14,12 +14,14 @@ namespace {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
VALUE Compile(VALUE self, VALUE source, VALUE source_name) {
|
17
|
+
HandleScope scope;
|
17
18
|
Local<String> src(rr_rb2v8(source)->ToString());
|
18
19
|
Local<String> src_name(rr_rb2v8(source_name)->ToString());
|
19
20
|
return rr_v8_ref_create(self, Script::Compile(src, src_name));
|
20
21
|
}
|
21
22
|
|
22
23
|
VALUE Run(VALUE self) {
|
24
|
+
HandleScope scope;
|
23
25
|
Local<Script> script(V8_Ref_Get<Script>(self));
|
24
26
|
Local<Value> result(script->Run());
|
25
27
|
return result.IsEmpty() ? Qnil : rr_v82rb(result);
|
data/ext/v8/v8_template.cpp
CHANGED
@@ -38,6 +38,13 @@ namespace {
|
|
38
38
|
return Qnil;
|
39
39
|
}
|
40
40
|
|
41
|
+
Handle<Value> RubyInvocationCallback(const Arguments& args) {
|
42
|
+
VALUE code = (VALUE)External::Unwrap(args.Data());
|
43
|
+
VALUE rb_args = rr_v82rb(args);
|
44
|
+
VALUE result = rb_funcall(code, rb_intern("call"), 1, rb_args);
|
45
|
+
return rr_rb2v8(result);
|
46
|
+
}
|
47
|
+
|
41
48
|
namespace Obj {
|
42
49
|
|
43
50
|
/**
|
@@ -238,17 +245,19 @@ namespace {
|
|
238
245
|
);
|
239
246
|
return Qnil;
|
240
247
|
}
|
248
|
+
VALUE SetCallAsFunctionHandler(VALUE self) {
|
249
|
+
HandleScope scope;
|
250
|
+
VALUE code = rb_block_proc();
|
251
|
+
if (NIL_P(code)) {
|
252
|
+
return Qnil;
|
253
|
+
}
|
254
|
+
obj(self)->SetCallAsFunctionHandler(RubyInvocationCallback, rr_v8_external_create(code));
|
255
|
+
return Qnil;
|
256
|
+
}
|
241
257
|
}
|
242
258
|
|
243
259
|
namespace Func {
|
244
260
|
|
245
|
-
Handle<Value> RubyInvocationCallback(const Arguments& args) {
|
246
|
-
VALUE code = (VALUE)External::Unwrap(args.Data());
|
247
|
-
VALUE rb_args = rr_v82rb(args);
|
248
|
-
VALUE result = rb_funcall(code, rb_intern("call"), 1, rb_args);
|
249
|
-
return rr_rb2v8(result);
|
250
|
-
}
|
251
|
-
|
252
261
|
VALUE New(VALUE function_template) {
|
253
262
|
HandleScope handles;
|
254
263
|
VALUE code = rb_block_proc();
|
@@ -307,6 +316,7 @@ void rr_init_template() {
|
|
307
316
|
rr_define_method(ObjectTemplateClass, "NewInstance", Obj::NewInstance, 0);
|
308
317
|
rr_define_method(ObjectTemplateClass, "SetNamedPropertyHandler", Obj::SetNamedPropertyHandler, 5);
|
309
318
|
rr_define_method(ObjectTemplateClass, "SetIndexedPropertyHandler", Obj::SetIndexedPropertyHandler, 5);
|
319
|
+
rr_define_method(ObjectTemplateClass, "SetCallAsFunctionHandler", Obj::SetCallAsFunctionHandler, 0);
|
310
320
|
|
311
321
|
FunctionTemplateClass = rr_define_class("FunctionTemplate", Template);
|
312
322
|
rr_define_singleton_method(FunctionTemplateClass, "New", Func::New, 0);
|
data/lib/v8.rb
CHANGED
@@ -2,9 +2,10 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
2
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
4
|
module V8
|
5
|
-
VERSION = '0.
|
5
|
+
VERSION = '0.8.0.pre'
|
6
6
|
require 'v8/v8' #native glue
|
7
|
-
require 'v8/
|
7
|
+
require 'v8/portal'
|
8
|
+
require 'v8/portal/functions'
|
8
9
|
require 'v8/context'
|
9
10
|
require 'v8/object'
|
10
11
|
require 'v8/array'
|
data/lib/v8/access.rb
CHANGED
@@ -1,202 +1,87 @@
|
|
1
1
|
require 'set'
|
2
2
|
module V8
|
3
|
-
|
4
|
-
#TODO each context should get its own access rules instead of sharing them across
|
5
|
-
# contetxts
|
6
|
-
###### --cowboyd 07/07/2010
|
7
3
|
class Access
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def [](cls)
|
18
|
-
@classes ||= {}
|
19
|
-
if ref = @classes[cls.object_id]
|
20
|
-
if ref.weakref_alive?
|
21
|
-
ref.__getobj__
|
22
|
-
else
|
23
|
-
@classes.delete(cls.object_id)
|
24
|
-
self[cls]
|
25
|
-
end
|
4
|
+
def get(obj, name, &dontintercept)
|
5
|
+
methods = accessible_methods(obj)
|
6
|
+
if methods.include?(name)
|
7
|
+
method = obj.method(name)
|
8
|
+
method.arity == 0 ? method.call : method.unbind
|
9
|
+
elsif obj.respond_to?(:[])
|
10
|
+
obj.send(:[], name, &dontintercept)
|
26
11
|
else
|
27
|
-
|
28
|
-
Access.setuptemplate(t.InstanceTemplate())
|
29
|
-
if cls.name && cls.name =~ /(::)?(\w+?)$/
|
30
|
-
t.SetClassName(C::String::NewSymbol("rb::" + $2))
|
31
|
-
else
|
32
|
-
t.SetClassName("Ruby")
|
33
|
-
end
|
34
|
-
@classes[cls.object_id] = WeakRef.new(t)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def template(cls)
|
40
|
-
C::FunctionTemplate::New() do |arguments|
|
41
|
-
unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
|
42
|
-
C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
|
43
|
-
else
|
44
|
-
arguments.This().tap do |this|
|
45
|
-
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), arguments[0])
|
46
|
-
end
|
47
|
-
end
|
12
|
+
yield
|
48
13
|
end
|
49
14
|
end
|
50
15
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
16
|
+
def iget(obj, index, &dontintercept)
|
17
|
+
if obj.respond_to?(:[])
|
18
|
+
obj.send(:[], index, &dontintercept)
|
19
|
+
else
|
20
|
+
yield
|
54
21
|
end
|
55
22
|
end
|
56
23
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
IndexedPropertyGetter,
|
67
|
-
IndexedPropertySetter,
|
68
|
-
nil,
|
69
|
-
nil,
|
70
|
-
IndexedPropertyEnumerator
|
71
|
-
)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
class Constructors < Access
|
76
|
-
def self.[](cls)
|
77
|
-
Access[cls].tap do |template|
|
78
|
-
template.SetCallHandler() do |arguments|
|
79
|
-
wrap = nil
|
80
|
-
if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
|
81
|
-
wrap = arguments[0]
|
82
|
-
else
|
83
|
-
rbargs = []
|
84
|
-
for i in 0..arguments.Length() - 1
|
85
|
-
rbargs << To.rb(arguments[i])
|
86
|
-
end
|
87
|
-
instance = V8::Function.rubysend(cls, :new, *rbargs)
|
88
|
-
wrap = C::External::New(instance)
|
89
|
-
end
|
90
|
-
arguments.This().tap do |this|
|
91
|
-
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), wrap)
|
92
|
-
end
|
93
|
-
end
|
24
|
+
def set(obj, name, value, &dontintercept)
|
25
|
+
setter = name + "="
|
26
|
+
methods = accessible_methods(obj, true)
|
27
|
+
if methods.include?(setter)
|
28
|
+
obj.send(setter, value)
|
29
|
+
elsif obj.respond_to?(:[]=)
|
30
|
+
obj.send(:[]=, name, value, &dontintercept)
|
31
|
+
else
|
32
|
+
yield
|
94
33
|
end
|
95
34
|
end
|
96
|
-
end
|
97
35
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
break if ancestor == ::Object
|
104
|
-
methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
|
105
|
-
end
|
106
|
-
methods.reject! {|m| m == "[]" || m == "[]="}
|
36
|
+
def iset(obj, index, value, &dontintercept)
|
37
|
+
if obj.respond_to?(:[]=)
|
38
|
+
obj.send(:[]=, index, value, &dontintercept)
|
39
|
+
else
|
40
|
+
yield
|
107
41
|
end
|
108
42
|
end
|
109
|
-
end
|
110
43
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
methods = accessible_methods(obj)
|
117
|
-
if methods.include?(name)
|
118
|
-
method = obj.method(name)
|
119
|
-
if method.arity == 0
|
120
|
-
Function.rubycall(method)
|
121
|
-
else
|
122
|
-
To.v8(method)
|
44
|
+
def query(obj, name, attributes)
|
45
|
+
if obj.respond_to?(name)
|
46
|
+
attributes.dont_delete
|
47
|
+
unless obj.respond_to?(name + "=")
|
48
|
+
attributes.read_only
|
123
49
|
end
|
124
|
-
elsif obj.respond_to?(:[])
|
125
|
-
Function.rubysend(obj, :[], name)
|
126
50
|
else
|
127
|
-
|
51
|
+
yield
|
128
52
|
end
|
129
53
|
end
|
130
|
-
end
|
131
54
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
methods = accessible_methods(obj)
|
139
|
-
if methods.include?(setter)
|
140
|
-
Function.rubysend(obj, setter, To.rb(value))
|
141
|
-
value
|
142
|
-
elsif obj.respond_to?(:[]=)
|
143
|
-
Function.rubysend(obj, :[]=, name, To.rb(value))
|
144
|
-
value
|
55
|
+
def iquery(obj, index, attributes)
|
56
|
+
if obj.respond_to?(:[])
|
57
|
+
attributes.dont_delete
|
58
|
+
unless obj.respond_to?(:[]=)
|
59
|
+
attributes.read_only
|
60
|
+
end
|
145
61
|
else
|
146
|
-
|
62
|
+
yield
|
147
63
|
end
|
148
64
|
end
|
149
|
-
end
|
150
65
|
|
151
|
-
|
152
|
-
|
153
|
-
def self.call(info)
|
154
|
-
obj = To.rb(info.This())
|
155
|
-
methods = accessible_methods(obj).reject! {|m| m.to_s =~ /=$/}
|
156
|
-
names = V8::C::Array::New(methods.length)
|
157
|
-
methods.each_with_index do |name, i|
|
158
|
-
names.Set(i, C::String::New(name))
|
159
|
-
end
|
160
|
-
return names
|
66
|
+
def names(obj)
|
67
|
+
accessible_methods(obj)
|
161
68
|
end
|
162
|
-
end
|
163
69
|
|
164
|
-
|
165
|
-
|
166
|
-
obj = To.rb(info.This())
|
167
|
-
if obj.respond_to?(:[])
|
168
|
-
Function.rubysend(obj, :[], index)
|
169
|
-
else
|
170
|
-
C::Empty
|
171
|
-
end
|
70
|
+
def indices(obj)
|
71
|
+
obj.respond_to?(:length) ? (0..obj.length).to_a : yield
|
172
72
|
end
|
173
|
-
end
|
174
73
|
|
175
|
-
|
176
|
-
def self.call(index, value, info)
|
177
|
-
obj = To.rb(info.This())
|
178
|
-
if obj.respond_to?(:[]=)
|
179
|
-
Function.rubysend(obj, :[]=, index, To.rb(value))
|
180
|
-
value
|
181
|
-
else
|
182
|
-
C::Empty
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
74
|
+
private
|
186
75
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
rputs "index: #{index}"
|
194
|
-
indices.Set(index,index)
|
195
|
-
end
|
76
|
+
def accessible_methods(obj, special_methods = false)
|
77
|
+
obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods|
|
78
|
+
ancestors = obj.class.ancestors.dup
|
79
|
+
while ancestor = ancestors.shift
|
80
|
+
break if ancestor == ::Object
|
81
|
+
methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
|
196
82
|
end
|
197
|
-
|
198
|
-
C::Array::New()
|
83
|
+
methods.reject! {|m| m == "[]" || m == "[]=" || m =~ /=$/} unless special_methods
|
199
84
|
end
|
200
85
|
end
|
201
86
|
end
|
202
|
-
end
|
87
|
+
end
|