mini_racer 0.17.0.pre7 → 0.17.0.pre9

Sign up to get free protection for your applications and to get access to all the features.
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: