mini_racer 0.5.0.pre → 0.6.2

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: b0a067ca868ffe75b89fc350d6d62b6e4d2670a4319eda9f6cd05fe424c762ec
4
- data.tar.gz: 26c865123cceec38530a9be40e32c1042063f3cbb400172438308a7eb0e06568
3
+ metadata.gz: e832863760637f983976194ebef263d8815c149d48ff26c7200367ab33640dda
4
+ data.tar.gz: 7c1c393ae6403a75d2a413395d56e7d5f3affe706b81c121273b4c6b5d471bf4
5
5
  SHA512:
6
- metadata.gz: 0e1de5f130d4cf5ddca606f57cf7864f9d05d87c9775cd6873d6bb6151983216f74bc7a7eb3e20a9382e5cf95a2ccd8958c7a548ddb491ac8cb9cb89d1c17fd8
7
- data.tar.gz: 7df5b7f82afbc9040a6d317bdd8d8600d6656a965bcb44c3ce4f7b6f02007ae1e9fc088022e6c5c10c4755aa4c0dea9badbd4ca8087e3e9185f6f93f42835775
6
+ metadata.gz: 4504cb3a564e5b311b65de74bac321b058995af17df47f9f3dc01fcb589a87eebfda55497e0ddb135a2ab15ef1818760652561d434d3f497c0dbd036451934c6
7
+ data.tar.gz: b83df123a61092ab4041212bb6e4f15b276d5e32e8be8d2b5cbc014988b8cf20ed0e0b3b30595de53ca4c0d599a86112d695009cda13891fe177742aff7d911e
data/CHANGELOG CHANGED
@@ -1,5 +1,35 @@
1
+ - 17-01-2021
2
+
3
+ - 0.6.2
4
+
5
+ - Fix support for compilation on 2.6, llvm compiles
6
+ - Stability patches to handle rare memory leaks
7
+ - Corrected re-raising of exceptions to support strings
8
+ - During early termination of context under certain conditions MiniRacer could crash
9
+
10
+
11
+ - 31-12-2021
12
+
13
+ - 0.6.1
14
+
15
+ - Added support for single threaded platform: `MiniRacer::Platform.set_flags! :single_threaded`
16
+ must be called prior to booting ANY MiniRacer::Context
17
+
18
+ - 0.6.0
19
+
20
+ - Ruby 3.1 support
21
+ - Fixes memory leak in heap snapshotting
22
+ - Improved compilation ergonomics in clang
23
+ - Migrated internal storage in c extension to TypedData
24
+
1
25
  - 11-04-2021
2
26
 
27
+ - 0.5.0
28
+ - Fixes issues on aarch (Apple M1)
29
+ - Update to use libv8-node 16.x (#210) [Loic Nageleisen]
30
+ - FEATURE: Configurable max marshal stack depth (#202) [seanmakesgames]
31
+ - Ruby 2.3 and 2.4 are EOL, we no longer support them
32
+
3
33
  - 0.4.0
4
34
 
5
35
  - FEATURE: upgrade to libv8 node 15.14.0 (v8 8.6.395.17)
data/Rakefile CHANGED
@@ -92,5 +92,5 @@ task :lint do
92
92
  portability-*
93
93
  readability-*).join(',')
94
94
 
95
- sh RbConfig::expand("clang-tidy -checks='#{checks}' ext/mini_racer_extension/mini_racer_extension.cc -- #$INCFLAGS #$CPPFLAGS", conf)
95
+ sh RbConfig::expand("clang-tidy -checks='#{checks}' ext/mini_racer_extension/mini_racer_extension.cc -- #$INCFLAGS #$CXXFLAGS", conf)
96
96
  end
@@ -7,18 +7,25 @@ IS_DARWIN = RUBY_PLATFORM =~ /darwin/
7
7
 
8
8
  have_library('pthread')
9
9
  have_library('objc') if IS_DARWIN
10
- $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
11
- $CPPFLAGS += " -g" unless $CPPFLAGS.split.include? "-g"
12
- $CPPFLAGS += " -rdynamic" unless $CPPFLAGS.split.include? "-rdynamic"
13
- $CPPFLAGS += " -fPIC" unless $CPPFLAGS.split.include? "-rdynamic" or IS_DARWIN
14
- $CPPFLAGS += " -std=c++14"
15
- $CPPFLAGS += " -fpermissive"
16
- #$CPPFLAGS += " -DV8_COMPRESS_POINTERS"
17
- $CPPFLAGS += " -fvisibility=hidden "
18
-
19
- $CPPFLAGS += " -Wno-reserved-user-defined-literal" if IS_DARWIN
20
-
21
- $LDFLAGS.insert(0, " -stdlib=libc++ ") if IS_DARWIN
10
+ $CXXFLAGS += " -Wall" unless $CXXFLAGS.split.include? "-Wall"
11
+ $CXXFLAGS += " -g" unless $CXXFLAGS.split.include? "-g"
12
+ $CXXFLAGS += " -rdynamic" unless $CXXFLAGS.split.include? "-rdynamic"
13
+ $CXXFLAGS += " -fPIC" unless $CXXFLAGS.split.include? "-rdynamic" or IS_DARWIN
14
+ $CXXFLAGS += " -std=c++14"
15
+ $CXXFLAGS += " -fpermissive"
16
+ #$CXXFLAGS += " -DV8_COMPRESS_POINTERS"
17
+ $CXXFLAGS += " -fvisibility=hidden "
18
+
19
+ # __declspec gets used by clang via ruby 3.x headers...
20
+ $CXXFLAGS += " -fms-extensions"
21
+
22
+ $CXXFLAGS += " -Wno-reserved-user-defined-literal" if IS_DARWIN
23
+
24
+ if IS_DARWIN
25
+ $LDFLAGS.insert(0, " -stdlib=libc++ ")
26
+ else
27
+ $LDFLAGS.insert(0, " -lstdc++ ")
28
+ end
22
29
 
23
30
  # check for missing symbols at link time
24
31
  # $LDFLAGS += " -Wl,--no-undefined " unless IS_DARWIN
@@ -64,8 +71,13 @@ end
64
71
  Libv8::Node.configure_makefile
65
72
 
66
73
  if enable_config('asan')
67
- $CPPFLAGS.insert(0, " -fsanitize=address ")
74
+ $CXXFLAGS.insert(0, " -fsanitize=address ")
68
75
  $LDFLAGS.insert(0, " -fsanitize=address ")
69
76
  end
70
77
 
78
+ # there doesn't seem to be a CPP macro for this in Ruby 2.6:
79
+ if RUBY_ENGINE == 'ruby'
80
+ $CPPFLAGS += ' -DENGINE_IS_CRUBY '
81
+ end
82
+
71
83
  create_makefile 'mini_racer_extension'
@@ -2,6 +2,7 @@
2
2
  #include <ruby.h>
3
3
  #include <ruby/thread.h>
4
4
  #include <ruby/io.h>
5
+ #include <ruby/version.h>
5
6
  #include <v8.h>
6
7
  #include <v8-profiler.h>
7
8
  #include <libplatform/libplatform.h>
@@ -11,6 +12,15 @@
11
12
  #include <mutex>
12
13
  #include <atomic>
13
14
  #include <math.h>
15
+ #include <errno.h>
16
+
17
+ /* workaround C Ruby <= 2.x problems w/ clang in C++ mode */
18
+ #if defined(ENGINE_IS_CRUBY) && \
19
+ RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR <= 6
20
+ # define MR_METHOD_FUNC(fn) RUBY_METHOD_FUNC(fn)
21
+ #else
22
+ # define MR_METHOD_FUNC(fn) fn
23
+ #endif
14
24
 
15
25
  using namespace v8;
16
26
 
@@ -299,6 +309,29 @@ static pthread_rwlock_t exit_lock = PTHREAD_RWLOCK_INITIALIZER;
299
309
  static bool ruby_exiting = false; // guarded by exit_lock
300
310
  static bool single_threaded = false;
301
311
 
312
+ static void mark_context(void *);
313
+ static void deallocate(void *);
314
+ static size_t context_memsize(const void *);
315
+ static const rb_data_type_t context_type = {
316
+ "mini_racer/context_info",
317
+ { mark_context, deallocate, context_memsize }
318
+ };
319
+
320
+ static void deallocate_snapshot(void *);
321
+ static size_t snapshot_memsize(const void *);
322
+ static const rb_data_type_t snapshot_type = {
323
+ "mini_racer/snapshot_info",
324
+ { NULL, deallocate_snapshot, snapshot_memsize }
325
+ };
326
+
327
+ static void mark_isolate(void *);
328
+ static void deallocate_isolate(void *);
329
+ static size_t isolate_memsize(const void *);
330
+ static const rb_data_type_t isolate_type = {
331
+ "mini_racer/isolate_info",
332
+ { mark_isolate, deallocate_isolate, isolate_memsize }
333
+ };
334
+
302
335
  static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
303
336
  bool platform_already_initialized = false;
304
337
 
@@ -313,7 +346,7 @@ static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
313
346
  if (!strcmp(RSTRING_PTR(flag_as_str), "--single_threaded")) {
314
347
  single_threaded = true;
315
348
  }
316
- V8::SetFlagsFromString(RSTRING_PTR(flag_as_str), (int)RSTRING_LEN(flag_as_str));
349
+ V8::SetFlagsFromString(RSTRING_PTR(flag_as_str), RSTRING_LENINT(flag_as_str));
317
350
  } else {
318
351
  platform_already_initialized = true;
319
352
  }
@@ -336,7 +369,11 @@ static void init_v8() {
336
369
 
337
370
  if (current_platform == NULL) {
338
371
  V8::InitializeICU();
339
- current_platform = platform::NewDefaultPlatform();
372
+ if (single_threaded) {
373
+ current_platform = platform::NewSingleThreadedDefaultPlatform();
374
+ } else {
375
+ current_platform = platform::NewDefaultPlatform();
376
+ }
340
377
  V8::InitializePlatform(current_platform.get());
341
378
  V8::Initialize();
342
379
  }
@@ -381,28 +418,32 @@ static void prepare_result(MaybeLocal<Value> v8res,
381
418
  Local<Value> local_value = v8res.ToLocalChecked();
382
419
  if ((local_value->IsObject() || local_value->IsArray()) &&
383
420
  !local_value->IsDate() && !local_value->IsFunction()) {
384
- Local<Object> JSON = context->Global()->Get(
385
- context, String::NewFromUtf8Literal(isolate, "JSON"))
386
- .ToLocalChecked().As<Object>();
387
-
388
- Local<Function> stringify = JSON->Get(
389
- context, v8::String::NewFromUtf8Literal(isolate, "stringify"))
390
- .ToLocalChecked().As<Function>();
421
+ MaybeLocal<v8::Value> ml = context->Global()->Get(
422
+ context, String::NewFromUtf8Literal(isolate, "JSON"));
391
423
 
392
- Local<Object> object = local_value->ToObject(context).ToLocalChecked();
393
- const unsigned argc = 1;
394
- Local<Value> argv[argc] = { object };
395
- MaybeLocal<Value> json = stringify->Call(context, JSON, argc, argv);
396
-
397
- if (json.IsEmpty()) {
424
+ if (ml.IsEmpty()) { // exception
398
425
  evalRes.executed = false;
399
426
  } else {
400
- evalRes.json = true;
401
- Persistent<Value>* persistent = new Persistent<Value>();
402
- persistent->Reset(isolate, json.ToLocalChecked());
403
- evalRes.value = persistent;
427
+ Local<Object> JSON = ml.ToLocalChecked().As<Object>();
428
+
429
+ Local<Function> stringify = JSON->Get(
430
+ context, v8::String::NewFromUtf8Literal(isolate, "stringify"))
431
+ .ToLocalChecked().As<Function>();
432
+
433
+ Local<Object> object = local_value->ToObject(context).ToLocalChecked();
434
+ const unsigned argc = 1;
435
+ Local<Value> argv[argc] = { object };
436
+ MaybeLocal<Value> json = stringify->Call(context, JSON, argc, argv);
437
+
438
+ if (json.IsEmpty()) {
439
+ evalRes.executed = false;
440
+ } else {
441
+ evalRes.json = true;
442
+ Persistent<Value>* persistent = new Persistent<Value>();
443
+ persistent->Reset(isolate, json.ToLocalChecked());
444
+ evalRes.value = persistent;
445
+ }
404
446
  }
405
-
406
447
  } else {
407
448
  Persistent<Value>* persistent = new Persistent<Value>();
408
449
  persistent->Reset(isolate, local_value);
@@ -453,7 +494,7 @@ static void prepare_result(MaybeLocal<Value> v8res,
453
494
  }
454
495
  }
455
496
 
456
- void*
497
+ static void*
457
498
  nogvl_context_eval(void* arg) {
458
499
 
459
500
  EvalParams* eval_params = (EvalParams*)arg;
@@ -683,7 +724,7 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, Local<Context> context,
683
724
  case T_FLOAT:
684
725
  return scope.Escape(Number::New(isolate, NUM2DBL(value)));
685
726
  case T_STRING:
686
- return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
727
+ return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, RSTRING_LENINT(value)).ToLocalChecked());
687
728
  case T_NIL:
688
729
  return scope.Escape(Null(isolate));
689
730
  case T_TRUE:
@@ -711,7 +752,7 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, Local<Context> context,
711
752
  return scope.Escape(object);
712
753
  case T_SYMBOL:
713
754
  value = rb_funcall(value, rb_intern("to_s"), 0);
714
- return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
755
+ return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, RSTRING_LENINT(value)).ToLocalChecked());
715
756
  case T_DATA:
716
757
  klass = rb_funcall(value, rb_intern("class"), 0);
717
758
  if (klass == rb_cTime || klass == rb_cDateTime)
@@ -786,6 +827,7 @@ create_snapshot_data_blob(const char *embedded_source = nullptr) {
786
827
  SnapshotCreator::FunctionCodeHandling::kClear);
787
828
  }
788
829
 
830
+ static
789
831
  StartupData warm_up_snapshot_data_blob(StartupData cold_snapshot_blob,
790
832
  const char *warmup_source) {
791
833
  // Use following steps to create a warmed up snapshot blob from a cold one:
@@ -821,14 +863,14 @@ StartupData warm_up_snapshot_data_blob(StartupData cold_snapshot_blob,
821
863
 
822
864
  static VALUE rb_snapshot_size(VALUE self, VALUE str) {
823
865
  SnapshotInfo* snapshot_info;
824
- Data_Get_Struct(self, SnapshotInfo, snapshot_info);
866
+ TypedData_Get_Struct(self, SnapshotInfo, &snapshot_type, snapshot_info);
825
867
 
826
868
  return INT2NUM(snapshot_info->raw_size);
827
869
  }
828
870
 
829
871
  static VALUE rb_snapshot_load(VALUE self, VALUE str) {
830
872
  SnapshotInfo* snapshot_info;
831
- Data_Get_Struct(self, SnapshotInfo, snapshot_info);
873
+ TypedData_Get_Struct(self, SnapshotInfo, &snapshot_type, snapshot_info);
832
874
 
833
875
  if(TYPE(str) != T_STRING) {
834
876
  rb_raise(rb_eArgError, "wrong type argument %" PRIsVALUE " (should be a string)",
@@ -851,14 +893,14 @@ static VALUE rb_snapshot_load(VALUE self, VALUE str) {
851
893
 
852
894
  static VALUE rb_snapshot_dump(VALUE self, VALUE str) {
853
895
  SnapshotInfo* snapshot_info;
854
- Data_Get_Struct(self, SnapshotInfo, snapshot_info);
896
+ TypedData_Get_Struct(self, SnapshotInfo, &snapshot_type, snapshot_info);
855
897
 
856
898
  return rb_str_new(snapshot_info->data, snapshot_info->raw_size);
857
899
  }
858
900
 
859
901
  static VALUE rb_snapshot_warmup_unsafe(VALUE self, VALUE str) {
860
902
  SnapshotInfo* snapshot_info;
861
- Data_Get_Struct(self, SnapshotInfo, snapshot_info);
903
+ TypedData_Get_Struct(self, SnapshotInfo, &snapshot_type, snapshot_info);
862
904
 
863
905
  if(TYPE(str) != T_STRING) {
864
906
  rb_raise(rb_eArgError, "wrong type argument %" PRIsVALUE " (should be a string)",
@@ -905,13 +947,13 @@ void IsolateInfo::init(SnapshotInfo* snapshot_info) {
905
947
 
906
948
  static VALUE rb_isolate_init_with_snapshot(VALUE self, VALUE snapshot) {
907
949
  IsolateInfo* isolate_info;
908
- Data_Get_Struct(self, IsolateInfo, isolate_info);
950
+ TypedData_Get_Struct(self, IsolateInfo, &isolate_type, isolate_info);
909
951
 
910
952
  init_v8();
911
953
 
912
954
  SnapshotInfo* snapshot_info = nullptr;
913
955
  if (!NIL_P(snapshot)) {
914
- Data_Get_Struct(snapshot, SnapshotInfo, snapshot_info);
956
+ TypedData_Get_Struct(snapshot, SnapshotInfo, &snapshot_type, snapshot_info);
915
957
  }
916
958
 
917
959
  isolate_info->init(snapshot_info);
@@ -922,7 +964,7 @@ static VALUE rb_isolate_init_with_snapshot(VALUE self, VALUE snapshot) {
922
964
 
923
965
  static VALUE rb_isolate_idle_notification(VALUE self, VALUE idle_time_in_ms) {
924
966
  IsolateInfo* isolate_info;
925
- Data_Get_Struct(self, IsolateInfo, isolate_info);
967
+ TypedData_Get_Struct(self, IsolateInfo, &isolate_type, isolate_info);
926
968
 
927
969
  if (current_platform == NULL) return Qfalse;
928
970
 
@@ -933,7 +975,7 @@ static VALUE rb_isolate_idle_notification(VALUE self, VALUE idle_time_in_ms) {
933
975
 
934
976
  static VALUE rb_isolate_low_memory_notification(VALUE self) {
935
977
  IsolateInfo* isolate_info;
936
- Data_Get_Struct(self, IsolateInfo, isolate_info);
978
+ TypedData_Get_Struct(self, IsolateInfo, &isolate_type, isolate_info);
937
979
 
938
980
  if (current_platform == NULL) return Qfalse;
939
981
 
@@ -943,7 +985,7 @@ static VALUE rb_isolate_low_memory_notification(VALUE self) {
943
985
 
944
986
  static VALUE rb_isolate_pump_message_loop(VALUE self) {
945
987
  IsolateInfo* isolate_info;
946
- Data_Get_Struct(self, IsolateInfo, isolate_info);
988
+ TypedData_Get_Struct(self, IsolateInfo, &isolate_type, isolate_info);
947
989
 
948
990
  if (current_platform == NULL) return Qfalse;
949
991
 
@@ -956,7 +998,7 @@ static VALUE rb_isolate_pump_message_loop(VALUE self) {
956
998
 
957
999
  static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) {
958
1000
  ContextInfo* context_info;
959
- Data_Get_Struct(self, ContextInfo, context_info);
1001
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
960
1002
 
961
1003
  init_v8();
962
1004
 
@@ -967,11 +1009,11 @@ static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) {
967
1009
 
968
1010
  SnapshotInfo *snapshot_info = nullptr;
969
1011
  if (!NIL_P(snap) && rb_obj_is_kind_of(snap, rb_cSnapshot)) {
970
- Data_Get_Struct(snap, SnapshotInfo, snapshot_info);
1012
+ TypedData_Get_Struct(snap, SnapshotInfo, &snapshot_type, snapshot_info);
971
1013
  }
972
1014
  isolate_info->init(snapshot_info);
973
1015
  } else { // given isolate or snapshot
974
- Data_Get_Struct(isolate, IsolateInfo, isolate_info);
1016
+ TypedData_Get_Struct(isolate, IsolateInfo, &isolate_type, isolate_info);
975
1017
  }
976
1018
 
977
1019
  context_info->isolate_info = isolate_info;
@@ -1001,7 +1043,7 @@ static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) {
1001
1043
  static VALUE convert_result_to_ruby(VALUE self /* context */,
1002
1044
  EvalResult& result) {
1003
1045
  ContextInfo *context_info;
1004
- Data_Get_Struct(self, ContextInfo, context_info);
1046
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1005
1047
 
1006
1048
  Isolate *isolate = context_info->isolate_info->isolate;
1007
1049
  Persistent<Context> *p_ctx = context_info->context;
@@ -1028,7 +1070,7 @@ static VALUE convert_result_to_ruby(VALUE self /* context */,
1028
1070
  // a v8 scope, if we do the scope is never cleaned up properly and we leak
1029
1071
  if (!result.parsed) {
1030
1072
  if(TYPE(message) == T_STRING) {
1031
- rb_raise(rb_eParseError, "%s", RSTRING_PTR(message));
1073
+ rb_raise(rb_eParseError, "%" PRIsVALUE, message);
1032
1074
  } else {
1033
1075
  rb_raise(rb_eParseError, "Unknown JavaScript Error during parse");
1034
1076
  }
@@ -1052,15 +1094,17 @@ static VALUE convert_result_to_ruby(VALUE self /* context */,
1052
1094
 
1053
1095
  // exception report about what happened
1054
1096
  if (TYPE(backtrace) == T_STRING) {
1055
- rb_raise(ruby_exception, "%s", RSTRING_PTR(backtrace));
1097
+ rb_raise(ruby_exception, "%" PRIsVALUE, backtrace);
1056
1098
  } else if(TYPE(message) == T_STRING) {
1057
- rb_raise(ruby_exception, "%s", RSTRING_PTR(message));
1099
+ rb_raise(ruby_exception, "%" PRIsVALUE, message);
1058
1100
  } else {
1059
1101
  rb_raise(ruby_exception, "Unknown JavaScript Error during execution");
1060
1102
  }
1103
+ } else if (rb_obj_is_kind_of(ruby_exception, rb_eException)) {
1104
+ rb_exc_raise(ruby_exception);
1061
1105
  } else {
1062
1106
  VALUE rb_str = rb_funcall(ruby_exception, rb_intern("to_s"), 0);
1063
- rb_raise(CLASS_OF(ruby_exception), "%s", RSTRING_PTR(rb_str));
1107
+ rb_raise(CLASS_OF(ruby_exception), "%" PRIsVALUE, rb_str);
1064
1108
  }
1065
1109
  }
1066
1110
 
@@ -1102,7 +1146,7 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) {
1102
1146
  EvalResult eval_result;
1103
1147
  ContextInfo* context_info;
1104
1148
 
1105
- Data_Get_Struct(self, ContextInfo, context_info);
1149
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1106
1150
  Isolate* isolate = context_info->isolate_info->isolate;
1107
1151
 
1108
1152
  if(TYPE(str) != T_STRING) {
@@ -1120,13 +1164,13 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) {
1120
1164
  HandleScope handle_scope(isolate);
1121
1165
 
1122
1166
  Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(str),
1123
- NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
1167
+ NewStringType::kNormal, RSTRING_LENINT(str)).ToLocalChecked();
1124
1168
 
1125
1169
  Local<String> local_filename;
1126
1170
 
1127
1171
  if (filename != Qnil) {
1128
1172
  local_filename = String::NewFromUtf8(isolate, RSTRING_PTR(filename),
1129
- NewStringType::kNormal, (int)RSTRING_LEN(filename)).ToLocalChecked();
1173
+ NewStringType::kNormal, RSTRING_LENINT(filename)).ToLocalChecked();
1130
1174
  eval_params.filename = &local_filename;
1131
1175
  } else {
1132
1176
  eval_params.filename = NULL;
@@ -1190,7 +1234,7 @@ VALUE rescue_callback(VALUE rdata, VALUE exception) {
1190
1234
  return exception;
1191
1235
  }
1192
1236
 
1193
- void*
1237
+ static void*
1194
1238
  gvl_ruby_callback(void* data) {
1195
1239
 
1196
1240
  FunctionCallbackInfo<Value>* args = (FunctionCallbackInfo<Value>*)data;
@@ -1206,7 +1250,7 @@ gvl_ruby_callback(void* data) {
1206
1250
  HandleScope scope(args->GetIsolate());
1207
1251
  Local<External> external = Local<External>::Cast(args->Data());
1208
1252
 
1209
- self = *(VALUE*)(external->Value());
1253
+ self = (VALUE)(external->Value());
1210
1254
  callback = rb_iv_get(self, "@callback");
1211
1255
 
1212
1256
  parent = rb_iv_get(self, "@parent");
@@ -1214,7 +1258,7 @@ gvl_ruby_callback(void* data) {
1214
1258
  return NULL;
1215
1259
  }
1216
1260
 
1217
- Data_Get_Struct(parent, ContextInfo, context_info);
1261
+ TypedData_Get_Struct(parent, ContextInfo, &context_type, context_info);
1218
1262
 
1219
1263
  if (length > 0) {
1220
1264
  ruby_args = rb_ary_tmp_new(length);
@@ -1243,7 +1287,6 @@ gvl_ruby_callback(void* data) {
1243
1287
  args->GetIsolate()->TerminateExecution();
1244
1288
  if (length > 0) {
1245
1289
  rb_ary_clear(ruby_args);
1246
- rb_gc_force_recycle(ruby_args);
1247
1290
  }
1248
1291
  return NULL;
1249
1292
  }
@@ -1251,8 +1294,8 @@ gvl_ruby_callback(void* data) {
1251
1294
  VALUE callback_data_value = (VALUE)&callback_data;
1252
1295
 
1253
1296
  // TODO: use rb_vrescue2 in Ruby 2.7 and above
1254
- result = rb_rescue2(RUBY_METHOD_FUNC(protected_callback), callback_data_value,
1255
- RUBY_METHOD_FUNC(rescue_callback), callback_data_value, rb_eException, (VALUE)0);
1297
+ result = rb_rescue2(MR_METHOD_FUNC(protected_callback), callback_data_value,
1298
+ MR_METHOD_FUNC(rescue_callback), callback_data_value, rb_eException, (VALUE)0);
1256
1299
 
1257
1300
  if(callback_data.failed) {
1258
1301
  rb_iv_set(parent, "@current_exception", result);
@@ -1266,7 +1309,6 @@ gvl_ruby_callback(void* data) {
1266
1309
 
1267
1310
  if (length > 0) {
1268
1311
  rb_ary_clear(ruby_args);
1269
- rb_gc_force_recycle(ruby_args);
1270
1312
  }
1271
1313
 
1272
1314
  if (IsolateData::Get(args->GetIsolate(), IsolateData::DO_TERMINATE)) {
@@ -1301,7 +1343,7 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1301
1343
  bool parse_error = false;
1302
1344
  bool attach_error = false;
1303
1345
 
1304
- Data_Get_Struct(parent, ContextInfo, context_info);
1346
+ TypedData_Get_Struct(parent, ContextInfo, &context_type, context_info);
1305
1347
  Isolate* isolate = context_info->isolate_info->isolate;
1306
1348
 
1307
1349
  {
@@ -1314,15 +1356,12 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1314
1356
 
1315
1357
  Local<String> v8_str =
1316
1358
  String::NewFromUtf8(isolate, RSTRING_PTR(name),
1317
- NewStringType::kNormal, (int)RSTRING_LEN(name))
1359
+ NewStringType::kNormal, RSTRING_LENINT(name))
1318
1360
  .ToLocalChecked();
1319
1361
 
1320
- // copy self so we can access from v8 external
1321
- VALUE* self_copy;
1322
- Data_Get_Struct(self, VALUE, self_copy);
1323
- *self_copy = self;
1324
-
1325
- Local<Value> external = External::New(isolate, self_copy);
1362
+ // Note that self (rb_cExternalFunction) is a pure Ruby T_OBJECT,
1363
+ // not a T_DATA type like most other classes in this file
1364
+ Local<Value> external = External::New(isolate, (void *)self);
1326
1365
 
1327
1366
  if (parent_object == Qnil) {
1328
1367
  Maybe<bool> success = context->Global()->Set(
@@ -1337,7 +1376,7 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1337
1376
  Local<String> eval =
1338
1377
  String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
1339
1378
  NewStringType::kNormal,
1340
- (int)RSTRING_LEN(parent_object_eval))
1379
+ RSTRING_LENINT(parent_object_eval))
1341
1380
  .ToLocalChecked();
1342
1381
 
1343
1382
  MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
@@ -1379,7 +1418,7 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1379
1418
 
1380
1419
  static VALUE rb_context_isolate_mutex(VALUE self) {
1381
1420
  ContextInfo* context_info;
1382
- Data_Get_Struct(self, ContextInfo, context_info);
1421
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1383
1422
 
1384
1423
  if (!context_info->isolate_info) {
1385
1424
  rb_raise(rb_eScriptRuntimeError, "Context has no Isolate available anymore");
@@ -1489,6 +1528,11 @@ static void mark_isolate(void* data) {
1489
1528
  isolate_info->mark();
1490
1529
  }
1491
1530
 
1531
+ static size_t isolate_memsize(const void *ptr) {
1532
+ const IsolateInfo *isolate_info = (const IsolateInfo *)ptr;
1533
+ return sizeof(*isolate_info);
1534
+ }
1535
+
1492
1536
  static void deallocate(void* data) {
1493
1537
  ContextInfo* context_info = (ContextInfo*)data;
1494
1538
 
@@ -1497,6 +1541,11 @@ static void deallocate(void* data) {
1497
1541
  xfree(data);
1498
1542
  }
1499
1543
 
1544
+ static size_t context_memsize(const void *ptr)
1545
+ {
1546
+ return sizeof(ContextInfo);
1547
+ }
1548
+
1500
1549
  static void mark_context(void* data) {
1501
1550
  ContextInfo* context_info = (ContextInfo*)data;
1502
1551
  if (context_info->isolate_info) {
@@ -1504,48 +1553,39 @@ static void mark_context(void* data) {
1504
1553
  }
1505
1554
  }
1506
1555
 
1507
- static void deallocate_external_function(void * data) {
1508
- xfree(data);
1509
- }
1510
-
1511
1556
  static void deallocate_snapshot(void * data) {
1512
1557
  SnapshotInfo* snapshot_info = (SnapshotInfo*)data;
1513
1558
  delete[] snapshot_info->data;
1514
1559
  xfree(snapshot_info);
1515
1560
  }
1516
1561
 
1517
- static VALUE allocate_external_function(VALUE klass) {
1518
- VALUE* self = ALLOC(VALUE);
1519
- return Data_Wrap_Struct(klass, NULL, deallocate_external_function, (void*)self);
1562
+ static size_t snapshot_memsize(const void *data) {
1563
+ SnapshotInfo* snapshot_info = (SnapshotInfo*)data;
1564
+ return sizeof(*snapshot_info) + snapshot_info->raw_size;
1520
1565
  }
1521
1566
 
1522
1567
  static VALUE allocate(VALUE klass) {
1523
- ContextInfo* context_info = ALLOC(ContextInfo);
1524
- context_info->isolate_info = NULL;
1525
- context_info->context = NULL;
1526
-
1527
- return Data_Wrap_Struct(klass, mark_context, deallocate, (void*)context_info);
1568
+ ContextInfo* context_info;
1569
+ return TypedData_Make_Struct(klass, ContextInfo, &context_type, context_info);
1528
1570
  }
1529
1571
 
1530
1572
  static VALUE allocate_snapshot(VALUE klass) {
1531
- SnapshotInfo* snapshot_info = ALLOC(SnapshotInfo);
1532
- snapshot_info->data = NULL;
1533
- snapshot_info->raw_size = 0;
1573
+ SnapshotInfo* snapshot_info;
1534
1574
 
1535
- return Data_Wrap_Struct(klass, NULL, deallocate_snapshot, (void*)snapshot_info);
1575
+ return TypedData_Make_Struct(klass, SnapshotInfo, &snapshot_type, snapshot_info);
1536
1576
  }
1537
1577
 
1538
1578
  static VALUE allocate_isolate(VALUE klass) {
1539
1579
  IsolateInfo* isolate_info = new IsolateInfo();
1540
1580
 
1541
- return Data_Wrap_Struct(klass, mark_isolate, deallocate_isolate, (void*)isolate_info);
1581
+ return TypedData_Wrap_Struct(klass, &isolate_type, isolate_info);
1542
1582
  }
1543
1583
 
1544
1584
  static VALUE
1545
1585
  rb_heap_stats(VALUE self) {
1546
1586
 
1547
1587
  ContextInfo* context_info;
1548
- Data_Get_Struct(self, ContextInfo, context_info);
1588
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1549
1589
  Isolate* isolate;
1550
1590
  v8::HeapStatistics stats;
1551
1591
 
@@ -1577,7 +1617,9 @@ rb_heap_stats(VALUE self) {
1577
1617
  // https://github.com/bnoordhuis/node-heapdump/blob/master/src/heapdump.cc
1578
1618
  class FileOutputStream : public OutputStream {
1579
1619
  public:
1580
- FileOutputStream(FILE* stream) : stream_(stream) {}
1620
+ int err;
1621
+
1622
+ FileOutputStream(int fd) : fd(fd) { err = 0; }
1581
1623
 
1582
1624
  virtual int GetChunkSize() {
1583
1625
  return 65536;
@@ -1586,17 +1628,27 @@ class FileOutputStream : public OutputStream {
1586
1628
  virtual void EndOfStream() {}
1587
1629
 
1588
1630
  virtual WriteResult WriteAsciiChunk(char* data, int size) {
1589
- const size_t len = static_cast<size_t>(size);
1590
- size_t off = 0;
1591
-
1592
- while (off < len && !feof(stream_) && !ferror(stream_))
1593
- off += fwrite(data + off, 1, len - off, stream_);
1594
-
1595
- return off == len ? kContinue : kAbort;
1631
+ size_t len = static_cast<size_t>(size);
1632
+
1633
+ while (len) {
1634
+ ssize_t w = write(fd, data, len);
1635
+
1636
+ if (w > 0) {
1637
+ data += w;
1638
+ len -= w;
1639
+ } else if (w < 0) {
1640
+ err = errno;
1641
+ return kAbort;
1642
+ } else { /* w == 0, could be out-of-space */
1643
+ err = -1;
1644
+ return kAbort;
1645
+ }
1646
+ }
1647
+ return kContinue;
1596
1648
  }
1597
1649
 
1598
1650
  private:
1599
- FILE* stream_;
1651
+ int fd;
1600
1652
  };
1601
1653
 
1602
1654
 
@@ -1609,13 +1661,11 @@ rb_heap_snapshot(VALUE self, VALUE file) {
1609
1661
 
1610
1662
  if (!fptr) return Qfalse;
1611
1663
 
1612
- FILE* fp;
1613
- fp = fdopen(fptr->fd, "w");
1614
- if (fp == NULL) return Qfalse;
1615
-
1664
+ // prepare for unbuffered write(2) below:
1665
+ rb_funcall(file, rb_intern("flush"), 0);
1616
1666
 
1617
1667
  ContextInfo* context_info;
1618
- Data_Get_Struct(self, ContextInfo, context_info);
1668
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1619
1669
  Isolate* isolate;
1620
1670
  isolate = context_info->isolate_info ? context_info->isolate_info->isolate : NULL;
1621
1671
 
@@ -1629,13 +1679,14 @@ rb_heap_snapshot(VALUE self, VALUE file) {
1629
1679
 
1630
1680
  const HeapSnapshot* const snap = heap_profiler->TakeHeapSnapshot();
1631
1681
 
1632
- FileOutputStream stream(fp);
1682
+ FileOutputStream stream(fptr->fd);
1633
1683
  snap->Serialize(&stream, HeapSnapshot::kJSON);
1634
1684
 
1635
- fflush(fp);
1636
-
1637
1685
  const_cast<HeapSnapshot*>(snap)->Delete();
1638
1686
 
1687
+ /* TODO: perhaps rb_sys_fail here */
1688
+ if (stream.err) return Qfalse;
1689
+
1639
1690
  return Qtrue;
1640
1691
  }
1641
1692
 
@@ -1643,7 +1694,7 @@ static VALUE
1643
1694
  rb_context_stop(VALUE self) {
1644
1695
 
1645
1696
  ContextInfo* context_info;
1646
- Data_Get_Struct(self, ContextInfo, context_info);
1697
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1647
1698
 
1648
1699
  Isolate* isolate = context_info->isolate_info->isolate;
1649
1700
 
@@ -1660,7 +1711,7 @@ static VALUE
1660
1711
  rb_context_dispose(VALUE self) {
1661
1712
 
1662
1713
  ContextInfo* context_info;
1663
- Data_Get_Struct(self, ContextInfo, context_info);
1714
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1664
1715
 
1665
1716
  free_context(context_info);
1666
1717
 
@@ -1723,7 +1774,7 @@ static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1723
1774
  FunctionCall call;
1724
1775
  VALUE *call_argv = NULL;
1725
1776
 
1726
- Data_Get_Struct(self, ContextInfo, context_info);
1777
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1727
1778
  Isolate* isolate = context_info->isolate_info->isolate;
1728
1779
 
1729
1780
  if (argc < 1) {
@@ -1784,23 +1835,15 @@ static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1784
1835
  if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) {
1785
1836
  missingFunction = true;
1786
1837
  } else {
1787
-
1788
1838
  Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
1839
+ VALUE tmp;
1789
1840
  call.fun = fun;
1790
- int fun_argc = call.argc;
1791
-
1792
- if (fun_argc > 0) {
1793
- call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
1794
- if (!call.argv) {
1795
- return Qnil;
1796
- }
1797
- for(int i=0; i < fun_argc; i++) {
1798
- call.argv[i] = convert_ruby_to_v8(isolate, context, call_argv[i]);
1799
- }
1841
+ call.argv = (v8::Local<Value> *)RB_ALLOCV_N(void *, tmp, call.argc);
1842
+ for(int i=0; i < call.argc; i++) {
1843
+ call.argv[i] = convert_ruby_to_v8(isolate, context, call_argv[i]);
1800
1844
  }
1801
1845
  rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
1802
- free(call.argv);
1803
-
1846
+ RB_ALLOCV_END(tmp);
1804
1847
  }
1805
1848
  }
1806
1849
 
@@ -1813,7 +1856,7 @@ static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1813
1856
 
1814
1857
  static VALUE rb_context_create_isolate_value(VALUE self) {
1815
1858
  ContextInfo* context_info;
1816
- Data_Get_Struct(self, ContextInfo, context_info);
1859
+ TypedData_Get_Struct(self, ContextInfo, &context_type, context_info);
1817
1860
  IsolateInfo *isolate_info = context_info->isolate_info;
1818
1861
 
1819
1862
  if (!isolate_info) {
@@ -1821,7 +1864,7 @@ static VALUE rb_context_create_isolate_value(VALUE self) {
1821
1864
  }
1822
1865
 
1823
1866
  isolate_info->hold();
1824
- return Data_Wrap_Struct(rb_cIsolate, NULL, &deallocate_isolate, isolate_info);
1867
+ return TypedData_Wrap_Struct(rb_cIsolate, &isolate_type, isolate_info);
1825
1868
  }
1826
1869
 
1827
1870
  static void set_ruby_exiting(VALUE value) {
@@ -1877,7 +1920,6 @@ extern "C" {
1877
1920
  rb_define_alloc_func(rb_cIsolate, allocate_isolate);
1878
1921
 
1879
1922
  rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
1880
- rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
1881
1923
 
1882
1924
  rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
1883
1925
  rb_define_method(rb_cSnapshot, "dump", (VALUE(*)(...))&rb_snapshot_dump, 0);
@@ -3,6 +3,6 @@ require 'mkmf'
3
3
  extension_name = 'mini_racer_loader'
4
4
  dir_config extension_name
5
5
 
6
- $CPPFLAGS += " -fvisibility=hidden "
6
+ $CXXFLAGS += " -fvisibility=hidden "
7
7
 
8
8
  create_makefile extension_name
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniRacer
4
- VERSION = "0.5.0.pre"
4
+ VERSION = "0.6.2"
5
5
  LIBV8_NODE_VERSION = "~> 16.10.0.0"
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.5.0.pre
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-03 00:00:00.000000000 Z
11
+ date: 2022-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -128,10 +128,10 @@ licenses:
128
128
  - MIT
129
129
  metadata:
130
130
  bug_tracker_uri: https://github.com/discourse/mini_racer/issues
131
- changelog_uri: https://github.com/discourse/mini_racer/blob/v0.5.0.pre/CHANGELOG
132
- documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.5.0.pre
133
- source_code_uri: https://github.com/discourse/mini_racer/tree/v0.5.0.pre
134
- post_install_message:
131
+ changelog_uri: https://github.com/discourse/mini_racer/blob/v0.6.2/CHANGELOG
132
+ documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.6.2
133
+ source_code_uri: https://github.com/discourse/mini_racer/tree/v0.6.2
134
+ post_install_message:
135
135
  rdoc_options: []
136
136
  require_paths:
137
137
  - lib
@@ -143,12 +143,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
143
  version: '2.6'
144
144
  required_rubygems_version: !ruby/object:Gem::Requirement
145
145
  requirements:
146
- - - ">"
146
+ - - ">="
147
147
  - !ruby/object:Gem::Version
148
- version: 1.3.1
148
+ version: '0'
149
149
  requirements: []
150
150
  rubygems_version: 3.1.6
151
- signing_key:
151
+ signing_key:
152
152
  specification_version: 4
153
153
  summary: Minimal embedded v8 for Ruby
154
154
  test_files: []