mini_racer 0.22.0 → 0.22.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: 7a20d79f246e2bd3f9aa86cdf19c83413d2b782b7738f0bfc13017227e2c20f7
4
- data.tar.gz: b1c6d7b75c8bbc7520f0722ed255d042e70e4e606bb627a59926523135640921
3
+ metadata.gz: 522742f60d9062d656ffab6c1eb7ead5ceb0eabb6918b9582e9eec32f1f8a4c8
4
+ data.tar.gz: 404097b19b0e243bcd995e54f2560dd8fa5097dcc94a9488b435242350bc6719
5
5
  SHA512:
6
- metadata.gz: 9c828f6078e1d6f48503bf9870cab6ced783e853decf679c0534735d7c3a9a8d6efb3c06ed7528f88f1ea8f90ddf5e2c8d50c73e89d8e7672d5b03ad7b85e3ef
7
- data.tar.gz: 62eb803f2a6aea12b7a80cc6385858631a60dadb61c2eb409e1f5ecf79cfa969f3d9350519377c0a169bf0ffd15987c06635da2d3aaa84f3017183d51b5216bb
6
+ metadata.gz: 723b3777cf8085b76662a3f4ede9fcdd8d4d8b31c31346ed0a87af1092b6a0323579b4dd6c3ec45a3c06f6cecedda7a30b8e807e69ecceaf5c3bf2ab9ceabc07
7
+ data.tar.gz: 36e1ce3f381f3d4017c10d811805320af94fd026a81eca8bdc71e6fa0cecd58a23f4668883de3cf8810ce57e41e33e9e4560810d4621b9825104a22dd2076e6b
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ - 0.22.1 - 27-08-2026
2
+ - Fix building with Clang 22+ and big-endian bigint serialization by making bigint serialization byte-oriented instead of relying on native `uint64_t`/`unsigned long` representations
3
+ - Fix Ruby integers at or above 512 bits being silently truncated when passed to JavaScript, and large JavaScript bigints producing an invalid internal value when returned to Ruby
4
+ - Support Ruby and JavaScript bigints up to a 16 MiB magnitude, using allocation-free conversion for common sizes and bounded dynamic storage for larger values
5
+
1
6
  - 0.22.0 - 12-08-2026
2
7
  - Add `Context#call_await` and `Context#eval_await`: like `call`/`eval` but block until a returned Promise settles and return the settled value; rejections raise `MiniRacer::RuntimeError`
3
8
  - Fix a `call` or `eval` made from a Ruby callback taking the timeout or `stop` meant for the evaluation around it, which then kept running
data/README.md CHANGED
@@ -60,6 +60,10 @@ puts context.eval("array_and_hash()")
60
60
  # => {"a" => 1, "b" => [1, {"a" => 1}]}
61
61
  ```
62
62
 
63
+ Ruby `Integer` and JavaScript `BigInt` values are converted exactly up to a
64
+ 16 MiB magnitude (about 134 million bits). Larger individual values are
65
+ rejected with a serialization error rather than truncated.
66
+
63
67
  ### Return binary data from Ruby to JavaScript
64
68
 
65
69
  Attached Ruby functions can return binary data as `Uint8Array` using `MiniRacer::Binary`:
@@ -518,6 +522,25 @@ gcc >= 12.2 and Xcode >= 13 are, at the time of writing, known to work.
518
522
  * Concurrent cause .... JRuby
519
523
  * Supports execjs
520
524
 
525
+ ## Community
526
+
527
+ Libraries and integrations built with MiniRacer:
528
+
529
+ - [Humid](https://github.com/thoughtbot/humid) — JavaScript server-side rendering helpers for Rails.
530
+ - [ExecJS](https://github.com/rails/execjs) — A common interface for executing JavaScript from Ruby, with a MiniRacer runtime.
531
+ - [Opal](https://github.com/opal/opal) — A Ruby-to-JavaScript compiler with a MiniRacer CLI runner.
532
+ - [Handlebars::Engine](https://github.com/gi/handlebars-ruby) — A complete Ruby interface to Handlebars.js.
533
+ - [Minibars](https://github.com/combinaut/minibars) — A lightweight Handlebars.rb replacement built on MiniRacer.
534
+ - [Rtlcss](https://github.com/discourse/rtlcss) — Runs rtlcss from Ruby to convert stylesheets between LTR and RTL.
535
+ - [MessageFormat](https://github.com/discourse/messageformat) — Compiles MessageFormat messages from Ruby using `@messageformat/core`.
536
+ - [feelin](https://github.com/ekzo-dev/ruby-feelin) — Evaluates DMN FEEL expressions from Ruby.
537
+ - [parse-css](https://github.com/camertron/parse-css) — Parses CSS, including nested CSS, through the JavaScript parse-css library.
538
+
539
+ ### Notable users
540
+
541
+ - [Discourse](https://github.com/discourse/discourse) — A large Rails application using MiniRacer for JavaScript compilation, processing, and sandboxed evaluation.
542
+ - [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler) — Uses MiniRacer in its JavaScript build tooling.
543
+
521
544
  ## Contributing
522
545
 
523
546
  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.
@@ -62,6 +62,8 @@ static inline void rb_thread_lock_native_thread(void)
62
62
 
63
63
  #define countof(x) (sizeof(x) / sizeof(*(x)))
64
64
  #define endof(x) ((x) + countof(x))
65
+ #define BIGINT_STACK_WORDS 64
66
+ #define BIGINT_MAX_BYTES (16 * 1024 * 1024)
65
67
 
66
68
  // mostly RO: assigned once by platform_set_flag1 while holding |flags_mtx|,
67
69
  // from then on read-only and accessible without holding locks
@@ -353,33 +355,32 @@ static void des_date(void *arg, double v)
353
355
  put(arg, rb_time_new(sec, usec));
354
356
  }
355
357
 
356
- // note: v8 stores bigints in 1's complement, ruby in 2's complement,
357
- // so we have to take additional steps to ensure correct conversion
358
+ // note: v8 stores bigints as a sign plus little-endian 64-bit magnitude words
358
359
  static void des_bigint(void *arg, const void *p, size_t n, int sign)
359
360
  {
360
361
  VALUE v;
361
- size_t i;
362
362
  DesCtx *c;
363
- unsigned long *a, t, limbs[65]; // +1 to suppress sign extension
363
+ int flags;
364
364
 
365
365
  c = arg;
366
366
  if (*c->err)
367
367
  return;
368
- if (n > sizeof(limbs) - sizeof(*limbs)) {
368
+ if (n % sizeof(uint64_t)) {
369
+ snprintf(c->err, sizeof(c->err), "bad bigint");
370
+ return;
371
+ }
372
+ if (n > BIGINT_MAX_BYTES) {
369
373
  snprintf(c->err, sizeof(c->err), "bigint too big");
370
374
  return;
371
375
  }
372
- a = limbs;
373
- t = 0;
374
- for (i = 0; i < n; a++, i += sizeof(*a)) {
375
- memcpy(a, (char *)p + i, sizeof(*a));
376
- t = *a;
376
+ if (n == 0) {
377
+ v = INT2FIX(0);
378
+ } else {
379
+ flags = INTEGER_PACK_LITTLE_ENDIAN;
380
+ if (sign < 0)
381
+ flags |= INTEGER_PACK_NEGATIVE;
382
+ v = rb_integer_unpack(p, n/sizeof(uint64_t), sizeof(uint64_t), 0, flags);
377
383
  }
378
- if (t >> 63)
379
- *a++ = 0; // suppress sign extension
380
- v = rb_big_unpack(limbs, a-limbs);
381
- if (sign < 0)
382
- v = rb_funcall(v, rb_intern("-@"), 0);
383
384
  put(c, v);
384
385
  }
385
386
 
@@ -580,12 +581,42 @@ static void add_string(Ser *s, VALUE v)
580
581
  return ser_string(s, p, n);
581
582
  }
582
583
 
584
+ // Keep small values allocation-free while allowing large values up to a
585
+ // deliberate per-value limit that bounds temporary conversion storage.
586
+ static int serialize_bigint(Ser *s, VALUE v)
587
+ {
588
+ uint64_t stack_words[BIGINT_STACK_WORDS];
589
+ uint64_t *words;
590
+ size_t nwords, nbytes;
591
+ int packed;
592
+
593
+ nwords = rb_absint_numwords(v, 64, NULL);
594
+ if (nwords == (size_t)-1 || nwords > BIGINT_MAX_BYTES/sizeof(*words))
595
+ return bail(&s->err, "bigint too big");
596
+ nbytes = nwords * sizeof(*words);
597
+ words = stack_words;
598
+ if (nwords > countof(stack_words)) {
599
+ words = malloc(nbytes);
600
+ if (!words)
601
+ return bail(&s->err, "out of memory");
602
+ }
603
+ packed = rb_integer_pack(v, words, nwords, sizeof(*words), 0,
604
+ INTEGER_PACK_LITTLE_ENDIAN);
605
+ if (packed < -1 || packed > 1) {
606
+ if (words != stack_words)
607
+ free(words);
608
+ return bail(&s->err, "bigint too big");
609
+ }
610
+ ser_bigint(s, words, nbytes, packed < 0 ? -1 : 1);
611
+ if (words != stack_words)
612
+ free(words);
613
+ return *s->err ? -1 : 0;
614
+ }
615
+
583
616
  static int serialize1(Ser *s, VALUE refs, VALUE v)
584
617
  {
585
- unsigned long limbs[64];
586
618
  VALUE a, t, id;
587
619
  size_t i, n;
588
- int sign;
589
620
 
590
621
  if (*s->err)
591
622
  return -1;
@@ -670,15 +701,7 @@ static int serialize1(Ser *s, VALUE refs, VALUE v)
670
701
  ser_bool(s, 0);
671
702
  break;
672
703
  case T_BIGNUM:
673
- // note: v8 stores bigints in 1's complement, ruby in 2's complement,
674
- // so we have to take additional steps to ensure correct conversion
675
- memset(limbs, 0, sizeof(limbs));
676
- sign = rb_big_sign(v) ? 1 : -1;
677
- if (sign < 0)
678
- v = rb_big_mul(v, LONG2FIX(-1));
679
- rb_big_pack(v, limbs, countof(limbs));
680
- ser_bigint(s, limbs, countof(limbs), sign);
681
- break;
704
+ return serialize_bigint(s, v);
682
705
  case T_FIXNUM:
683
706
  ser_int(s, FIX2LONG(v));
684
707
  break;
@@ -958,6 +981,8 @@ static VALUE deserialize1(DesCtx *d, const uint8_t *p, size_t n)
958
981
 
959
982
  if (des(&err, p, n, d))
960
983
  rb_raise(runtime_error, "%s", err);
984
+ if (*d->err)
985
+ rb_raise(runtime_error, "%s", d->err);
961
986
  if (d->tos != d->stack) // should not happen
962
987
  rb_raise(runtime_error, "parse stack not empty");
963
988
  return d->tos->a;
@@ -1020,7 +1045,7 @@ static void *rendezvous_callback(void *arg)
1020
1045
  goto fail;
1021
1046
  }
1022
1047
  ser_init1(&s, 'c'); // callback reply
1023
- if (serialize(&s, r)) { // should not happen
1048
+ if (serialize(&s, r)) {
1024
1049
  c->exception = rb_exc_new_cstr(internal_error, s.err);
1025
1050
  ser_reset(&s);
1026
1051
  goto fail;
@@ -243,33 +243,38 @@ static void ser_num(Ser *s, double v)
243
243
  }
244
244
  }
245
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)
246
+ // ser_bigint: |p| points to |n| bytes, interpreted as little-endian
247
+ // 64-bit words. Keep the interface byte-oriented so callers don't need to
248
+ // expose a concrete word type.
249
+ static void ser_bigint(Ser *s, const void *p, size_t n, int sign)
248
250
  {
251
+ const uint8_t *bytes;
252
+
249
253
  if (*s->err)
250
254
  return;
251
255
  if (n % 8) {
252
256
  snprintf(s->err, sizeof(s->err), "bad bigint");
253
257
  return;
254
258
  }
259
+ bytes = p;
255
260
  w_byte(s, 'Z');
256
261
  // 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
+ while (n > 0 && bytes[n-1] == 0)
263
+ n--;
264
+ if (n == 0) {
262
265
  w_byte(s, 0); // normalized zero
263
266
  } else {
264
- n = 8*n + 8;
267
+ n = (n + 7) & ~(size_t)7;
265
268
  w_varint(s, 2*n + (sign < 0));
266
- w(s, p, n);
269
+ w(s, bytes, n);
267
270
  }
268
271
  }
269
272
 
270
273
  static void ser_int(Ser *s, int64_t v)
271
274
  {
275
+ uint8_t bytes[8];
272
276
  uint64_t t;
277
+ size_t i;
273
278
  int sign;
274
279
 
275
280
  if (*s->err)
@@ -279,8 +284,10 @@ static void ser_int(Ser *s, int64_t v)
279
284
  if (v <= INT64_MAX/1024)
280
285
  return ser_num(s, v);
281
286
  t = v < 0 ? (uint64_t)(-(v + 1)) + 1 : (uint64_t)v;
287
+ for (i = 0; i < sizeof(bytes); i++)
288
+ bytes[i] = t >> (8*i);
282
289
  sign = v < 0 ? -1 : 1;
283
- ser_bigint(s, &t, sizeof(t), sign);
290
+ ser_bigint(s, bytes, sizeof(bytes), sign);
284
291
  } else {
285
292
  w_byte(s, 'I');
286
293
  w_zigzag(s, v);
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniRacer
4
- VERSION = "0.22.0"
4
+ VERSION = "0.22.1"
5
5
  LIBV8_NODE_VERSION = "~> 24.12.0.1"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_racer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
@@ -164,9 +164,9 @@ licenses:
164
164
  - MIT
165
165
  metadata:
166
166
  bug_tracker_uri: https://github.com/discourse/mini_racer/issues
167
- changelog_uri: https://github.com/discourse/mini_racer/blob/v0.22.0/CHANGELOG
168
- documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.22.0
169
- source_code_uri: https://github.com/discourse/mini_racer/tree/v0.22.0
167
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.22.1/CHANGELOG
168
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.22.1
169
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.22.1
170
170
  rdoc_options: []
171
171
  require_paths:
172
172
  - lib