mini_racer 0.1.12 → 0.1.13

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
  SHA1:
3
- metadata.gz: '08140e359a83fd1d2314fa1e0a23749753eae7de'
4
- data.tar.gz: efaa86883c82dd935dddf541c55f22ae842ff27f
3
+ metadata.gz: 02fb924ef1736f4c3626fba401b25725bc70e99d
4
+ data.tar.gz: 15b87d9a11b8104204fc5def731360ae101c6eb7
5
5
  SHA512:
6
- metadata.gz: cd13cd385c184e74ac5a5777d7ab5403c072a228521270f0312d64b72a7b362f23bc9c0daad2491df198079bc137aaa9c59cc363c5c3e87e9676e9ec096a7239
7
- data.tar.gz: 5ca1c21d15528ed6a35da21e1997bfde523ce8920a13ad4d9ba52a84fd9bd9b58284a5685f6aef8a9a562771022b6a2369f37e9b3f478adda25de91f478df799
6
+ metadata.gz: 4d2c4dc1eade12fa0c6ba01b38d91366fa0edcab211fc2483014191cd00c685d16eb469f4f9dd5e93ac8263803f7570b40e19e525671be5d5f6fbd154ac8cdca
7
+ data.tar.gz: 10c2065a5eaa3a967a6109d7e67339e914125c047c9302ab4fedeeac9b058e827503f96936465cfe0465afe5757546ff14ba3ecc21714b6a2616af17b2b93623
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 23-08-2017
2
+
3
+ - 0.1.13
4
+
5
+ - Fix: amend array buffer allocator to use v8 6.0 compatible allocator @ignisf
6
+
1
7
  18-07-2017
2
8
 
3
9
  - 0.1.12
data/README.md CHANGED
@@ -68,6 +68,17 @@ context.eval 'while(true){}'
68
68
  # => exception is raised
69
69
  ```
70
70
 
71
+ ### Memory softlimit support
72
+
73
+ Contexts can specify a memory softlimit for scripts
74
+
75
+ ```ruby
76
+ # terminates script if heap usage exceeds 200mb after V8 garbage collection has run
77
+ context = MiniRacer::Context.new(max_memory: 200000000)
78
+ context.eval 'var a = new Array(10000); while(true) {a = a.concat(new Array(10000)); print("loop " + a.length);}'
79
+ # => V8OutOfMemoryError is raised
80
+ ```
81
+
71
82
  ### Rich debugging with "filename" support
72
83
 
73
84
  ```ruby
@@ -11,20 +11,6 @@
11
11
 
12
12
  using namespace v8;
13
13
 
14
- class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
15
- public:
16
- virtual void* Allocate(size_t length) {
17
- void* data = AllocateUninitialized(length);
18
- return data == NULL ? data : memset(data, 0, length);
19
- }
20
- virtual void* AllocateUninitialized(size_t length) {
21
- return malloc(length);
22
- }
23
- virtual void Free(void* data, size_t) {
24
- free(data);
25
- }
26
- };
27
-
28
14
  typedef struct {
29
15
  const char* data;
30
16
  int raw_size;
@@ -32,7 +18,7 @@ typedef struct {
32
18
 
33
19
  typedef struct {
34
20
  Isolate* isolate;
35
- ArrayBufferAllocator* allocator;
21
+ ArrayBuffer::Allocator* allocator;
36
22
  StartupData* startup_data;
37
23
  bool interrupted;
38
24
  bool disposed;
@@ -67,9 +53,11 @@ typedef struct {
67
53
  Local<String>* filename;
68
54
  useconds_t timeout;
69
55
  EvalResult* result;
56
+ long max_memory;
70
57
  } EvalParams;
71
58
 
72
59
  static VALUE rb_eScriptTerminatedError;
60
+ static VALUE rb_eV8OutOfMemoryError;
73
61
  static VALUE rb_eParseError;
74
62
  static VALUE rb_eScriptRuntimeError;
75
63
  static VALUE rb_cJavaScriptFunction;
@@ -120,6 +108,21 @@ static void init_v8() {
120
108
  platform_lock.unlock();
121
109
  }
122
110
 
111
+ static void gc_callback(Isolate *isolate, GCType type, GCCallbackFlags flags) {
112
+ if((bool)isolate->GetData(3)) return;
113
+
114
+ long softlimit = *(long*) isolate->GetData(2);
115
+
116
+ HeapStatistics* stats = new HeapStatistics();
117
+ isolate->GetHeapStatistics(stats);
118
+ long used = stats->used_heap_size();
119
+
120
+ if(used > softlimit) {
121
+ isolate->SetData(3, (void*)true);
122
+ V8::TerminateExecution(isolate);
123
+ }
124
+ }
125
+
123
126
  void*
124
127
  nogvl_context_eval(void* arg) {
125
128
 
@@ -138,6 +141,10 @@ nogvl_context_eval(void* arg) {
138
141
  isolate->SetData(0, (void*)false);
139
142
  // terminate ASAP
140
143
  isolate->SetData(1, (void*)false);
144
+ // Memory softlimit
145
+ isolate->SetData(2, (void*)false);
146
+ // Memory softlimit hit flag
147
+ isolate->SetData(3, (void*)false);
141
148
 
142
149
  MaybeLocal<Script> parsed_script;
143
150
 
@@ -162,6 +169,11 @@ nogvl_context_eval(void* arg) {
162
169
  result->message->Reset(isolate, trycatch.Exception());
163
170
  } else {
164
171
 
172
+ if(eval_params->max_memory > 0) {
173
+ isolate->SetData(2, &eval_params->max_memory);
174
+ isolate->AddGCEpilogueCallback(gc_callback);
175
+ }
176
+
165
177
  MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
166
178
 
167
179
  result->executed = !maybe_value.IsEmpty();
@@ -453,7 +465,7 @@ static VALUE rb_isolate_init_with_snapshot(VALUE self, VALUE snapshot) {
453
465
 
454
466
  init_v8();
455
467
 
456
- isolate_info->allocator = new ArrayBufferAllocator();
468
+ isolate_info->allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
457
469
  isolate_info->interrupted = false;
458
470
  isolate_info->refs_count = 1;
459
471
 
@@ -555,11 +567,17 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) {
555
567
  eval_params.eval = &eval;
556
568
  eval_params.result = &eval_result;
557
569
  eval_params.timeout = 0;
570
+ eval_params.max_memory = 0;
558
571
  VALUE timeout = rb_iv_get(self, "@timeout");
559
572
  if (timeout != Qnil) {
560
573
  eval_params.timeout = (useconds_t)NUM2LONG(timeout);
561
574
  }
562
575
 
576
+ VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
577
+ if (mem_softlimit != Qnil) {
578
+ eval_params.max_memory = (long)NUM2LONG(mem_softlimit);
579
+ }
580
+
563
581
  eval_result.message = NULL;
564
582
  eval_result.backtrace = NULL;
565
583
 
@@ -593,7 +611,14 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) {
593
611
  if (!eval_result.executed) {
594
612
  VALUE ruby_exception = rb_iv_get(self, "@current_exception");
595
613
  if (ruby_exception == Qnil) {
596
- ruby_exception = eval_result.terminated ? rb_eScriptTerminatedError : rb_eScriptRuntimeError;
614
+ bool mem_softlimit_reached = (bool)isolate->GetData(3);
615
+ // If we were terminated or have the memory softlimit flag set
616
+ if(eval_result.terminated || mem_softlimit_reached) {
617
+ ruby_exception = mem_softlimit_reached ? rb_eV8OutOfMemoryError : rb_eScriptTerminatedError;
618
+ } else {
619
+ ruby_exception = rb_eScriptRuntimeError;
620
+ }
621
+
597
622
  // exception report about what happened
598
623
  if(TYPE(backtrace) == T_STRING) {
599
624
  rb_raise(ruby_exception, "%s", RSTRING_PTR(backtrace));
@@ -701,7 +726,7 @@ gvl_ruby_callback(void* data) {
701
726
  callback_data.failed = false;
702
727
 
703
728
  if ((bool)args->GetIsolate()->GetData(1) == true) {
704
- args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Terminated execution during tansition from Ruby to JS"));
729
+ args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Terminated execution during transition from Ruby to JS"));
705
730
  V8::TerminateExecution(args->GetIsolate());
706
731
  return NULL;
707
732
  }
@@ -1035,6 +1060,7 @@ extern "C" {
1035
1060
 
1036
1061
  VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
1037
1062
  rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
1063
+ rb_eV8OutOfMemoryError = rb_define_class_under(rb_mMiniRacer, "V8OutOfMemoryError", rb_eEvalError);
1038
1064
  rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
1039
1065
  rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
1040
1066
 
@@ -14,6 +14,7 @@ module MiniRacer
14
14
  class EvalError < Error; end
15
15
  class ParseError < EvalError; end
16
16
  class ScriptTerminatedError < EvalError; end
17
+ class V8OutOfMemoryError < EvalError; end
17
18
 
18
19
  class FailedV8Conversion
19
20
  attr_reader :info
@@ -144,8 +145,10 @@ module MiniRacer
144
145
 
145
146
  @functions = {}
146
147
  @timeout = nil
148
+ @max_memory = nil
147
149
  @current_exception = nil
148
150
  @timeout = options[:timeout]
151
+ @max_memory = options[:max_memory]
149
152
  @isolate = options[:isolate] || Isolate.new(options[:snapshot])
150
153
  @disposed = false
151
154
 
@@ -1,3 +1,3 @@
1
1
  module MiniRacer
2
- VERSION = "0.1.12"
2
+ VERSION = "0.1.13"
3
3
  end
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "minitest", "~> 5.0"
26
26
  spec.add_development_dependency "rake-compiler"
27
27
 
28
- spec.add_dependency 'libv8', '~> 5.9'
28
+ spec.add_dependency 'libv8', ' = 6.0.286.44.0beta1'
29
29
  spec.require_paths = ["lib", "ext"]
30
30
 
31
31
  spec.extensions = ["ext/mini_racer_extension/extconf.rb"]
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.1.12
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-26 00:00:00.000000000 Z
11
+ date: 2017-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: libv8
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: '5.9'
75
+ version: 6.0.286.44.0beta1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: '5.9'
82
+ version: 6.0.286.44.0beta1
83
83
  description: Minimal embedded v8 engine for Ruby
84
84
  email:
85
85
  - sam.saffron@gmail.com