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 +4 -4
- data/CHANGELOG +9 -0
- data/README.md +51 -5
- data/ext/mini_racer_extension/extconf.rb +1 -1
- data/ext/mini_racer_extension/mini_racer_extension.cc +154 -34
- data/lib/mini_racer/version.rb +1 -1
- data/lib/mini_racer.rb +23 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0af151705087d66782e15f8a45952d95e3a7ff80
|
4
|
+
data.tar.gz: 13c8ac7228b49b3c4be26a521ffd01b9cf2b77ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
312
|
-
- Hold
|
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
|
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) {
|
21
|
-
|
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
|
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
|
-
|
488
|
-
|
489
|
-
|
505
|
+
Locker lock(isolate_info->isolate);
|
506
|
+
Isolate::Scope isolate_scope(isolate_info->isolate);
|
507
|
+
HandleScope handle_scope(isolate_info->isolate);
|
490
508
|
|
491
|
-
|
509
|
+
Local<Context> context = Context::New(isolate_info->isolate);
|
492
510
|
|
493
|
-
|
494
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
843
|
+
isolate_info->disposed = true;
|
821
844
|
}
|
822
845
|
|
823
|
-
void
|
824
|
-
|
825
|
-
|
826
|
-
|
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
|
-
|
856
|
+
free_isolate(isolate_info);
|
829
857
|
}
|
830
858
|
|
831
|
-
|
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
|
-
|
844
|
-
|
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
|
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",
|
927
|
-
rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized",
|
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,
|
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);
|
data/lib/mini_racer/version.rb
CHANGED
data/lib/mini_racer.rb
CHANGED
@@ -5,11 +5,15 @@ require "json"
|
|
5
5
|
|
6
6
|
module MiniRacer
|
7
7
|
|
8
|
-
class
|
9
|
-
|
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
|
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.
|
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-
|
11
|
+
date: 2017-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|