mini_racer 0.2.6 → 0.2.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c16fa0feb3cbf1b8421934aa90d12326e054ae439355e205f419ae1b74f6ad5
4
- data.tar.gz: ae46660f1ae64a14a528d26d53e3a1a0d7229556124cd17e0b7f5fdb16e42267
3
+ metadata.gz: 276af6ac1a39ed9f00576b34e1944c0c27c9ee745871fc50de8010f06c642abf
4
+ data.tar.gz: 911e1bf55677699df6623afec3430be7eccba88664c60e085562fb37e5a62847
5
5
  SHA512:
6
- metadata.gz: 55eaf9550322b6d3151b0dc17e86e9faadff9fe48cf64765d722281a8d6cd2af42ab8d46614f1ac59946aeffe2c02dbb09673042006c164e4eb132224acfe069
7
- data.tar.gz: 2b367ff94b68ed24579c6d750aef1532398bacedcd42a6149c16fbf176a76d079eddb12e9c3f15b12fb141703b0f38d37ca6e017e46d685826db64891347475e
6
+ metadata.gz: 17494a1abe347480cd62671155bcde45e60c8d47fee115338606a2b793308d9fe06f756da795f2b4fc84bbf8fded92ec6f6c3a656164ba195298efc4f27144e3
7
+ data.tar.gz: 0c9cc0bad0cf4963582c00d4a6ac8df547fb1b655464f01ae115ec286c864c364521bba5d70ed2081c589d007328151af34e001ad48280f18d9afeca0af879c4
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3
4
3
  - 2.4
5
4
  - 2.5
5
+ - 2.6
6
+ - 2.7
6
7
  - ruby-head
7
8
  matrix:
8
9
  include:
data/CHANGELOG CHANGED
@@ -1,3 +1,34 @@
1
+ - 14-05-2020
2
+
3
+ - 0.2.11
4
+
5
+ - FIX: dumping heap snapshots was not flushing the file leading to corrupt snapshots
6
+ - FIX: a use-after-free shutdown crash
7
+
8
+ - 0.2.10
9
+
10
+ - 22-04-2020
11
+
12
+ - FEATURE: memory softlimit support for nogvl_context_call
13
+
14
+ - 0.2.9
15
+
16
+ - 09-01-2020
17
+
18
+ - FIX: correct segfault when JS returns a Symbol and properly cast to ruby symbol
19
+
20
+ - 0.2.8
21
+
22
+ - 11-11-2019
23
+
24
+ - FIX: ensure thread live cycle is properly accounter for following file descriptor fix
25
+
26
+ - 0.2.7
27
+
28
+ - 11-11-2019
29
+
30
+ - FIX: release the file descriptor for timeout pipe earlier (this avoids holding too many files open in Ruby 2.7)
31
+
1
32
  - 14-05-2019
2
33
 
3
34
  - 0.2.6
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MiniRacer
2
2
 
3
- [![Build Status](https://travis-ci.org/discourse/mini_racer.svg?branch=master)](https://travis-ci.org/discourse/mini_racer)
3
+ [![Build Status](https://travis-ci.org/rubyjs/mini_racer.svg?branch=master)](https://travis-ci.org/rubyjs/mini_racer)
4
4
 
5
5
  Minimal, modern embedded V8 for Ruby.
6
6
 
@@ -97,6 +97,27 @@ context.eval('bar()', filename: 'a/bar.js')
97
97
 
98
98
  ```
99
99
 
100
+ ### Fork safety
101
+
102
+ Some Ruby web servers employ forking (for example unicorn or puma in clustered mode). V8 is not fork safe.
103
+ Sadly Ruby does not have support for fork notifications per [#5446](https://bugs.ruby-lang.org/issues/5446).
104
+
105
+ If you want to ensure your application does not leak memory after fork either:
106
+
107
+ 1. Ensure no MiniRacer::Context objects are created in the master process
108
+
109
+ Or
110
+
111
+ 2. Dispose manually of all MiniRacer::Context objects prior to forking
112
+
113
+ ```ruby
114
+ # before fork
115
+
116
+ require 'objspace'
117
+ ObjectSpace.each_object(MiniRacer::Context){|c| c.dispose}
118
+
119
+ # fork here
120
+ ```
100
121
 
101
122
  ### Threadsafe
102
123
 
@@ -252,7 +273,7 @@ context.eval js
252
273
  The same code without the harmony runtime flag results in a `MiniRacer::RuntimeError: RangeError: Maximum call stack size exceeded` exception.
253
274
  Please refer to http://node.green/ as a reference on other harmony features.
254
275
 
255
- A list of all V8 runtime flags can be found using `node --v8-options`, or else by perusing [the V8 source code for flags (make sure to use the right version of V8)](https://github.com/v8/v8/blob/master/src/flag-definitions.h).
276
+ A list of all V8 runtime flags can be found using `node --v8-options`, or else by perusing [the V8 source code for flags (make sure to use the right version of V8)](https://github.com/v8/v8/blob/master/src/flags/flag-definitions.h).
256
277
 
257
278
  Note that runtime flags must be set before any other operation (e.g. creating a context, a snapshot or an isolate), otherwise an exception will be thrown.
258
279
 
@@ -426,7 +447,7 @@ Add this to your .travis.yml file:
426
447
 
427
448
  ## Contributing
428
449
 
429
- Bug reports and pull requests are welcome on GitHub at https://github.com/discourse/mini_racer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
450
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rubyjs/mini_racer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
430
451
 
431
452
 
432
453
  ## License
data/Rakefile CHANGED
@@ -16,6 +16,22 @@ Rake::ExtensionTask.new( 'mini_racer_extension', gem )
16
16
 
17
17
  # via http://blog.flavorjon.es/2009/06/easily-valgrind-gdb-your-ruby-c.html
18
18
  namespace :test do
19
+ desc "run test suite with Address Sanitizer"
20
+ task :asan do
21
+ ENV["CONFIGURE_ARGS"] = [ENV["CONFIGURE_ARGS"], '--enable-asan'].compact.join(' ')
22
+ Rake::Task['compile'].invoke
23
+
24
+ asan_path = `ldconfig -N -p |grep libasan | grep -v 32 | sed 's/.* => \\(.*\\)$/\\1/'`.chomp.split("\n")[-1]
25
+
26
+
27
+ cmdline = "env LD_PRELOAD=\"#{asan_path}\" ruby test/test_leak.rb"
28
+ puts cmdline
29
+ system cmdline
30
+
31
+ cmdline = "env LD_PRELOAD=\"#{asan_path}\" rake test"
32
+ puts cmdline
33
+ system cmdline
34
+ end
19
35
  # partial-loads-ok and undef-value-errors necessary to ignore
20
36
  # spurious (and eminently ignorable) warnings from the ruby
21
37
  # interpreter
@@ -49,10 +49,15 @@ if CONFIG['warnflags']
49
49
  CONFIG['warnflags'].gsub!('-Wimplicit-function-declaration', '')
50
50
  end
51
51
 
52
- if enable_config('debug')
52
+ if enable_config('debug') || enable_config('asan')
53
53
  CONFIG['debugflags'] << ' -ggdb3 -O0'
54
54
  end
55
55
 
56
56
  Libv8.configure_makefile
57
57
 
58
+ if enable_config('asan')
59
+ $CPPFLAGS.insert(0, " -fsanitize=address ")
60
+ $LDFLAGS.insert(0, " -fsanitize=address ")
61
+ end
62
+
58
63
  create_makefile 'mini_racer_extension'
@@ -127,6 +127,7 @@ typedef struct {
127
127
  Local<Function> fun;
128
128
  Local<Value> *argv;
129
129
  EvalResult result;
130
+ size_t max_memory;
130
131
  } FunctionCall;
131
132
 
132
133
  enum IsolateFlags {
@@ -152,9 +153,13 @@ static VALUE rb_mJSON;
152
153
  static VALUE rb_cFailedV8Conversion;
153
154
  static VALUE rb_cDateTime = Qnil;
154
155
 
155
- static Platform* current_platform = NULL;
156
+ static std::unique_ptr<Platform> current_platform = NULL;
156
157
  static std::mutex platform_lock;
157
158
 
159
+ static pthread_attr_t *thread_attr_p;
160
+ static pthread_rwlock_t exit_lock = PTHREAD_RWLOCK_INITIALIZER;
161
+ static bool ruby_exiting; // guarded by exit_lock
162
+
158
163
  static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
159
164
  bool platform_already_initialized = false;
160
165
 
@@ -189,8 +194,8 @@ static void init_v8() {
189
194
 
190
195
  if (current_platform == NULL) {
191
196
  V8::InitializeICU();
192
- current_platform = platform::CreateDefaultPlatform();
193
- V8::InitializePlatform(current_platform);
197
+ current_platform = platform::NewDefaultPlatform();
198
+ V8::InitializePlatform(current_platform.get());
194
199
  V8::Initialize();
195
200
  }
196
201
 
@@ -241,7 +246,7 @@ static void prepare_result(MaybeLocal v8res,
241
246
  Local<Object> object = local_value->ToObject(context).ToLocalChecked();
242
247
  const unsigned argc = 1;
243
248
  Local<Value> argv[argc] = { object };
244
- MaybeLocal<Value> json = stringify->Call(JSON, argc, argv);
249
+ MaybeLocal<Value> json = stringify->Call(context, JSON, argc, argv);
245
250
 
246
251
  if (json.IsEmpty()) {
247
252
  evalRes.executed = false;
@@ -444,8 +449,27 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local context,
444
449
  return rb_hash;
445
450
  }
446
451
 
447
- Local<String> rstr = value->ToString(context).ToLocalChecked();
448
- return rb_enc_str_new(*String::Utf8Value(isolate, rstr), rstr->Utf8Length(isolate), rb_enc_find("utf-8"));
452
+ if (value->IsSymbol()) {
453
+ v8::String::Utf8Value symbol_name(isolate,
454
+ Local<Symbol>::Cast(value)->Name());
455
+
456
+ VALUE str_symbol = rb_enc_str_new(
457
+ *symbol_name,
458
+ symbol_name.length(),
459
+ rb_enc_find("utf-8")
460
+ );
461
+
462
+ return ID2SYM(rb_intern_str(str_symbol));
463
+ }
464
+
465
+ MaybeLocal<String> rstr_maybe = value->ToString(context);
466
+
467
+ if (rstr_maybe.IsEmpty()) {
468
+ return Qnil;
469
+ } else {
470
+ Local<String> rstr = rstr_maybe.ToLocalChecked();
471
+ return rb_enc_str_new(*String::Utf8Value(isolate, rstr), rstr->Utf8Length(isolate), rb_enc_find("utf-8"));
472
+ }
449
473
  }
450
474
 
451
475
  static VALUE convert_v8_to_ruby(Isolate* isolate,
@@ -1086,8 +1110,10 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1086
1110
  Local<Context> context = context_info->context->Get(isolate);
1087
1111
  Context::Scope context_scope(context);
1088
1112
 
1089
- Local<String> v8_str = String::NewFromUtf8(isolate, RSTRING_PTR(name),
1090
- NewStringType::kNormal, (int)RSTRING_LEN(name)).ToLocalChecked();
1113
+ Local<String> v8_str =
1114
+ String::NewFromUtf8(isolate, RSTRING_PTR(name),
1115
+ NewStringType::kNormal, (int)RSTRING_LEN(name))
1116
+ .ToLocalChecked();
1091
1117
 
1092
1118
  // copy self so we can access from v8 external
1093
1119
  VALUE* self_copy;
@@ -1097,24 +1123,35 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1097
1123
  Local<Value> external = External::New(isolate, self_copy);
1098
1124
 
1099
1125
  if (parent_object == Qnil) {
1100
- context->Global()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
1101
- } else {
1126
+ context->Global()->Set(
1127
+ v8_str, FunctionTemplate::New(isolate, ruby_callback, external)
1128
+ ->GetFunction(context)
1129
+ .ToLocalChecked());
1102
1130
 
1103
- Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
1104
- NewStringType::kNormal, (int)RSTRING_LEN(parent_object_eval)).ToLocalChecked();
1131
+ } else {
1132
+ Local<String> eval =
1133
+ String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
1134
+ NewStringType::kNormal,
1135
+ (int)RSTRING_LEN(parent_object_eval))
1136
+ .ToLocalChecked();
1105
1137
 
1106
1138
  MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
1107
1139
  if (parsed_script.IsEmpty()) {
1108
- parse_error = true;
1140
+ parse_error = true;
1109
1141
  } else {
1110
- MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
1142
+ MaybeLocal<Value> maybe_value =
1143
+ parsed_script.ToLocalChecked()->Run(context);
1111
1144
  attach_error = true;
1112
1145
 
1113
1146
  if (!maybe_value.IsEmpty()) {
1114
1147
  Local<Value> value = maybe_value.ToLocalChecked();
1115
- if (value->IsObject()){
1116
- value.As<Object>()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
1117
- attach_error = false;
1148
+ if (value->IsObject()) {
1149
+ value.As<Object>()->Set(
1150
+ v8_str, FunctionTemplate::New(
1151
+ isolate, ruby_callback, external)
1152
+ ->GetFunction(context)
1153
+ .ToLocalChecked());
1154
+ attach_error = false;
1118
1155
  }
1119
1156
  }
1120
1157
  }
@@ -1172,7 +1209,7 @@ void free_isolate(IsolateInfo* isolate_info) {
1172
1209
  delete isolate_info->allocator;
1173
1210
  }
1174
1211
 
1175
- static void *free_context_raw(void* arg) {
1212
+ static void free_context_raw(void *arg) {
1176
1213
  ContextInfo* context_info = (ContextInfo*)arg;
1177
1214
  IsolateInfo* isolate_info = context_info->isolate_info;
1178
1215
  Persistent<Context>* context = context_info->context;
@@ -1189,6 +1226,20 @@ static void *free_context_raw(void* arg) {
1189
1226
  }
1190
1227
 
1191
1228
  xfree(context_info);
1229
+ }
1230
+
1231
+ static void *free_context_thr(void* arg) {
1232
+ if (pthread_rwlock_tryrdlock(&exit_lock) != 0) {
1233
+ return NULL;
1234
+ }
1235
+ if (ruby_exiting) {
1236
+ return NULL;
1237
+ }
1238
+
1239
+ free_context_raw(arg);
1240
+
1241
+ pthread_rwlock_unlock(&exit_lock);
1242
+
1192
1243
  return NULL;
1193
1244
  }
1194
1245
 
@@ -1202,22 +1253,17 @@ static void free_context(ContextInfo* context_info) {
1202
1253
  context_info_copy->context = context_info->context;
1203
1254
 
1204
1255
  if (isolate_info && isolate_info->refs() > 1) {
1205
- pthread_t free_context_thread;
1206
- if (pthread_create(&free_context_thread, NULL, free_context_raw, (void*)context_info_copy)) {
1207
- fprintf(stderr, "WARNING failed to release memory in MiniRacer, thread to release could not be created, process will leak memory\n");
1208
- }
1209
-
1256
+ pthread_t free_context_thread;
1257
+ if (pthread_create(&free_context_thread, thread_attr_p,
1258
+ free_context_thr, (void*)context_info_copy)) {
1259
+ fprintf(stderr, "WARNING failed to release memory in MiniRacer, thread to release could not be created, process will leak memory\n");
1260
+ }
1210
1261
  } else {
1211
1262
  free_context_raw(context_info_copy);
1212
1263
  }
1213
1264
 
1214
- if (context_info->context && isolate_info && isolate_info->isolate) {
1215
- context_info->context = NULL;
1216
- }
1217
-
1218
- if (isolate_info) {
1219
- context_info->isolate_info = NULL;
1220
- }
1265
+ context_info->context = NULL;
1266
+ context_info->isolate_info = NULL;
1221
1267
  }
1222
1268
 
1223
1269
  static void deallocate_isolate(void* data) {
@@ -1375,6 +1421,8 @@ rb_heap_snapshot(VALUE self, VALUE file) {
1375
1421
  FileOutputStream stream(fp);
1376
1422
  snap->Serialize(&stream, HeapSnapshot::kJSON);
1377
1423
 
1424
+ fflush(fp);
1425
+
1378
1426
  const_cast<HeapSnapshot*>(snap)->Delete();
1379
1427
 
1380
1428
  return Qtrue;
@@ -1422,6 +1470,12 @@ nogvl_context_call(void *args) {
1422
1470
  // terminate ASAP
1423
1471
  isolate->SetData(DO_TERMINATE, (void*)false);
1424
1472
 
1473
+ if (call->max_memory > 0) {
1474
+ isolate->SetData(MEM_SOFTLIMIT_VALUE, &call->max_memory);
1475
+ isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)false);
1476
+ isolate->AddGCEpilogueCallback(gc_callback);
1477
+ }
1478
+
1425
1479
  Isolate::Scope isolate_scope(isolate);
1426
1480
  EscapableHandleScope handle_scope(isolate);
1427
1481
  TryCatch trycatch(isolate);
@@ -1479,6 +1533,13 @@ static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1479
1533
  call_argv = argv + 1;
1480
1534
  }
1481
1535
 
1536
+ call.max_memory = 0;
1537
+ VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
1538
+ if (mem_softlimit != Qnil) {
1539
+ unsigned long sl_int = NUM2ULONG(mem_softlimit);
1540
+ call.max_memory = (size_t)sl_int;
1541
+ }
1542
+
1482
1543
  bool missingFunction = false;
1483
1544
  {
1484
1545
  Locker lock(isolate);
@@ -1536,6 +1597,16 @@ static VALUE rb_context_create_isolate_value(VALUE self) {
1536
1597
  return Data_Wrap_Struct(rb_cIsolate, NULL, &deallocate_isolate, isolate_info);
1537
1598
  }
1538
1599
 
1600
+ static void set_ruby_exiting(VALUE value) {
1601
+ (void)value;
1602
+
1603
+ int res = pthread_rwlock_wrlock(&exit_lock);
1604
+ ruby_exiting = true;
1605
+ if (res == 0) {
1606
+ pthread_rwlock_unlock(&exit_lock);
1607
+ }
1608
+ }
1609
+
1539
1610
  extern "C" {
1540
1611
 
1541
1612
  void Init_mini_racer_extension ( void )
@@ -1589,5 +1660,14 @@ extern "C" {
1589
1660
  rb_define_private_method(rb_cIsolate, "init_with_snapshot",(VALUE(*)(...))&rb_isolate_init_with_snapshot, 1);
1590
1661
 
1591
1662
  rb_define_singleton_method(rb_cPlatform, "set_flag_as_str!", (VALUE(*)(...))&rb_platform_set_flag_as_str, 1);
1663
+
1664
+ rb_set_end_proc(set_ruby_exiting, Qnil);
1665
+
1666
+ static pthread_attr_t attr;
1667
+ if (pthread_attr_init(&attr) == 0) {
1668
+ if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0) {
1669
+ thread_attr_p = &attr;
1670
+ }
1671
+ }
1592
1672
  }
1593
1673
  }
@@ -313,9 +313,17 @@ module MiniRacer
313
313
 
314
314
  # ensure we do not leak a thread in state
315
315
  t.join
316
+ t = nil
316
317
 
317
318
  rval
318
-
319
+ ensure
320
+ # exceptions need to be handled
321
+ if t && wp
322
+ wp.write("done")
323
+ t.join
324
+ end
325
+ wp.close if wp
326
+ rp.close if rp
319
327
  end
320
328
 
321
329
  def check_init_options!(options)
@@ -1,3 +1,3 @@
1
1
  module MiniRacer
2
- VERSION = "0.2.6"
2
+ VERSION = "0.2.11"
3
3
  end
@@ -14,18 +14,24 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/discourse/mini_racer"
15
15
  spec.license = "MIT"
16
16
 
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
+ }
17
23
 
18
24
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(benchmark|test|spec|features|examples)/}) }
19
25
  spec.bindir = "exe"
20
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
27
  spec.require_paths = ["lib"]
22
28
 
23
- spec.add_development_dependency "bundler", "~> 1.12"
29
+ spec.add_development_dependency "bundler"
24
30
  spec.add_development_dependency "rake", "~> 10.0"
25
31
  spec.add_development_dependency "minitest", "~> 5.0"
26
32
  spec.add_development_dependency "rake-compiler"
27
33
 
28
- spec.add_dependency 'libv8', '>= 6.9.411'
34
+ spec.add_dependency 'libv8', '> 7.3'
29
35
  spec.require_paths = ["lib", "ext"]
30
36
 
31
37
  spec.extensions = ["ext/mini_racer_extension/extconf.rb"]
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_racer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-14 00:00:00.000000000 Z
11
+ date: 2020-05-14 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
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: libv8
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - ">"
74
74
  - !ruby/object:Gem::Version
75
- version: 6.9.411
75
+ version: '7.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
- version: 6.9.411
82
+ version: '7.3'
83
83
  description: Minimal embedded v8 engine for Ruby
84
84
  email:
85
85
  - sam.saffron@gmail.com
@@ -106,7 +106,11 @@ files:
106
106
  homepage: https://github.com/discourse/mini_racer
107
107
  licenses:
108
108
  - MIT
109
- metadata: {}
109
+ metadata:
110
+ bug_tracker_uri: https://github.com/discourse/mini_racer/issues
111
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.2.11/CHANGELOG
112
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.2.11
113
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.2.11
110
114
  post_install_message:
111
115
  rdoc_options: []
112
116
  require_paths: