bullring 0.6 → 0.7

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.
@@ -1,20 +1,28 @@
1
1
  require 'bullring/version'
2
2
  require 'bullring/worker'
3
+ require 'uglifier'
3
4
 
4
5
  module Bullring
5
6
 
6
7
  class << self
7
8
 
8
- attr_accessor :logger
9
+ def logger=(logger)
10
+ @logger = logger
11
+ end
12
+
13
+ def logger
14
+ @logger ||= DummyLogger.new
15
+ end
9
16
 
10
17
  # Order is important (and relative to calls to add_library)
11
- def add_library_file(filename)
12
- worker.add_library_file(filename)
18
+ def add_library_file(name, filename)
19
+ worker.add_library_file(name, filename)
13
20
  end
14
21
 
15
22
  # Order is important (and relative to calls to add_library_script)
16
- def add_library(script)
17
- worker.add_library(script)
23
+ def add_library(name, script)
24
+ script = Uglifier.compile(script, :copyright => false) if configuration.minify_libraries
25
+ worker.add_library(name, script)
18
26
  end
19
27
 
20
28
  def check(script, options = {})
@@ -65,6 +73,8 @@ module Bullring
65
73
  attr_accessor :jvm_init_heap_size
66
74
  attr_accessor :jvm_max_heap_size
67
75
  attr_accessor :jvm_young_heap_size
76
+ attr_accessor :minify_libraries
77
+ attr_accessor :server_max_bringup_time
68
78
 
69
79
  def initialize
70
80
  @execution_timeout_secs = 0.5
@@ -72,6 +82,8 @@ module Bullring
72
82
  @jvm_init_heap_size = '128m'
73
83
  @jvm_max_heap_size = '128m'
74
84
  @jvm_young_heap_size = '64m'
85
+ @minify_libraries = true
86
+ @server_max_bringup_time = 20 #seconds
75
87
  super
76
88
  end
77
89
  end
@@ -89,47 +101,12 @@ module Bullring
89
101
  @worker
90
102
  end
91
103
 
92
- # ESCAPE_MAP = {
93
- # '\\' => '\\\\',
94
- # "\r\n" => '\n',
95
- # "\n" => '\n',
96
- # "\r" => '\n',
97
- # '"' => '\"',
98
- # "'" => "\'"
99
- # }
100
- #
101
- # def prepare_source(source)
102
- #
103
- # # escape javascript characters (similar to Rails escape_javascript)
104
- # source.gsub!(/(\\|\r\n|[\n\r"'])/u) {|match| ESCAPE_MAP[match] }
105
- #
106
- # # make sure the source string is set up to be a multiline string in JS
107
- # source.gsub!(/\n/, '\ \n')
108
- #
109
- # source
110
- # end
111
-
112
- # ESCAPE_MAP2 = {
113
- # '\\' => '\\\\',
114
- # "\r\n" => "\n",
115
- # "\n" => "\n",
116
- # "\r" => "\n", # take these semicolons out b/c we should only use them at the end of a statement; in fact just kill comments
117
- # '"' => '\"', #need to make this surrounded by double quotes
118
- # "'" => "\'"
119
- # }
120
- #
121
- #
122
- # def prep_source(source)
123
- # # escape javascript characters (similar to Rails escape_javascript)
124
- # source.gsub!(/(\\|\r\n|[\n\r"'])/u) {|match| ESCAPE_MAP2[match] }
125
- #
126
- # # make sure the source string is set up to be a multiline string in JS
127
- # source.gsub!(/\n/, "\ \n")
128
- #
129
- # source
130
- #
131
- # end
132
- #
104
+ end
105
+
106
+ class DummyLogger
107
+ def method_missing(m, *args, &block)
108
+ # ignore
109
+ end
133
110
  end
134
111
 
135
112
  end
@@ -19,48 +19,91 @@ module Bullring
19
19
  # }
20
20
  # }
21
21
  #
22
- def initialize(options)
22
+ # The provided block will be called whenever this process connects (or
23
+ # reconnects) to a process, including when the process is restarted. This
24
+ # makes the block a good place to put initialization code for the process.
25
+ #
26
+ def initialize(options, &block)
23
27
  @options = options
28
+ @after_connect_block = block
24
29
  connect_to_process!
25
30
  end
26
31
 
27
32
  def alive?
28
33
  begin
29
- @process.nil? || @process.alive?
30
- rescue DRb::DRbConnError
34
+ (@process.nil? || @process.alive?).tap{|is_alive| Bullring.logger.debug {"#{caller_name} #{is_alive ? 'is alive!' : 'is not alive!'}"}}
35
+ rescue DRb::DRbConnError => e
36
+ Bullring.logger.debug {"#{caller_name}: Checking if server alive and got a connection error: " + e.inspect}
31
37
  return false
32
- rescue # things like name errors, in case server doesn't have an alive? method
38
+ rescue StandardError => e # things like name errors, in case server doesn't have an alive? method
39
+ Bullring.logger.debug {"#{caller_name}: Checking if server alive and got an error: " + e.inspect}
40
+ true
41
+ rescue
42
+ Bullring.logger.debug {"#{caller_name}: Checking if server alive and got an unknown error"}
33
43
  true
34
44
  end
35
45
  end
36
46
 
37
47
  def restart_if_needed!
48
+ Bullring.logger.debug {"#{caller_name}: In restart_if_needed!"}
38
49
  alive? || connect_to_process!
39
50
  end
40
51
 
41
52
  def method_missing(m, *args, &block)
42
53
  restart_if_needed!
43
- # @process.method_missing(m, args, block)
44
- @process.send(m, *args, &block)
54
+
55
+ @process.logger = Bullring.logger
56
+ result = @process.send(m, *args, &block)
57
+ @process.logger = nil
58
+
59
+ result
45
60
  end
46
61
 
47
62
  def process_port_active?
48
- Network::is_port_in_use?(@options[:process][:host],@options[:process][:port])
63
+ in_use = Network::is_port_in_use?(host,port)
64
+ Bullring.logger.debug {"#{caller_name}: Port #{port} on #{host} is #{in_use ? 'active' : 'inactive'}."}
65
+ in_use
49
66
  end
50
67
 
51
68
  # Creates a druby connection to the process, starting it up if necessary
52
69
  def connect_to_process!
70
+ Bullring.logger.debug{"#{caller_name}: Connecting to process..."}
71
+
53
72
  if !process_port_active?
54
- Process.spawn([@options[:process][:command], @options[:process][:args]].flatten.join(" "))
73
+ Bullring.logger.debug {"#{caller_name}: Spawning process..."}
74
+
75
+ # Spawn the process in its own process group so it stays alive even if this process dies
76
+ pid = Process.spawn([@options[:process][:command], @options[:process][:args]].flatten.join(" "), {:pgroup => true})
77
+ Process.detach(pid)
55
78
 
79
+ time_sleeping = 0
56
80
  while (!process_port_active?)
57
81
  sleep(0.2)
82
+ if (time_sleeping += 0.2) > @options[:process][:max_bringup_time]
83
+ Bullring.logger.error {"#{caller_name}: Timed out waiting to bring up the process"}
84
+ raise StandardError, "#{caller_name}: Timed out waiting to bring up the process", caller
85
+ end
58
86
  end
59
87
  end
60
88
 
61
- DRb.start_service "druby://localhost:0"
62
- @process = DRbObject.new nil, "druby://#{@options[:process][:host]}:#{@options[:process][:port]}"
89
+ if !@local_service.nil?
90
+ @local_service.stop_service
91
+ Bullring.logger.debug {"#{caller_name}: Stopped local service on #{@local_service.uri}"}
92
+ end
93
+
94
+ @local_service = DRb.start_service "druby://localhost:0"
95
+ Bullring.logger.debug {"#{caller_name}: Started local service on #{@local_service.uri}"}
96
+
97
+ @process = DRbObject.new nil, "druby://#{host}:#{port}"
98
+
99
+ @after_connect_block.call(@process) if !@after_connect_block.nil?
63
100
  end
101
+
102
+ protected
103
+
104
+ def caller_name; @options[:caller_name]; end
105
+ def port; @options[:process][:port]; end
106
+ def host; @options[:process][:host]; end
64
107
  end
65
108
 
66
109
  end
@@ -7,11 +7,6 @@ module Bullring
7
7
  class IllegalArgument < StandardError; end
8
8
  class IllegalState < StandardError; end
9
9
  class PidDirUnavailable < StandardError; end
10
-
11
- class JSError < StandardError
12
- attr_accessor :cause
13
- attr_accessor :backtrace
14
- attr_accessor :message
15
- end
10
+ class JSError < StandardError; end
16
11
 
17
12
  end
@@ -1,3 +1,3 @@
1
1
  module Bullring
2
- VERSION = "0.6"
2
+ VERSION = "0.7"
3
3
  end
@@ -6,11 +6,11 @@ require 'bullring/util/exceptions'
6
6
  module Bullring
7
7
  class Worker
8
8
 
9
- def add_library(script)
9
+ def add_library(name, script)
10
10
  raise AbstractMethodCalled
11
11
  end
12
12
 
13
- def add_library_file(filename)
13
+ def add_library_file(name, filename)
14
14
  raise AbstractMethodCalled
15
15
  end
16
16
 
@@ -4,11 +4,21 @@ require 'logger'
4
4
 
5
5
  module Bullring
6
6
 
7
+ class DummyLogger
8
+ def method_missing(m, *args, &block)
9
+ # ignore
10
+ end
11
+ end
12
+
7
13
  class RhinoServer
8
14
 
15
+ @@dummy_logger = Bullring::DummyLogger.new
16
+
9
17
  def initialize
10
- @library_scripts = []
18
+ @library_scripts = {}
19
+ @setup_providers = []
11
20
  configure
21
+ logger.info {"#{logname}: Started a RhinoServer instance at #{Time.now}"}
12
22
  end
13
23
 
14
24
  def configure(options={})
@@ -18,18 +28,38 @@ module Bullring
18
28
 
19
29
  # Don't do a merge b/c jruby and ruby don't play nicely for some reason
20
30
  options.each{|k,v| @options[k] = v}
31
+ end
32
+
33
+ def load_setup(setup_provider)
34
+ # Get the libraries from the setup provider and add them to our local list.
35
+ # Hopefully, by calling 'to_s' we are getting copies that live only on our
36
+ # side of DRb. Store the provider so we can go back to it later if we
37
+ # find that we don't have a required library. Use a list of providers b/c
38
+ # some providers may have died off.
39
+
40
+ setup_provider.libraries.each do |name, script|
41
+ add_library(name.to_s, library.to_s)
42
+ end
21
43
 
22
- @logger = options[:logger] || DummyLogger.new
44
+ @setup_providers.push(setup_provider)
45
+ end
46
+
47
+ def logger=(logger)
48
+ @logger = logger
23
49
  end
24
50
 
25
- def add_library(script)
26
- @library_scripts.push(script)
51
+ def logger
52
+ @logger || @@dummy_logger
53
+ end
54
+
55
+ def add_library(name, script)
56
+ @library_scripts[name] = script
27
57
  end
28
58
 
29
- def add_library_file(filename)
59
+ def add_library_file(name, filename)
30
60
  raise NotYetImplemented
31
61
  script = read file into string
32
- @library_scripts.push(script)
62
+ @library_scripts[name] = script
33
63
  end
34
64
 
35
65
  def check(script, options)
@@ -67,8 +97,10 @@ module Bullring
67
97
 
68
98
  def run(script, options)
69
99
  Rhino::Context.open(:sealed => @options[:run_is_sealed], :restrictable => @options[:run_is_restrictable]) do |context|
70
- @library_scripts.each do |library|
71
- context_wrapper {context.eval(library)}
100
+
101
+ (options['library_names'] || []).each do |library_name|
102
+ library_script = @library_scripts[library_name] || fetch_library_script!(library_name)
103
+ context_wrapper {context.eval(library_script)}
72
104
  end
73
105
 
74
106
  context.timeout_limit = @options[:run_timeout_secs]
@@ -100,29 +132,20 @@ module Bullring
100
132
  result = yield
101
133
  duration = Time.now - start_time
102
134
 
103
- @logger.debug("Ran script (#{duration} secs); result: " + result.inspect)
135
+ logger.debug {"#{logname}: Ran script (#{duration} secs); result: " + result.inspect}
104
136
 
105
137
  return duration, result
106
138
  rescue Rhino::JSError => e
107
- @logger.debug("JSError! Cause: " + e.cause + "; Message: " + e.message)
108
- jsError = JSError.new
109
- jsError.cause = e.cause.to_s
110
- jsError.message = e.message.to_s
111
- jsError.backtrace = []
112
- raise jsError
113
- rescue Rhino::RunawayScriptError => e
114
- @logger.debug("Runaway Script: " + e.inspect)
115
- jsError = JSError.new
116
- jsError.cause = "Script took too long to run"
117
- raise jsError
139
+ logger.debug {"#{logname}: JSError! Cause: " + e.cause + "; Message: " + e.message}
140
+ raise Bullring::JSError, e.message.to_s, caller
141
+ rescue Rhino::RunawayScriptError, Rhino::ScriptTimeoutError => e
142
+ logger.debug {"#{logname}: Runaway Script: " + e.inspect}
143
+ raise Bullring::JSError, "Script took too long to run", caller
118
144
  rescue NameError => e
119
- @logger.debug("Name error: " + e.inspect)
120
- rescue Exception => e
121
- @logger.debug("Exception: " + e.inspect)
122
- raise e
123
- rescue Error => e
124
- @logger.debug("Error: " + e.inspect)
125
- raise e
145
+ logger.debug {"#{logname}: Name error: " + e.inspect}
146
+ rescue StandardError => e
147
+ logger.debug {"#{logname}: StandardError: " + e.inspect}
148
+ raise
126
149
  end
127
150
  end
128
151
 
@@ -141,20 +164,37 @@ module Bullring
141
164
  source
142
165
  end
143
166
 
144
- end
145
-
146
- class JSError < StandardError
147
- attr_accessor :cause
148
- attr_accessor :backtrace
149
- attr_accessor :message
150
- end
151
-
152
- class DummyLogger
153
- def method_missing(m, *args, &block)
154
- # ignore
167
+ # Goes back to the setup provider to the get the named script or throws an
168
+ # exception if there is no such script to retrieve.
169
+ def fetch_library_script!(name)
170
+ logger.debug {"#{logname}: The script named #{name} was not available so trying to fetch from clients"}
171
+
172
+ while (provider = @setup_providers.last)
173
+ begin
174
+ library_script = provider.libraries[name]
175
+ break if !library_script.nil?
176
+ rescue DRb::DRbConnError => e
177
+ logger.debug {"#{logname}: Could not connect to setup provider (its process probably died): " + e.inspect}
178
+ rescue StandardError => e
179
+ logger.error {"#{logname}: Encountered an unknown error searching setup providers for a script named #{name}: " + e.inspect}
180
+ ensure
181
+ # Toss the last element so we can continue searching prior elements
182
+ setup_providers.pop
183
+ end
184
+ end
185
+
186
+ # If after looking through the providers we are still empty handed, raise an error
187
+ raise NameError, "Client doesn't have script named #{name}", caller if library_script.nil?
188
+
189
+ add_library(name, library_script)
155
190
  end
191
+
192
+ def logname; "Bullring Server"; end
193
+
156
194
  end
157
195
 
196
+ class JSError < StandardError; end
197
+
158
198
  end
159
199
 
160
200
  #
@@ -4,6 +4,8 @@ module Bullring
4
4
 
5
5
  class RhinoServerWorker < Bullring::Worker
6
6
 
7
+ attr_reader :libraries
8
+
7
9
  def discard
8
10
  # Daemons.run(server_command, stop_options)
9
11
  # @server.kill if !@server.nil?
@@ -17,6 +19,7 @@ module Bullring
17
19
  # If already using jruby, can also just use rhino directly
18
20
 
19
21
  options = {}
22
+ options[:caller_name] = "Bullring"
20
23
  options[:process] = {
21
24
  :host => 'localhost',
22
25
  :port => Bullring.configuration.server_port,
@@ -26,40 +29,45 @@ module Bullring
26
29
  "#{Bullring.configuration.server_port}",
27
30
  Bullring.configuration.jvm_init_heap_size,
28
31
  Bullring.configuration.jvm_max_heap_size,
29
- Bullring.configuration.jvm_young_heap_size]
32
+ Bullring.configuration.jvm_young_heap_size],
33
+ :max_bringup_time => Bullring.configuration.server_max_bringup_time
30
34
  }
35
+
36
+ @libraries = {}
31
37
 
32
- @server = DrubiedProcess.new(options)
33
-
34
- @server.configure({:run_timeout_secs => Bullring.configuration.execution_timeout_secs,
35
- :logger => Bullring.logger})
36
- end
37
-
38
- # TODO important! this guy needs to know if the daemon crashed and restarted (so that it
39
- # can repopulate its library scripts; alternatively, we could pass the library scripts
40
- # in on the command line, in which case the restarting would pick them up)
38
+ @server = DrubiedProcess.new(options) do |process|
39
+ process.configure({:run_timeout_secs => Bullring.configuration.execution_timeout_secs})
40
+ process.load_setup(SetupProvider.new(self))
41
+ end
42
+ end
41
43
 
42
- def add_library(script)
43
- # this guy needs to maintain the library scripts in case the daemon restarts
44
- server.add_library(script)
44
+ def add_library(name, script)
45
+ # this guy needs to maintain the library scripts in case the server restarts, in which
46
+ # case the server will request the libraries through the SetupProvider
47
+ rescue_me do
48
+ Bullring.logger.debug { "Bullring: Adding library named '#{name}'" }
49
+ @libraries[name] = script
50
+ server.add_library(name, script)
51
+ end
45
52
  end
46
53
 
47
- def add_library_file(filename)
48
- server.add_library_script(filename)
54
+ def add_library_file(name, filename)
55
+ raise NotYetImplemented
56
+ # server.add_library_script(filename)
49
57
  end
50
58
 
51
59
  def check(script, options)
52
- server.check(script, options)
60
+ Bullring.logger.debug { "Bullring: Checking script with hash '#{script.hash}'" }
61
+ rescue_me do
62
+ server.check(script, options)
63
+ end
53
64
  end
54
65
 
55
66
  def run(script, options)
56
- begin
67
+ Bullring.logger.debug { "Bullring: Running script with hash '#{script.hash}'" }
68
+ rescue_me do
57
69
  result = server.run(script, options)
58
- result.respond_to?(:to_h) ? result.to_h : result
59
- rescue DRb::DRbUnknownError => e
60
- raise e.unknown
61
- rescue Bullring::JSError => e
62
- raise e
70
+ result.respond_to?(:to_h) ? result.to_h : result
63
71
  end
64
72
  end
65
73
 
@@ -67,13 +75,46 @@ module Bullring
67
75
  server.alive?
68
76
  end
69
77
 
78
+ class SetupProvider
79
+ include DRbUndumped
80
+
81
+ def initialize(wrapped_provider)
82
+ @wrapped_provider = wrapped_provider
83
+ end
84
+
85
+ def libraries
86
+ @wrapped_provider.libraries
87
+ end
88
+ end
89
+
70
90
  private
91
+
92
+ def rescue_me
93
+ @times_rescued = 0
94
+ begin
95
+ yield
96
+ rescue DRb::DRbConnError => e
97
+ Bullring.logger.error {"Bullring: Encountered a DRb connection error at time #{Time.now}: " + e.inspect}
98
+
99
+ if (@times_rescued += 1) < 2
100
+ Bullring.logger.debug {"Bullring: Attempting to restart the server at time #{Time.now}"}
101
+ @server.restart_if_needed!
102
+ retry
103
+ else
104
+ raise e
105
+ end
106
+ rescue Bullring::JSError => e
107
+ Bullring.logger.debug {"Bullring: Encountered a JSError: " + e.inspect}
108
+ raise e
109
+ rescue DRb::DRbUnknownError => e
110
+ Bullring.logger.error {"Bullring: Caught an unknown DRb error: " + e.inspect}
111
+ raise e.unknown
112
+ end
113
+ end
71
114
 
72
115
  attr_accessor :server
73
116
 
74
117
  end
75
118
 
76
-
77
-
78
119
  end
79
120
 
@@ -1,6 +1,12 @@
1
1
  require 'test_helper'
2
2
  # require 'test/unit'
3
3
  # require 'bullring'
4
+ require 'logger'
5
+
6
+ if false
7
+ Bullring.logger = Logger.new('bullring_test_log.txt')
8
+ Bullring.logger.level = Logger::DEBUG
9
+ end
4
10
 
5
11
  class BullringTest < Test::Unit::TestCase #ActiveSupport::TestCase
6
12
  test "truth" do
@@ -25,3 +25,15 @@
25
25
 
26
26
  ***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****
27
27
 
28
+
29
+ ***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****
30
+
31
+
32
+ ***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****
33
+
34
+
35
+ ***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****
36
+
37
+
38
+ ***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****
39
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullring
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.6'
4
+ version: '0.7'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-19 00:00:00.000000000Z
12
+ date: 2012-04-30 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: uglifier
16
- requirement: &2151838560 !ruby/object:Gem::Requirement
16
+ requirement: &2151829140 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2151838560
24
+ version_requirements: *2151829140
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: therubyrhino
27
- requirement: &2151837840 !ruby/object:Gem::Requirement
27
+ requirement: &2151828300 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2151837840
35
+ version_requirements: *2151828300
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sqlite3
38
- requirement: &2151837080 !ruby/object:Gem::Requirement
38
+ requirement: &2151827660 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2151837080
46
+ version_requirements: *2151827660
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rails
49
- requirement: &2151832800 !ruby/object:Gem::Requirement
49
+ requirement: &2151826580 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 3.2.2
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2151832800
57
+ version_requirements: *2151826580
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: test-unit
60
- requirement: &2151831460 !ruby/object:Gem::Requirement
60
+ requirement: &2151825960 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2151831460
68
+ version_requirements: *2151825960
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ruby-debug19
71
- requirement: &2151830600 !ruby/object:Gem::Requirement
71
+ requirement: &2151825060 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2151830600
79
+ version_requirements: *2151825060
80
80
  description: Safely run untrusted Javascript from Ruby
81
81
  email:
82
82
  - jps@kindlinglabs.com
@@ -155,7 +155,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
155
  version: '0'
156
156
  segments:
157
157
  - 0
158
- hash: -1682714108002767292
158
+ hash: -918890081008683451
159
159
  required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
@@ -164,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  version: '0'
165
165
  segments:
166
166
  - 0
167
- hash: -1682714108002767292
167
+ hash: -918890081008683451
168
168
  requirements: []
169
169
  rubyforge_project:
170
170
  rubygems_version: 1.8.6