mini_racer 0.1.12 → 0.1.13

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
  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