mini_racer 0.5.0.pre → 0.6.2

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: 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: []