mini_racer 0.1.15 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,15 +59,9 @@ module MiniRacer
59
59
  raise ArgumentError, "snapshot must be a Snapshot object, passed a #{snapshot.inspect}"
60
60
  end
61
61
 
62
- @lock = Mutex.new
63
-
64
62
  # defined in the C class
65
63
  init_with_snapshot(snapshot)
66
64
  end
67
-
68
- def with_lock
69
- @lock.synchronize { yield }
70
- end
71
65
  end
72
66
 
73
67
  class Platform
@@ -136,8 +130,6 @@ module MiniRacer
136
130
  end
137
131
  end
138
132
 
139
- attr_reader :isolate
140
-
141
133
  def initialize(options = nil)
142
134
  options ||= {}
143
135
 
@@ -151,7 +143,8 @@ module MiniRacer
151
143
  if options[:max_memory].is_a?(Numeric) && options[:max_memory] > 0
152
144
  @max_memory = options[:max_memory]
153
145
  end
154
- @isolate = options[:isolate] || Isolate.new(options[:snapshot])
146
+ # false signals it should be fetched if requested
147
+ @isolate = options[:isolate] || false
155
148
  @disposed = false
156
149
 
157
150
  @callback_mutex = Mutex.new
@@ -159,10 +152,14 @@ module MiniRacer
159
152
  @thread_raise_called = false
160
153
  @eval_thread = nil
161
154
 
162
- isolate.with_lock do
163
- # defined in the C class
164
- init_with_isolate(@isolate)
165
- end
155
+ # defined in the C class
156
+ init_unsafe(options[:isolate], options[:snapshot])
157
+ end
158
+
159
+ def isolate
160
+ return @isolate if @isolate != false
161
+ # defined in the C class
162
+ @isolate = create_isolate_value
166
163
  end
167
164
 
168
165
  def load(filename)
@@ -176,7 +173,7 @@ module MiniRacer
176
173
  filename = options && options[:filename].to_s
177
174
 
178
175
  @eval_thread = Thread.current
179
- isolate.with_lock do
176
+ isolate_mutex.synchronize do
180
177
  @current_exception = nil
181
178
  timeout do
182
179
  eval_unsafe(str, filename)
@@ -186,41 +183,67 @@ module MiniRacer
186
183
  @eval_thread = nil
187
184
  end
188
185
 
189
- def dispose
190
- if !@disposed
191
- isolate.with_lock do
192
- dispose_unsafe
186
+ def call(function_name, *arguments)
187
+ raise(ContextDisposedError, 'attempted to call function on a disposed context!') if @disposed
188
+
189
+ @eval_thread = Thread.current
190
+ isolate_mutex.synchronize do
191
+ timeout do
192
+ call_unsafe(function_name, *arguments)
193
193
  end
194
- @disposed = true
195
194
  end
195
+ ensure
196
+ @eval_thread = nil
197
+ end
198
+
199
+ def dispose
200
+ return if @disposed
201
+ isolate_mutex.synchronize do
202
+ dispose_unsafe
203
+ end
204
+ @disposed = true
205
+ @isolate = nil # allow it to be garbage collected, if set
196
206
  end
197
207
 
198
208
 
199
209
  def attach(name, callback)
210
+ raise(ContextDisposedError, 'attempted to call function on a disposed context!') if @disposed
200
211
 
201
212
  wrapped = lambda do |*args|
202
213
  begin
203
- @callback_mutex.synchronize{
204
- @callback_running = true
205
- }
206
214
 
207
- callback.call(*args)
208
- ensure
209
- @callback_mutex.synchronize {
210
- @callback_running = false
215
+ r = nil
216
+
217
+ begin
218
+ @callback_mutex.synchronize{
219
+ @callback_running = true
220
+ }
221
+ r = callback.call(*args)
222
+ ensure
223
+ @callback_mutex.synchronize{
224
+ @callback_running = false
225
+ }
226
+ end
211
227
 
212
- # this is some odd code, but it is required
213
- # if we raised on this thread we better wait for it
214
- # otherwise we may end up raising in an unsafe spot
228
+ # wait up to 2 seconds for this to be interrupted
229
+ # will very rarely be called cause #raise is called
230
+ # in another mutex
231
+ @callback_mutex.synchronize {
215
232
  if @thread_raise_called
216
- sleep 0.1
233
+ sleep 2
217
234
  end
235
+ }
236
+
237
+ r
238
+
239
+ ensure
240
+ @callback_mutex.synchronize {
218
241
  @thread_raise_called = false
219
242
  }
220
243
  end
221
244
  end
222
245
 
223
- isolate.with_lock do
246
+ isolate_mutex.synchronize do
224
247
  external = ExternalFunction.new(name, wrapped, self)
225
248
  @functions["#{name}"] = external
226
249
  end
@@ -245,7 +268,7 @@ module MiniRacer
245
268
 
246
269
  rp,wp = IO.pipe
247
270
 
248
- Thread.new do
271
+ t = Thread.new do
249
272
  begin
250
273
  result = IO.select([rp],[],[],(@timeout/1000.0))
251
274
  if !result
@@ -265,6 +288,10 @@ module MiniRacer
265
288
  end
266
289
 
267
290
  wp.write("done")
291
+
292
+ # ensure we do not leak a thread in state
293
+ t.join
294
+
268
295
  rval
269
296
 
270
297
  end
@@ -288,8 +315,33 @@ module MiniRacer
288
315
  # `size` and `warmup!` public methods are defined in the C class
289
316
  class Snapshot
290
317
  def initialize(str = '')
318
+ # ensure it first can load
319
+ begin
320
+ ctx = MiniRacer::Context.new
321
+ ctx.eval(str)
322
+ rescue MiniRacer::RuntimeError => e
323
+ raise MiniRacer::SnapshotError.new, e.message
324
+ end
325
+
326
+ @source = str
327
+
291
328
  # defined in the C class
292
329
  load(str)
293
330
  end
331
+
332
+ def warmup!(src)
333
+ # we have to do something here
334
+ # we are bloating memory a bit but it is more correct
335
+ # than hitting an exception when attempty to compile invalid source
336
+ begin
337
+ ctx = MiniRacer::Context.new
338
+ ctx.eval(@source)
339
+ ctx.eval(src)
340
+ rescue MiniRacer::RuntimeError => e
341
+ raise MiniRacer::SnapshotError.new, e.message
342
+ end
343
+
344
+ warmup_unsafe!(src)
345
+ end
294
346
  end
295
347
  end
@@ -1,3 +1,3 @@
1
1
  module MiniRacer
2
- VERSION = "0.1.15"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -25,10 +25,10 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "minitest", "~> 5.0"
26
26
  spec.add_development_dependency "rake-compiler"
27
27
 
28
- spec.add_dependency 'libv8', '~> 6.3'
28
+ spec.add_dependency 'libv8', '>= 6.3'
29
29
  spec.require_paths = ["lib", "ext"]
30
30
 
31
31
  spec.extensions = ["ext/mini_racer_extension/extconf.rb"]
32
32
 
33
- spec.required_ruby_version = '>= 2.0'
33
+ spec.required_ruby_version = '>= 2.3'
34
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_racer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.15
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-27 00:00:00.000000000 Z
11
+ date: 2018-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,14 +70,14 @@ dependencies:
70
70
  name: libv8
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '6.3'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '6.3'
83
83
  description: Minimal embedded v8 engine for Ruby
@@ -116,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: '2.0'
119
+ version: '2.3'
120
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  version: '0'
125
125
  requirements: []
126
126
  rubyforge_project:
127
- rubygems_version: 2.6.13
127
+ rubygems_version: 2.7.6
128
128
  signing_key:
129
129
  specification_version: 4
130
130
  summary: Minimal embedded v8 for Ruby