sq_mini_racer 0.2.3.sqreen4 → 0.2.4.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
1
  #include <stdio.h>
2
+ #include <string.h>
3
+ #include <assert.h>
2
4
 
3
5
  // workaround for Ruby 2.3.0 and perhaps certain 2.2 versions
4
6
  // see https://bugs.ruby-lang.org/issues/11962
@@ -6,8 +8,18 @@
6
8
  # undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P
7
9
  # undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P
8
10
 
9
- #include <ruby.h>
10
11
  #include <ruby/version.h>
12
+
13
+ // workaround for Ruby 2.3.0 on macOS
14
+ #if RUBY_API_VERSION_CODE == 20300
15
+ #ifdef _DARWIN_C_SOURCE
16
+ #ifndef __STDC_LIB_EXT1__
17
+ #undef HAVE_MEMSET_S
18
+ #endif
19
+ #endif
20
+ #endif
21
+
22
+ #include <ruby.h>
11
23
  #if RUBY_API_VERSION_MAJOR > 1
12
24
  #include <ruby/thread.h>
13
25
  #endif
@@ -20,6 +32,7 @@
20
32
  #include <atomic>
21
33
  #include <math.h>
22
34
  #include "compat.hpp"
35
+ #include "simdutf8check.h"
23
36
 
24
37
  using namespace v8;
25
38
 
@@ -81,6 +94,10 @@ public:
81
94
  }
82
95
  }
83
96
 
97
+ int refs() {
98
+ return refs_count;
99
+ }
100
+
84
101
  static void* operator new(size_t size) {
85
102
  return ruby_xmalloc(size);
86
103
  }
@@ -207,9 +224,9 @@ static void gc_callback(Isolate *isolate, GCType type, GCCallbackFlags flags) {
207
224
 
208
225
  size_t softlimit = *(size_t*) isolate->GetData(MEM_SOFTLIMIT_VALUE);
209
226
 
210
- HeapStatistics* stats = new HeapStatistics();
211
- isolate->GetHeapStatistics(stats);
212
- size_t used = stats->used_heap_size();
227
+ HeapStatistics stats;
228
+ isolate->GetHeapStatistics(&stats);
229
+ size_t used = stats.used_heap_size();
213
230
 
214
231
  if(used > softlimit) {
215
232
  isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)true);
@@ -271,8 +288,8 @@ static void prepare_result(MaybeLocal<Value> v8res,
271
288
  Local<Message> message = trycatch.Message();
272
289
  char buf[1000];
273
290
  int len;
274
- len = snprintf(buf, sizeof(buf), "%s at %s:%i:%i", *String::Utf8Value(message->Get()),
275
- *String::Utf8Value(message->GetScriptResourceName()->ToString()),
291
+ len = snprintf(buf, sizeof(buf), "%s at %s:%i:%i", *String::Utf8Value(isolate, message->Get()),
292
+ *String::Utf8Value(isolate, message->GetScriptResourceName()->ToString()),
276
293
  message->GetLineNumber(),
277
294
  message->GetStartColumn());
278
295
  if ((size_t) len >= sizeof(buf)) {
@@ -288,9 +305,9 @@ static void prepare_result(MaybeLocal<Value> v8res,
288
305
  Local<String> tmp = String::NewFromUtf8(isolate, "JavaScript was terminated (either by timeout or explicitly)");
289
306
  evalRes.message->Reset(isolate, tmp);
290
307
  }
291
- if (!trycatch.StackTrace().IsEmpty()) {
308
+ if (!trycatch.StackTrace(context).IsEmpty()) {
292
309
  evalRes.backtrace = new Persistent<Value>();
293
- evalRes.backtrace->Reset(isolate, trycatch.StackTrace()->ToString());
310
+ evalRes.backtrace->Reset(isolate, trycatch.StackTrace(context).ToLocalChecked()->ToString());
294
311
  }
295
312
  }
296
313
  }
@@ -326,13 +343,13 @@ nogvl_context_eval(void* arg) {
326
343
  MaybeLocal<Script> parsed_script;
327
344
 
328
345
  if (eval_params->filename) {
329
- origin = new v8::ScriptOrigin(*eval_params->filename);
346
+ origin = new v8::ScriptOrigin(*eval_params->filename);
330
347
  }
331
348
 
332
349
  parsed_script = Script::Compile(context, *eval_params->eval, origin);
333
350
 
334
351
  if (origin) {
335
- delete origin;
352
+ delete origin;
336
353
  }
337
354
 
338
355
  result->parsed = !parsed_script.IsEmpty();
@@ -343,8 +360,8 @@ nogvl_context_eval(void* arg) {
343
360
 
344
361
  MaybeLocal<Value> maybe_value;
345
362
  if (!result->parsed) {
346
- result->message = new Persistent<Value>();
347
- result->message->Reset(isolate, trycatch.Exception());
363
+ result->message = new Persistent<Value>();
364
+ result->message->Reset(isolate, trycatch.Exception());
348
365
  } else {
349
366
  // parsing successful
350
367
  if (eval_params->max_memory > 0) {
@@ -370,41 +387,41 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context,
370
387
  HandleScope scope(isolate);
371
388
 
372
389
  if (value->IsNull() || value->IsUndefined()){
373
- return Qnil;
390
+ return Qnil;
374
391
  }
375
392
 
376
393
  if (value->IsInt32()) {
377
- return INT2FIX(value->Int32Value());
394
+ return INT2FIX(value->Int32Value());
378
395
  }
379
396
 
380
397
  if (value->IsNumber()) {
381
- return rb_float_new(value->NumberValue());
398
+ return rb_float_new(value->NumberValue());
382
399
  }
383
400
 
384
401
  if (value->IsTrue()) {
385
- return Qtrue;
402
+ return Qtrue;
386
403
  }
387
404
 
388
405
  if (value->IsFalse()) {
389
- return Qfalse;
406
+ return Qfalse;
390
407
  }
391
408
 
392
409
  if (value->IsArray()) {
393
410
  VALUE rb_array = rb_ary_new();
394
411
  Local<Array> arr = Local<Array>::Cast(value);
395
412
  for(uint32_t i=0; i < arr->Length(); i++) {
396
- Local<Value> element = arr->Get(i);
397
- VALUE rb_elem = convert_v8_to_ruby(isolate, context, element);
398
- if (rb_funcall(rb_elem, rb_intern("class"), 0) == rb_cFailedV8Conversion) {
399
- return rb_elem;
400
- }
413
+ Local<Value> element = arr->Get(i);
414
+ VALUE rb_elem = convert_v8_to_ruby(isolate, context, element);
415
+ if (rb_funcall(rb_elem, rb_intern("class"), 0) == rb_cFailedV8Conversion) {
416
+ return rb_elem;
417
+ }
401
418
  rb_ary_push(rb_array, rb_elem);
402
419
  }
403
420
  return rb_array;
404
421
  }
405
422
 
406
423
  if (value->IsFunction()){
407
- return rb_funcall(rb_cJavaScriptFunction, rb_intern("new"), 0);
424
+ return rb_funcall(rb_cJavaScriptFunction, rb_intern("new"), 0);
408
425
  }
409
426
 
410
427
  if (value->IsDate()){
@@ -416,34 +433,34 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context,
416
433
  }
417
434
 
418
435
  if (value->IsObject()) {
419
- VALUE rb_hash = rb_hash_new();
420
- TryCatch trycatch(isolate);
421
-
422
- Local<Object> object = value->ToObject();
423
- auto maybe_props = object->GetOwnPropertyNames(context);
424
- if (!maybe_props.IsEmpty()) {
425
- Local<Array> props = maybe_props.ToLocalChecked();
426
- for(uint32_t i=0; i < props->Length(); i++) {
427
- Local<Value> key = props->Get(i);
428
- VALUE rb_key = convert_v8_to_ruby(isolate, context, key);
429
- Local<Value> prop_value = object->Get(key);
430
- // this may have failed due to Get raising
431
-
432
- if (trycatch.HasCaught()) {
433
- // TODO isolate code that translates execption to ruby
434
- // exception so we can properly return it
435
- return rb_funcall(rb_cFailedV8Conversion, rb_intern("new"), 1, rb_str_new2(""));
436
- }
437
-
438
- VALUE rb_value = convert_v8_to_ruby(isolate, context, prop_value);
439
- rb_hash_aset(rb_hash, rb_key, rb_value);
440
- }
441
- }
442
- return rb_hash;
436
+ VALUE rb_hash = rb_hash_new();
437
+ TryCatch trycatch(isolate);
438
+
439
+ Local<Object> object = value->ToObject();
440
+ auto maybe_props = object->GetOwnPropertyNames(context);
441
+ if (!maybe_props.IsEmpty()) {
442
+ Local<Array> props = maybe_props.ToLocalChecked();
443
+ for(uint32_t i=0; i < props->Length(); i++) {
444
+ Local<Value> key = props->Get(i);
445
+ VALUE rb_key = convert_v8_to_ruby(isolate, context, key);
446
+ Local<Value> prop_value = object->Get(key);
447
+ // this may have failed due to Get raising
448
+
449
+ if (trycatch.HasCaught()) {
450
+ // TODO isolate code that translates execption to ruby
451
+ // exception so we can properly return it
452
+ return rb_funcall(rb_cFailedV8Conversion, rb_intern("new"), 1, rb_str_new2(""));
453
+ }
454
+
455
+ VALUE rb_value = convert_v8_to_ruby(isolate, context, prop_value);
456
+ rb_hash_aset(rb_hash, rb_key, rb_value);
457
+ }
458
+ }
459
+ return rb_hash;
443
460
  }
444
461
 
445
462
  Local<String> rstr = value->ToString();
446
- return rb_enc_str_new(*String::Utf8Value(rstr), rstr->Utf8Length(), rb_enc_find("utf-8"));
463
+ return rb_enc_str_new(*String::Utf8Value(isolate, rstr), rstr->Utf8Length(), rb_enc_find("utf-8"));
447
464
  }
448
465
 
449
466
  static VALUE convert_v8_to_ruby(Isolate* isolate,
@@ -464,7 +481,84 @@ static VALUE convert_v8_to_ruby(Isolate* isolate,
464
481
  Local<Value>::New(isolate, value));
465
482
  }
466
483
 
467
- static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) {
484
+ static VALUE encode_as_utf8(VALUE string)
485
+ {
486
+ return rb_funcall(string, rb_intern("encode"), 1, rb_str_new2("UTF-8"));
487
+ }
488
+
489
+ #ifdef __AVX2__
490
+ static bool (*best_utf8_validate_func(void))(const char *, size_t)
491
+ {
492
+ __builtin_cpu_init();
493
+ if (__builtin_cpu_supports("avx2")) {
494
+ return validate_utf8_fast_avx;
495
+ } else {
496
+ return validate_utf8_fast;
497
+ }
498
+ }
499
+ #endif
500
+
501
+ static inline Local<Value> convert_ruby_str_to_v8(
502
+ HandleScope& scope, Isolate *isolate, VALUE value)
503
+ {
504
+ static const rb_encoding *utf8_enc = rb_utf8_encoding();
505
+ static const rb_encoding *ascii8bit_enc = rb_ascii8bit_encoding();
506
+ static const rb_encoding *usascii_enc = rb_usascii_encoding();
507
+ static const rb_encoding *latin1_enc = rb_enc_find("ISO-8859-1");
508
+ assert(latin1_enc != nullptr);
509
+ #ifndef __AVX2__
510
+ # define validate_utf8 validate_utf8_fast
511
+ #else
512
+ static const (*validate_utf8)(const char *, size_t) =
513
+ best_utf8_validate_func();
514
+ #endif
515
+
516
+ rb_encoding *enc = rb_enc_get(value);
517
+ char *str = RSTRING_PTR(value);
518
+ long len = RSTRING_LEN(value);
519
+ if (len < 0 || len > INT_MAX) {
520
+ return Null(isolate);
521
+ }
522
+ bool is_valid_utf8 = enc == utf8_enc &&
523
+ validate_utf8(str, static_cast<size_t>(len));
524
+
525
+ MaybeLocal<String> v8str;
526
+ int int_len = static_cast<int>(len);
527
+ if (is_valid_utf8) {
528
+ convert_from_utf8:
529
+ v8str = String::NewFromUtf8(
530
+ isolate, str, NewStringType::kNormal, int_len);
531
+ } else if (enc == utf8_enc || enc == ascii8bit_enc ||
532
+ enc == usascii_enc || enc == latin1_enc ||
533
+ rb_funcall(value, rb_intern("valid_encoding?"), 0) == Qfalse) {
534
+ treat_as_latin1:
535
+ // if ASCII, it could be that the string is invalid
536
+ // ignore that possibility (effectively treat it as latin1)
537
+ v8str = String::NewFromOneByte(
538
+ isolate, reinterpret_cast<uint8_t *>(str),
539
+ NewStringType::kNormal, int_len);
540
+ } else {
541
+ int state;
542
+ VALUE result = rb_protect(encode_as_utf8, value, &state);
543
+
544
+ //Ran into an exception!
545
+ if (state) {
546
+ rb_set_errinfo(Qnil);
547
+ goto treat_as_latin1;
548
+ } else if (rb_enc_get(result) != utf8_enc) {
549
+ // conversion did not result in UTF-8. Odd!
550
+ goto treat_as_latin1;
551
+ } else {
552
+ str = RSTRING_PTR(result);
553
+ int_len = RSTRING_LEN(result);
554
+ goto convert_from_utf8;
555
+ }
556
+ }
557
+ return v8str.ToLocalChecked();
558
+ }
559
+
560
+ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value)
561
+ {
468
562
  EscapableHandleScope scope(isolate);
469
563
 
470
564
  Local<Array> array;
@@ -477,67 +571,85 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) {
477
571
  VALUE klass;
478
572
 
479
573
  switch (TYPE(value)) {
480
- case T_FIXNUM:
481
- fixnum = NUM2LONG(value);
482
- if (fixnum > INT_MAX)
574
+ case T_FIXNUM:
575
+ {
576
+ fixnum = NUM2LONG(value);
577
+ if (fixnum > INT_MAX)
578
+ {
579
+ return scope.Escape(Number::New(isolate, (double)fixnum));
580
+ }
581
+ return scope.Escape(Integer::New(isolate, (int)fixnum));
582
+ }
583
+ case T_FLOAT:
584
+ return scope.Escape(Number::New(isolate, NUM2DBL(value)));
585
+ case T_STRING:
586
+ return scope.Escape(convert_ruby_str_to_v8(scope, isolate, value));
587
+ case T_NIL:
588
+ return scope.Escape(Null(isolate));
589
+ case T_TRUE:
590
+ return scope.Escape(True(isolate));
591
+ case T_FALSE:
592
+ return scope.Escape(False(isolate));
593
+ case T_ARRAY:
594
+ {
595
+ length = RARRAY_LEN(value);
596
+ array = Array::New(isolate, (int)length);
597
+ for(i=0; i<length; i++) {
598
+ array->Set(i, convert_ruby_to_v8(isolate, rb_ary_entry(value, i)));
599
+ }
600
+ return scope.Escape(array);
601
+ }
602
+ case T_HASH:
603
+ {
604
+ object = Object::New(isolate);
605
+ hash_as_array = rb_funcall(value, rb_intern("to_a"), 0);
606
+ length = RARRAY_LEN(hash_as_array);
607
+ for(i=0; i<length; i++) {
608
+ pair = rb_ary_entry(hash_as_array, i);
609
+ object->Set(convert_ruby_to_v8(isolate, rb_ary_entry(pair, 0)),
610
+ convert_ruby_to_v8(isolate, rb_ary_entry(pair, 1)));
611
+ }
612
+ return scope.Escape(object);
613
+ }
614
+ case T_SYMBOL:
483
615
  {
484
- return scope.Escape(Number::New(isolate, (double)fixnum));
616
+ value = rb_funcall(value, rb_intern("to_s"), 0);
617
+ return scope.Escape(convert_ruby_str_to_v8(scope, isolate, value));
485
618
  }
486
- return scope.Escape(Integer::New(isolate, (int)fixnum));
487
- case T_FLOAT:
488
- return scope.Escape(Number::New(isolate, NUM2DBL(value)));
489
- case T_STRING:
490
- return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
491
- case T_NIL:
492
- return scope.Escape(Null(isolate));
493
- case T_TRUE:
494
- return scope.Escape(True(isolate));
495
- case T_FALSE:
496
- return scope.Escape(False(isolate));
497
- case T_ARRAY:
498
- length = RARRAY_LEN(value);
499
- array = Array::New(isolate, (int)length);
500
- for(i=0; i<length; i++) {
501
- array->Set(i, convert_ruby_to_v8(isolate, rb_ary_entry(value, i)));
502
- }
503
- return scope.Escape(array);
504
- case T_HASH:
505
- object = Object::New(isolate);
506
- hash_as_array = rb_funcall(value, rb_intern("to_a"), 0);
507
- length = RARRAY_LEN(hash_as_array);
508
- for(i=0; i<length; i++) {
509
- pair = rb_ary_entry(hash_as_array, i);
510
- object->Set(convert_ruby_to_v8(isolate, rb_ary_entry(pair, 0)),
511
- convert_ruby_to_v8(isolate, rb_ary_entry(pair, 1)));
512
- }
513
- return scope.Escape(object);
514
- case T_SYMBOL:
515
- value = rb_funcall(value, rb_intern("to_s"), 0);
516
- return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
517
- case T_DATA:
518
- klass = rb_funcall(value, rb_intern("class"), 0);
519
- if (klass == rb_cTime || klass == rb_cDateTime)
619
+ case T_DATA:
520
620
  {
521
- if (klass == rb_cDateTime)
621
+ klass = rb_funcall(value, rb_intern("class"), 0);
622
+ if (klass == rb_cTime || klass == rb_cDateTime)
522
623
  {
523
- value = rb_funcall(value, rb_intern("to_time"), 0);
624
+ if (klass == rb_cDateTime)
625
+ {
626
+ value = rb_funcall(value, rb_intern("to_time"), 0);
627
+ }
628
+ value = rb_funcall(value, rb_intern("to_f"), 0);
629
+ return scope.Escape(Date::New(isolate, NUM2DBL(value) * 1000));
630
+ }
631
+ // break intentionally missing
632
+ }
633
+ case T_OBJECT:
634
+ case T_CLASS:
635
+ case T_ICLASS:
636
+ case T_MODULE:
637
+ case T_REGEXP:
638
+ case T_MATCH:
639
+ case T_STRUCT:
640
+ case T_BIGNUM:
641
+ case T_FILE:
642
+ case T_UNDEF:
643
+ case T_NODE:
644
+ default:
645
+ {
646
+ if (rb_respond_to(value, rb_intern("to_s"))) {
647
+ // TODO: if this throws we're screwed
648
+ value = rb_funcall(value, rb_intern("to_s"), 0);
649
+ return scope.Escape(convert_ruby_str_to_v8(scope, isolate, value));
524
650
  }
525
- value = rb_funcall(value, rb_intern("to_f"), 0);
526
- return scope.Escape(Date::New(isolate, NUM2DBL(value) * 1000));
651
+ return scope.Escape(String::NewFromUtf8(isolate, "Undefined Conversion"));
527
652
  }
528
- case T_OBJECT:
529
- case T_CLASS:
530
- case T_ICLASS:
531
- case T_MODULE:
532
- case T_REGEXP:
533
- case T_MATCH:
534
- case T_STRUCT:
535
- case T_BIGNUM:
536
- case T_FILE:
537
- case T_UNDEF:
538
- case T_NODE:
539
- default:
540
- return scope.Escape(String::NewFromUtf8(isolate, "Undefined Conversion"));
541
653
  }
542
654
 
543
655
  }
@@ -686,13 +798,13 @@ static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) {
686
798
  // the ruby lock is needed if this isn't a new isolate
687
799
  IsolateInfo::Lock ruby_lock(isolate_info->mutex);
688
800
  Locker lock(isolate_info->isolate);
689
- Isolate::Scope isolate_scope(isolate_info->isolate);
690
- HandleScope handle_scope(isolate_info->isolate);
801
+ Isolate::Scope isolate_scope(isolate_info->isolate);
802
+ HandleScope handle_scope(isolate_info->isolate);
691
803
 
692
- Local<Context> context = Context::New(isolate_info->isolate);
804
+ Local<Context> context = Context::New(isolate_info->isolate);
693
805
 
694
- context_info->context = new Persistent<Context>();
695
- context_info->context->Reset(isolate_info->isolate, context);
806
+ context_info->context = new Persistent<Context>();
807
+ context_info->context->Reset(isolate_info->isolate, context);
696
808
  }
697
809
 
698
810
  if (Qnil == rb_cDateTime && rb_funcall(rb_cObject, rb_intern("const_defined?"), 1, rb_str_new2("DateTime")) == Qtrue)
@@ -776,7 +888,7 @@ static VALUE convert_result_to_ruby(VALUE self /* context */,
776
888
 
777
889
  if (result.json) {
778
890
  Local<String> rstr = tmp->ToString();
779
- VALUE json_string = rb_enc_str_new(*String::Utf8Value(rstr), rstr->Utf8Length(), rb_enc_find("utf-8"));
891
+ VALUE json_string = rb_enc_str_new(*String::Utf8Value(isolate, rstr), rstr->Utf8Length(), rb_enc_find("utf-8"));
780
892
  ret = rb_funcall(rb_mJSON, rb_intern("parse"), 1, json_string);
781
893
  } else {
782
894
  ret = convert_v8_to_ruby(isolate, *p_ctx, tmp);
@@ -814,45 +926,45 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) {
814
926
  }
815
927
 
816
928
  {
817
- Locker lock(isolate);
818
- Isolate::Scope isolate_scope(isolate);
819
- HandleScope handle_scope(isolate);
820
-
821
- Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(str),
822
- NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
823
-
824
- Local<String> local_filename;
825
-
826
- if (filename != Qnil) {
827
- local_filename = String::NewFromUtf8(isolate, RSTRING_PTR(filename),
828
- NewStringType::kNormal, (int)RSTRING_LEN(filename)).ToLocalChecked();
829
- eval_params.filename = &local_filename;
830
- } else {
831
- eval_params.filename = NULL;
832
- }
833
-
834
- eval_params.context_info = context_info;
835
- eval_params.eval = &eval;
836
- eval_params.result = &eval_result;
837
- eval_params.timeout = 0;
838
- eval_params.max_memory = 0;
839
- VALUE timeout = rb_iv_get(self, "@timeout");
840
- if (timeout != Qnil) {
841
- eval_params.timeout = (useconds_t)NUM2LONG(timeout);
842
- }
843
-
844
- VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
845
- if (mem_softlimit != Qnil) {
846
- eval_params.max_memory = (size_t)NUM2ULONG(mem_softlimit);
847
- }
848
-
849
- eval_result.message = NULL;
850
- eval_result.backtrace = NULL;
929
+ Locker lock(isolate);
930
+ Isolate::Scope isolate_scope(isolate);
931
+ HandleScope handle_scope(isolate);
932
+
933
+ Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(str),
934
+ NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
935
+
936
+ Local<String> local_filename;
937
+
938
+ if (filename != Qnil) {
939
+ local_filename = String::NewFromUtf8(isolate, RSTRING_PTR(filename),
940
+ NewStringType::kNormal, (int)RSTRING_LEN(filename)).ToLocalChecked();
941
+ eval_params.filename = &local_filename;
942
+ } else {
943
+ eval_params.filename = NULL;
944
+ }
945
+
946
+ eval_params.context_info = context_info;
947
+ eval_params.eval = &eval;
948
+ eval_params.result = &eval_result;
949
+ eval_params.timeout = 0;
950
+ eval_params.max_memory = 0;
951
+ VALUE timeout = rb_iv_get(self, "@timeout");
952
+ if (timeout != Qnil) {
953
+ eval_params.timeout = (useconds_t)NUM2LONG(timeout);
954
+ }
955
+
956
+ VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
957
+ if (mem_softlimit != Qnil) {
958
+ eval_params.max_memory = (size_t)NUM2ULONG(mem_softlimit);
959
+ }
960
+
961
+ eval_result.message = NULL;
962
+ eval_result.backtrace = NULL;
851
963
 
852
964
  #if RUBY_API_VERSION_MAJOR > 1
853
- rb_thread_call_without_gvl(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
965
+ rb_thread_call_without_gvl(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
854
966
  #else
855
- rb_thread_blocking_region(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
967
+ rb_thread_blocking_region(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
856
968
  #endif
857
969
  }
858
970
 
@@ -866,17 +978,16 @@ typedef struct {
866
978
  bool failed;
867
979
  } protected_callback_data;
868
980
 
869
- static
870
- VALUE protected_callback(VALUE rdata) {
981
+ static VALUE protected_callback(VALUE rdata) {
871
982
  protected_callback_data* data = (protected_callback_data*)rdata;
872
983
  VALUE result;
873
984
 
874
985
  if (data->length > 0) {
875
- result = rb_funcall2(data->callback, rb_intern("call"), data->length,
876
- RARRAY_PTR(data->ruby_args));
877
- RB_GC_GUARD(data->ruby_args);
986
+ result = rb_funcall2(data->callback, rb_intern("call"), data->length,
987
+ RARRAY_PTR(data->ruby_args));
988
+ RB_GC_GUARD(data->ruby_args);
878
989
  } else {
879
- result = rb_funcall(data->callback, rb_intern("call"), 0);
990
+ result = rb_funcall(data->callback, rb_intern("call"), 0);
880
991
  }
881
992
  return result;
882
993
  }
@@ -913,16 +1024,16 @@ gvl_ruby_callback(void* data) {
913
1024
  ContextInfo* context_info;
914
1025
  Data_Get_Struct(parent, ContextInfo, context_info);
915
1026
 
916
- if (length > 0) {
917
- ruby_args = rb_ary_tmp_new(length);
918
- }
1027
+ if (length > 0) {
1028
+ ruby_args = rb_ary_tmp_new(length);
1029
+ }
919
1030
 
920
- for (int i = 0; i < length; i++) {
921
- Local<Value> value = ((*args)[i]).As<Value>();
922
- VALUE tmp = convert_v8_to_ruby(args->GetIsolate(),
923
- *context_info->context, value);
924
- rb_ary_push(ruby_args, tmp);
925
- }
1031
+ for (int i = 0; i < length; i++) {
1032
+ Local<Value> value = ((*args)[i]).As<Value>();
1033
+ VALUE tmp = convert_v8_to_ruby(args->GetIsolate(),
1034
+ *context_info->context, value);
1035
+ rb_ary_push(ruby_args, tmp);
1036
+ }
926
1037
  }
927
1038
 
928
1039
  // may raise exception stay clear of handle scope
@@ -933,31 +1044,31 @@ gvl_ruby_callback(void* data) {
933
1044
  callback_data.failed = false;
934
1045
 
935
1046
  if ((bool)args->GetIsolate()->GetData(DO_TERMINATE) == true) {
936
- args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Terminated execution during transition from Ruby to JS"));
937
- args->GetIsolate()->TerminateExecution();
938
- if (length > 0) {
939
- rb_ary_clear(ruby_args);
940
- rb_gc_force_recycle(ruby_args);
941
- }
942
- return NULL;
1047
+ args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Terminated execution during transition from Ruby to JS"));
1048
+ args->GetIsolate()->TerminateExecution();
1049
+ if (length > 0) {
1050
+ rb_ary_clear(ruby_args);
1051
+ rb_gc_force_recycle(ruby_args);
1052
+ }
1053
+ return NULL;
943
1054
  }
944
1055
 
945
1056
  result = rb_rescue2((VALUE(*)(...))&protected_callback, (VALUE)(&callback_data),
946
- (VALUE(*)(...))&rescue_callback, (VALUE)(&callback_data), rb_eException, (VALUE)0);
1057
+ (VALUE(*)(...))&rescue_callback, (VALUE)(&callback_data), rb_eException, (VALUE)0);
947
1058
 
948
1059
  if(callback_data.failed) {
949
- rb_iv_set(parent, "@current_exception", result);
950
- args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Ruby exception"));
1060
+ rb_iv_set(parent, "@current_exception", result);
1061
+ args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Ruby exception"));
951
1062
  }
952
1063
  else {
953
- HandleScope scope(args->GetIsolate());
954
- Handle<Value> v8_result = convert_ruby_to_v8(args->GetIsolate(), result);
955
- args->GetReturnValue().Set(v8_result);
1064
+ HandleScope scope(args->GetIsolate());
1065
+ Handle<Value> v8_result = convert_ruby_to_v8(args->GetIsolate(), result);
1066
+ args->GetReturnValue().Set(v8_result);
956
1067
  }
957
1068
 
958
1069
  if (length > 0) {
959
- rb_ary_clear(ruby_args);
960
- rb_gc_force_recycle(ruby_args);
1070
+ rb_ary_clear(ruby_args);
1071
+ rb_gc_force_recycle(ruby_args);
961
1072
  }
962
1073
 
963
1074
  if ((bool)args->GetIsolate()->GetData(DO_TERMINATE) == true) {
@@ -976,11 +1087,11 @@ static void ruby_callback(const FunctionCallbackInfo<Value>& args) {
976
1087
  bool has_gvl = (bool)args.GetIsolate()->GetData(IN_GVL);
977
1088
 
978
1089
  if(has_gvl) {
979
- gvl_ruby_callback((void*)&args);
1090
+ gvl_ruby_callback((void*)&args);
980
1091
  } else {
981
- args.GetIsolate()->SetData(IN_GVL, (void*)true);
982
- rb_thread_call_with_gvl(gvl_ruby_callback, (void*)(&args));
983
- args.GetIsolate()->SetData(IN_GVL, (void*)false);
1092
+ args.GetIsolate()->SetData(IN_GVL, (void*)true);
1093
+ rb_thread_call_with_gvl(gvl_ruby_callback, (void*)(&args));
1094
+ args.GetIsolate()->SetData(IN_GVL, (void*)false);
984
1095
  }
985
1096
  }
986
1097
 
@@ -1001,46 +1112,46 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
1001
1112
  Isolate* isolate = context_info->isolate_info->isolate;
1002
1113
 
1003
1114
  {
1004
- Locker lock(isolate);
1005
- Isolate::Scope isolate_scope(isolate);
1006
- HandleScope handle_scope(isolate);
1007
-
1008
- Local<Context> context = context_info->context->Get(isolate);
1009
- Context::Scope context_scope(context);
1115
+ Locker lock(isolate);
1116
+ Isolate::Scope isolate_scope(isolate);
1117
+ HandleScope handle_scope(isolate);
1010
1118
 
1011
- Local<String> v8_str = String::NewFromUtf8(isolate, RSTRING_PTR(name),
1012
- NewStringType::kNormal, (int)RSTRING_LEN(name)).ToLocalChecked();
1119
+ Local<Context> context = context_info->context->Get(isolate);
1120
+ Context::Scope context_scope(context);
1013
1121
 
1014
- // copy self so we can access from v8 external
1015
- VALUE* self_copy;
1016
- Data_Get_Struct(self, VALUE, self_copy);
1017
- *self_copy = self;
1122
+ Local<String> v8_str = String::NewFromUtf8(isolate, RSTRING_PTR(name),
1123
+ NewStringType::kNormal, (int)RSTRING_LEN(name)).ToLocalChecked();
1018
1124
 
1019
- Local<Value> external = External::New(isolate, self_copy);
1125
+ // copy self so we can access from v8 external
1126
+ VALUE* self_copy;
1127
+ Data_Get_Struct(self, VALUE, self_copy);
1128
+ *self_copy = self;
1020
1129
 
1021
- if (parent_object == Qnil) {
1022
- context->Global()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
1023
- } else {
1130
+ Local<Value> external = External::New(isolate, self_copy);
1024
1131
 
1025
- Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
1026
- NewStringType::kNormal, (int)RSTRING_LEN(parent_object_eval)).ToLocalChecked();
1132
+ if (parent_object == Qnil) {
1133
+ context->Global()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
1134
+ } else {
1027
1135
 
1028
- MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
1029
- if (parsed_script.IsEmpty()) {
1030
- parse_error = true;
1031
- } else {
1032
- MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
1033
- attach_error = true;
1136
+ Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
1137
+ NewStringType::kNormal, (int)RSTRING_LEN(parent_object_eval)).ToLocalChecked();
1034
1138
 
1035
- if (!maybe_value.IsEmpty()) {
1036
- Local<Value> value = maybe_value.ToLocalChecked();
1037
- if (value->IsObject()){
1038
- value.As<Object>()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
1039
- attach_error = false;
1040
- }
1041
- }
1042
- }
1043
- }
1139
+ MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
1140
+ if (parsed_script.IsEmpty()) {
1141
+ parse_error = true;
1142
+ } else {
1143
+ MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
1144
+ attach_error = true;
1145
+
1146
+ if (!maybe_value.IsEmpty()) {
1147
+ Local<Value> value = maybe_value.ToLocalChecked();
1148
+ if (value->IsObject()){
1149
+ value.As<Object>()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
1150
+ attach_error = false;
1151
+ }
1152
+ }
1153
+ }
1154
+ }
1044
1155
  }
1045
1156
 
1046
1157
  // always raise out of V8 context
@@ -1069,19 +1180,19 @@ static VALUE rb_context_isolate_mutex(VALUE self) {
1069
1180
  void free_isolate(IsolateInfo* isolate_info) {
1070
1181
 
1071
1182
  if (isolate_info->isolate) {
1072
- Locker lock(isolate_info->isolate);
1183
+ Locker lock(isolate_info->isolate);
1073
1184
  }
1074
1185
 
1075
1186
  if (isolate_info->isolate) {
1076
1187
  if (isolate_info->interrupted) {
1077
1188
  fprintf(stderr, "WARNING: V8 isolate was interrupted by Ruby, it can not be disposed and memory will not be reclaimed till the Ruby process exits.\n");
1078
1189
  } else {
1079
-
1080
- if (isolate_info->pid != getpid()) {
1081
- fprintf(stderr, "WARNING: V8 isolate was forked, it can not be disposed and memory will not be reclaimed till the Ruby process exits.\n");
1082
- } else {
1083
- isolate_info->isolate->Dispose();
1084
- }
1190
+
1191
+ if (isolate_info->pid != getpid()) {
1192
+ fprintf(stderr, "WARNING: V8 isolate was forked, it can not be disposed and memory will not be reclaimed till the Ruby process exits.\n");
1193
+ } else {
1194
+ isolate_info->isolate->Dispose();
1195
+ }
1085
1196
  }
1086
1197
  isolate_info->isolate = NULL;
1087
1198
  }
@@ -1094,21 +1205,50 @@ void free_isolate(IsolateInfo* isolate_info) {
1094
1205
  delete isolate_info->allocator;
1095
1206
  }
1096
1207
 
1208
+ static void *free_context_raw(void* arg) {
1209
+ ContextInfo* context_info = (ContextInfo*)arg;
1210
+ IsolateInfo* isolate_info = context_info->isolate_info;
1211
+ Persistent<Context>* context = context_info->context;
1212
+
1213
+ if (context && isolate_info && isolate_info->isolate) {
1214
+ Locker lock(isolate_info->isolate);
1215
+ v8::Isolate::Scope isolate_scope(isolate_info->isolate);
1216
+ context->Reset();
1217
+ delete context;
1218
+ }
1219
+
1220
+ if (isolate_info) {
1221
+ isolate_info->release();
1222
+ }
1223
+
1224
+ xfree(context_info);
1225
+ return NULL;
1226
+ }
1227
+
1097
1228
  // destroys everything except freeing the ContextInfo struct (see deallocate())
1098
1229
  static void free_context(ContextInfo* context_info) {
1099
1230
 
1100
1231
  IsolateInfo* isolate_info = context_info->isolate_info;
1101
1232
 
1233
+ ContextInfo* context_info_copy = ALLOC(ContextInfo);
1234
+ context_info_copy->isolate_info = context_info->isolate_info;
1235
+ context_info_copy->context = context_info->context;
1236
+
1237
+ if (isolate_info && isolate_info->refs() > 1) {
1238
+ pthread_t free_context_thread;
1239
+ if (pthread_create(&free_context_thread, NULL, free_context_raw, (void*)context_info_copy)) {
1240
+ fprintf(stderr, "WARNING failed to release memory in MiniRacer, thread to release could not be created, process will leak memory\n");
1241
+ }
1242
+
1243
+ } else {
1244
+ free_context_raw(context_info_copy);
1245
+ }
1246
+
1102
1247
  if (context_info->context && isolate_info && isolate_info->isolate) {
1103
- Locker lock(isolate_info->isolate);
1104
- v8::Isolate::Scope isolate_scope(isolate_info->isolate);
1105
- context_info->context->Reset();
1106
- delete context_info->context;
1107
- context_info->context = NULL;
1248
+ context_info->context = NULL;
1108
1249
  }
1109
1250
 
1110
1251
  if (isolate_info) {
1111
- isolate_info->release();
1112
1252
  context_info->isolate_info = NULL;
1113
1253
  }
1114
1254
  }
@@ -1191,20 +1331,20 @@ rb_heap_stats(VALUE self) {
1191
1331
 
1192
1332
  if (!isolate) {
1193
1333
 
1194
- rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(0));
1195
- rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(0));
1196
- rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(0));
1197
- rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(0));
1198
- rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(0));
1334
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(0));
1335
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(0));
1336
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(0));
1337
+ rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(0));
1338
+ rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(0));
1199
1339
 
1200
1340
  } else {
1201
- isolate->GetHeapStatistics(&stats);
1341
+ isolate->GetHeapStatistics(&stats);
1202
1342
 
1203
- rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(stats.total_physical_size()));
1204
- rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(stats.total_heap_size_executable()));
1205
- rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(stats.total_heap_size()));
1206
- rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(stats.used_heap_size()));
1207
- rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(stats.heap_size_limit()));
1343
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(stats.total_physical_size()));
1344
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(stats.total_heap_size_executable()));
1345
+ rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(stats.total_heap_size()));
1346
+ rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(stats.used_heap_size()));
1347
+ rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(stats.heap_size_limit()));
1208
1348
  }
1209
1349
 
1210
1350
  return rval;
@@ -1238,6 +1378,19 @@ rb_context_dispose(VALUE self) {
1238
1378
  return Qnil;
1239
1379
  }
1240
1380
 
1381
+ static VALUE
1382
+ rb_context_low_memory_notification(VALUE self) {
1383
+
1384
+ ContextInfo* context_info;
1385
+ Data_Get_Struct(self, ContextInfo, context_info);
1386
+
1387
+ if (context_info->isolate_info && context_info->isolate_info->isolate) {
1388
+ context_info->isolate_info->isolate->LowMemoryNotification();
1389
+ }
1390
+
1391
+ return Qnil;
1392
+ }
1393
+
1241
1394
  #if RUBY_API_VERSION_MAJOR > 1
1242
1395
  static void*
1243
1396
  #else
@@ -1281,8 +1434,7 @@ static void unblock_function(void *args) {
1281
1434
  call->context_info->isolate_info->interrupted = true;
1282
1435
  }
1283
1436
 
1284
- static VALUE
1285
- rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1437
+ static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1286
1438
  ContextInfo* context_info;
1287
1439
  FunctionCall call;
1288
1440
  VALUE *call_argv = NULL;
@@ -1315,7 +1467,6 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1315
1467
  }
1316
1468
 
1317
1469
  bool missingFunction = false;
1318
-
1319
1470
  {
1320
1471
  Locker lock(isolate);
1321
1472
  Isolate::Scope isolate_scope(isolate);
@@ -1326,38 +1477,38 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
1326
1477
 
1327
1478
  // examples of such usage can be found in
1328
1479
  // https://github.com/v8/v8/blob/36b32aa28db5e993312f4588d60aad5c8330c8a5/test/cctest/test-api.cc#L15711
1329
- Local<String> fname = String::NewFromUtf8(isolate, call.function_name);
1330
- MaybeLocal<v8::Value> val = context->Global()->Get(fname);
1331
-
1332
- if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) {
1333
- missingFunction = true;
1334
- } else {
1335
-
1336
- Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
1337
- call.fun = fun;
1338
- int fun_argc = call.argc;
1339
-
1340
- if (fun_argc > 0) {
1341
- call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
1342
- if (!call.argv) {
1343
- return Qnil;
1344
- }
1345
- for(int i=0; i < fun_argc; i++) {
1346
- call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
1347
- }
1348
- }
1349
- #if RUBY_API_VERSION_MAJOR > 1
1350
- rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
1351
- #else
1352
- rb_thread_blocking_region(nogvl_context_call, &call, unblock_function, &call);
1353
- #endif
1354
- free(call.argv);
1480
+ Local<String> fname = String::NewFromUtf8(isolate, call.function_name);
1481
+ MaybeLocal<v8::Value> val = context->Global()->Get(fname);
1482
+
1483
+ if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) {
1484
+ missingFunction = true;
1485
+ } else {
1486
+
1487
+ Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
1488
+ call.fun = fun;
1489
+ int fun_argc = call.argc;
1355
1490
 
1356
- }
1491
+ if (fun_argc > 0) {
1492
+ call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
1493
+ if (!call.argv) {
1494
+ return Qnil;
1495
+ }
1496
+ for(int i=0; i < fun_argc; i++) {
1497
+ call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
1498
+ }
1499
+ }
1500
+ #if RUBY_API_VERSION_MAJOR > 1
1501
+ rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
1502
+ #else
1503
+ rb_thread_blocking_region(nogvl_context_call, &call, unblock_function, &call);
1504
+ #endif
1505
+ free(call.argv);
1506
+
1507
+ }
1357
1508
  }
1358
1509
 
1359
1510
  if (missingFunction) {
1360
- rb_raise(rb_eScriptRuntimeError, "Unknown JavaScript method invoked");
1511
+ rb_raise(rb_eScriptRuntimeError, "Unknown JavaScript method invoked");
1361
1512
  }
1362
1513
 
1363
1514
  return convert_result_to_ruby(self, call.result);
@@ -1382,52 +1533,52 @@ extern "C" {
1382
1533
  {
1383
1534
  VALUE rb_mSqreen = rb_define_module("Sqreen");
1384
1535
  VALUE rb_mMiniRacer = rb_define_module_under(rb_mSqreen, "MiniRacer");
1385
- rb_cContext = rb_define_class_under(rb_mMiniRacer, "Context", rb_cObject);
1386
- rb_cSnapshot = rb_define_class_under(rb_mMiniRacer, "Snapshot", rb_cObject);
1387
- rb_cIsolate = rb_define_class_under(rb_mMiniRacer, "Isolate", rb_cObject);
1388
- VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
1389
-
1390
- VALUE rb_eError = rb_define_class_under(rb_mMiniRacer, "Error", rb_eStandardError);
1391
-
1392
- VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
1393
- rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
1394
- rb_eV8OutOfMemoryError = rb_define_class_under(rb_mMiniRacer, "V8OutOfMemoryError", rb_eEvalError);
1395
- rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
1396
- rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
1397
-
1398
- rb_cJavaScriptFunction = rb_define_class_under(rb_mMiniRacer, "JavaScriptFunction", rb_cObject);
1399
- rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eError);
1400
- rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eError);
1401
- rb_cFailedV8Conversion = rb_define_class_under(rb_mMiniRacer, "FailedV8Conversion", rb_cObject);
1402
- rb_mJSON = rb_define_module("JSON");
1403
-
1404
- VALUE rb_cExternalFunction = rb_define_class_under(rb_cContext, "ExternalFunction", rb_cObject);
1405
-
1406
- rb_define_method(rb_cContext, "stop", (VALUE(*)(...))&rb_context_stop, 0);
1407
- rb_define_method(rb_cContext, "dispose_unsafe", (VALUE(*)(...))&rb_context_dispose, 0);
1408
- rb_define_method(rb_cContext, "heap_stats", (VALUE(*)(...))&rb_heap_stats, 0);
1409
- rb_define_private_method(rb_cContext, "create_isolate_value",(VALUE(*)(...))&rb_context_create_isolate_value, 0);
1410
- rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 2);
1411
- rb_define_private_method(rb_cContext, "call_unsafe", (VALUE(*)(...))&rb_context_call_unsafe, -1);
1412
- rb_define_private_method(rb_cContext, "isolate_mutex", (VALUE(*)(...))&rb_context_isolate_mutex, 0);
1413
- rb_define_private_method(rb_cContext, "init_unsafe",(VALUE(*)(...))&rb_context_init_unsafe, 2);
1414
-
1415
- rb_define_alloc_func(rb_cContext, allocate);
1416
- rb_define_alloc_func(rb_cSnapshot, allocate_snapshot);
1417
- rb_define_alloc_func(rb_cIsolate, allocate_isolate);
1418
-
1419
- rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
1420
- rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
1421
-
1422
- rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
1423
- rb_define_method(rb_cSnapshot, "dump", (VALUE(*)(...))&rb_snapshot_dump, 0);
1424
- rb_define_method(rb_cSnapshot, "warmup_unsafe!", (VALUE(*)(...))&rb_snapshot_warmup_unsafe, 1);
1425
- rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1);
1426
-
1427
- rb_define_method(rb_cIsolate, "idle_notification", (VALUE(*)(...))&rb_isolate_idle_notification, 1);
1428
- rb_define_private_method(rb_cIsolate, "init_with_snapshot",(VALUE(*)(...))&rb_isolate_init_with_snapshot, 1);
1429
-
1430
- rb_define_singleton_method(rb_cPlatform, "set_flag_as_str!", (VALUE(*)(...))&rb_platform_set_flag_as_str, 1);
1536
+ rb_cContext = rb_define_class_under(rb_mMiniRacer, "Context", rb_cObject);
1537
+ rb_cSnapshot = rb_define_class_under(rb_mMiniRacer, "Snapshot", rb_cObject);
1538
+ rb_cIsolate = rb_define_class_under(rb_mMiniRacer, "Isolate", rb_cObject);
1539
+ VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
1540
+
1541
+ VALUE rb_eError = rb_define_class_under(rb_mMiniRacer, "Error", rb_eStandardError);
1542
+
1543
+ VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
1544
+ rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
1545
+ rb_eV8OutOfMemoryError = rb_define_class_under(rb_mMiniRacer, "V8OutOfMemoryError", rb_eEvalError);
1546
+ rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
1547
+ rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
1548
+
1549
+ rb_cJavaScriptFunction = rb_define_class_under(rb_mMiniRacer, "JavaScriptFunction", rb_cObject);
1550
+ rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eError);
1551
+ rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eError);
1552
+ rb_cFailedV8Conversion = rb_define_class_under(rb_mMiniRacer, "FailedV8Conversion", rb_cObject);
1553
+ rb_mJSON = rb_define_module("JSON");
1554
+
1555
+ VALUE rb_cExternalFunction = rb_define_class_under(rb_cContext, "ExternalFunction", rb_cObject);
1556
+
1557
+ rb_define_method(rb_cContext, "stop", (VALUE(*)(...))&rb_context_stop, 0);
1558
+ rb_define_method(rb_cContext, "dispose_unsafe", (VALUE(*)(...))&rb_context_dispose, 0);
1559
+ rb_define_method(rb_cContext, "low_memory_notification", (VALUE(*)(...))&rb_context_low_memory_notification, 0);
1560
+ rb_define_method(rb_cContext, "heap_stats", (VALUE(*)(...))&rb_heap_stats, 0);
1561
+ rb_define_private_method(rb_cContext, "create_isolate_value",(VALUE(*)(...))&rb_context_create_isolate_value, 0);
1562
+ rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 2);
1563
+ rb_define_private_method(rb_cContext, "call_unsafe", (VALUE(*)(...))&rb_context_call_unsafe, -1);
1564
+ rb_define_private_method(rb_cContext, "isolate_mutex", (VALUE(*)(...))&rb_context_isolate_mutex, 0);
1565
+ rb_define_private_method(rb_cContext, "init_unsafe",(VALUE(*)(...))&rb_context_init_unsafe, 2);
1566
+
1567
+ rb_define_alloc_func(rb_cContext, allocate);
1568
+ rb_define_alloc_func(rb_cSnapshot, allocate_snapshot);
1569
+ rb_define_alloc_func(rb_cIsolate, allocate_isolate);
1570
+
1571
+ rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
1572
+ rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
1573
+
1574
+ rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
1575
+ rb_define_method(rb_cSnapshot, "dump", (VALUE(*)(...))&rb_snapshot_dump, 0);
1576
+ rb_define_method(rb_cSnapshot, "warmup_unsafe!", (VALUE(*)(...))&rb_snapshot_warmup_unsafe, 1);
1577
+ rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1);
1578
+
1579
+ rb_define_method(rb_cIsolate, "idle_notification", (VALUE(*)(...))&rb_isolate_idle_notification, 1);
1580
+ rb_define_private_method(rb_cIsolate, "init_with_snapshot",(VALUE(*)(...))&rb_isolate_init_with_snapshot, 1);
1581
+
1582
+ rb_define_singleton_method(rb_cPlatform, "set_flag_as_str!", (VALUE(*)(...))&rb_platform_set_flag_as_str, 1);
1431
1583
  }
1432
-
1433
1584
  }