therubyracer-freebsd 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +8 -0
  4. data/.yardopts +1 -0
  5. data/Changelog.md +231 -0
  6. data/Gemfile +3 -0
  7. data/README.md +167 -0
  8. data/Rakefile +26 -0
  9. data/bin/therubyracer +11 -0
  10. data/ext/v8/extconf.rb +26 -0
  11. data/ext/v8/rr.cpp +189 -0
  12. data/ext/v8/rr.h +41 -0
  13. data/ext/v8/v8.cpp +48 -0
  14. data/ext/v8/v8_array.cpp +48 -0
  15. data/ext/v8/v8_array.h +8 -0
  16. data/ext/v8/v8_callbacks.cpp +81 -0
  17. data/ext/v8/v8_callbacks.h +8 -0
  18. data/ext/v8/v8_context.cpp +92 -0
  19. data/ext/v8/v8_context.h +6 -0
  20. data/ext/v8/v8_date.cpp +40 -0
  21. data/ext/v8/v8_date.h +6 -0
  22. data/ext/v8/v8_debug.cpp +17 -0
  23. data/ext/v8/v8_debug.h +6 -0
  24. data/ext/v8/v8_exception.cpp +133 -0
  25. data/ext/v8/v8_exception.h +11 -0
  26. data/ext/v8/v8_external.cpp +70 -0
  27. data/ext/v8/v8_external.h +8 -0
  28. data/ext/v8/v8_function.cpp +69 -0
  29. data/ext/v8/v8_function.h +11 -0
  30. data/ext/v8/v8_handle.cpp +186 -0
  31. data/ext/v8/v8_handle.h +48 -0
  32. data/ext/v8/v8_locker.cpp +139 -0
  33. data/ext/v8/v8_locker.h +6 -0
  34. data/ext/v8/v8_message.cpp +67 -0
  35. data/ext/v8/v8_message.h +10 -0
  36. data/ext/v8/v8_object.cpp +122 -0
  37. data/ext/v8/v8_object.h +10 -0
  38. data/ext/v8/v8_script.cpp +36 -0
  39. data/ext/v8/v8_script.h +8 -0
  40. data/ext/v8/v8_string.cpp +52 -0
  41. data/ext/v8/v8_string.h +9 -0
  42. data/ext/v8/v8_template.cpp +344 -0
  43. data/ext/v8/v8_template.h +8 -0
  44. data/ext/v8/v8_try_catch.cpp +70 -0
  45. data/ext/v8/v8_try_catch.h +5 -0
  46. data/ext/v8/v8_v8.cpp +34 -0
  47. data/ext/v8/v8_v8.h +6 -0
  48. data/ext/v8/v8_value.cpp +175 -0
  49. data/ext/v8/v8_value.h +10 -0
  50. data/ext/v8/v8_weakref.cpp +61 -0
  51. data/ext/v8/v8_weakref.h +29 -0
  52. data/lib/v8.rb +23 -0
  53. data/lib/v8/access.rb +92 -0
  54. data/lib/v8/array.rb +17 -0
  55. data/lib/v8/c/locker.rb +18 -0
  56. data/lib/v8/cli.rb +133 -0
  57. data/lib/v8/context.rb +111 -0
  58. data/lib/v8/error.rb +130 -0
  59. data/lib/v8/function.rb +44 -0
  60. data/lib/v8/object.rb +69 -0
  61. data/lib/v8/portal.rb +86 -0
  62. data/lib/v8/portal/caller.rb +37 -0
  63. data/lib/v8/portal/constructor.rb +98 -0
  64. data/lib/v8/portal/function.rb +63 -0
  65. data/lib/v8/portal/interceptors.rb +152 -0
  66. data/lib/v8/portal/proxies.rb +151 -0
  67. data/lib/v8/portal/templates.rb +73 -0
  68. data/lib/v8/stack.rb +66 -0
  69. data/lib/v8/tap.rb +9 -0
  70. data/lib/v8/version.rb +3 -0
  71. data/spec/ext/array_spec.rb +15 -0
  72. data/spec/ext/cxt_spec.rb +57 -0
  73. data/spec/ext/ext_spec_helper.rb +27 -0
  74. data/spec/ext/func_spec.rb +64 -0
  75. data/spec/ext/object_spec.rb +10 -0
  76. data/spec/ext/string_spec.rb +11 -0
  77. data/spec/ext/try_catch_spec.rb +60 -0
  78. data/spec/redjs_spec.rb +9 -0
  79. data/spec/spec_helper.rb +9 -0
  80. data/spec/v8/error_spec.rb +131 -0
  81. data/spec/v8/portal/proxies_spec.rb +106 -0
  82. data/specmem/handle_memspec.rb +41 -0
  83. data/specmem/object_memspec.rb +14 -0
  84. data/specmem/proxies_memspec.rb +49 -0
  85. data/specmem/spec_helper.rb +24 -0
  86. data/specthread/spec_helper.rb +2 -0
  87. data/specthread/threading_spec.rb +13 -0
  88. data/thefrontside.png +0 -0
  89. data/therubyracer.gemspec +27 -0
  90. metadata +183 -0
@@ -0,0 +1,69 @@
1
+
2
+ module V8
3
+ class Object
4
+ include Enumerable
5
+
6
+ def initialize(native, portal)
7
+ @native, @portal = native, portal
8
+ end
9
+
10
+ def [](key)
11
+ @portal.open do |to|
12
+ to.rb(@native.Get(to.v8(key)))
13
+ end
14
+ end
15
+
16
+ def []=(key, value)
17
+ value.tap do
18
+ @portal.open do |to|
19
+ @native.Set(to.v8(key), to.v8(value))
20
+ end
21
+ end
22
+ end
23
+
24
+ def to_s
25
+ @portal.open do |to|
26
+ to.rb(@native.ToString())
27
+ end
28
+ end
29
+
30
+ def each
31
+ @portal.open do |to|
32
+ for prop in to.rb(@native.GetPropertyNames())
33
+ yield prop, self[prop]
34
+ end
35
+ end
36
+ end
37
+
38
+ def respond_to?(method)
39
+ super or self[method] != nil
40
+ end
41
+
42
+ def method_missing(name, *args, &block)
43
+ if name.to_s =~ /(.*)=$/
44
+ if args.length > 1
45
+ self[$1] = args
46
+ return args
47
+ else
48
+ self[$1] = args.first
49
+ return args
50
+ end
51
+ end
52
+ return super(name, *args, &block) unless self.respond_to?(name)
53
+ property = self[name]
54
+ if property.kind_of?(V8::Function)
55
+ property.methodcall(self, *args)
56
+ elsif args.empty?
57
+ property
58
+ else
59
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 0)" unless args.empty?
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ class Object
66
+ def eval_js(javascript)
67
+ V8::Context.new(:with => self).eval(javascript)
68
+ end
69
+ end
@@ -0,0 +1,86 @@
1
+
2
+ module V8
3
+ class Portal
4
+ attr_reader :context, :access, :proxies, :templates, :interceptors, :caller
5
+
6
+ def initialize(context, access)
7
+ @context, @access = context, access
8
+ @proxies = Proxies.new
9
+ @templates = Templates.new(self)
10
+ @interceptors = Interceptors.new(self)
11
+ @caller = Caller.new(self)
12
+ end
13
+
14
+ def lock
15
+ lock = V8::C::Locker.new
16
+ yield
17
+ ensure
18
+ lock.delete
19
+ end
20
+
21
+ def open
22
+ lock do
23
+ @context.native.enter do
24
+ yield(self)
25
+ end if block_given?
26
+ end
27
+ end
28
+
29
+ def rb(value)
30
+ @proxies.js2rb(value) do
31
+ case value
32
+ when V8::C::Function then V8::Function.new(value, self)
33
+ when V8::C::Array then V8::Array.new(value, self)
34
+ when V8::C::Object then V8::Object.new(value, self)
35
+ when V8::C::String then value.Utf8Value.tap {|s| return s.respond_to?(:force_encoding) ? s.force_encoding("UTF-8") : s}
36
+ when V8::C::Date then Time.at(value.NumberValue() / 1000)
37
+ when V8::C::StackTrace then V8::StackTrace.new(self, value)
38
+ when V8::C::Value then nil if value.IsEmpty()
39
+ else
40
+ value
41
+ end
42
+ end
43
+ end
44
+
45
+ def v8(value)
46
+ case value
47
+ when V8::Object
48
+ value.instance_eval {@native}
49
+ when String
50
+ C::String::New(value)
51
+ when Symbol
52
+ C::String::NewSymbol(value.to_s)
53
+ when Proc,Method,UnboundMethod
54
+ @proxies.rb2js(value) do
55
+ @templates.to_function(value).function
56
+ end
57
+ when ::Array
58
+ C::Array::New(value.length).tap do |a|
59
+ value.each_with_index do |item, i|
60
+ a.Set(i, v8(item))
61
+ end
62
+ end
63
+ when ::Hash
64
+ C::Object::New().tap do |o|
65
+ value.each do |key, val|
66
+ o.Set(v8(key), v8(val))
67
+ end
68
+ end
69
+ when ::Time
70
+ C::Date::New(value.to_f * 1000)
71
+ when ::Class
72
+ @proxies.rb2js(value) do
73
+ constructor = @templates.to_constructor(value)
74
+ constructor.exposed = true
75
+ constructor.function
76
+ end
77
+ when nil,Numeric,TrueClass,FalseClass, C::Value
78
+ value
79
+ else
80
+ @proxies.rb2js(value) do
81
+ @templates.to_constructor(value.class).allocate(value)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,37 @@
1
+
2
+ module V8
3
+ class Portal
4
+ class Caller
5
+
6
+ def initialize(portal)
7
+ @portal = portal
8
+ end
9
+
10
+ def raw
11
+ yield
12
+ rescue Exception => e
13
+ case e
14
+ when SystemExit, NoMemoryError
15
+ raise e
16
+ else
17
+ error = V8::C::Exception::Error(V8::C::String::New(e.message))
18
+ #TODO: This is almost certainly a crash here.
19
+ #we need to hold onto `error` while it bubbles up the javascript stack.
20
+ error.SetHiddenValue("TheRubyRacer::Cause", C::External::New(e))
21
+ V8::C::ThrowException(error)
22
+ end
23
+ end
24
+
25
+ def protect(*args, &block)
26
+ @portal.v8 raw(*args, &block)
27
+ end
28
+
29
+ def invoke(code, *args, &block)
30
+ protect do
31
+ args = args.slice(0, code.arity) if code.arity >= 0
32
+ code.call(*args, &block)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,98 @@
1
+
2
+ module V8
3
+ class Portal
4
+ class ConstructorAdapter
5
+ attr_reader :template, :exposed
6
+ alias_method :exposed?, :exposed
7
+
8
+ def initialize(templates, class_id)
9
+ @exposed = false
10
+ @class_id = class_id
11
+ @templates = templates
12
+ @invoke = method(:invoke)
13
+ @template = C::FunctionTemplate::New(@invoke)
14
+ portal.interceptors.setup(@template.InstanceTemplate())
15
+ cls = self.ruby_class
16
+ superclass = cls.superclass
17
+ if cls != ::Object && superclass != ::Object && superclass != ::Class
18
+ @template.Inherit(templates.to_constructor(superclass).template)
19
+ end
20
+ if cls.name && cls.name =~ /(::)?(\w+?)$/
21
+ template.SetClassName(C::String::NewSymbol("rb::" + $2))
22
+ else
23
+ template.SetClassName("Ruby")
24
+ end
25
+ end
26
+
27
+ def function
28
+ @template.GetFunction()
29
+ end
30
+
31
+ def allocate(object)
32
+ arguments = C::Array::New(1)
33
+ arguments.Set(0, C::External::New(object))
34
+ function.NewInstance(arguments)
35
+ end
36
+
37
+ def disable
38
+ @disabled = true
39
+ end
40
+
41
+ def enable
42
+ @disabled = nil
43
+ end
44
+
45
+ def invoke(arguments)
46
+ return if @disabled
47
+ if !@exposed
48
+ unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
49
+ C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
50
+ else
51
+ object = arguments[0].Value()
52
+ proxies.register_javascript_proxy arguments.This(), :for => object
53
+ end
54
+ else
55
+ instance = nil
56
+ if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
57
+ instance = arguments[0].Value()
58
+ else
59
+ rbargs = []
60
+ for i in 0..arguments.Length() - 1
61
+ rbargs << @templates.portal.rb(arguments[i])
62
+ end
63
+ instance = portal.caller.raw do
64
+ self.ruby_class.new(*rbargs)
65
+ end
66
+ end
67
+ proxies.register_javascript_proxy arguments.This(), :for => instance
68
+ end
69
+ end
70
+
71
+ def exposed=(exposed)
72
+ if exposed && !@augmented
73
+ #create a prototype so that this constructor also acts like a ruby object
74
+ prototype_template = C::ObjectTemplate::New()
75
+ portal.interceptors.setup(prototype_template)
76
+ prototype = prototype_template.NewInstance()
77
+ #set *that* object's prototype to an empty function so that it will look and behave like a function.
78
+ prototype.SetPrototype(C::FunctionTemplate::New().GetFunction())
79
+ template.GetFunction().SetPrototype(prototype)
80
+ @augmented = true
81
+ end
82
+ @exposed = exposed
83
+ end
84
+
85
+ def ruby_class
86
+ ObjectSpace._id2ref(@class_id)
87
+ end
88
+
89
+ def proxies
90
+ @templates.proxies
91
+ end
92
+
93
+ def portal
94
+ @templates.portal
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,63 @@
1
+ module V8
2
+ class Portal
3
+ class FunctionAdapter
4
+
5
+ attr_reader :template
6
+
7
+ def initialize(portal, code)
8
+ @portal = portal
9
+ @caller = case code
10
+ when Method then BoundCall.new(portal)
11
+ when UnboundMethod then BindAndCall.new(portal)
12
+ else Call.new(portal)
13
+ end
14
+ @code = code
15
+ @template = V8::C::FunctionTemplate::New(@caller, @code)
16
+ end
17
+
18
+ def function
19
+ @template.GetFunction()
20
+ end
21
+
22
+ class Call
23
+ def initialize(portal)
24
+ @portal = portal
25
+ end
26
+
27
+ def call(arguments)
28
+ proc = arguments.Data()
29
+ rbargs = [@portal.rb(arguments.This())]
30
+ for i in 0..arguments.Length() - 1
31
+ rbargs << @portal.rb(arguments[i])
32
+ end
33
+ @portal.caller.invoke(proc, *rbargs)
34
+ end
35
+ end
36
+
37
+ class BoundCall < Call
38
+ def call(arguments)
39
+ proc = arguments.Data()
40
+ rbargs = []
41
+ for i in 0..arguments.Length() - 1
42
+ rbargs << @portal.rb(arguments[i])
43
+ end
44
+ @portal.caller.invoke(proc, *rbargs)
45
+ end
46
+ end
47
+
48
+ class BindAndCall < Call
49
+ def call(arguments)
50
+ method = arguments.Data()
51
+ rbargs = []
52
+ for i in 0..arguments.Length() - 1
53
+ rbargs << @portal.rb(arguments[i])
54
+ end
55
+ this = @portal.rb(arguments.This())
56
+ @portal.caller.protect do
57
+ method.bind(this).call(*rbargs)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,152 @@
1
+ module V8
2
+ class Portal
3
+ class Interceptors
4
+ def initialize(portal)
5
+ @getter = NamedPropertyGetter.new(portal)
6
+ @setter = NamedPropertySetter.new(portal)
7
+ @query = nil
8
+ @deleter = nil
9
+ @enumerator = NamedPropertyEnumerator.new(portal)
10
+ @igetter = IndexedPropertyGetter.new(portal)
11
+ @isetter = IndexedPropertySetter.new(portal)
12
+ @iquery = nil
13
+ @ideleter = nil
14
+ @ienumerator = IndexedPropertyEnumerator.new(portal)
15
+ end
16
+
17
+ def setup(template)
18
+ template.SetNamedPropertyHandler(@getter,@setter,@query,@deleter,@enumerator, nil)
19
+ template.SetIndexedPropertyHandler(@igetter,@isetter,@iquery,@ideleter,@ienumerator, nil)
20
+ end
21
+
22
+ class PropertyAttributes
23
+ attr_reader :flags
24
+ def initialize
25
+ @flags = 0
26
+ end
27
+
28
+ def read_only
29
+ tap do
30
+ @flags |= V8::C::ReadOnly
31
+ end
32
+ end
33
+
34
+ def dont_enum
35
+ tap do
36
+ @flags |= V8::C::DontEnum
37
+ end
38
+ end
39
+
40
+ def dont_delete
41
+ tap do
42
+ @flags |= V8::C::DontDelete
43
+ end
44
+ end
45
+ end
46
+
47
+ class Interceptor
48
+
49
+ def initialize(portal)
50
+ @to, @access = portal, portal.access
51
+ end
52
+
53
+ def intercept(info, retval = nil, &code)
54
+ obj = @to.rb(info.This())
55
+ intercepts = true
56
+ result = @to.caller.protect do
57
+ dontintercept = proc do
58
+ intercepts = false
59
+ end
60
+ code.call(obj, dontintercept)
61
+ end
62
+ intercepts ? (retval || result) : C::Empty
63
+ end
64
+ end
65
+
66
+ class NamedPropertyGetter < Interceptor
67
+ def call(property, info)
68
+ intercept(info) do |obj, dontintercept|
69
+ @access.get(obj, @to.rb(property), &dontintercept)
70
+ end
71
+ end
72
+ end
73
+
74
+ class NamedPropertySetter < Interceptor
75
+ def call(property, value, info)
76
+ intercept(info, value) do |obj, dontintercept|
77
+ @access.set(obj, @to.rb(property), @to.rb(value), &dontintercept)
78
+ end
79
+ end
80
+ end
81
+
82
+ class NamedPropertyQuery
83
+ def call(property, info)
84
+ attributes = PropertyAttributes.new
85
+ result = intercept(info) do |obj, dontintercept|
86
+ @access.query(obj, @to.rb(property), attributes, &dontintercept)
87
+ end
88
+ return result == C::Empty ? result : C::Integer::New(attributes.flags)
89
+ end
90
+ end
91
+
92
+ class NamedPropertyEnumerator < Interceptor
93
+ def call(info)
94
+ intercept(info) do |obj, dontintercept|
95
+ @access.names(obj, &dontintercept).to_a
96
+ end
97
+ end
98
+ end
99
+
100
+ class NamedPropertyDeleter < Interceptor
101
+ def call(property, info)
102
+ intercept(info) do |obj, dontintercept|
103
+ @access.delete(obj, property, &dontintercept)
104
+ end
105
+ end
106
+ end
107
+
108
+ class IndexedPropertyGetter < Interceptor
109
+ def call(index, info)
110
+ intercept(info) do |obj, dontintercept|
111
+ @access.iget(obj, index, &dontintercept)
112
+ end
113
+ end
114
+ end
115
+
116
+ class IndexedPropertySetter < Interceptor
117
+ def call(index, value, info)
118
+ intercept(info, value) do |obj, dontintercept|
119
+ @access.iset(obj, index, @to.rb(value), &dontintercept)
120
+ end
121
+ end
122
+ end
123
+
124
+ class IndexedPropertyQuery < Interceptor
125
+ def call(property, info)
126
+ attributes = PropertyAttributes.new
127
+ result = intercept(info) do |obj, dontintercept|
128
+ @access.indices(obj, &dontintercept)
129
+ end
130
+ result == C::Empty ? C::Empty : C::Integer::New(attributes.flags)
131
+ end
132
+ end
133
+
134
+ class IndexedPropertyDeleter < Interceptor
135
+ def call(index, info)
136
+ intercept(info) do |obj, dontintercept|
137
+ @access.idelete(obj, index, &dontintercept)
138
+ end
139
+ end
140
+ end
141
+
142
+ class IndexedPropertyEnumerator < Interceptor
143
+ def call(info)
144
+ intercept(info) do |obj, dontintercept|
145
+ @access.indices(obj, &dontintercept)
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+