mini_racer 0.17.0.pre7 → 0.17.0.pre9

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: 1d058a397309a0e5354576fa25b299f26e9ca9576b23333063dbcd46fcf9f775
4
- data.tar.gz: 3dde7c0c2e713ebb419593eb6fb0d7634f07ee4d91e35549aa9fb57987a255e5
3
+ metadata.gz: b3be215eb4d4e72b01480ffa28863ea7ff1947b3f8cf0b6dcd860ffde2e48799
4
+ data.tar.gz: adcae327e54c2c372871c255e4bfd19a07b28964cd4c7c51cbc1cc251d1f71db
5
5
  SHA512:
6
- metadata.gz: 8cf3e4c85acafb8161ff8a88d193b7bfde7e2b1ab241366364306a72416f462cbd31b4886a3b1f01402557a6045fd6ad40b1837849f307df9d3ac3fafdd7c6d0
7
- data.tar.gz: a08db269e750b147daa7501cdf38dccdee8de7d07530b0112aecd1da3949b8daab704c778f1b3657d0dea328b087db9173f30e9aeb43f9d755d4a95dd1e51bac
6
+ metadata.gz: 98bdc234f17c0e16ae995c8fe3566f6ec80cbd92c569e4aa31ac1999d309ae2a197b0c7cb1c5de62f542f25b4f73287d0a34ab7967e1e24c32d02fc73ade33f2
7
+ data.tar.gz: 7ade32c683f240c3e19eaa58b6a044192f57b1e651966c042654d401f1f5dae1aff20d1c545dd7fd05afb2b0f70659080825b5a788ab82379b119c497ac31e47
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ - 0.17.0.pre9 - 13-01-2025
2
+ - For backwards compatibility convert v8 return values to UTF-8 (invalidly encoded string still get returned using V8 encoding)
3
+
4
+ - 0.17.0.pre8 - 11-01-2025
5
+ - Fix handling of UTF 32 LE and Ascii encoding strings - Ben Noordhuis
6
+ - Handle rare edge case in V8 serialization - Ben Noordhuis
7
+
1
8
  - 0.17.0.pre7 - 10-01-2025
2
9
 
3
10
  - Objects containing non serializable properties will return an Error object vs raising an exception. Ben Noordhuis
@@ -164,12 +164,6 @@ static VALUE js_function_class;
164
164
  static pthread_mutex_t flags_mtx = PTHREAD_MUTEX_INITIALIZER;
165
165
  static Buf flags; // protected by |flags_mtx|
166
166
 
167
- struct rendezvous_nogvl
168
- {
169
- Context *context;
170
- Buf *req, *res;
171
- };
172
-
173
167
  // arg == &(struct rendezvous_nogvl){...}
174
168
  static void *rendezvous_callback(void *arg);
175
169
 
@@ -184,16 +178,30 @@ typedef struct DesCtx
184
178
  {
185
179
  State *tos;
186
180
  VALUE refs; // array
181
+ uint8_t transcode_latin1:1;
187
182
  char err[64];
188
183
  State stack[512];
189
184
  } DesCtx;
190
185
 
186
+ struct rendezvous_nogvl
187
+ {
188
+ Context *context;
189
+ Buf *req, *res;
190
+ };
191
+
192
+ struct rendezvous_des
193
+ {
194
+ DesCtx *d;
195
+ Buf *res;
196
+ };
197
+
191
198
  static void DesCtx_init(DesCtx *c)
192
199
  {
193
200
  c->tos = c->stack;
194
201
  c->refs = rb_ary_new();
195
202
  *c->tos = (State){Qundef, Qundef};
196
203
  *c->err = '\0';
204
+ c->transcode_latin1 = 1; // convert to utf8
197
205
  }
198
206
 
199
207
  static void put(DesCtx *c, VALUE v)
@@ -321,9 +329,22 @@ static void des_string(void *arg, const char *s, size_t n)
321
329
  put(arg, rb_utf8_str_new(s, n));
322
330
  }
323
331
 
332
+ static VALUE str_encode_bang(VALUE v)
333
+ {
334
+ // TODO cache these? this function can get called often
335
+ return rb_funcall(v, rb_intern("encode!"), 1, rb_str_new_cstr("UTF-8"));
336
+ }
337
+
324
338
  static void des_string8(void *arg, const uint8_t *s, size_t n)
325
339
  {
326
- put(arg, rb_enc_str_new((char *)s, n, rb_ascii8bit_encoding()));
340
+ DesCtx *c;
341
+ VALUE v;
342
+
343
+ c = arg;
344
+ v = rb_enc_str_new((char *)s, n, rb_ascii8bit_encoding());
345
+ if (c->transcode_latin1)
346
+ v = str_encode_bang(v); // cannot fail
347
+ put(c, v);
327
348
  }
328
349
 
329
350
  // des_string16: |s| is not word aligned
@@ -331,7 +352,9 @@ static void des_string8(void *arg, const uint8_t *s, size_t n)
331
352
  static void des_string16(void *arg, const void *s, size_t n)
332
353
  {
333
354
  rb_encoding *e;
355
+ VALUE v, r;
334
356
  DesCtx *c;
357
+ int exc;
335
358
 
336
359
  c = arg;
337
360
  if (*c->err)
@@ -344,7 +367,15 @@ static void des_string16(void *arg, const void *s, size_t n)
344
367
  snprintf(c->err, sizeof(c->err), "no UTF16-LE encoding");
345
368
  return;
346
369
  }
347
- put(c, rb_enc_str_new((char *)s, n, e));
370
+ v = rb_enc_str_new((char *)s, n, e);
371
+ // JS strings can contain unmatched or illegal surrogate pairs
372
+ // that Ruby won't decode; return the string as-is in that case
373
+ r = rb_protect(str_encode_bang, v, &exc);
374
+ if (exc) {
375
+ rb_set_errinfo(Qnil);
376
+ r = v;
377
+ }
378
+ put(c, r);
348
379
  }
349
380
 
350
381
  // ruby doesn't really have a concept of a byte array so store it as
@@ -422,6 +453,25 @@ static int collect(VALUE k, VALUE v, VALUE a)
422
453
  return ST_CONTINUE;
423
454
  }
424
455
 
456
+ static void add_string(Ser *s, VALUE v)
457
+ {
458
+ rb_encoding *e;
459
+ const void *p;
460
+ size_t n;
461
+
462
+ Check_Type(v, T_STRING);
463
+ e = rb_enc_get(v);
464
+ p = RSTRING_PTR(v);
465
+ n = RSTRING_LEN(v);
466
+ if (e) {
467
+ if (!strcmp(e->name, "ISO-8859-1"))
468
+ return ser_string8(s, p, n);
469
+ if (!strcmp(e->name, "UTF-16LE"))
470
+ return ser_string16(s, p, n);
471
+ }
472
+ return ser_string(s, p, n);
473
+ }
474
+
425
475
  static int serialize1(Ser *s, VALUE refs, VALUE v)
426
476
  {
427
477
  unsigned long limbs[64];
@@ -525,7 +575,7 @@ static int serialize1(Ser *s, VALUE refs, VALUE v)
525
575
  v = rb_sym2str(v);
526
576
  // fallthru
527
577
  case T_STRING:
528
- ser_string(s, RSTRING_PTR(v), RSTRING_LENINT(v));
578
+ add_string(s, v);
529
579
  break;
530
580
  default:
531
581
  snprintf(s->err, sizeof(s->err), "unsupported type %x", TYPE(v));
@@ -721,25 +771,25 @@ static void *v8_thread_start(void *arg)
721
771
  return NULL;
722
772
  }
723
773
 
724
- static VALUE deserialize1(const uint8_t *p, size_t n)
774
+ static VALUE deserialize1(DesCtx *d, const uint8_t *p, size_t n)
725
775
  {
726
776
  char err[64];
727
- DesCtx d;
728
777
 
729
- DesCtx_init(&d);
730
- if (des(&err, p, n, &d))
778
+ if (des(&err, p, n, d))
731
779
  rb_raise(runtime_error, "%s", err);
732
- if (d.tos != d.stack) // should not happen
780
+ if (d->tos != d->stack) // should not happen
733
781
  rb_raise(runtime_error, "parse stack not empty");
734
- return d.tos->a;
782
+ return d->tos->a;
735
783
  }
736
784
 
737
785
  static VALUE deserialize(VALUE arg)
738
786
  {
787
+ struct rendezvous_des *a;
739
788
  Buf *b;
740
789
 
741
- b = (void *)arg;
742
- return deserialize1(b->buf, b->len);
790
+ a = (void *)arg;
791
+ b = a->res;
792
+ return deserialize1(a->d, b->buf, b->len);
743
793
  }
744
794
 
745
795
  // called with |rr_mtx| and GVL held; can raise exception
@@ -748,6 +798,7 @@ static VALUE rendezvous_callback_do(VALUE arg)
748
798
  struct rendezvous_nogvl *a;
749
799
  VALUE func, args;
750
800
  Context *c;
801
+ DesCtx d;
751
802
  Buf *b;
752
803
 
753
804
  a = (void *)arg;
@@ -755,7 +806,8 @@ static VALUE rendezvous_callback_do(VALUE arg)
755
806
  c = a->context;
756
807
  assert(b->len > 0);
757
808
  assert(*b->buf == 'c');
758
- args = deserialize1(b->buf+1, b->len-1); // skip 'c' marker
809
+ DesCtx_init(&d);
810
+ args = deserialize1(&d, b->buf+1, b->len-1); // skip 'c' marker
759
811
  func = rb_ary_pop(args); // callback id
760
812
  func = rb_ary_entry(c->procs, FIX2LONG(func));
761
813
  return rb_funcall2(func, rb_intern("call"), RARRAY_LENINT(args), RARRAY_PTR(args));
@@ -847,14 +899,14 @@ static void rendezvous_no_des(Context *c, Buf *req, Buf *res)
847
899
 
848
900
  // send request to & receive reply from v8 thread; takes ownership of |req|
849
901
  // can raise exceptions and longjmp away but won't leak |req|
850
- static VALUE rendezvous(Context *c, Buf *req)
902
+ static VALUE rendezvous1(Context *c, Buf *req, DesCtx *d)
851
903
  {
852
904
  VALUE r;
853
905
  Buf res;
854
906
  int exc;
855
907
 
856
908
  rendezvous_no_des(c, req, &res); // takes ownership of |req|
857
- r = rb_protect(deserialize, (VALUE)&res, &exc);
909
+ r = rb_protect(deserialize, (VALUE)&(struct rendezvous_des){d, &res}, &exc);
858
910
  buf_reset(&res);
859
911
  if (exc) {
860
912
  r = rb_errinfo();
@@ -869,6 +921,14 @@ static VALUE rendezvous(Context *c, Buf *req)
869
921
  return r;
870
922
  }
871
923
 
924
+ static VALUE rendezvous(Context *c, Buf *req)
925
+ {
926
+ DesCtx d;
927
+
928
+ DesCtx_init(&d);
929
+ return rendezvous1(c, req, &d);
930
+ }
931
+
872
932
  static void handle_exception(VALUE e)
873
933
  {
874
934
  const char *s;
@@ -1062,7 +1122,7 @@ static VALUE context_attach(VALUE self, VALUE name, VALUE proc)
1062
1122
  // request is (A)ttach, [name, id] array
1063
1123
  ser_init1(&s, 'A');
1064
1124
  ser_array_begin(&s, 2);
1065
- ser_string(&s, RSTRING_PTR(name), RSTRING_LENINT(name));
1125
+ add_string(&s, name);
1066
1126
  ser_int(&s, RARRAY_LENINT(c->procs));
1067
1127
  ser_array_end(&s, 2);
1068
1128
  rb_ary_push(c->procs, proc);
@@ -1159,8 +1219,8 @@ static VALUE context_eval(int argc, VALUE *argv, VALUE self)
1159
1219
  // request is (E)val, [filename, source] array
1160
1220
  ser_init1(&s, 'E');
1161
1221
  ser_array_begin(&s, 2);
1162
- ser_string(&s, RSTRING_PTR(filename), RSTRING_LENINT(filename));
1163
- ser_string(&s, RSTRING_PTR(source), RSTRING_LENINT(source));
1222
+ add_string(&s, filename);
1223
+ add_string(&s, source);
1164
1224
  ser_array_end(&s, 2);
1165
1225
  // response is [result, errname] array
1166
1226
  a = rendezvous(c, &s.b); // takes ownership of |s.b|
@@ -1450,6 +1510,7 @@ static VALUE snapshot_initialize(int argc, VALUE *argv, VALUE self)
1450
1510
  VALUE a, e, code, cv;
1451
1511
  Snapshot *ss;
1452
1512
  Context *c;
1513
+ DesCtx d;
1453
1514
  Ser s;
1454
1515
 
1455
1516
  TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
@@ -1462,9 +1523,11 @@ static VALUE snapshot_initialize(int argc, VALUE *argv, VALUE self)
1462
1523
  TypedData_Get_Struct(cv, Context, &context_type, c);
1463
1524
  // request is snapsho(T), "code"
1464
1525
  ser_init1(&s, 'T');
1465
- ser_string(&s, RSTRING_PTR(code), RSTRING_LENINT(code));
1526
+ add_string(&s, code);
1466
1527
  // response is [arraybuffer, error]
1467
- a = rendezvous(c, &s.b);
1528
+ DesCtx_init(&d);
1529
+ d.transcode_latin1 = 0; // don't mangle snapshot binary data
1530
+ a = rendezvous1(c, &s.b, &d);
1468
1531
  e = rb_ary_pop(a);
1469
1532
  context_dispose(cv);
1470
1533
  if (*RSTRING_PTR(e))
@@ -1478,6 +1541,7 @@ static VALUE snapshot_warmup(VALUE self, VALUE arg)
1478
1541
  VALUE a, e, cv;
1479
1542
  Snapshot *ss;
1480
1543
  Context *c;
1544
+ DesCtx d;
1481
1545
  Ser s;
1482
1546
 
1483
1547
  TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
@@ -1489,10 +1553,12 @@ static VALUE snapshot_warmup(VALUE self, VALUE arg)
1489
1553
  ser_init1(&s, 'W');
1490
1554
  ser_array_begin(&s, 2);
1491
1555
  ser_string8(&s, (const uint8_t *)RSTRING_PTR(ss->blob), RSTRING_LENINT(ss->blob));
1492
- ser_string(&s, RSTRING_PTR(arg), RSTRING_LENINT(arg));
1556
+ add_string(&s, arg);
1493
1557
  ser_array_end(&s, 2);
1494
1558
  // response is [arraybuffer, error]
1495
- a = rendezvous(c, &s.b);
1559
+ DesCtx_init(&d);
1560
+ d.transcode_latin1 = 0; // don't mangle snapshot binary data
1561
+ a = rendezvous1(c, &s.b, &d);
1496
1562
  e = rb_ary_pop(a);
1497
1563
  context_dispose(cv);
1498
1564
  if (*RSTRING_PTR(e))
@@ -303,6 +303,14 @@ static void ser_string8(Ser *s, const uint8_t *p, size_t n)
303
303
  w(s, p, n);
304
304
  }
305
305
 
306
+ // string must be utf16le; |n| is in bytes, not code points
307
+ static void ser_string16(Ser *s, const void *p, size_t n)
308
+ {
309
+ w_byte(s, 'c');
310
+ w_varint(s, n);
311
+ w(s, p, n);
312
+ }
313
+
306
314
  static void ser_object_begin(Ser *s)
307
315
  {
308
316
  w_byte(s, 'o');
@@ -362,6 +370,7 @@ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
362
370
 
363
371
  if (depth < 0)
364
372
  return bail(err, "too much recursion");
373
+ again:
365
374
  if (*p >= pe)
366
375
  goto too_short;
367
376
  switch ((c = *(*p)++)) {
@@ -372,7 +381,9 @@ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
372
381
  snprintf(*err, sizeof(*err), "bad tag: %02x", c);
373
382
  }
374
383
  return -1;
375
- case '\0': // padding
384
+ case '\0': // skip alignment padding for two-byte strings
385
+ if (*p < pe)
386
+ goto again;
376
387
  break;
377
388
  case '^':
378
389
  if (r_varint(p, pe, &u))
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniRacer
4
- VERSION = "0.17.0.pre7"
4
+ VERSION = "0.17.0.pre9"
5
5
  LIBV8_NODE_VERSION = "~> 22.7.0.4"
6
6
  end
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.17.0.pre7
4
+ version: 0.17.0.pre9
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-01-09 00:00:00.000000000 Z
11
+ date: 2025-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -123,9 +123,9 @@ licenses:
123
123
  - MIT
124
124
  metadata:
125
125
  bug_tracker_uri: https://github.com/discourse/mini_racer/issues
126
- changelog_uri: https://github.com/discourse/mini_racer/blob/v0.17.0.pre7/CHANGELOG
127
- documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.17.0.pre7
128
- source_code_uri: https://github.com/discourse/mini_racer/tree/v0.17.0.pre7
126
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.17.0.pre9/CHANGELOG
127
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.17.0.pre9
128
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.17.0.pre9
129
129
  post_install_message:
130
130
  rdoc_options: []
131
131
  require_paths: