mini_racer 0.1.15 → 0.5.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.
@@ -0,0 +1,8 @@
1
+ require 'mkmf'
2
+
3
+ extension_name = 'mini_racer_loader'
4
+ dir_config extension_name
5
+
6
+ $CPPFLAGS += " -fvisibility=hidden "
7
+
8
+ create_makefile extension_name
@@ -0,0 +1,123 @@
1
+ #include <ruby.h>
2
+ #include <dlfcn.h>
3
+ #include <string.h>
4
+ #include <stdint.h>
5
+ #include <stdlib.h>
6
+
7
+ // Load a Ruby extension like Ruby does, only with flags that:
8
+ // a) hide symbols from other extensions (RTLD_LOCAL)
9
+ // b) bind symbols tightly (RTLD_DEEPBIND, when available)
10
+
11
+ void Init_mini_racer_loader(void);
12
+
13
+ static void *_dln_load(const char *file);
14
+
15
+ static VALUE _load_shared_lib(VALUE self, volatile VALUE fname)
16
+ {
17
+ (void) self;
18
+
19
+ // check that path is not tainted
20
+ SafeStringValue(fname);
21
+
22
+ FilePathValue(fname);
23
+ VALUE path = rb_str_encode_ospath(fname);
24
+
25
+ char *loc = StringValueCStr(path);
26
+ void *handle = _dln_load(loc);
27
+
28
+ return handle ? Qtrue : Qfalse;
29
+ }
30
+
31
+ // adapted from Ruby's dln.c
32
+ #define INIT_FUNC_PREFIX ((char[]) {'I', 'n', 'i', 't', '_'})
33
+ #define INIT_FUNCNAME(buf, file) do { \
34
+ const char *base = (file); \
35
+ const size_t flen = _init_funcname(&base); \
36
+ const size_t plen = sizeof(INIT_FUNC_PREFIX); \
37
+ char *const tmp = ALLOCA_N(char, plen + flen + 1); \
38
+ memcpy(tmp, INIT_FUNC_PREFIX, plen); \
39
+ memcpy(tmp+plen, base, flen); \
40
+ tmp[plen+flen] = '\0'; \
41
+ *(buf) = tmp; \
42
+ } while(0)
43
+
44
+ // adapted from Ruby's dln.c
45
+ static size_t _init_funcname(const char **file)
46
+ {
47
+ const char *p = *file,
48
+ *base,
49
+ *dot = NULL;
50
+
51
+ for (base = p; *p; p++) { /* Find position of last '/' */
52
+ if (*p == '.' && !dot) {
53
+ dot = p;
54
+ }
55
+ if (*p == '/') {
56
+ base = p + 1;
57
+ dot = NULL;
58
+ }
59
+ }
60
+ *file = base;
61
+ return (uintptr_t) ((dot ? dot : p) - base);
62
+ }
63
+
64
+ // adapted from Ruby's dln.c
65
+ static void *_dln_load(const char *file)
66
+ {
67
+ char *buf;
68
+ const char *error;
69
+ #define DLN_ERROR() (error = dlerror(), strcpy(ALLOCA_N(char, strlen(error) + 1), error))
70
+
71
+ void *handle;
72
+ void (*init_fct)(void);
73
+
74
+ INIT_FUNCNAME(&buf, file);
75
+
76
+ #ifndef RTLD_DEEPBIND
77
+ # define RTLD_DEEPBIND 0
78
+ #endif
79
+ /* Load file */
80
+ if ((handle = dlopen(file, RTLD_LAZY|RTLD_LOCAL|RTLD_DEEPBIND)) == NULL) {
81
+ DLN_ERROR();
82
+ goto failed;
83
+ }
84
+ #if defined(RUBY_EXPORT)
85
+ {
86
+ static const char incompatible[] = "incompatible library version";
87
+ void *ex = dlsym(handle, "ruby_xmalloc");
88
+ if (ex && ex != (void *) &ruby_xmalloc) {
89
+
90
+ # if defined __APPLE__
91
+ /* dlclose() segfaults */
92
+ rb_fatal("%s - %s", incompatible, file);
93
+ # else
94
+ dlclose(handle);
95
+ error = incompatible;
96
+ goto failed;
97
+ #endif
98
+ }
99
+ }
100
+ # endif
101
+
102
+ init_fct = (void (*)(void)) dlsym(handle, buf);
103
+ if (init_fct == NULL) {
104
+ error = DLN_ERROR();
105
+ dlclose(handle);
106
+ goto failed;
107
+ }
108
+
109
+ /* Call the init code */
110
+ (*init_fct)();
111
+
112
+ return handle;
113
+
114
+ failed:
115
+ rb_raise(rb_eLoadError, "%s", error);
116
+ }
117
+
118
+ __attribute__((visibility("default"))) void Init_mini_racer_loader()
119
+ {
120
+ VALUE mMiniRacer = rb_define_module("MiniRacer");
121
+ VALUE mLoader = rb_define_module_under(mMiniRacer, "Loader");
122
+ rb_define_singleton_method(mLoader, "load", _load_shared_lib, 1);
123
+ }
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MiniRacer
2
- VERSION = "0.1.15"
4
+ VERSION = "0.5.0"
5
+ LIBV8_NODE_VERSION = "~> 16.10.0.0"
3
6
  end
data/lib/mini_racer.rb CHANGED
@@ -1,10 +1,23 @@
1
1
  require "mini_racer/version"
2
- require "mini_racer_extension"
2
+ require "mini_racer_loader"
3
+ require "pathname"
4
+
5
+ ext_filename = "mini_racer_extension.#{RbConfig::CONFIG['DLEXT']}"
6
+ ext_path = Gem.loaded_specs['mini_racer'].require_paths
7
+ .map { |p| (p = Pathname.new(p)).absolute? ? p : Pathname.new(__dir__).parent + p }
8
+ ext_found = ext_path.map { |p| p + ext_filename }.find { |p| p.file? }
9
+
10
+ raise LoadError, "Could not find #{ext_filename} in #{ext_path.map(&:to_s)}" unless ext_found
11
+ MiniRacer::Loader.load(ext_found.to_s)
12
+
3
13
  require "thread"
4
14
  require "json"
5
15
 
6
16
  module MiniRacer
7
17
 
18
+ MARSHAL_STACKDEPTH_DEFAULT = 2**9-2
19
+ MARSHAL_STACKDEPTH_MAX_VALUE = 2**10-2
20
+
8
21
  class Error < ::StandardError; end
9
22
 
10
23
  class ContextDisposedError < Error; end
@@ -59,15 +72,9 @@ module MiniRacer
59
72
  raise ArgumentError, "snapshot must be a Snapshot object, passed a #{snapshot.inspect}"
60
73
  end
61
74
 
62
- @lock = Mutex.new
63
-
64
75
  # defined in the C class
65
76
  init_with_snapshot(snapshot)
66
77
  end
67
-
68
- def with_lock
69
- @lock.synchronize { yield }
70
- end
71
78
  end
72
79
 
73
80
  class Platform
@@ -136,22 +143,30 @@ module MiniRacer
136
143
  end
137
144
  end
138
145
 
139
- attr_reader :isolate
140
-
141
- def initialize(options = nil)
146
+ def initialize(max_memory: nil, timeout: nil, isolate: nil, ensure_gc_after_idle: nil, snapshot: nil, marshal_stack_depth: nil)
142
147
  options ||= {}
143
148
 
144
- check_init_options!(options)
149
+ check_init_options!(isolate: isolate, snapshot: snapshot, max_memory: max_memory, marshal_stack_depth: marshal_stack_depth, ensure_gc_after_idle: ensure_gc_after_idle, timeout: timeout)
145
150
 
146
151
  @functions = {}
147
152
  @timeout = nil
148
153
  @max_memory = nil
149
154
  @current_exception = nil
150
- @timeout = options[:timeout]
151
- if options[:max_memory].is_a?(Numeric) && options[:max_memory] > 0
152
- @max_memory = options[:max_memory]
155
+ @timeout = timeout
156
+ @max_memory = max_memory
157
+ @marshal_stack_depth = marshal_stack_depth
158
+
159
+ # false signals it should be fetched if requested
160
+ @isolate = isolate || false
161
+
162
+ @ensure_gc_after_idle = ensure_gc_after_idle
163
+
164
+ if @ensure_gc_after_idle
165
+ @last_eval = nil
166
+ @ensure_gc_thread = nil
167
+ @ensure_gc_mutex = Mutex.new
153
168
  end
154
- @isolate = options[:isolate] || Isolate.new(options[:snapshot])
169
+
155
170
  @disposed = false
156
171
 
157
172
  @callback_mutex = Mutex.new
@@ -159,10 +174,14 @@ module MiniRacer
159
174
  @thread_raise_called = false
160
175
  @eval_thread = nil
161
176
 
162
- isolate.with_lock do
163
- # defined in the C class
164
- init_with_isolate(@isolate)
165
- end
177
+ # defined in the C class
178
+ init_unsafe(isolate, snapshot)
179
+ end
180
+
181
+ def isolate
182
+ return @isolate if @isolate != false
183
+ # defined in the C class
184
+ @isolate = create_isolate_value
166
185
  end
167
186
 
168
187
  def load(filename)
@@ -170,13 +189,35 @@ module MiniRacer
170
189
  eval(File.read(filename))
171
190
  end
172
191
 
192
+ def write_heap_snapshot(file_or_io)
193
+ f = nil
194
+ implicit = false
195
+
196
+
197
+ if String === file_or_io
198
+ f = File.open(file_or_io, "w")
199
+ implicit = true
200
+ else
201
+ f = file_or_io
202
+ end
203
+
204
+ if !(File === f)
205
+ raise ArgumentError("file_or_io")
206
+ end
207
+
208
+ write_heap_snapshot_unsafe(f)
209
+
210
+ ensure
211
+ f.close if implicit
212
+ end
213
+
173
214
  def eval(str, options=nil)
174
215
  raise(ContextDisposedError, 'attempted to call eval on a disposed context!') if @disposed
175
216
 
176
217
  filename = options && options[:filename].to_s
177
218
 
178
219
  @eval_thread = Thread.current
179
- isolate.with_lock do
220
+ isolate_mutex.synchronize do
180
221
  @current_exception = nil
181
222
  timeout do
182
223
  eval_unsafe(str, filename)
@@ -184,43 +225,72 @@ module MiniRacer
184
225
  end
185
226
  ensure
186
227
  @eval_thread = nil
228
+ ensure_gc_thread if @ensure_gc_after_idle
187
229
  end
188
230
 
189
- def dispose
190
- if !@disposed
191
- isolate.with_lock do
192
- dispose_unsafe
231
+ def call(function_name, *arguments)
232
+ raise(ContextDisposedError, 'attempted to call function on a disposed context!') if @disposed
233
+
234
+ @eval_thread = Thread.current
235
+ isolate_mutex.synchronize do
236
+ timeout do
237
+ call_unsafe(function_name, *arguments)
193
238
  end
239
+ end
240
+ ensure
241
+ @eval_thread = nil
242
+ ensure_gc_thread if @ensure_gc_after_idle
243
+ end
244
+
245
+ def dispose
246
+ return if @disposed
247
+ isolate_mutex.synchronize do
248
+ return if @disposed
249
+ dispose_unsafe
194
250
  @disposed = true
251
+ @isolate = nil # allow it to be garbage collected, if set
195
252
  end
196
253
  end
197
254
 
198
255
 
199
256
  def attach(name, callback)
257
+ raise(ContextDisposedError, 'attempted to call function on a disposed context!') if @disposed
200
258
 
201
259
  wrapped = lambda do |*args|
202
260
  begin
203
- @callback_mutex.synchronize{
204
- @callback_running = true
205
- }
206
261
 
207
- callback.call(*args)
208
- ensure
209
- @callback_mutex.synchronize {
210
- @callback_running = false
262
+ r = nil
263
+
264
+ begin
265
+ @callback_mutex.synchronize{
266
+ @callback_running = true
267
+ }
268
+ r = callback.call(*args)
269
+ ensure
270
+ @callback_mutex.synchronize{
271
+ @callback_running = false
272
+ }
273
+ end
211
274
 
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
275
+ # wait up to 2 seconds for this to be interrupted
276
+ # will very rarely be called cause #raise is called
277
+ # in another mutex
278
+ @callback_mutex.synchronize {
215
279
  if @thread_raise_called
216
- sleep 0.1
280
+ sleep 2
217
281
  end
282
+ }
283
+
284
+ r
285
+
286
+ ensure
287
+ @callback_mutex.synchronize {
218
288
  @thread_raise_called = false
219
289
  }
220
290
  end
221
291
  end
222
292
 
223
- isolate.with_lock do
293
+ isolate_mutex.synchronize do
224
294
  external = ExternalFunction.new(name, wrapped, self)
225
295
  @functions["#{name}"] = external
226
296
  end
@@ -228,6 +298,38 @@ module MiniRacer
228
298
 
229
299
  private
230
300
 
301
+ def ensure_gc_thread
302
+ @last_eval = Process.clock_gettime(Process::CLOCK_MONOTONIC)
303
+ @ensure_gc_mutex.synchronize do
304
+ @ensure_gc_thread = nil if !@ensure_gc_thread&.alive?
305
+ @ensure_gc_thread ||= Thread.new do
306
+ ensure_gc_after_idle_seconds = @ensure_gc_after_idle / 1000.0
307
+ done = false
308
+ while !done
309
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
310
+
311
+ if @disposed
312
+ @ensure_gc_thread = nil
313
+ break
314
+ end
315
+
316
+ if !@eval_thread && ensure_gc_after_idle_seconds < now - @last_eval
317
+ @ensure_gc_mutex.synchronize do
318
+ isolate_mutex.synchronize do
319
+ if !@eval_thread
320
+ isolate.low_memory_notification if !@disposed
321
+ @ensure_gc_thread = nil
322
+ done = true
323
+ end
324
+ end
325
+ end
326
+ end
327
+ sleep ensure_gc_after_idle_seconds if !done
328
+ end
329
+ end
330
+ end
331
+ end
332
+
231
333
  def stop_attached
232
334
  @callback_mutex.synchronize{
233
335
  if @callback_running
@@ -245,7 +347,7 @@ module MiniRacer
245
347
 
246
348
  rp,wp = IO.pipe
247
349
 
248
- Thread.new do
350
+ t = Thread.new do
249
351
  begin
250
352
  result = IO.select([rp],[],[],(@timeout/1000.0))
251
353
  if !result
@@ -265,19 +367,50 @@ module MiniRacer
265
367
  end
266
368
 
267
369
  wp.write("done")
268
- rval
269
370
 
371
+ # ensure we do not leak a thread in state
372
+ t.join
373
+ t = nil
374
+
375
+ rval
376
+ ensure
377
+ # exceptions need to be handled
378
+ if t && wp
379
+ wp.write("done")
380
+ t.join
381
+ end
382
+ wp.close if wp
383
+ rp.close if rp
270
384
  end
271
385
 
272
- def check_init_options!(options)
273
- assert_option_is_nil_or_a('isolate', options[:isolate], Isolate)
274
- assert_option_is_nil_or_a('snapshot', options[:snapshot], Snapshot)
386
+ def check_init_options!(isolate:, snapshot:, max_memory:, marshal_stack_depth:, ensure_gc_after_idle:, timeout:)
387
+ assert_option_is_nil_or_a('isolate', isolate, Isolate)
388
+ assert_option_is_nil_or_a('snapshot', snapshot, Snapshot)
389
+
390
+ assert_numeric_or_nil('max_memory', max_memory, min_value: 10_000, max_value: 2**32-1)
391
+ assert_numeric_or_nil('marshal_stack_depth', marshal_stack_depth, min_value: 1, max_value: MARSHAL_STACKDEPTH_MAX_VALUE)
392
+ assert_numeric_or_nil('ensure_gc_after_idle', ensure_gc_after_idle, min_value: 1)
393
+ assert_numeric_or_nil('timeout', timeout, min_value: 1)
275
394
 
276
- if options[:isolate] && options[:snapshot]
395
+ if isolate && snapshot
277
396
  raise ArgumentError, 'can only pass one of isolate and snapshot options'
278
397
  end
279
398
  end
280
399
 
400
+ def assert_numeric_or_nil(option_name, object, min_value:, max_value: nil)
401
+ if max_value && object.is_a?(Numeric) && object > max_value
402
+ raise ArgumentError, "#{option_name} must be less than or equal to #{max_value}"
403
+ end
404
+
405
+ if object.is_a?(Numeric) && object < min_value
406
+ raise ArgumentError, "#{option_name} must be larger than or equal to #{min_value}"
407
+ end
408
+
409
+ if !object.nil? && !object.is_a?(Numeric)
410
+ raise ArgumentError, "#{option_name} must be a number, passed a #{object.inspect}"
411
+ end
412
+ end
413
+
281
414
  def assert_option_is_nil_or_a(option_name, object, klass)
282
415
  unless object.nil? || object.is_a?(klass)
283
416
  raise ArgumentError, "#{option_name} must be a #{klass} object, passed a #{object.inspect}"
@@ -288,8 +421,33 @@ module MiniRacer
288
421
  # `size` and `warmup!` public methods are defined in the C class
289
422
  class Snapshot
290
423
  def initialize(str = '')
424
+ # ensure it first can load
425
+ begin
426
+ ctx = MiniRacer::Context.new
427
+ ctx.eval(str)
428
+ rescue MiniRacer::RuntimeError => e
429
+ raise MiniRacer::SnapshotError.new, e.message, e.backtrace
430
+ end
431
+
432
+ @source = str
433
+
291
434
  # defined in the C class
292
435
  load(str)
293
436
  end
437
+
438
+ def warmup!(src)
439
+ # we have to do something here
440
+ # we are bloating memory a bit but it is more correct
441
+ # than hitting an exception when attempty to compile invalid source
442
+ begin
443
+ ctx = MiniRacer::Context.new
444
+ ctx.eval(@source)
445
+ ctx.eval(src)
446
+ rescue MiniRacer::RuntimeError => e
447
+ raise MiniRacer::SnapshotError.new, e.message, e.backtrace
448
+ end
449
+
450
+ warmup_unsafe!(src)
451
+ end
294
452
  end
295
453
  end
data/mini_racer.gemspec CHANGED
@@ -14,21 +14,26 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/discourse/mini_racer"
15
15
  spec.license = "MIT"
16
16
 
17
-
18
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(benchmark|test|spec|features)/}) }
19
- spec.bindir = "exe"
20
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.metadata = {
18
+ "bug_tracker_uri" => "https://github.com/discourse/mini_racer/issues",
19
+ "changelog_uri" => "https://github.com/discourse/mini_racer/blob/v#{spec.version}/CHANGELOG",
20
+ "documentation_uri" => "https://www.rubydoc.info/gems/mini_racer/#{spec.version}",
21
+ "source_code_uri" => "https://github.com/discourse/mini_racer/tree/v#{spec.version}",
22
+ }
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(benchmark|test|spec|features|examples)/}) }
21
25
  spec.require_paths = ["lib"]
22
26
 
23
- spec.add_development_dependency "bundler", "~> 1.12"
24
- spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "bundler"
28
+ spec.add_development_dependency "rake", ">= 12.3.3"
25
29
  spec.add_development_dependency "minitest", "~> 5.0"
26
30
  spec.add_development_dependency "rake-compiler"
31
+ spec.add_development_dependency "m"
27
32
 
28
- spec.add_dependency 'libv8', '~> 6.3'
33
+ spec.add_dependency 'libv8-node', MiniRacer::LIBV8_NODE_VERSION
29
34
  spec.require_paths = ["lib", "ext"]
30
35
 
31
- spec.extensions = ["ext/mini_racer_extension/extconf.rb"]
36
+ spec.extensions = ["ext/mini_racer_loader/extconf.rb", "ext/mini_racer_extension/extconf.rb"]
32
37
 
33
- spec.required_ruby_version = '>= 2.0'
38
+ spec.required_ruby_version = '>= 2.6'
34
39
  end
metadata CHANGED
@@ -1,43 +1,43 @@
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.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-27 00:00:00.000000000 Z
11
+ date: 2021-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.12'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.12'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 12.3.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 12.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -67,31 +67,49 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: libv8
70
+ name: m
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: libv8-node
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '6.3'
89
+ version: 16.10.0.0
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '6.3'
96
+ version: 16.10.0.0
83
97
  description: Minimal embedded v8 engine for Ruby
84
98
  email:
85
99
  - sam.saffron@gmail.com
86
100
  executables: []
87
101
  extensions:
102
+ - ext/mini_racer_loader/extconf.rb
88
103
  - ext/mini_racer_extension/extconf.rb
89
104
  extra_rdoc_files: []
90
105
  files:
106
+ - ".dockerignore"
107
+ - ".github/workflows/ci.yml"
91
108
  - ".gitignore"
92
109
  - ".travis.yml"
93
110
  - CHANGELOG
94
111
  - CODE_OF_CONDUCT.md
112
+ - Dockerfile
95
113
  - Gemfile
96
114
  - LICENSE.txt
97
115
  - README.md
@@ -100,13 +118,19 @@ files:
100
118
  - bin/setup
101
119
  - ext/mini_racer_extension/extconf.rb
102
120
  - ext/mini_racer_extension/mini_racer_extension.cc
121
+ - ext/mini_racer_loader/extconf.rb
122
+ - ext/mini_racer_loader/mini_racer_loader.c
103
123
  - lib/mini_racer.rb
104
124
  - lib/mini_racer/version.rb
105
125
  - mini_racer.gemspec
106
126
  homepage: https://github.com/discourse/mini_racer
107
127
  licenses:
108
128
  - MIT
109
- metadata: {}
129
+ metadata:
130
+ bug_tracker_uri: https://github.com/discourse/mini_racer/issues
131
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.5.0/CHANGELOG
132
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.5.0
133
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.5.0
110
134
  post_install_message:
111
135
  rdoc_options: []
112
136
  require_paths:
@@ -116,15 +140,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
140
  requirements:
117
141
  - - ">="
118
142
  - !ruby/object:Gem::Version
119
- version: '2.0'
143
+ version: '2.6'
120
144
  required_rubygems_version: !ruby/object:Gem::Requirement
121
145
  requirements:
122
146
  - - ">="
123
147
  - !ruby/object:Gem::Version
124
148
  version: '0'
125
149
  requirements: []
126
- rubyforge_project:
127
- rubygems_version: 2.6.13
150
+ rubygems_version: 3.1.6
128
151
  signing_key:
129
152
  specification_version: 4
130
153
  summary: Minimal embedded v8 for Ruby