mini_racer 0.18.1 → 0.19.1

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: d136b28eba55fb9518691cd3dc38a0e95af3171d6d1796c7e892ce411023cfe6
4
- data.tar.gz: '07829f6048ef890b28574629b94f0371f441fcef176cb3c70c78da266280dd1f'
3
+ metadata.gz: 8c2110c8c14882bd775ad556afdeb79e1ab42bfabddc24101b82f8390a5be830
4
+ data.tar.gz: 8c70e50ac0edbe545ddd0a17737c045f21ebd6a2aa47f8d730a7f7ced79248b3
5
5
  SHA512:
6
- metadata.gz: a0a80d3d34ba093a39f95fea716048c448800515667a426558fe00d6ffbd70614a375b64c2be923750d57e868c01a959c4396ab5c9afd25e0caefd2816ca4a82
7
- data.tar.gz: a3d7655f8f1ec369a1f279f8d983098d4f8fac381e6404116a0d72133e32a06f8c99309001d33628a440085b7b36079bcba318ae6dedd1a1eff0f381e6b8b9d4
6
+ metadata.gz: e8b17ae50c4455ed2c3db185f5e03d9554bb30096fc1540989cc7aa0e56f471ade5a7d0f815f1a24b3e492cd9c8c7db80bb5146bcf52dfdcb707caaf7323daaa
7
+ data.tar.gz: f1ef6b7225779091ab4c488f0177da8b7d8dd19e779d80a99ae307e9efbfd49e654c645f76315c4b766090cc50ce7f2ec2568586432a122d7d7aef3f7ba93d0d
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ - 0.19.1 - 20-10-2025
2
+ - JS code can now catch ruby exceptions - Ben Noordhuis
3
+ - Retain string encoding when raising exceptions - Ben Noordhuis
4
+ - Fix object identity bug with Ruby to JS conversion - Benjamin Wood
5
+
6
+ - 0.19.0 - 24-06-2025
7
+ - upgrade to node 24.1.0
8
+
1
9
  - 0.18.1 - 03-04-2025
2
10
  - Convert round doubles to fixnum for very big floats - this has better parity with JavaScript - Ben Noorhuis
3
11
 
@@ -13,6 +13,13 @@
13
13
  #include "serde.c"
14
14
  #include "mini_racer_v8.h"
15
15
 
16
+ // for debugging
17
+ #define RB_PUTS(v) \
18
+ do { \
19
+ fflush(stdout); \
20
+ rb_funcall(rb_mKernel, rb_intern("puts"), 1, v); \
21
+ } while (0)
22
+
16
23
  #if RUBY_API_VERSION_CODE < 3*10000+4*100 // 3.4.0
17
24
  static inline void rb_thread_lock_native_thread(void)
18
25
  {
@@ -154,6 +161,7 @@ static VALUE platform_init_error;
154
161
  static VALUE context_disposed_error;
155
162
  static VALUE parse_error;
156
163
  static VALUE memory_error;
164
+ static VALUE script_error;
157
165
  static VALUE runtime_error;
158
166
  static VALUE internal_error;
159
167
  static VALUE snapshot_error;
@@ -327,8 +335,19 @@ static void des_bigint(void *arg, const void *p, size_t n, int sign)
327
335
  if (t >> 63)
328
336
  *a++ = 0; // suppress sign extension
329
337
  v = rb_big_unpack(limbs, a-limbs);
330
- if (sign < 0)
331
- v = rb_big_mul(v, LONG2FIX(-1));
338
+ if (sign < 0) {
339
+ // rb_big_unpack returns T_FIXNUM for smallish bignums
340
+ switch (TYPE(v)) {
341
+ case T_BIGNUM:
342
+ v = rb_big_mul(v, LONG2FIX(-1));
343
+ break;
344
+ case T_FIXNUM:
345
+ v = LONG2FIX(-1 * FIX2LONG(v));
346
+ break;
347
+ default:
348
+ abort();
349
+ }
350
+ }
332
351
  put(c, v);
333
352
  }
334
353
 
@@ -471,12 +490,36 @@ static void des_object_ref(void *arg, uint32_t id)
471
490
 
472
491
  static void des_error_begin(void *arg)
473
492
  {
474
- push(arg, rb_class_new_instance(0, NULL, rb_eRuntimeError));
493
+ push(arg, rb_ary_new());
475
494
  }
476
495
 
477
496
  static void des_error_end(void *arg)
478
497
  {
479
- pop(arg);
498
+ VALUE *a, h, message, stack, cause, newline;
499
+ DesCtx *c;
500
+
501
+ c = arg;
502
+ if (*c->err)
503
+ return;
504
+ if (c->tos == c->stack) {
505
+ snprintf(c->err, sizeof(c->err), "stack underflow");
506
+ return;
507
+ }
508
+ a = &c->tos->a;
509
+ h = rb_ary_pop(*a);
510
+ message = rb_hash_aref(h, rb_str_new_cstr("message"));
511
+ stack = rb_hash_aref(h, rb_str_new_cstr("stack"));
512
+ cause = rb_hash_aref(h, rb_str_new_cstr("cause"));
513
+ if (NIL_P(message))
514
+ message = rb_str_new_cstr("JS exception");
515
+ if (!NIL_P(stack)) {
516
+ newline = rb_str_new_cstr("\n");
517
+ message = rb_funcall(message, rb_intern("concat"), 2, newline, stack);
518
+ }
519
+ *a = rb_class_new_instance(1, &message, script_error);
520
+ if (!NIL_P(cause))
521
+ rb_iv_set(*a, "@cause", cause);
522
+ pop(c);
480
523
  }
481
524
 
482
525
  static int collect(VALUE k, VALUE v, VALUE a)
@@ -516,52 +559,58 @@ static int serialize1(Ser *s, VALUE refs, VALUE v)
516
559
  return -1;
517
560
  switch (TYPE(v)) {
518
561
  case T_ARRAY:
519
- id = rb_hash_lookup(refs, v);
520
- if (NIL_P(id)) {
521
- n = RARRAY_LENINT(v);
522
- i = rb_hash_size_num(refs);
523
- rb_hash_aset(refs, v, LONG2FIX(i));
524
- ser_array_begin(s, n);
525
- for (i = 0; i < n; i++)
526
- if (serialize1(s, refs, rb_ary_entry(v, i)))
527
- return -1;
528
- ser_array_end(s, n);
529
- } else {
530
- ser_object_ref(s, FIX2LONG(id));
562
+ {
563
+ VALUE obj_id = rb_obj_id(v);
564
+ id = rb_hash_lookup(refs, obj_id);
565
+ if (NIL_P(id)) {
566
+ n = RARRAY_LENINT(v);
567
+ i = rb_hash_size_num(refs);
568
+ rb_hash_aset(refs, obj_id, LONG2FIX(i));
569
+ ser_array_begin(s, n);
570
+ for (i = 0; i < n; i++)
571
+ if (serialize1(s, refs, rb_ary_entry(v, i)))
572
+ return -1;
573
+ ser_array_end(s, n);
574
+ } else {
575
+ ser_object_ref(s, FIX2LONG(id));
576
+ }
531
577
  }
532
578
  break;
533
579
  case T_HASH:
534
- id = rb_hash_lookup(refs, v);
535
- if (NIL_P(id)) {
536
- a = rb_ary_new();
537
- i = rb_hash_size_num(refs);
538
- n = rb_hash_size_num(v);
539
- rb_hash_aset(refs, v, LONG2FIX(i));
540
- rb_hash_foreach(v, collect, a);
541
- for (i = 0; i < 2*n; i += 2) {
542
- t = rb_ary_entry(a, i);
543
- switch (TYPE(t)) {
544
- case T_FIXNUM:
545
- case T_STRING:
546
- case T_SYMBOL:
547
- continue;
548
- }
549
- break;
550
- }
551
- if (i == 2*n) {
552
- ser_object_begin(s);
580
+ {
581
+ VALUE obj_id = rb_obj_id(v);
582
+ id = rb_hash_lookup(refs, obj_id);
583
+ if (NIL_P(id)) {
584
+ a = rb_ary_new();
585
+ i = rb_hash_size_num(refs);
586
+ n = rb_hash_size_num(v);
587
+ rb_hash_aset(refs, obj_id, LONG2FIX(i));
588
+ rb_hash_foreach(v, collect, a);
553
589
  for (i = 0; i < 2*n; i += 2) {
554
- if (serialize1(s, refs, rb_ary_entry(a, i+0)))
555
- return -1;
556
- if (serialize1(s, refs, rb_ary_entry(a, i+1)))
557
- return -1;
590
+ t = rb_ary_entry(a, i);
591
+ switch (TYPE(t)) {
592
+ case T_FIXNUM:
593
+ case T_STRING:
594
+ case T_SYMBOL:
595
+ continue;
596
+ }
597
+ break;
598
+ }
599
+ if (i == 2*n) {
600
+ ser_object_begin(s);
601
+ for (i = 0; i < 2*n; i += 2) {
602
+ if (serialize1(s, refs, rb_ary_entry(a, i+0)))
603
+ return -1;
604
+ if (serialize1(s, refs, rb_ary_entry(a, i+1)))
605
+ return -1;
606
+ }
607
+ ser_object_end(s, n);
608
+ } else {
609
+ return bail(&s->err, "TODO serialize as Map");
558
610
  }
559
- ser_object_end(s, n);
560
611
  } else {
561
- return bail(&s->err, "TODO serialize as Map");
612
+ ser_object_ref(s, FIX2LONG(id));
562
613
  }
563
- } else {
564
- ser_object_ref(s, FIX2LONG(id));
565
614
  }
566
615
  break;
567
616
  case T_DATA:
@@ -620,14 +669,16 @@ static int serialize1(Ser *s, VALUE refs, VALUE v)
620
669
  struct timeval tv = rb_time_timeval(v);
621
670
  ser_date(s, tv.tv_sec*1e3 + tv.tv_usec/1e3);
622
671
  } else {
623
- snprintf(s->err, sizeof(s->err), "unsupported type %s", rb_class2name(CLASS_OF(v)));
624
- return -1;
672
+ snprintf(s->err, sizeof(s->err), "unsupported type %s", rb_class2name(CLASS_OF(v)));
673
+ return -1;
625
674
  }
626
675
  break;
627
676
  default:
628
677
  snprintf(s->err, sizeof(s->err), "unsupported type %x", TYPE(v));
629
678
  return -1;
630
679
  }
680
+ if (*s->err)
681
+ return -1;
631
682
  return 0;
632
683
  }
633
684
 
@@ -875,6 +926,7 @@ static VALUE rendezvous_callback_do(VALUE arg)
875
926
  static void *rendezvous_callback(void *arg)
876
927
  {
877
928
  struct rendezvous_nogvl *a;
929
+ const char *err;
878
930
  Context *c;
879
931
  int exc;
880
932
  VALUE r;
@@ -898,7 +950,12 @@ out:
898
950
  buf_move(&s.b, a->req);
899
951
  return NULL;
900
952
  fail:
901
- ser_init1(&s, 'e'); // exception pending
953
+ ser_init0(&s); // ruby exception pending
954
+ w_byte(&s, 'e'); // send ruby error message to v8 thread
955
+ r = rb_funcall(c->exception, rb_intern("to_s"), 0);
956
+ err = StringValueCStr(r);
957
+ if (err)
958
+ w(&s, err, strlen(err));
902
959
  goto out;
903
960
  }
904
961
 
@@ -956,6 +1013,13 @@ static VALUE rendezvous1(Context *c, Buf *req, DesCtx *d)
956
1013
  int exc;
957
1014
 
958
1015
  rendezvous_no_des(c, req, &res); // takes ownership of |req|
1016
+ r = c->exception;
1017
+ c->exception = Qnil;
1018
+ // if js land didn't handle exception from ruby callback, re-raise it now
1019
+ if (res.len == 1 && *res.buf == 'e') {
1020
+ assert(!NIL_P(r));
1021
+ rb_exc_raise(r);
1022
+ }
959
1023
  r = rb_protect(deserialize, (VALUE)&(struct rendezvous_des){d, &res}, &exc);
960
1024
  buf_reset(&res);
961
1025
  if (exc) {
@@ -963,11 +1027,6 @@ static VALUE rendezvous1(Context *c, Buf *req, DesCtx *d)
963
1027
  rb_set_errinfo(Qnil);
964
1028
  rb_exc_raise(r);
965
1029
  }
966
- if (!NIL_P(c->exception)) {
967
- r = c->exception;
968
- c->exception = Qnil;
969
- rb_exc_raise(r);
970
- }
971
1030
  return r;
972
1031
  }
973
1032
 
@@ -986,8 +1045,8 @@ static void handle_exception(VALUE e)
986
1045
 
987
1046
  if (NIL_P(e))
988
1047
  return;
989
- StringValue(e);
990
- s = RSTRING_PTR(e);
1048
+ e = StringValue(e);
1049
+ s = StringValueCStr(e);
991
1050
  switch (*s) {
992
1051
  case NO_ERROR:
993
1052
  return;
@@ -1009,7 +1068,7 @@ static void handle_exception(VALUE e)
1009
1068
  default:
1010
1069
  rb_raise(internal_error, "bad error class %02x", *s);
1011
1070
  }
1012
- rb_raise(klass, "%s", s+1);
1071
+ rb_enc_raise(rb_enc_get(e), klass, "%s", s+1);
1013
1072
  }
1014
1073
 
1015
1074
  static VALUE context_alloc(VALUE klass)
@@ -1615,6 +1674,11 @@ static VALUE snapshot_size0(VALUE self)
1615
1674
  return LONG2FIX(RSTRING_LENINT(ss->blob));
1616
1675
  }
1617
1676
 
1677
+ static VALUE script_error_cause(VALUE self)
1678
+ {
1679
+ return rb_iv_get(self, "@cause");
1680
+ }
1681
+
1618
1682
  __attribute__((visibility("default")))
1619
1683
  void Init_mini_racer_extension(void)
1620
1684
  {
@@ -1629,10 +1693,13 @@ void Init_mini_racer_extension(void)
1629
1693
  c = rb_define_class_under(m, "EvalError", c);
1630
1694
  parse_error = rb_define_class_under(m, "ParseError", c);
1631
1695
  memory_error = rb_define_class_under(m, "V8OutOfMemoryError", c);
1696
+ script_error = rb_define_class_under(m, "ScriptError", c);
1632
1697
  runtime_error = rb_define_class_under(m, "RuntimeError", c);
1633
1698
  internal_error = rb_define_class_under(m, "InternalError", c);
1634
1699
  terminated_error = rb_define_class_under(m, "ScriptTerminatedError", c);
1635
1700
 
1701
+ rb_define_method(script_error, "cause", script_error_cause, 0);
1702
+
1636
1703
  c = context_class = rb_define_class_under(m, "Context", rb_cObject);
1637
1704
  rb_define_method(c, "initialize", context_initialize, -1);
1638
1705
  rb_define_method(c, "attach", context_attach, 2);
@@ -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
  }
@@ -239,15 +243,44 @@ static void ser_num(Ser *s, double v)
239
243
  }
240
244
  }
241
245
 
246
+ // ser_bigint: |n| is in bytes, not quadwords
247
+ static void ser_bigint(Ser *s, const uint64_t *p, size_t n, int sign)
248
+ {
249
+ if (*s->err)
250
+ return;
251
+ if (n % 8) {
252
+ snprintf(s->err, sizeof(s->err), "bad bigint");
253
+ return;
254
+ }
255
+ w_byte(s, 'Z');
256
+ // chop off high all-zero words
257
+ n /= 8;
258
+ while (n--)
259
+ if (p[n])
260
+ break;
261
+ if (n == (size_t)-1) {
262
+ w_byte(s, 0); // normalized zero
263
+ } else {
264
+ n = 8*n + 8;
265
+ w_varint(s, 2*n + (sign < 0));
266
+ w(s, p, n);
267
+ }
268
+ }
269
+
242
270
  static void ser_int(Ser *s, int64_t v)
243
271
  {
272
+ uint64_t t;
273
+ int sign;
274
+
244
275
  if (*s->err)
245
276
  return;
246
277
  if (v < INT32_MIN || v > INT32_MAX) {
247
278
  if (v > INT64_MIN/1024)
248
279
  if (v <= INT64_MAX/1024)
249
280
  return ser_num(s, v);
250
- snprintf(s->err, sizeof(s->err), "out of range: %lld", (long long)v);
281
+ t = v < 0 ? -v : v;
282
+ sign = v < 0 ? -1 : 1;
283
+ ser_bigint(s, &t, sizeof(t), sign);
251
284
  } else {
252
285
  w_byte(s, 'I');
253
286
  w_zigzag(s, v);
@@ -265,30 +298,6 @@ static void ser_date(Ser *s, double v)
265
298
  }
266
299
  }
267
300
 
268
- // ser_bigint: |n| is in bytes, not quadwords
269
- static void ser_bigint(Ser *s, const uint64_t *p, size_t n, int sign)
270
- {
271
- if (*s->err)
272
- return;
273
- if (n % 8) {
274
- snprintf(s->err, sizeof(s->err), "bad bigint");
275
- return;
276
- }
277
- w_byte(s, 'Z');
278
- // chop off high all-zero words
279
- n /= 8;
280
- while (n--)
281
- if (p[n])
282
- break;
283
- if (n == (size_t)-1) {
284
- w_byte(s, 0); // normalized zero
285
- } else {
286
- n = 8*n + 8;
287
- w_varint(s, 2*n + (sign < 0));
288
- w(s, p, n);
289
- }
290
- }
291
-
292
301
  // string must be utf8
293
302
  static void ser_string(Ser *s, const char *p, size_t n)
294
303
  {
@@ -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.18.1"
5
- LIBV8_NODE_VERSION = "~> 23.6.1.0"
4
+ VERSION = "0.19.1"
5
+ LIBV8_NODE_VERSION = "~> 24.1.0.0"
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.18.1
4
+ version: 0.19.1
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-04-03 00:00:00.000000000 Z
11
+ date: 2025-10-19 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: 23.6.1.0
103
+ version: 24.1.0.0
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: 23.6.1.0
110
+ version: 24.1.0.0
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.18.1/CHANGELOG
141
- documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.18.1
142
- source_code_uri: https://github.com/discourse/mini_racer/tree/v0.18.1
140
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.19.1/CHANGELOG
141
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.19.1
142
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.19.1
143
143
  post_install_message:
144
144
  rdoc_options: []
145
145
  require_paths: