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,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