mini_racer 0.1.9 → 0.1.10

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