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 +4 -4
- data/CHANGELOG +8 -0
- data/ext/mini_racer_extension/mini_racer_extension.c +121 -54
- data/ext/mini_racer_extension/mini_racer_v8.cc +29 -2
- data/ext/mini_racer_extension/serde.c +37 -28
- data/lib/mini_racer/truffleruby.rb +4 -0
- data/lib/mini_racer/version.rb +2 -2
- data/lib/mini_racer.rb +13 -0
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c2110c8c14882bd775ad556afdeb79e1ab42bfabddc24101b82f8390a5be830
|
|
4
|
+
data.tar.gz: 8c70e50ac0edbe545ddd0a17737c045f21ebd6a2aa47f8d730a7f7ced79248b3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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,
|
|
493
|
+
push(arg, rb_ary_new());
|
|
475
494
|
}
|
|
476
495
|
|
|
477
496
|
static void des_error_end(void *arg)
|
|
478
497
|
{
|
|
479
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
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
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
-
|
|
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
|
-
|
|
624
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 = {}
|
data/lib/mini_racer/version.rb
CHANGED
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.
|
|
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-
|
|
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:
|
|
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:
|
|
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.
|
|
141
|
-
documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.
|
|
142
|
-
source_code_uri: https://github.com/discourse/mini_racer/tree/v0.
|
|
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:
|