therubyracer-freebsd 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,17 @@
1
+
2
+ module V8
3
+ class Array < V8::Object
4
+
5
+ def each
6
+ @portal.open do |to|
7
+ for i in 0..(@native.Length() - 1)
8
+ yield to.rb(@native.Get(i))
9
+ end
10
+ end
11
+ end
12
+
13
+ def length
14
+ @native.Length()
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module V8
2
+ module C
3
+ # Shim to support the old style locking syntax. We don't currently
4
+ # deprecate this because it might make a comeback at some point.
5
+ #
6
+ # to synchronize access to V8, and to associate V8 with this thread:
7
+ #
8
+ # Locker() do
9
+ # #... interact with v8
10
+ # end
11
+ def self.Locker
12
+ lock = Locker.new
13
+ yield
14
+ ensure
15
+ lock.delete
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,133 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+
4
+ module V8
5
+ module CLI
6
+ def self.run(exename = 'v8', args = [])
7
+ options = OpenStruct.new
8
+ options.libs = []
9
+ options.libdirs = []
10
+ parser = OptionParser.new
11
+ parser.banner = "Usage: #{exename} [options]"
12
+ parser.on("-r", "--require FILE", "load and execute FILE as JavaScript source") {|r| options.libs << r}
13
+ parser.on("-i", "--interactive", "interactive mode") {options.interactive = true}
14
+ parser.on("-e", "--execute JAVASCRIPT", String, "evaluate JAVASCRIPT and exit") {|src| options.execute = src}
15
+ parser.on("--selftest", "check that therubyracer is functioning properly") {options.selftest = true}
16
+ parser.on_tail("-v", "--version", "Show version and exit") {options.version_info = true}
17
+ parser.on_tail("-h", "--help", "Show this message") do
18
+ puts parser
19
+ exit
20
+ end
21
+ begin
22
+ parser.parse!(args.dup)
23
+ rescue OptionParser::InvalidOption => e
24
+ puts "#{exename}: #{e.message}"
25
+ exit(1)
26
+ end
27
+ if options.version_info
28
+ require 'libv8'
29
+ puts "The Ruby Racer #{V8::VERSION}"
30
+ puts "V8 Version #{Libv8::V8_VERSION}"
31
+ exit
32
+ elsif options.selftest
33
+ self.test
34
+ end
35
+ Context.new(:with => Shell.new) do |cxt|
36
+ for libfile in options.libs do
37
+ load(cxt,libfile)
38
+ end
39
+ if options.interactive
40
+ repl(cxt, exename)
41
+ elsif options.execute
42
+ cxt.eval(options.execute, '<execute>')
43
+ else
44
+ begin
45
+ cxt.eval($stdin, '<stdin>')
46
+ rescue Interrupt => e
47
+ puts; exit
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def self.load(cxt, libfile)
54
+ begin
55
+ cxt.load(libfile)
56
+ rescue V8::JSError => e
57
+ puts e.message
58
+ puts e.backtrace(:javascript)
59
+ rescue StandardError => e
60
+ puts e
61
+ end
62
+ end
63
+
64
+ def self.test
65
+ begin
66
+ require 'rspec'
67
+ specs = File.expand_path('../../../spec', __FILE__)
68
+ $:.unshift specs
69
+ ARGV.clear
70
+ ARGV << specs
71
+ ::RSpec::Core::Runner.autorun
72
+ exit(0)
73
+ rescue LoadError => e
74
+ puts "selftest requires rspec to be installed (gem install rspec)"
75
+ exit(1)
76
+ end
77
+
78
+ end
79
+
80
+ def self.repl(cxt, exename)
81
+ require 'readline'
82
+ puts "help() for help. quit() to quit."
83
+ puts "The Ruby Racer #{V8::VERSION}"
84
+ puts "Vroom Vroom!"
85
+ trap("SIGINT") do
86
+ puts "^C"
87
+ end
88
+ loop do
89
+ line = Readline.readline("#{exename}> ", true)
90
+ begin
91
+ result = cxt.eval(line, '<shell>')
92
+ puts(result) unless result.nil?
93
+ rescue V8::JSError => e
94
+ puts e.message
95
+ puts e.backtrace(:javascript)
96
+ rescue StandardError => e
97
+ puts e
98
+ puts e.backtrace.join("\n")
99
+ end
100
+ end
101
+ end
102
+
103
+ class Shell
104
+ def to_s
105
+ "[object Shell]"
106
+ end
107
+
108
+ def print(string)
109
+ puts string
110
+ end
111
+
112
+ def exit(status = 0)
113
+ Kernel.exit(status)
114
+ end
115
+
116
+ alias_method :quit, :exit
117
+
118
+ def help(*args)
119
+ <<-HELP
120
+ print(msg)
121
+ print msg to STDOUT
122
+
123
+ exit(status = 0)
124
+ exit the shell
125
+ also: quit()
126
+
127
+ evalrb(source)
128
+ evaluate some ruby source
129
+ HELP
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,111 @@
1
+ require 'stringio'
2
+
3
+ module V8
4
+ class Context
5
+ attr_reader :native, :scope, :access
6
+
7
+ def initialize(opts = {})
8
+ @access = Access.new
9
+ @to = Portal.new(self, @access)
10
+ @to.lock do
11
+ with = opts[:with]
12
+ constructor = nil
13
+ template = if with
14
+ constructor = @to.templates.to_constructor(with.class)
15
+ constructor.disable()
16
+ constructor.template.InstanceTemplate()
17
+ else
18
+ C::ObjectTemplate::New()
19
+ end
20
+ @native = opts[:with] ? C::Context::New(template) : C::Context::New()
21
+ @native.enter do
22
+ @global = @native.Global()
23
+ @to.proxies.register_javascript_proxy @global, :for => with if with
24
+ constructor.enable() if constructor
25
+ @scope = @to.rb(@global)
26
+ @global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
27
+ end
28
+ yield(self) if block_given?
29
+ end
30
+ end
31
+
32
+ def eval(javascript, filename = "<eval>", line = 1)
33
+ if IO === javascript || StringIO === javascript
34
+ javascript = javascript.read()
35
+ end
36
+ err = nil
37
+ value = nil
38
+ @to.lock do
39
+ C::TryCatch.try do |try|
40
+ @native.enter do
41
+ script = C::Script::Compile(@to.v8(javascript.to_s), @to.v8(filename.to_s))
42
+ if try.HasCaught()
43
+ err = JSError.new(try, @to)
44
+ else
45
+ result = script.Run()
46
+ if try.HasCaught()
47
+ err = JSError.new(try, @to)
48
+ else
49
+ value = @to.rb(result)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ raise err if err
56
+ return value
57
+ end
58
+
59
+ def load(filename)
60
+ File.open(filename) do |file|
61
+ self.eval file, filename, 1
62
+ end
63
+ end
64
+
65
+ def [](key)
66
+ @to.open do
67
+ @to.rb @global.Get(@to.v8(key))
68
+ end
69
+ end
70
+
71
+ def []=(key, value)
72
+ @to.open do
73
+ @global.Set(@to.v8(key), @to.v8(value))
74
+ end
75
+ return value
76
+ end
77
+
78
+ def self.stack(limit = 99)
79
+ if native = C::Context::GetEntered()
80
+ global = native.Global()
81
+ cxt = global.GetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext")).Value()
82
+ cxt.instance_eval {@to.rb(C::StackTrace::CurrentStackTrace(limit))}
83
+ else
84
+ []
85
+ end
86
+ end
87
+
88
+ def self.passes_this_argument?
89
+ true
90
+ end
91
+ end
92
+
93
+ module C
94
+ class Context
95
+ def enter
96
+ if block_given?
97
+ if IsEntered()
98
+ yield(self)
99
+ else
100
+ Enter()
101
+ begin
102
+ yield(self)
103
+ ensure
104
+ Exit()
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,130 @@
1
+
2
+ module V8
3
+ class JSError < StandardError
4
+ attr_reader :value, :boundaries
5
+
6
+ def initialize(try, to)
7
+ @to = to
8
+ super(initialize_unsafe(try))
9
+ rescue Exception => e
10
+ @boundaries = [Boundary.new(:rbframes => e.backtrace)]
11
+ @value = e
12
+ super(<<-EOMSG)
13
+ You have uncovered what is probably a BUG in therubyracer exception code. An error report would be very helpful.
14
+ JSError#initialize failed!: #{e.message}"
15
+ EOMSG
16
+ end
17
+
18
+ def initialize_unsafe(try)
19
+ message = nil
20
+ ex = @to.rb(try.Exception())
21
+ @boundaries = [Boundary.new(:rbframes => caller(3), :jsframes => parse_js_frames(try))]
22
+ if V8::Object === ex
23
+ if msg = ex['message']
24
+ message = msg
25
+ else
26
+ message = ex.to_s
27
+ end
28
+ if cause = ex.instance_variable_get(:@native).GetHiddenValue("TheRubyRacer::Cause")
29
+ if !cause.IsEmpty()
30
+ prev = cause.Value()
31
+ if prev.kind_of?(JSError)
32
+ @boundaries.concat prev.boundaries
33
+ @value = prev.value
34
+ else
35
+ @value = prev
36
+ @boundaries.concat [Boundary.new(:rbframes => prev.backtrace)]
37
+ end
38
+ else
39
+ @value = ex
40
+ end
41
+ end
42
+ else
43
+ @value = ex
44
+ message = ex.to_s
45
+ end
46
+ return message
47
+ end
48
+
49
+ def in_ruby?
50
+ @value.kind_of?(Exception)
51
+ end
52
+
53
+ def in_javascript?
54
+ !in_ruby?
55
+ end
56
+
57
+ def backtrace(*modifiers)
58
+ trace_framework = modifiers.include?(:framework)
59
+ trace_ruby = modifiers.length == 0 || modifiers.include?(:ruby)
60
+ trace_javascript = modifiers.length == 0 || modifiers.include?(:javascript)
61
+ mixed = []
62
+ rbcontext = []
63
+ jscontext = []
64
+ @boundaries.each do |b|
65
+ rbframes = b.rbframes.dup
66
+ rbcontext.reverse_each do |frame|
67
+ if frame == rbframes.last
68
+ rbframes.pop
69
+ else
70
+ break
71
+ end
72
+ end if trace_ruby
73
+ jsframes = b.jsframes.dup
74
+ jscontext.reverse_each do |frame|
75
+ if frame == jsframes.last
76
+ jsframes.pop
77
+ else
78
+ break
79
+ end
80
+ end if trace_javascript
81
+ rbcontext = b.rbframes
82
+ jscontext = b.jsframes
83
+ rbframes.reject! {|f| f =~ /lib\/v8\/.*\.rb/} unless trace_framework
84
+ mixed.unshift(*rbframes) if trace_ruby
85
+ mixed.unshift(*jsframes) if trace_javascript
86
+ end
87
+ return mixed
88
+ end
89
+
90
+ def parse_js_frames(try)
91
+ #I can't figure out why V8 is not capturing the stacktrace here
92
+ #in terms of StackTrace and StackFrame objects, so we have to
93
+ #parse the string.
94
+ raw = @to.rb(try.StackTrace())
95
+ if raw && !raw.empty? && !syntax_error?(try)
96
+ raw.split("\n")[1..-1].tap do |frames|
97
+ frames.each {|frame| frame.strip!; frame.chomp!(",")}
98
+ end.reject(&:empty?)
99
+ else
100
+ msg = try.Message()
101
+ ["at #{@to.rb(msg.GetScriptResourceName())}:#{msg.GetLineNumber()}:#{msg.GetStartColumn() + 1}"]
102
+ end
103
+ end
104
+
105
+ #Syntax errors are weird in that they have a non-empty stack trace
106
+ #but it does not contain any source location information, so
107
+ #in these instances, we have to pull it out of the Message object
108
+ #in the TryCatch. Is there a better way to detect a syntax error
109
+ def syntax_error?(try)
110
+ ex = @to.rb(try.Exception())
111
+ if ex && ex.kind_of?(V8::Object)
112
+ type = ex["constructor"]
113
+ type && type.kind_of?(V8::Function) && type.name == "SyntaxError"
114
+ else
115
+ false
116
+ end
117
+ end
118
+
119
+ class Boundary
120
+ attr_reader :rbframes, :jsframes
121
+
122
+ def initialize(frames = {})
123
+ @rbframes = frames[:rbframes] || []
124
+ @jsframes = frames[:jsframes] || []
125
+ end
126
+ end
127
+ end
128
+ #deprecated -- use JSError
129
+ JavasriptError = JSError
130
+ end
@@ -0,0 +1,44 @@
1
+ module V8
2
+ class Function < V8::Object
3
+
4
+ def methodcall(thisObject, *args)
5
+ err = nil
6
+ return_value = nil
7
+ @portal.open do |to|
8
+ C::TryCatch.try do |try|
9
+ this = to.v8(thisObject)
10
+ return_value = to.rb(@native.Call(this, to.v8(args)))
11
+ err = JSError.new(try, to) if try.HasCaught()
12
+ end
13
+ end
14
+ raise err if err
15
+ return return_value
16
+ end
17
+
18
+ def call(*args)
19
+ @portal.open do
20
+ self.methodcall(@portal.context.native.Global(), *args)
21
+ end
22
+ end
23
+
24
+ def new(*args)
25
+ @portal.open do |to|
26
+ to.rb(@native.NewInstance(to.v8(args)))
27
+ end
28
+ end
29
+
30
+ def name
31
+ @portal.open do |to|
32
+ to.rb(@native.GetName())
33
+ end
34
+ end
35
+
36
+ def name=(name)
37
+ name.tap do
38
+ @portal.open do |to|
39
+ @native.SetName(to.v8(name))
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end