mini_racer 0.1.15 → 0.2.0

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.
@@ -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