mini_racer 0.19.0 → 0.20.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5923ad9b3aa9cdea7785f0f2eb3fa27357217d0feb5ed439dad46b5ea7eaea8f
4
- data.tar.gz: ffac8a1b740c74467f40e0200730a3fe25892d63105022f8775fe8aaffdcdd20
3
+ metadata.gz: 5aa16bf587a6e12df562d7a946ce3a965a8444debd9769b376075cafd10a3b5c
4
+ data.tar.gz: 5aaf6a08ae90f05bc554bae0a06e93efce5318d00aacdfe959f36513533caac4
5
5
  SHA512:
6
- metadata.gz: 0f8ab9852328121e3d55119fb1a2a8a875806b0a256d2c79ab09846fe2ed7df174beb68949213057fe8186376b73993b21dc21fe22ce82632f26e0a4354c982e
7
- data.tar.gz: 88c0a37a5a26ab746312c76499a202578a0604098a1ec3fcf7b98110aace6facd95490b19bd0f6abb8afba136b9ae94f5f1367d55050d6abdcf62bd628d6b8f2
6
+ metadata.gz: 2b2641ceb0fd1770efd32cfb9e37aee92ca857ad6acbe2129157a58be9ed6bbef4a355c5af133f5749f229d578e10a452ef77a62eadbe436993f005146d242cd
7
+ data.tar.gz: 3264e95d4951aa52ba080a94b847c5080705e1de0e3dd5fefae0786342ccece850b00db4f151220e65068e9e5d62fb0eebae0fda65e79647196903fae70d8012
data/CHANGELOG CHANGED
@@ -1,3 +1,14 @@
1
+ - 0.20.0 - 24-02-2026
2
+ - Add Snapshot.load to restore snapshots from binary data, enabling disk persistence
3
+
4
+ - 0.19.2 - 24-12-2025
5
+ - upgrade to node 24.12.0
6
+
7
+ - 0.19.1 - 20-10-2025
8
+ - JS code can now catch ruby exceptions - Ben Noordhuis
9
+ - Retain string encoding when raising exceptions - Ben Noordhuis
10
+ - Fix object identity bug with Ruby to JS conversion - Benjamin Wood
11
+
1
12
  - 0.19.0 - 24-06-2025
2
13
  - upgrade to node 24.1.0
3
14
 
data/README.md CHANGED
@@ -193,6 +193,25 @@ context.eval("counter")
193
193
  # => 1
194
194
  ```
195
195
 
196
+ Snapshots can also be persisted to disk for faster startup:
197
+
198
+ ```ruby
199
+ # Save a snapshot to disk
200
+ snapshot = MiniRacer::Snapshot.new('var foo = "bar";')
201
+ File.binwrite("snapshot.bin", snapshot.dump)
202
+
203
+ # Load it back in a later process
204
+ blob = File.binread("snapshot.bin")
205
+ snapshot = MiniRacer::Snapshot.load(blob)
206
+ context = MiniRacer::Context.new(snapshot: snapshot)
207
+ context.eval("foo")
208
+ # => "bar"
209
+ ```
210
+
211
+ Note that snapshots are architecture and V8-version specific. A snapshot created on one platform (e.g., ARM64 macOS) cannot be loaded on a different platform (e.g., x86_64 Linux). Snapshots are best used for same-machine caching or homogeneous deployment environments.
212
+
213
+ **Security note:** Only load snapshots from trusted sources. V8 snapshots are not designed to be safely loaded from untrusted input—malformed or malicious snapshot data may cause crashes or memory corruption.
214
+
196
215
  ### Garbage collection
197
216
 
198
217
  You can make the garbage collector more aggressive by defining the context with `MiniRacer::Context.new(ensure_gc_after_idle: 1000)`. Using this will ensure V8 will run a full GC using `context.low_memory_notification` 1 second after the last eval on the context. Low memory notifications ensure long living contexts use minimal amounts of memory.
@@ -6,6 +6,30 @@
6
6
  #include <pthread.h>
7
7
  #include <math.h>
8
8
 
9
+ #if defined(__linux__) && !defined(__GLIBC__)
10
+ // musl compatibility for glibc-linked libraries (e.g. libv8-node)
11
+ // some versions of libv8-node are accidentally linked against glibc symbols
12
+ // or compiled with a toolchain that emits these C23 compatibility symbols
13
+ unsigned long long __isoc23_strtoull(const char *nptr, char **endptr, int base) {
14
+ return strtoull(nptr, endptr, base);
15
+ }
16
+ unsigned long __isoc23_strtoul(const char *nptr, char **endptr, int base) {
17
+ return strtoul(nptr, endptr, base);
18
+ }
19
+ long long __isoc23_strtoll(const char *nptr, char **endptr, int base) {
20
+ return strtoll(nptr, endptr, base);
21
+ }
22
+ long __isoc23_strtol(const char *nptr, char **endptr, int base) {
23
+ return strtol(nptr, endptr, base);
24
+ }
25
+ double __isoc23_strtod(const char *nptr, char **endptr) {
26
+ return strtod(nptr, endptr);
27
+ }
28
+ float __isoc23_strtof(const char *nptr, char **endptr) {
29
+ return strtof(nptr, endptr);
30
+ }
31
+ #endif
32
+
9
33
  #include "ruby.h"
10
34
  #include "ruby/encoding.h"
11
35
  #include "ruby/version.h"
@@ -13,6 +37,13 @@
13
37
  #include "serde.c"
14
38
  #include "mini_racer_v8.h"
15
39
 
40
+ // for debugging
41
+ #define RB_PUTS(v) \
42
+ do { \
43
+ fflush(stdout); \
44
+ rb_funcall(rb_mKernel, rb_intern("puts"), 1, v); \
45
+ } while (0)
46
+
16
47
  #if RUBY_API_VERSION_CODE < 3*10000+4*100 // 3.4.0
17
48
  static inline void rb_thread_lock_native_thread(void)
18
49
  {
@@ -154,6 +185,7 @@ static VALUE platform_init_error;
154
185
  static VALUE context_disposed_error;
155
186
  static VALUE parse_error;
156
187
  static VALUE memory_error;
188
+ static VALUE script_error;
157
189
  static VALUE runtime_error;
158
190
  static VALUE internal_error;
159
191
  static VALUE snapshot_error;
@@ -482,12 +514,36 @@ static void des_object_ref(void *arg, uint32_t id)
482
514
 
483
515
  static void des_error_begin(void *arg)
484
516
  {
485
- push(arg, rb_class_new_instance(0, NULL, rb_eRuntimeError));
517
+ push(arg, rb_ary_new());
486
518
  }
487
519
 
488
520
  static void des_error_end(void *arg)
489
521
  {
490
- pop(arg);
522
+ VALUE *a, h, message, stack, cause, newline;
523
+ DesCtx *c;
524
+
525
+ c = arg;
526
+ if (*c->err)
527
+ return;
528
+ if (c->tos == c->stack) {
529
+ snprintf(c->err, sizeof(c->err), "stack underflow");
530
+ return;
531
+ }
532
+ a = &c->tos->a;
533
+ h = rb_ary_pop(*a);
534
+ message = rb_hash_aref(h, rb_str_new_cstr("message"));
535
+ stack = rb_hash_aref(h, rb_str_new_cstr("stack"));
536
+ cause = rb_hash_aref(h, rb_str_new_cstr("cause"));
537
+ if (NIL_P(message))
538
+ message = rb_str_new_cstr("JS exception");
539
+ if (!NIL_P(stack)) {
540
+ newline = rb_str_new_cstr("\n");
541
+ message = rb_funcall(message, rb_intern("concat"), 2, newline, stack);
542
+ }
543
+ *a = rb_class_new_instance(1, &message, script_error);
544
+ if (!NIL_P(cause))
545
+ rb_iv_set(*a, "@cause", cause);
546
+ pop(c);
491
547
  }
492
548
 
493
549
  static int collect(VALUE k, VALUE v, VALUE a)
@@ -527,52 +583,58 @@ static int serialize1(Ser *s, VALUE refs, VALUE v)
527
583
  return -1;
528
584
  switch (TYPE(v)) {
529
585
  case T_ARRAY:
530
- id = rb_hash_lookup(refs, v);
531
- if (NIL_P(id)) {
532
- n = RARRAY_LENINT(v);
533
- i = rb_hash_size_num(refs);
534
- rb_hash_aset(refs, v, LONG2FIX(i));
535
- ser_array_begin(s, n);
536
- for (i = 0; i < n; i++)
537
- if (serialize1(s, refs, rb_ary_entry(v, i)))
538
- return -1;
539
- ser_array_end(s, n);
540
- } else {
541
- ser_object_ref(s, FIX2LONG(id));
586
+ {
587
+ VALUE obj_id = rb_obj_id(v);
588
+ id = rb_hash_lookup(refs, obj_id);
589
+ if (NIL_P(id)) {
590
+ n = RARRAY_LENINT(v);
591
+ i = rb_hash_size_num(refs);
592
+ rb_hash_aset(refs, obj_id, LONG2FIX(i));
593
+ ser_array_begin(s, n);
594
+ for (i = 0; i < n; i++)
595
+ if (serialize1(s, refs, rb_ary_entry(v, i)))
596
+ return -1;
597
+ ser_array_end(s, n);
598
+ } else {
599
+ ser_object_ref(s, FIX2LONG(id));
600
+ }
542
601
  }
543
602
  break;
544
603
  case T_HASH:
545
- id = rb_hash_lookup(refs, v);
546
- if (NIL_P(id)) {
547
- a = rb_ary_new();
548
- i = rb_hash_size_num(refs);
549
- n = rb_hash_size_num(v);
550
- rb_hash_aset(refs, v, LONG2FIX(i));
551
- rb_hash_foreach(v, collect, a);
552
- for (i = 0; i < 2*n; i += 2) {
553
- t = rb_ary_entry(a, i);
554
- switch (TYPE(t)) {
555
- case T_FIXNUM:
556
- case T_STRING:
557
- case T_SYMBOL:
558
- continue;
559
- }
560
- break;
561
- }
562
- if (i == 2*n) {
563
- ser_object_begin(s);
604
+ {
605
+ VALUE obj_id = rb_obj_id(v);
606
+ id = rb_hash_lookup(refs, obj_id);
607
+ if (NIL_P(id)) {
608
+ a = rb_ary_new();
609
+ i = rb_hash_size_num(refs);
610
+ n = rb_hash_size_num(v);
611
+ rb_hash_aset(refs, obj_id, LONG2FIX(i));
612
+ rb_hash_foreach(v, collect, a);
564
613
  for (i = 0; i < 2*n; i += 2) {
565
- if (serialize1(s, refs, rb_ary_entry(a, i+0)))
566
- return -1;
567
- if (serialize1(s, refs, rb_ary_entry(a, i+1)))
568
- return -1;
614
+ t = rb_ary_entry(a, i);
615
+ switch (TYPE(t)) {
616
+ case T_FIXNUM:
617
+ case T_STRING:
618
+ case T_SYMBOL:
619
+ continue;
620
+ }
621
+ break;
622
+ }
623
+ if (i == 2*n) {
624
+ ser_object_begin(s);
625
+ for (i = 0; i < 2*n; i += 2) {
626
+ if (serialize1(s, refs, rb_ary_entry(a, i+0)))
627
+ return -1;
628
+ if (serialize1(s, refs, rb_ary_entry(a, i+1)))
629
+ return -1;
630
+ }
631
+ ser_object_end(s, n);
632
+ } else {
633
+ return bail(&s->err, "TODO serialize as Map");
569
634
  }
570
- ser_object_end(s, n);
571
635
  } else {
572
- return bail(&s->err, "TODO serialize as Map");
636
+ ser_object_ref(s, FIX2LONG(id));
573
637
  }
574
- } else {
575
- ser_object_ref(s, FIX2LONG(id));
576
638
  }
577
639
  break;
578
640
  case T_DATA:
@@ -888,6 +950,7 @@ static VALUE rendezvous_callback_do(VALUE arg)
888
950
  static void *rendezvous_callback(void *arg)
889
951
  {
890
952
  struct rendezvous_nogvl *a;
953
+ const char *err;
891
954
  Context *c;
892
955
  int exc;
893
956
  VALUE r;
@@ -911,7 +974,12 @@ out:
911
974
  buf_move(&s.b, a->req);
912
975
  return NULL;
913
976
  fail:
914
- ser_init1(&s, 'e'); // exception pending
977
+ ser_init0(&s); // ruby exception pending
978
+ w_byte(&s, 'e'); // send ruby error message to v8 thread
979
+ r = rb_funcall(c->exception, rb_intern("to_s"), 0);
980
+ err = StringValueCStr(r);
981
+ if (err)
982
+ w(&s, err, strlen(err));
915
983
  goto out;
916
984
  }
917
985
 
@@ -969,6 +1037,13 @@ static VALUE rendezvous1(Context *c, Buf *req, DesCtx *d)
969
1037
  int exc;
970
1038
 
971
1039
  rendezvous_no_des(c, req, &res); // takes ownership of |req|
1040
+ r = c->exception;
1041
+ c->exception = Qnil;
1042
+ // if js land didn't handle exception from ruby callback, re-raise it now
1043
+ if (res.len == 1 && *res.buf == 'e') {
1044
+ assert(!NIL_P(r));
1045
+ rb_exc_raise(r);
1046
+ }
972
1047
  r = rb_protect(deserialize, (VALUE)&(struct rendezvous_des){d, &res}, &exc);
973
1048
  buf_reset(&res);
974
1049
  if (exc) {
@@ -976,11 +1051,6 @@ static VALUE rendezvous1(Context *c, Buf *req, DesCtx *d)
976
1051
  rb_set_errinfo(Qnil);
977
1052
  rb_exc_raise(r);
978
1053
  }
979
- if (!NIL_P(c->exception)) {
980
- r = c->exception;
981
- c->exception = Qnil;
982
- rb_exc_raise(r);
983
- }
984
1054
  return r;
985
1055
  }
986
1056
 
@@ -999,8 +1069,8 @@ static void handle_exception(VALUE e)
999
1069
 
1000
1070
  if (NIL_P(e))
1001
1071
  return;
1002
- StringValue(e);
1003
- s = RSTRING_PTR(e);
1072
+ e = StringValue(e);
1073
+ s = StringValueCStr(e);
1004
1074
  switch (*s) {
1005
1075
  case NO_ERROR:
1006
1076
  return;
@@ -1022,7 +1092,7 @@ static void handle_exception(VALUE e)
1022
1092
  default:
1023
1093
  rb_raise(internal_error, "bad error class %02x", *s);
1024
1094
  }
1025
- rb_raise(klass, "%s", s+1);
1095
+ rb_enc_raise(rb_enc_get(e), klass, "%s", s+1);
1026
1096
  }
1027
1097
 
1028
1098
  static VALUE context_alloc(VALUE klass)
@@ -1620,6 +1690,20 @@ static VALUE snapshot_dump(VALUE self)
1620
1690
  return ss->blob;
1621
1691
  }
1622
1692
 
1693
+ static VALUE snapshot_load(VALUE klass, VALUE blob)
1694
+ {
1695
+ Snapshot *ss;
1696
+ VALUE self;
1697
+
1698
+ Check_Type(blob, T_STRING);
1699
+ self = snapshot_alloc(klass);
1700
+ TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
1701
+ ss->blob = rb_str_dup(blob);
1702
+ rb_enc_associate(ss->blob, rb_ascii8bit_encoding());
1703
+ ENC_CODERANGE_SET(ss->blob, ENC_CODERANGE_VALID);
1704
+ return self;
1705
+ }
1706
+
1623
1707
  static VALUE snapshot_size0(VALUE self)
1624
1708
  {
1625
1709
  Snapshot *ss;
@@ -1628,6 +1712,11 @@ static VALUE snapshot_size0(VALUE self)
1628
1712
  return LONG2FIX(RSTRING_LENINT(ss->blob));
1629
1713
  }
1630
1714
 
1715
+ static VALUE script_error_cause(VALUE self)
1716
+ {
1717
+ return rb_iv_get(self, "@cause");
1718
+ }
1719
+
1631
1720
  __attribute__((visibility("default")))
1632
1721
  void Init_mini_racer_extension(void)
1633
1722
  {
@@ -1642,10 +1731,13 @@ void Init_mini_racer_extension(void)
1642
1731
  c = rb_define_class_under(m, "EvalError", c);
1643
1732
  parse_error = rb_define_class_under(m, "ParseError", c);
1644
1733
  memory_error = rb_define_class_under(m, "V8OutOfMemoryError", c);
1734
+ script_error = rb_define_class_under(m, "ScriptError", c);
1645
1735
  runtime_error = rb_define_class_under(m, "RuntimeError", c);
1646
1736
  internal_error = rb_define_class_under(m, "InternalError", c);
1647
1737
  terminated_error = rb_define_class_under(m, "ScriptTerminatedError", c);
1648
1738
 
1739
+ rb_define_method(script_error, "cause", script_error_cause, 0);
1740
+
1649
1741
  c = context_class = rb_define_class_under(m, "Context", rb_cObject);
1650
1742
  rb_define_method(c, "initialize", context_initialize, -1);
1651
1743
  rb_define_method(c, "attach", context_attach, 2);
@@ -1664,6 +1756,7 @@ void Init_mini_racer_extension(void)
1664
1756
  rb_define_method(c, "warmup!", snapshot_warmup, 1);
1665
1757
  rb_define_method(c, "dump", snapshot_dump, 0);
1666
1758
  rb_define_method(c, "size", snapshot_size0, 0);
1759
+ rb_define_singleton_method(c, "load", snapshot_load, 1);
1667
1760
  rb_define_alloc_func(c, snapshot_alloc);
1668
1761
 
1669
1762
  c = rb_define_class_under(m, "Platform", rb_cObject);
@@ -86,6 +86,7 @@ struct State
86
86
  v8::Persistent<v8::Context> persistent_context; // single-thread mode only
87
87
  v8::Persistent<v8::Context> persistent_safe_context; // single-thread mode only
88
88
  v8::Persistent<v8::Function> persistent_safe_context_function; // single-thread mode only
89
+ v8::Persistent<v8::Value> ruby_exception;
89
90
  Context *ruby_context;
90
91
  int64_t max_memory;
91
92
  int err_reason;
@@ -122,6 +123,20 @@ struct Serialized
122
123
  }
123
124
  };
124
125
 
126
+ bool bubble_up_ruby_exception(State& st, v8::TryCatch *try_catch)
127
+ {
128
+ auto exception = try_catch->Exception();
129
+ if (exception.IsEmpty()) return false;
130
+ auto ruby_exception = v8::Local<v8::Value>::New(st.isolate, st.ruby_exception);
131
+ if (ruby_exception.IsEmpty()) return false;
132
+ if (!ruby_exception->SameValue(exception)) return false;
133
+ // signal that the ruby thread should reraise the exception
134
+ // that it caught earlier when executing a js->ruby callback
135
+ uint8_t c = 'e';
136
+ v8_reply(st.ruby_context, &c, 1);
137
+ return true;
138
+ }
139
+
125
140
  // throws JS exception on serialization error
126
141
  bool reply(State& st, v8::Local<v8::Value> v)
127
142
  {
@@ -388,8 +403,17 @@ void v8_api_callback(const v8::FunctionCallbackInfo<v8::Value>& info)
388
403
  v8_roundtrip(st.ruby_context, &p, &n);
389
404
  if (*p == 'c') // callback reply
390
405
  break;
391
- if (*p == 'e') // ruby exception pending
392
- return st.isolate->TerminateExecution();
406
+ if (*p == 'e') { // ruby exception pending
407
+ v8::Local<v8::String> message;
408
+ auto type = v8::NewStringType::kNormal;
409
+ if (!v8::String::NewFromOneByte(st.isolate, p+1, type, n-1).ToLocal(&message)) {
410
+ message = v8::String::NewFromUtf8Literal(st.isolate, "Ruby exception");
411
+ }
412
+ auto exception = v8::Exception::Error(message);
413
+ st.ruby_exception.Reset(st.isolate, exception);
414
+ st.isolate->ThrowException(exception);
415
+ return;
416
+ }
393
417
  v8_dispatch(st.ruby_context);
394
418
  }
395
419
  v8::ValueDeserializer des(st.isolate, p+1, n-1);
@@ -523,6 +547,7 @@ fail:
523
547
  cause = st.err_reason ? st.err_reason : TERMINATED_ERROR;
524
548
  st.err_reason = NO_ERROR;
525
549
  }
550
+ if (bubble_up_ruby_exception(st, &try_catch)) return;
526
551
  if (!cause && try_catch.HasCaught()) cause = RUNTIME_ERROR;
527
552
  if (cause) result = v8::Undefined(st.isolate);
528
553
  auto err = to_error(st, &try_catch, cause);
@@ -571,6 +596,7 @@ fail:
571
596
  cause = st.err_reason ? st.err_reason : TERMINATED_ERROR;
572
597
  st.err_reason = NO_ERROR;
573
598
  }
599
+ if (bubble_up_ruby_exception(st, &try_catch)) return;
574
600
  if (!cause && try_catch.HasCaught()) cause = RUNTIME_ERROR;
575
601
  if (cause) result = v8::Undefined(st.isolate);
576
602
  auto err = to_error(st, &try_catch, cause);
@@ -895,6 +921,7 @@ State::~State()
895
921
  v8::Isolate::Scope isolate_scope(isolate);
896
922
  persistent_safe_context.Reset();
897
923
  persistent_context.Reset();
924
+ ruby_exception.Reset();
898
925
  }
899
926
  isolate->Dispose();
900
927
  for (Callback *cb : callbacks)
@@ -194,17 +194,21 @@ static inline int r_zigzag(const uint8_t **p, const uint8_t *pe, int64_t *r)
194
194
  return 0;
195
195
  }
196
196
 
197
- static inline void ser_init(Ser *s)
197
+ static void ser_init0(Ser *s)
198
198
  {
199
199
  memset(s, 0, sizeof(*s));
200
200
  buf_init(&s->b);
201
+ }
202
+
203
+ static inline void ser_init(Ser *s)
204
+ {
205
+ ser_init0(s);
201
206
  w(s, "\xFF\x0F", 2);
202
207
  }
203
208
 
204
209
  static void ser_init1(Ser *s, uint8_t c)
205
210
  {
206
- memset(s, 0, sizeof(*s));
207
- buf_init(&s->b);
211
+ ser_init0(s);
208
212
  w_byte(s, c);
209
213
  w(s, "\xFF\x0F", 2);
210
214
  }
@@ -246,6 +246,10 @@ module MiniRacer
246
246
  js_map_to_hash(value)
247
247
  elsif map_iterator?(value)
248
248
  value.map { |e| convert_js_to_ruby(e) }
249
+ elsif Polyglot::ForeignException === value
250
+ exc = MiniRacer::ScriptError.new(value.message)
251
+ exc.set_backtrace(value.backtrace)
252
+ exc
249
253
  else
250
254
  object = value
251
255
  h = {}
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniRacer
4
- VERSION = "0.19.0"
5
- LIBV8_NODE_VERSION = "~> 24.1.0.0"
4
+ VERSION = "0.20.0"
5
+ LIBV8_NODE_VERSION = "~> 24.12.0.1"
6
6
  end
data/lib/mini_racer.rb CHANGED
@@ -51,6 +51,19 @@ module MiniRacer
51
51
  end
52
52
  end
53
53
 
54
+ class ScriptError < EvalError
55
+ def initialize(message)
56
+ message, *@frames = message.split("\n")
57
+ @frames.map! { "JavaScript #{_1.strip}" }
58
+ super(message)
59
+ end
60
+
61
+ def backtrace
62
+ frames = super || []
63
+ @frames + frames
64
+ end
65
+ end
66
+
54
67
  class SnapshotError < Error
55
68
  def initialize(message)
56
69
  message, *@frames = message.split("\n")
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.19.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-24 00:00:00.000000000 Z
11
+ date: 2026-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 24.1.0.0
103
+ version: 24.12.0.1
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 24.1.0.0
110
+ version: 24.12.0.1
111
111
  description: Minimal embedded v8 engine for Ruby
112
112
  email:
113
113
  - sam.saffron@gmail.com
@@ -137,9 +137,9 @@ licenses:
137
137
  - MIT
138
138
  metadata:
139
139
  bug_tracker_uri: https://github.com/discourse/mini_racer/issues
140
- changelog_uri: https://github.com/discourse/mini_racer/blob/v0.19.0/CHANGELOG
141
- documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.19.0
142
- source_code_uri: https://github.com/discourse/mini_racer/tree/v0.19.0
140
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.20.0/CHANGELOG
141
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.20.0
142
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.20.0
143
143
  post_install_message:
144
144
  rdoc_options: []
145
145
  require_paths: