mini_racer 0.1.9 → 0.1.10

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: bcbf79004383ed09c2b2ceb6821a13a01ef11c36
4
- data.tar.gz: d18d5d701d8067a011f2e778c257a076036cb029
3
+ metadata.gz: 0af151705087d66782e15f8a45952d95e3a7ff80
4
+ data.tar.gz: 13c8ac7228b49b3c4be26a521ffd01b9cf2b77ee
5
5
  SHA512:
6
- metadata.gz: fa133304bbbbac7c0a7cd205d19928cc0bfd074a340c0ef18ceef92bff9bc4e3ff4924085c418ee32e14663c84c856837f7f745b09db65d5ecd89241b5081689
7
- data.tar.gz: 9bbfa1a279aef49bcfe500583b73796c4766bc5bbbd278f1d3c76bdf8c9ce2df67d292f2c1e25d94e739f532f252356497b7e4d43dc94fab9c0e8d0819b2cd09
6
+ metadata.gz: 3c0359323d659fe170453a0b0304bc512c0d3d66edc07d991eb4383f354f788b9a54bc7abeec4f7280ae9e1c85bf9652fa2682d0c54ed5e41a3677009fdbb5d7
7
+ data.tar.gz: 3da5843bd59f285d3fcc3e9eaf92ee6cc823974016f669d01eeeb36a886055c3b9e6038b6f5e6e9ccc9a74eab4a7729ac2da9ed75df9ab388a5e0e34b4d22542
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ 13-07-2017
2
+
3
+ - 0.1.10
4
+
5
+ - Fix leak: memory leak when disposing a context (20 bytes per context)
6
+ - Feature: added #heap_stats so you can get visibility from context to actual memory usage of isolate
7
+ - Feature: added #dispose so you reclaim all v8 memory right away as opposed to waiting for GC
8
+ - Feature: you can now specify filename in an eval eg: eval('a = 1', filename: 'my_awesome.js')
9
+
1
10
  09-03-2017
2
11
 
3
12
  - 0.1.9
data/README.md CHANGED
@@ -68,6 +68,19 @@ context.eval 'while(true){}'
68
68
  # => exception is raised
69
69
  ```
70
70
 
71
+ ### Rich debugging with "filename" support
72
+
73
+ ```ruby
74
+
75
+ context = MiniRacer::Context.new
76
+ context.eval('var foo = function() {bar();}', filename: 'a/foo.js')
77
+ context.eval('bar()', filename: 'a/bar.js')
78
+
79
+ # MiniRacer::RuntimeError is raised containing the filenames you specified for evals in backtrace
80
+
81
+ ```
82
+
83
+
71
84
  ### Threadsafe
72
85
 
73
86
  Context usage is threadsafe
@@ -226,6 +239,39 @@ A list of all V8 runtime flags can be found using `node --v8-options`, or else b
226
239
 
227
240
  Note that runtime flags must be set before any other operation (e.g. creating a context, a snapshot or an isolate), otherwise an exception will be thrown.
228
241
 
242
+ Flags:
243
+
244
+ - :expose_gc : Will expose `gc()` which you can run in JavaScript to issue a gc
245
+ - :max_old_space_size : defaults to 1400 (megs) on 64 bit, you can restric memory usage by limiting this.
246
+ - **NOTE TO READER** our documentation could be awesome we could be properly documenting all the flags, they are hugely useful, if you feel like documenting a few more, PLEASE DO, PRs are welcome.
247
+
248
+ ## Controlling memory
249
+
250
+ When hosting v8 you may want to keep track of memory usage, use #heap_stats to get memory usage:
251
+
252
+ ```ruby
253
+ context = MiniRacer::Context.new(timeout: 5)
254
+ context.eval("let a='testing';")
255
+ p context.heap_stats
256
+ # {:total_physical_size=>1280640,
257
+ # :total_heap_size_executable=>4194304,
258
+ # :total_heap_size=>3100672,
259
+ # :used_heap_size=>1205376,
260
+ # :heap_size_limit=>1501560832}
261
+ ```
262
+
263
+ If you wish to dispose of a context before waiting on the GC use
264
+
265
+ ```ruby
266
+ context = MiniRacer::Context.new(timeout: 5)
267
+ context.eval("let a='testing';")
268
+ context.dispose
269
+ context.eval("a = 2")
270
+ # MiniRacer::ContextDisposedError
271
+
272
+ # nothing works on the context from now on, its a shell waiting to be disposed
273
+ ```
274
+
229
275
  ## Performance
230
276
 
231
277
  The `bench` folder contains benchmark.
@@ -302,14 +348,14 @@ Add this to your .travis.yml file:
302
348
 
303
349
  ## Similar Projects
304
350
 
305
- ###therubyracer
351
+ ### therubyracer
306
352
 
307
353
  - https://github.com/cowboyd/therubyracer
308
354
  - Most comprehensive bridge available
309
355
  - Provides the ability to "eval" JavaScript
310
356
  - Provides the ability to invoke Ruby code from JavaScript
311
- - Hold refrences to JavaScript objects and methods in your Ruby code
312
- - Hold refrences to Ruby objects and methods in JavaScript code
357
+ - Hold references to JavaScript objects and methods in your Ruby code
358
+ - Hold references to Ruby objects and methods in JavaScript code
313
359
  - Uses libv8, so installation is fast
314
360
  - Supports timeouts for JavaScript execution
315
361
  - Does not release global interpreter lock, so performance is constrained to a single thread
@@ -317,7 +363,7 @@ Add this to your .travis.yml file:
317
363
  - Supports execjs
318
364
 
319
365
 
320
- ###v8eval
366
+ ### v8eval
321
367
 
322
368
  - https://github.com/sony/v8eval
323
369
  - Provides the ability to "eval" JavaScript using the latest V8 engine
@@ -330,7 +376,7 @@ Add this to your .travis.yml file:
330
376
  - No support for execjs (can not be used with Rails uglifier and coffeescript gems)
331
377
 
332
378
 
333
- ###therubyrhino
379
+ ### therubyrhino
334
380
 
335
381
  - https://github.com/cowboyd/therubyrhino
336
382
  - API compatible with therubyracer
@@ -32,7 +32,7 @@ WARNING: C++11 support is required for compiling mini_racer. Please make sure
32
32
  you are using a compiler that supports at least C++11. Examples of such
33
33
  compilers are GCC 4.7+ and Clang 3.2+.
34
34
 
35
- If you are using Travis, consider either migrating your bulid to Ubuntu Trusty or
35
+ If you are using Travis, consider either migrating your build to Ubuntu Trusty or
36
36
  installing GCC 4.8. See mini_racer's README.md for more information.
37
37
 
38
38
 
@@ -17,8 +17,12 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
17
17
  void* data = AllocateUninitialized(length);
18
18
  return data == NULL ? data : memset(data, 0, length);
19
19
  }
20
- virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
21
- virtual void Free(void* data, size_t) { free(data); }
20
+ virtual void* AllocateUninitialized(size_t length) {
21
+ return malloc(length);
22
+ }
23
+ virtual void Free(void* data, size_t) {
24
+ free(data);
25
+ }
22
26
  };
23
27
 
24
28
  typedef struct {
@@ -31,6 +35,7 @@ typedef struct {
31
35
  ArrayBufferAllocator* allocator;
32
36
  StartupData* startup_data;
33
37
  bool interrupted;
38
+ bool disposed;
34
39
  pid_t pid;
35
40
 
36
41
  // how many references to this isolate exist
@@ -38,7 +43,7 @@ typedef struct {
38
43
  // objects, Ruby will destroy ruby objects first, then call the
39
44
  // extenstion's deallocators. In this case, that means it would
40
45
  // call `deallocate_isolate` _before_ `deallocate`, causing a segfault
41
- int refs_count;
46
+ volatile int refs_count;
42
47
  } IsolateInfo;
43
48
 
44
49
  typedef struct {
@@ -59,6 +64,7 @@ typedef struct {
59
64
  typedef struct {
60
65
  ContextInfo* context_info;
61
66
  Local<String>* eval;
67
+ Local<String>* filename;
62
68
  useconds_t timeout;
63
69
  EvalResult* result;
64
70
  } EvalParams;
@@ -126,13 +132,25 @@ nogvl_context_eval(void* arg) {
126
132
  TryCatch trycatch(isolate);
127
133
  Local<Context> context = eval_params->context_info->context->Get(isolate);
128
134
  Context::Scope context_scope(context);
135
+ v8::ScriptOrigin *origin = NULL;
129
136
 
130
137
  // in gvl flag
131
138
  isolate->SetData(0, (void*)false);
132
139
  // terminate ASAP
133
140
  isolate->SetData(1, (void*)false);
134
141
 
135
- MaybeLocal<Script> parsed_script = Script::Compile(context, *eval_params->eval);
142
+ MaybeLocal<Script> parsed_script;
143
+
144
+ if (eval_params->filename) {
145
+ origin = new v8::ScriptOrigin(*eval_params->filename);
146
+ }
147
+
148
+ parsed_script = Script::Compile(context, *eval_params->eval, origin);
149
+
150
+ if (origin) {
151
+ delete origin;
152
+ }
153
+
136
154
  result->parsed = !parsed_script.IsEmpty();
137
155
  result->executed = false;
138
156
  result->terminated = false;
@@ -484,14 +502,14 @@ static VALUE rb_context_init_with_isolate(VALUE self, VALUE isolate) {
484
502
  isolate_info->refs_count++;
485
503
 
486
504
  {
487
- Locker lock(isolate_info->isolate);
488
- Isolate::Scope isolate_scope(isolate_info->isolate);
489
- HandleScope handle_scope(isolate_info->isolate);
505
+ Locker lock(isolate_info->isolate);
506
+ Isolate::Scope isolate_scope(isolate_info->isolate);
507
+ HandleScope handle_scope(isolate_info->isolate);
490
508
 
491
- Local<Context> context = Context::New(isolate_info->isolate);
509
+ Local<Context> context = Context::New(isolate_info->isolate);
492
510
 
493
- context_info->context = new Persistent<Context>();
494
- context_info->context->Reset(isolate_info->isolate, context);
511
+ context_info->context = new Persistent<Context>();
512
+ context_info->context->Reset(isolate_info->isolate, context);
495
513
  }
496
514
 
497
515
  if (Qnil == rb_cDateTime && rb_funcall(rb_cObject, rb_intern("const_defined?"), 1, rb_str_new2("DateTime")) == Qtrue)
@@ -502,7 +520,7 @@ static VALUE rb_context_init_with_isolate(VALUE self, VALUE isolate) {
502
520
  return Qnil;
503
521
  }
504
522
 
505
- static VALUE rb_context_eval_unsafe(VALUE self, VALUE str) {
523
+ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) {
506
524
 
507
525
  EvalParams eval_params;
508
526
  EvalResult eval_result;
@@ -521,7 +539,17 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str) {
521
539
  HandleScope handle_scope(isolate);
522
540
 
523
541
  Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(str),
524
- NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
542
+ NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
543
+
544
+ Local<String> local_filename;
545
+
546
+ if (filename != Qnil) {
547
+ local_filename = String::NewFromUtf8(isolate, RSTRING_PTR(filename),
548
+ NewStringType::kNormal, (int)RSTRING_LEN(filename)).ToLocalChecked();
549
+ eval_params.filename = &local_filename;
550
+ } else {
551
+ eval_params.filename = NULL;
552
+ }
525
553
 
526
554
  eval_params.context_info = context_info;
527
555
  eval_params.eval = &eval;
@@ -786,15 +814,10 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
786
814
  return Qnil;
787
815
  }
788
816
 
789
- void maybe_free_isolate_info(IsolateInfo* isolate_info) {
790
- // an isolate can only be freed if no Isolate or Context (ruby) object
791
- // still need it
792
- if (isolate_info == NULL || isolate_info->refs_count > 0) {
793
- return;
794
- }
817
+ void free_isolate(IsolateInfo* isolate_info) {
795
818
 
796
819
  if (isolate_info->isolate) {
797
- Locker lock(isolate_info->isolate);
820
+ Locker lock(isolate_info->isolate);
798
821
  }
799
822
 
800
823
  if (isolate_info->isolate) {
@@ -817,18 +840,25 @@ void maybe_free_isolate_info(IsolateInfo* isolate_info) {
817
840
  }
818
841
 
819
842
  delete isolate_info->allocator;
820
- xfree(isolate_info);
843
+ isolate_info->disposed = true;
821
844
  }
822
845
 
823
- void deallocate_isolate(void* data) {
824
- IsolateInfo* isolate_info = (IsolateInfo*) data;
825
-
826
- isolate_info->refs_count--;
846
+ void maybe_free_isolate(IsolateInfo* isolate_info) {
847
+ // an isolate can only be freed if no Isolate or Context (ruby) object
848
+ // still need it
849
+ //
850
+ // there is a sequence issue here where Ruby may call the deallocator on the
851
+ // context object after it calles the dallocator on the isolate
852
+ if (isolate_info->refs_count != 0 || isolate_info->disposed) {
853
+ return;
854
+ }
827
855
 
828
- maybe_free_isolate_info(isolate_info);
856
+ free_isolate(isolate_info);
829
857
  }
830
858
 
831
- void deallocate(void* data) {
859
+
860
+ void free_context(void* data) {
861
+
832
862
  ContextInfo* context_info = (ContextInfo*)data;
833
863
  IsolateInfo* isolate_info = context_info->isolate_info;
834
864
 
@@ -837,23 +867,56 @@ void deallocate(void* data) {
837
867
  v8::Isolate::Scope isolate_scope(isolate_info->isolate);
838
868
  context_info->context->Reset();
839
869
  delete context_info->context;
870
+ context_info->context = NULL;
840
871
  }
872
+ }
873
+
874
+ void deallocate_context(void* data) {
875
+
876
+ ContextInfo* context_info = (ContextInfo*)data;
877
+ IsolateInfo* isolate_info = context_info->isolate_info;
878
+
879
+ free_context(data);
841
880
 
842
881
  if (isolate_info) {
843
- isolate_info->refs_count--;
844
- maybe_free_isolate_info(isolate_info);
882
+ isolate_info->refs_count--;
883
+ maybe_free_isolate(isolate_info);
845
884
  }
846
885
  }
847
886
 
887
+ void deallocate_isolate(void* data) {
888
+
889
+ IsolateInfo* isolate_info = (IsolateInfo*) data;
890
+
891
+ isolate_info->refs_count--;
892
+ maybe_free_isolate(isolate_info);
893
+
894
+ if (isolate_info->refs_count == 0) {
895
+ xfree(isolate_info);
896
+ }
897
+ }
898
+
899
+ void deallocate(void* data) {
900
+ ContextInfo* context_info = (ContextInfo*)data;
901
+ IsolateInfo* isolate_info = context_info->isolate_info;
902
+
903
+ deallocate_context(data);
904
+
905
+ if (isolate_info && isolate_info->refs_count == 0) {
906
+ xfree(isolate_info);
907
+ }
908
+
909
+ xfree(data);
910
+ }
911
+
912
+
848
913
  void deallocate_external_function(void * data) {
849
914
  xfree(data);
850
915
  }
851
916
 
852
917
  void deallocate_snapshot(void * data) {
853
918
  SnapshotInfo* snapshot_info = (SnapshotInfo*)data;
854
-
855
919
  delete[] snapshot_info->data;
856
-
857
920
  xfree(snapshot_info);
858
921
  }
859
922
 
@@ -887,10 +950,44 @@ VALUE allocate_isolate(VALUE klass) {
887
950
  isolate_info->interrupted = false;
888
951
  isolate_info->refs_count = 0;
889
952
  isolate_info->pid = getpid();
953
+ isolate_info->disposed = false;
890
954
 
891
955
  return Data_Wrap_Struct(klass, NULL, deallocate_isolate, (void*)isolate_info);
892
956
  }
893
957
 
958
+ static VALUE
959
+ rb_heap_stats(VALUE self) {
960
+
961
+ ContextInfo* context_info;
962
+ Data_Get_Struct(self, ContextInfo, context_info);
963
+ Isolate* isolate;
964
+ v8::HeapStatistics stats;
965
+
966
+ isolate = context_info->isolate_info ? context_info->isolate_info->isolate : NULL;
967
+
968
+ VALUE rval = rb_hash_new();
969
+
970
+ if (!isolate) {
971
+
972
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(0));
973
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(0));
974
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(0));
975
+ rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(0));
976
+ rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(0));
977
+
978
+ } else {
979
+ isolate->GetHeapStatistics(&stats);
980
+
981
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(stats.total_physical_size()));
982
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(stats.total_heap_size_executable()));
983
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(stats.total_heap_size()));
984
+ rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(stats.used_heap_size()));
985
+ rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(stats.heap_size_limit()));
986
+ }
987
+
988
+ return rval;
989
+ }
990
+
894
991
  static VALUE
895
992
  rb_context_stop(VALUE self) {
896
993
 
@@ -908,6 +1005,22 @@ rb_context_stop(VALUE self) {
908
1005
  return Qnil;
909
1006
  }
910
1007
 
1008
+ static VALUE
1009
+ rb_context_dispose(VALUE self) {
1010
+
1011
+ ContextInfo* context_info;
1012
+ Data_Get_Struct(self, ContextInfo, context_info);
1013
+
1014
+ free_context(context_info);
1015
+
1016
+ if (context_info->isolate_info && context_info->isolate_info->refs_count == 2) {
1017
+ // special case, we only have isolate + context so we can burn the
1018
+ // isolate as well
1019
+ free_isolate(context_info->isolate_info);
1020
+ }
1021
+ return Qnil;
1022
+ }
1023
+
911
1024
  extern "C" {
912
1025
 
913
1026
  void Init_mini_racer_extension ( void )
@@ -918,23 +1031,30 @@ extern "C" {
918
1031
  VALUE rb_cIsolate = rb_define_class_under(rb_mMiniRacer, "Isolate", rb_cObject);
919
1032
  VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
920
1033
 
921
- VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eStandardError);
1034
+ VALUE rb_eError = rb_define_class_under(rb_mMiniRacer, "Error", rb_eStandardError);
1035
+
1036
+ VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
922
1037
  rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
923
1038
  rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
924
1039
  rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
1040
+
925
1041
  rb_cJavaScriptFunction = rb_define_class_under(rb_mMiniRacer, "JavaScriptFunction", rb_cObject);
926
- rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eStandardError);
927
- rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eStandardError);
1042
+ rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eError);
1043
+ rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eError);
928
1044
  rb_cFailedV8Conversion = rb_define_class_under(rb_mMiniRacer, "FailedV8Conversion", rb_cObject);
929
1045
  rb_mJSON = rb_define_module("JSON");
930
1046
 
931
1047
  VALUE rb_cExternalFunction = rb_define_class_under(rb_cContext, "ExternalFunction", rb_cObject);
1048
+
932
1049
  rb_define_method(rb_cContext, "stop", (VALUE(*)(...))&rb_context_stop, 0);
1050
+ rb_define_method(rb_cContext, "dispose_unsafe", (VALUE(*)(...))&rb_context_dispose, 0);
1051
+ rb_define_method(rb_cContext, "heap_stats", (VALUE(*)(...))&rb_heap_stats, 0);
1052
+
933
1053
  rb_define_alloc_func(rb_cContext, allocate);
934
1054
  rb_define_alloc_func(rb_cSnapshot, allocate_snapshot);
935
1055
  rb_define_alloc_func(rb_cIsolate, allocate_isolate);
936
1056
 
937
- rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 1);
1057
+ rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 2);
938
1058
  rb_define_private_method(rb_cContext, "init_with_isolate",(VALUE(*)(...))&rb_context_init_with_isolate, 1);
939
1059
  rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
940
1060
  rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
@@ -1,3 +1,3 @@
1
1
  module MiniRacer
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
data/lib/mini_racer.rb CHANGED
@@ -5,11 +5,15 @@ require "json"
5
5
 
6
6
  module MiniRacer
7
7
 
8
- class EvalError < StandardError; end
9
- class ScriptTerminatedError < EvalError; end
8
+ class Error < ::StandardError; end
9
+
10
+ class ContextDisposedError < Error; end
11
+ class SnapshotError < Error; end
12
+ class PlatformAlreadyInitialized < Error; end
13
+
14
+ class EvalError < Error; end
10
15
  class ParseError < EvalError; end
11
- class SnapshotError < StandardError; end
12
- class PlatformAlreadyInitialized < StandardError; end
16
+ class ScriptTerminatedError < EvalError; end
13
17
 
14
18
  class FailedV8Conversion
15
19
  attr_reader :info
@@ -160,18 +164,31 @@ module MiniRacer
160
164
  eval(File.read(filename))
161
165
  end
162
166
 
163
- def eval(str)
167
+ def eval(str, options=nil)
168
+ raise(ContextDisposedError, 'attempted to call eval on a disposed context!') if @disposed
169
+
170
+ filename = options && options[:filename].to_s
171
+
164
172
  @eval_thread = Thread.current
165
173
  isolate.with_lock do
166
174
  @current_exception = nil
167
175
  timeout do
168
- eval_unsafe(str)
176
+ eval_unsafe(str, filename)
169
177
  end
170
178
  end
171
179
  ensure
172
180
  @eval_thread = nil
173
181
  end
174
182
 
183
+ def dispose
184
+ if !@disposed
185
+ isolate.with_lock do
186
+ dispose_unsafe
187
+ end
188
+ @disposed = true
189
+ end
190
+ end
191
+
175
192
 
176
193
  def attach(name, callback)
177
194
 
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.9
4
+ version: 0.1.10
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-03-09 00:00:00.000000000 Z
11
+ date: 2017-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler