mini_racer 0.20.0 → 0.21.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/README.md +28 -0
- data/ext/mini_racer_extension/mini_racer_extension.c +98 -20
- data/ext/mini_racer_extension/serde.c +13 -0
- data/lib/mini_racer/truffleruby.rb +33 -19
- data/lib/mini_racer/version.rb +1 -1
- data/lib/mini_racer.rb +11 -0
- metadata +7 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6c838b1bc35ed1adb0156f0e01d699afc180c174718f197a6afc1356fe9e4815
|
|
4
|
+
data.tar.gz: 7a4b00c4bcd4572bf7fdcce3df6455ded628706975fa8540946faee17e53617d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d826ca742dbe6580f92faebf11c827795536c55596c279fa070dd38836d03b7dcecc0b43fe254b6d95590bea1a24d8ec168f9d5008b668ba488a5aff7b6e3aea
|
|
7
|
+
data.tar.gz: 985effeb709d8dfc1481c679dfdc86a3930a0d84de6d3b6d9d154d6801a6766af76ffecd468e22d8b20b68952e02b756ab0ec11b1bc3c93736b078d046719798
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
- 0.21.1 - 25-05-2026
|
|
2
|
+
- Run `:single_threaded` V8 dispatches on a reusable mini_racer-owned native thread so V8 does not execute on Ruby-owned threads
|
|
3
|
+
- Stop and join the reusable `:single_threaded` runner when contexts are disposed
|
|
4
|
+
- Document `:single_threaded` fork-safety requirements for pre-fork contexts
|
|
5
|
+
|
|
6
|
+
- 0.21.0 - 16-04-2026
|
|
7
|
+
- Add MiniRacer::Binary for returning Uint8Array to JavaScript from attached Ruby callbacks
|
|
8
|
+
|
|
1
9
|
- 0.20.0 - 24-02-2026
|
|
2
10
|
- Add Snapshot.load to restore snapshots from binary data, enabling disk persistence
|
|
3
11
|
|
data/README.md
CHANGED
|
@@ -60,6 +60,25 @@ puts context.eval("array_and_hash()")
|
|
|
60
60
|
# => {"a" => 1, "b" => [1, {"a" => 1}]}
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
### Return binary data from Ruby to JavaScript
|
|
64
|
+
|
|
65
|
+
Attached Ruby functions can return binary data as `Uint8Array` using `MiniRacer::Binary`:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
require "digest"
|
|
69
|
+
|
|
70
|
+
context = MiniRacer::Context.new
|
|
71
|
+
context.attach("sha256_raw", ->(data) {
|
|
72
|
+
MiniRacer::Binary.new(Digest::SHA256.digest(data))
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
# Inside JavaScript the return value is a Uint8Array
|
|
76
|
+
context.eval("sha256_raw('hello') instanceof Uint8Array") # => true
|
|
77
|
+
context.eval("sha256_raw('hello').length") # => 32
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This is useful when you need to pass raw bytes (e.g., cryptographic digests, compressed data, binary file contents) from Ruby to JavaScript. The `MiniRacer::Binary` wrapper tells the bridge to serialize the data as a `Uint8Array` on the JavaScript side rather than a string.
|
|
81
|
+
|
|
63
82
|
### GIL free JavaScript execution
|
|
64
83
|
|
|
65
84
|
The Ruby Global interpreter lock is released when scripts are executing:
|
|
@@ -120,6 +139,15 @@ Since 0.6.1 mini_racer does support V8 single threaded platform mode which shoul
|
|
|
120
139
|
MiniRacer::Platform.set_flags!(:single_threaded)
|
|
121
140
|
```
|
|
122
141
|
|
|
142
|
+
When using pre-fork `MiniRacer::Context` objects in `:single_threaded` mode,
|
|
143
|
+
ensure the process only forks while MiniRacer is quiescent: no thread may be
|
|
144
|
+
evaluating JavaScript, calling into a context, disposing/freeing a context,
|
|
145
|
+
running a Ruby callback from JavaScript, or otherwise using MiniRacer at the
|
|
146
|
+
instant of `fork`. In multi-threaded applications, guard all MiniRacer context
|
|
147
|
+
operations and the `fork` itself with the same application-level lock. Forking
|
|
148
|
+
while a MiniRacer operation is in progress can leave inherited pthread mutexes
|
|
149
|
+
in an unusable state in the child process.
|
|
150
|
+
|
|
123
151
|
If you want to ensure your application does not leak memory after fork either:
|
|
124
152
|
|
|
125
153
|
1. Ensure no `MiniRacer::Context` objects are created in the master process; or
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <stdlib.h>
|
|
5
5
|
#include <string.h>
|
|
6
6
|
#include <pthread.h>
|
|
7
|
+
#include <unistd.h>
|
|
7
8
|
#include <math.h>
|
|
8
9
|
|
|
9
10
|
#if defined(__linux__) && !defined(__GLIBC__)
|
|
@@ -136,6 +137,9 @@ typedef struct Context
|
|
|
136
137
|
VALUE exception; // pending exception or Qnil
|
|
137
138
|
Buf req, res; // ruby->v8 request/response, mediated by |mtx| and |cv|
|
|
138
139
|
Buf snapshot;
|
|
140
|
+
pthread_t single_threaded_thr;
|
|
141
|
+
pid_t single_threaded_pid;
|
|
142
|
+
int single_threaded_thr_started;
|
|
139
143
|
// |rr_mtx| stands for "recursive ruby mutex"; it's used to exclude
|
|
140
144
|
// other ruby threads but allow reentrancy from the same ruby thread
|
|
141
145
|
// (think ruby->js->ruby->js calls)
|
|
@@ -193,6 +197,7 @@ static VALUE terminated_error;
|
|
|
193
197
|
static VALUE context_class;
|
|
194
198
|
static VALUE snapshot_class;
|
|
195
199
|
static VALUE date_time_class;
|
|
200
|
+
static VALUE binary_class;
|
|
196
201
|
static VALUE js_function_class;
|
|
197
202
|
|
|
198
203
|
static pthread_mutex_t flags_mtx = PTHREAD_MUTEX_INITIALIZER;
|
|
@@ -688,10 +693,17 @@ static int serialize1(Ser *s, VALUE refs, VALUE v)
|
|
|
688
693
|
// entirely new objects
|
|
689
694
|
if (rb_respond_to(v, rb_intern("to_time"))) {
|
|
690
695
|
v = rb_funcall(v, rb_intern("to_time"), 0);
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
696
|
+
if (rb_obj_is_kind_of(v, rb_cTime)) {
|
|
697
|
+
struct timeval tv = rb_time_timeval(v);
|
|
698
|
+
ser_date(s, tv.tv_sec*1e3 + tv.tv_usec/1e3);
|
|
699
|
+
} else {
|
|
700
|
+
snprintf(s->err, sizeof(s->err), "unsupported type %s", rb_class2name(CLASS_OF(v)));
|
|
701
|
+
return -1;
|
|
702
|
+
}
|
|
703
|
+
} else if (!NIL_P(binary_class) && rb_obj_is_kind_of(v, binary_class)) {
|
|
704
|
+
t = rb_ivar_get(v, rb_intern("@data"));
|
|
705
|
+
Check_Type(t, T_STRING);
|
|
706
|
+
ser_uint8array(s, RSTRING_PTR(t), RSTRING_LEN(t));
|
|
695
707
|
} else {
|
|
696
708
|
snprintf(s->err, sizeof(s->err), "unsupported type %s", rb_class2name(CLASS_OF(v)));
|
|
697
709
|
return -1;
|
|
@@ -860,18 +872,10 @@ void v8_dispatch(Context *c)
|
|
|
860
872
|
// only called when inside v8_call, v8_eval, or v8_pump_message_loop
|
|
861
873
|
void v8_roundtrip(Context *c, const uint8_t **p, size_t *n)
|
|
862
874
|
{
|
|
863
|
-
struct rendezvous_nogvl *args;
|
|
864
|
-
|
|
865
875
|
buf_reset(&c->req);
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
rb_thread_call_with_gvl(rendezvous_callback, args);
|
|
870
|
-
} else {
|
|
871
|
-
pthread_cond_signal(&c->cv);
|
|
872
|
-
while (!c->req.len)
|
|
873
|
-
pthread_cond_wait(&c->cv, &c->mtx);
|
|
874
|
-
}
|
|
876
|
+
pthread_cond_signal(&c->cv);
|
|
877
|
+
while (!c->req.len)
|
|
878
|
+
pthread_cond_wait(&c->cv, &c->mtx);
|
|
875
879
|
buf_reset(&c->res);
|
|
876
880
|
*p = c->req.buf;
|
|
877
881
|
*n = c->req.len;
|
|
@@ -983,10 +987,45 @@ fail:
|
|
|
983
987
|
goto out;
|
|
984
988
|
}
|
|
985
989
|
|
|
990
|
+
static void *single_threaded_runner(void *arg)
|
|
991
|
+
{
|
|
992
|
+
Context *c;
|
|
993
|
+
|
|
994
|
+
c = arg;
|
|
995
|
+
pthread_mutex_lock(&c->mtx);
|
|
996
|
+
for (;;) {
|
|
997
|
+
while (!c->req.len && atomic_load(&c->quit) < 1)
|
|
998
|
+
pthread_cond_wait(&c->cv, &c->mtx);
|
|
999
|
+
if (atomic_load(&c->quit) >= 1)
|
|
1000
|
+
break;
|
|
1001
|
+
v8_single_threaded_enter(c->pst, c, dispatch);
|
|
1002
|
+
pthread_cond_signal(&c->cv);
|
|
1003
|
+
}
|
|
1004
|
+
pthread_mutex_unlock(&c->mtx);
|
|
1005
|
+
return NULL;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
static int single_threaded_runner_start(Context *c)
|
|
1009
|
+
{
|
|
1010
|
+
pid_t pid;
|
|
1011
|
+
int r;
|
|
1012
|
+
|
|
1013
|
+
pid = getpid();
|
|
1014
|
+
if (c->single_threaded_thr_started && c->single_threaded_pid == pid)
|
|
1015
|
+
return 0;
|
|
1016
|
+
c->single_threaded_thr_started = 0;
|
|
1017
|
+
c->single_threaded_pid = pid;
|
|
1018
|
+
r = pthread_create(&c->single_threaded_thr, NULL, single_threaded_runner, c);
|
|
1019
|
+
if (!r)
|
|
1020
|
+
c->single_threaded_thr_started = 1;
|
|
1021
|
+
return r;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
986
1024
|
static inline void *rendezvous_nogvl(void *arg)
|
|
987
1025
|
{
|
|
988
1026
|
struct rendezvous_nogvl *a;
|
|
989
1027
|
Context *c;
|
|
1028
|
+
int r;
|
|
990
1029
|
|
|
991
1030
|
a = arg;
|
|
992
1031
|
c = a->context;
|
|
@@ -1002,7 +1041,16 @@ next:
|
|
|
1002
1041
|
assert(c->res.len == 0);
|
|
1003
1042
|
buf_move(a->req, &c->req); // v8 thread takes ownership of req
|
|
1004
1043
|
if (single_threaded) {
|
|
1005
|
-
|
|
1044
|
+
r = single_threaded_runner_start(c);
|
|
1045
|
+
if (r) {
|
|
1046
|
+
buf_move(&c->req, a->req);
|
|
1047
|
+
pthread_mutex_unlock(&c->mtx);
|
|
1048
|
+
c->depth--;
|
|
1049
|
+
pthread_mutex_unlock(&c->rr_mtx);
|
|
1050
|
+
return (void *)(intptr_t)r;
|
|
1051
|
+
}
|
|
1052
|
+
pthread_cond_signal(&c->cv);
|
|
1053
|
+
do pthread_cond_wait(&c->cv, &c->mtx); while (!c->res.len);
|
|
1006
1054
|
} else {
|
|
1007
1055
|
pthread_cond_signal(&c->cv);
|
|
1008
1056
|
do pthread_cond_wait(&c->cv, &c->mtx); while (!c->res.len);
|
|
@@ -1011,6 +1059,7 @@ next:
|
|
|
1011
1059
|
pthread_mutex_unlock(&c->mtx);
|
|
1012
1060
|
if (*a->res->buf == 'c') { // js -> ruby callback?
|
|
1013
1061
|
rb_thread_call_with_gvl(rendezvous_callback, a);
|
|
1062
|
+
buf_reset(a->res);
|
|
1014
1063
|
goto next;
|
|
1015
1064
|
}
|
|
1016
1065
|
c->depth--;
|
|
@@ -1020,12 +1069,16 @@ next:
|
|
|
1020
1069
|
|
|
1021
1070
|
static void rendezvous_no_des(Context *c, Buf *req, Buf *res)
|
|
1022
1071
|
{
|
|
1072
|
+
void *r;
|
|
1073
|
+
|
|
1023
1074
|
if (atomic_load(&c->quit)) {
|
|
1024
1075
|
buf_reset(req);
|
|
1025
1076
|
rb_raise(context_disposed_error, "disposed context");
|
|
1026
1077
|
}
|
|
1027
|
-
rb_nogvl(rendezvous_nogvl, &(struct rendezvous_nogvl){c, req, res},
|
|
1028
|
-
|
|
1078
|
+
r = rb_nogvl(rendezvous_nogvl, &(struct rendezvous_nogvl){c, req, res},
|
|
1079
|
+
NULL, NULL, 0);
|
|
1080
|
+
if (r)
|
|
1081
|
+
rb_raise(runtime_error, "pthread_create: %s", strerror((int)(intptr_t)r));
|
|
1029
1082
|
}
|
|
1030
1083
|
|
|
1031
1084
|
// send request to & receive reply from v8 thread; takes ownership of |req|
|
|
@@ -1111,6 +1164,11 @@ static VALUE context_alloc(VALUE klass)
|
|
|
1111
1164
|
if (Qtrue == rb_funcall(rb_cObject, f, 1, a))
|
|
1112
1165
|
date_time_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
|
1113
1166
|
}
|
|
1167
|
+
if (NIL_P(binary_class)) {
|
|
1168
|
+
VALUE m = rb_const_get(rb_cObject, rb_intern("MiniRacer"));
|
|
1169
|
+
if (Qtrue == rb_funcall(m, rb_intern("const_defined?"), 1, rb_str_new_cstr("Binary")))
|
|
1170
|
+
binary_class = rb_const_get(m, rb_intern("Binary"));
|
|
1171
|
+
}
|
|
1114
1172
|
c = ruby_xmalloc(sizeof(*c));
|
|
1115
1173
|
memset(c, 0, sizeof(*c));
|
|
1116
1174
|
c->exception = Qnil;
|
|
@@ -1177,7 +1235,16 @@ static void *context_free_thread_do(void *arg)
|
|
|
1177
1235
|
Context *c;
|
|
1178
1236
|
|
|
1179
1237
|
c = arg;
|
|
1180
|
-
|
|
1238
|
+
if (single_threaded && c->single_threaded_thr_started && c->single_threaded_pid == getpid()) {
|
|
1239
|
+
pthread_mutex_lock(&c->mtx);
|
|
1240
|
+
atomic_store(&c->quit, 2);
|
|
1241
|
+
pthread_cond_signal(&c->cv);
|
|
1242
|
+
pthread_mutex_unlock(&c->mtx);
|
|
1243
|
+
pthread_join(c->single_threaded_thr, NULL);
|
|
1244
|
+
}
|
|
1245
|
+
if (c->pst)
|
|
1246
|
+
v8_single_threaded_dispose(c->pst);
|
|
1247
|
+
pthread_mutex_lock(&c->mtx);
|
|
1181
1248
|
context_destroy(c);
|
|
1182
1249
|
return NULL;
|
|
1183
1250
|
}
|
|
@@ -1271,8 +1338,18 @@ static void *context_dispose_do(void *arg)
|
|
|
1271
1338
|
|
|
1272
1339
|
c = arg;
|
|
1273
1340
|
if (single_threaded) {
|
|
1341
|
+
pthread_mutex_lock(&c->mtx);
|
|
1342
|
+
while (c->req.len || c->res.len)
|
|
1343
|
+
pthread_cond_wait(&c->cv, &c->mtx);
|
|
1274
1344
|
atomic_store(&c->quit, 1); // disposed
|
|
1275
|
-
|
|
1345
|
+
if (c->single_threaded_thr_started && c->single_threaded_pid == getpid()) {
|
|
1346
|
+
pthread_cond_signal(&c->cv);
|
|
1347
|
+
pthread_mutex_unlock(&c->mtx);
|
|
1348
|
+
pthread_join(c->single_threaded_thr, NULL);
|
|
1349
|
+
pthread_mutex_lock(&c->mtx);
|
|
1350
|
+
c->single_threaded_thr_started = 0;
|
|
1351
|
+
}
|
|
1352
|
+
pthread_mutex_unlock(&c->mtx);
|
|
1276
1353
|
} else {
|
|
1277
1354
|
pthread_mutex_lock(&c->mtx);
|
|
1278
1355
|
while (c->req.len || c->res.len)
|
|
@@ -1763,5 +1840,6 @@ void Init_mini_racer_extension(void)
|
|
|
1763
1840
|
rb_define_singleton_method(c, "set_flags!", platform_set_flags, -1);
|
|
1764
1841
|
|
|
1765
1842
|
date_time_class = Qnil; // lazy init
|
|
1843
|
+
binary_class = Qnil; // lazy init
|
|
1766
1844
|
js_function_class = rb_define_class_under(m, "JavaScriptFunction", rb_cObject);
|
|
1767
1845
|
}
|
|
@@ -322,6 +322,19 @@ static void ser_string16(Ser *s, const void *p, size_t n)
|
|
|
322
322
|
w(s, p, n);
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
+
// Uint8Array: ArrayBuffer header + data + typed array view descriptor
|
|
326
|
+
static void ser_uint8array(Ser *s, const void *p, size_t n)
|
|
327
|
+
{
|
|
328
|
+
w_byte(s, 'B'); // ArrayBuffer tag
|
|
329
|
+
w_varint(s, n); // byte length
|
|
330
|
+
w(s, p, n); // raw bytes
|
|
331
|
+
w_byte(s, 'V'); // typed array view tag
|
|
332
|
+
w_byte(s, 'B'); // Uint8Array type
|
|
333
|
+
w_varint(s, 0); // byteOffset
|
|
334
|
+
w_varint(s, n); // byteLength
|
|
335
|
+
w_varint(s, 0); // flags
|
|
336
|
+
}
|
|
337
|
+
|
|
325
338
|
static void ser_object_begin(Ser *s)
|
|
326
339
|
{
|
|
327
340
|
w_byte(s, 'o');
|
|
@@ -77,9 +77,13 @@ module MiniRacer
|
|
|
77
77
|
raise "TruffleRuby #{RUBY_ENGINE_VERSION} does not have support for inner contexts, use a more recent version"
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
|
|
81
|
+
if TruffleRuby.native?
|
|
82
|
+
raise "You need the TruffleRuby JVM Standalone for mini_racer because it is not possible to install the js component in the the Native standalone"
|
|
83
|
+
end
|
|
84
|
+
|
|
80
85
|
unless Polyglot.languages.include? "js"
|
|
81
|
-
raise "The language 'js' is not available, you
|
|
82
|
-
"You also need to install the 'js' component, see https://github.com/oracle/truffleruby/blob/master/doc/user/polyglot.md#installing-other-languages"
|
|
86
|
+
raise "The language 'js' is not available, you need to install the 'js' component.\nSee https://github.com/oracle/truffleruby/blob/master/doc/user/polyglot.md#installing-other-languages"
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
@context = Polyglot::InnerContext.new(on_cancelled: -> {
|
|
@@ -102,19 +106,19 @@ module MiniRacer
|
|
|
102
106
|
else
|
|
103
107
|
@snapshot = nil
|
|
104
108
|
end
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
|
|
110
|
+
@is_object_or_array_func = eval_in_context "(x) => { return (x instanceof Object || x instanceof Array) && !(x instanceof Date) && !(x instanceof Function) }"
|
|
111
|
+
@is_map_func = eval_in_context "(x) => { return x instanceof Map }"
|
|
112
|
+
@is_map_iterator_func = eval_in_context "(x) => { return x[Symbol.toStringTag] === 'Map Iterator' }"
|
|
113
|
+
@is_time_func = eval_in_context "(x) => { return x instanceof Date }"
|
|
114
|
+
@is_symbol_func = eval_in_context "(x) => { return typeof x === 'symbol' }"
|
|
115
|
+
@is_uint8_array_func = eval_in_context "(x) => { return x instanceof Uint8Array }"
|
|
116
|
+
|
|
117
|
+
@js_date_to_time_func = eval_in_context "(x) => { return x.getTime(x) }"
|
|
118
|
+
@js_symbol_to_symbol_func = eval_in_context "(x) => { var r = x.description; return r === undefined ? 'undefined' : r }"
|
|
119
|
+
@js_new_date_func = eval_in_context "(x) => { return new Date(x) }"
|
|
120
|
+
@js_new_array_func = eval_in_context "(x) => { return new Array(x) }"
|
|
121
|
+
@js_new_uint8array_func = eval_in_context "(x) => { return new Uint8Array(x) }"
|
|
118
122
|
end
|
|
119
123
|
|
|
120
124
|
def dispose_unsafe
|
|
@@ -231,6 +235,10 @@ module MiniRacer
|
|
|
231
235
|
elsif value.respond_to?(:to_str)
|
|
232
236
|
value.to_str.dup
|
|
233
237
|
elsif value.respond_to?(:to_ary)
|
|
238
|
+
if uint8_array?(value)
|
|
239
|
+
return value.to_a.pack('C*')
|
|
240
|
+
end
|
|
241
|
+
|
|
234
242
|
value.to_ary.map do |e|
|
|
235
243
|
if e.respond_to?(:call)
|
|
236
244
|
nil
|
|
@@ -280,15 +288,19 @@ module MiniRacer
|
|
|
280
288
|
@is_time_func.call(value)
|
|
281
289
|
end
|
|
282
290
|
|
|
291
|
+
def symbol?(value)
|
|
292
|
+
@is_symbol_func.call(value)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def uint8_array?(value)
|
|
296
|
+
@is_uint8_array_func.call(value)
|
|
297
|
+
end
|
|
298
|
+
|
|
283
299
|
def js_date_to_time(value)
|
|
284
300
|
millis = @js_date_to_time_func.call(value)
|
|
285
301
|
Time.at(Rational(millis, 1000))
|
|
286
302
|
end
|
|
287
303
|
|
|
288
|
-
def symbol?(value)
|
|
289
|
-
@is_symbol_func.call(value)
|
|
290
|
-
end
|
|
291
|
-
|
|
292
304
|
def js_symbol_to_symbol(value)
|
|
293
305
|
@js_symbol_to_symbol_func.call(value).to_s.to_sym
|
|
294
306
|
end
|
|
@@ -329,6 +341,8 @@ module MiniRacer
|
|
|
329
341
|
js_new_date(value.to_f * 1000)
|
|
330
342
|
when DateTime
|
|
331
343
|
js_new_date(value.to_time.to_f * 1000)
|
|
344
|
+
when MiniRacer::Binary
|
|
345
|
+
@js_new_uint8array_func.call(value.data.bytes)
|
|
332
346
|
else
|
|
333
347
|
"Undefined Conversion"
|
|
334
348
|
end
|
data/lib/mini_racer/version.rb
CHANGED
data/lib/mini_racer.rb
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
require "mini_racer/version"
|
|
2
2
|
require "pathname"
|
|
3
3
|
|
|
4
|
+
module MiniRacer
|
|
5
|
+
class Binary
|
|
6
|
+
attr_reader :data
|
|
7
|
+
|
|
8
|
+
def initialize(data)
|
|
9
|
+
raise TypeError, "wrong argument type #{data.class} (expected String)" unless data.is_a?(String)
|
|
10
|
+
@data = data
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
4
15
|
if RUBY_ENGINE == "truffleruby"
|
|
5
16
|
require "mini_racer/truffleruby"
|
|
6
17
|
else
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mini_racer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.21.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sam Saffron
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: bundler
|
|
@@ -113,8 +112,8 @@ email:
|
|
|
113
112
|
- sam.saffron@gmail.com
|
|
114
113
|
executables: []
|
|
115
114
|
extensions:
|
|
116
|
-
- ext/mini_racer_loader/extconf.rb
|
|
117
115
|
- ext/mini_racer_extension/extconf.rb
|
|
116
|
+
- ext/mini_racer_loader/extconf.rb
|
|
118
117
|
extra_rdoc_files: []
|
|
119
118
|
files:
|
|
120
119
|
- CHANGELOG
|
|
@@ -137,10 +136,9 @@ licenses:
|
|
|
137
136
|
- MIT
|
|
138
137
|
metadata:
|
|
139
138
|
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.
|
|
143
|
-
post_install_message:
|
|
139
|
+
changelog_uri: https://github.com/discourse/mini_racer/blob/v0.21.1/CHANGELOG
|
|
140
|
+
documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.21.1
|
|
141
|
+
source_code_uri: https://github.com/discourse/mini_racer/tree/v0.21.1
|
|
144
142
|
rdoc_options: []
|
|
145
143
|
require_paths:
|
|
146
144
|
- lib
|
|
@@ -156,8 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
156
154
|
- !ruby/object:Gem::Version
|
|
157
155
|
version: '0'
|
|
158
156
|
requirements: []
|
|
159
|
-
rubygems_version:
|
|
160
|
-
signing_key:
|
|
157
|
+
rubygems_version: 4.0.6
|
|
161
158
|
specification_version: 4
|
|
162
159
|
summary: Minimal embedded v8 for Ruby
|
|
163
160
|
test_files: []
|