sq_mini_racer 0.2.3.sqreen4 → 0.2.4.0.2

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.
@@ -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
  }