bullring 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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