sq_mini_racer 0.2.4.sqreen1 → 0.2.4.sqreen2
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/LICENSE.txt +8 -1
- data/ext/mini_racer_extension/extconf.rb +5 -0
- data/ext/mini_racer_extension/mini_racer_extension.cc +401 -307
- data/ext/mini_racer_extension/simdutf8check.h +463 -0
- data/lib/sqreen/mini_racer/version.rb +1 -1
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 8e20539790e64f4295e6e1e09a4e1acf6b4220b7c706886fb8411f4aa27318ba
         | 
| 4 | 
            +
              data.tar.gz: d8e1504d61888f9fbc486362b497540b4f8d2ecb97e568039dd2ad221d5ff44a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 80df85cc03fd5ce85da08699bdc9e7d384b0be879c5cce96044a35db5e63e11483b8e60808d3433e6734573458477ac432a7abe347d816ef38049f36818adc25
         | 
| 7 | 
            +
              data.tar.gz: cd5d54e082237ee0b06b6d98bff69a9f671a94d8ab827550b691d0edf5c4e4a932a173b1b7b5f4dde9f4cc6b89aafeda8f36f8b70a28bb0ebaac1390f101da40
         | 
    
        data/LICENSE.txt
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            The MIT License (MIT)
         | 
| 2 2 |  | 
| 3 | 
            -
            Copyright (c) 2016  | 
| 3 | 
            +
            Copyright (c) 2016-2019 The contributors
         | 
| 4 4 |  | 
| 5 5 | 
             
            Permission is hereby granted, free of charge, to any person obtaining a copy
         | 
| 6 6 | 
             
            of this software and associated documentation files (the "Software"), to deal
         | 
| @@ -19,3 +19,10 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 19 | 
             
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         | 
| 20 20 | 
             
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         | 
| 21 21 | 
             
            THE SOFTWARE.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
             | 
| 24 | 
            +
            The file ext/mini_racer_extension/simdutf8check.h is a slighly modified file
         | 
| 25 | 
            +
            from https://github.com/lemire/fastvalidate-utf-8, which is licensed under the
         | 
| 26 | 
            +
            Apache 2.0 license. For more details, see:
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            https://github.com/lemire/fastvalidate-utf-8/blob/0f04b4068288711b72f1c3c730a8fb2d1b4cdd00/LICENSE
         | 
| @@ -14,6 +14,11 @@ $CPPFLAGS += " -fPIC" unless $CPPFLAGS.split.include? "-rdynamic" or IS_DARWIN | |
| 14 14 | 
             
            $CPPFLAGS += " -std=c++0x"
         | 
| 15 15 | 
             
            $CPPFLAGS += " -fpermissive"
         | 
| 16 16 | 
             
            $CPPFLAGS += " -fno-omit-frame-pointer"
         | 
| 17 | 
            +
            if enable_config('avx2')
         | 
| 18 | 
            +
              $CPPFLAGS += " -mavx2"
         | 
| 19 | 
            +
            else
         | 
| 20 | 
            +
              $CPPFLAGS += " -mssse3"
         | 
| 21 | 
            +
            end
         | 
| 17 22 |  | 
| 18 23 | 
             
            $CPPFLAGS += " -Wno-reserved-user-defined-literal" if IS_DARWIN
         | 
| 19 24 |  | 
| @@ -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
         | 
| @@ -20,6 +22,7 @@ | |
| 20 22 | 
             
            #include <atomic>
         | 
| 21 23 | 
             
            #include <math.h>
         | 
| 22 24 | 
             
            #include "compat.hpp"
         | 
| 25 | 
            +
            #include "simdutf8check.h"
         | 
| 23 26 |  | 
| 24 27 | 
             
            using namespace v8;
         | 
| 25 28 |  | 
| @@ -82,7 +85,7 @@ public: | |
| 82 85 | 
             
                }
         | 
| 83 86 |  | 
| 84 87 | 
             
                int refs() {
         | 
| 85 | 
            -
             | 
| 88 | 
            +
                    return refs_count;
         | 
| 86 89 | 
             
                }
         | 
| 87 90 |  | 
| 88 91 | 
             
                static void* operator new(size_t size) {
         | 
| @@ -330,13 +333,13 @@ nogvl_context_eval(void* arg) { | |
| 330 333 | 
             
                MaybeLocal<Script> parsed_script;
         | 
| 331 334 |  | 
| 332 335 | 
             
                if (eval_params->filename) {
         | 
| 333 | 
            -
             | 
| 336 | 
            +
                    origin = new v8::ScriptOrigin(*eval_params->filename);
         | 
| 334 337 | 
             
                }
         | 
| 335 338 |  | 
| 336 339 | 
             
                parsed_script = Script::Compile(context, *eval_params->eval, origin);
         | 
| 337 340 |  | 
| 338 341 | 
             
                if (origin) {
         | 
| 339 | 
            -
             | 
| 342 | 
            +
                    delete origin;
         | 
| 340 343 | 
             
                }
         | 
| 341 344 |  | 
| 342 345 | 
             
                result->parsed = !parsed_script.IsEmpty();
         | 
| @@ -347,8 +350,8 @@ nogvl_context_eval(void* arg) { | |
| 347 350 |  | 
| 348 351 | 
             
                MaybeLocal<Value> maybe_value;
         | 
| 349 352 | 
             
                if (!result->parsed) {
         | 
| 350 | 
            -
             | 
| 351 | 
            -
             | 
| 353 | 
            +
                    result->message = new Persistent<Value>();
         | 
| 354 | 
            +
                    result->message->Reset(isolate, trycatch.Exception());
         | 
| 352 355 | 
             
                } else {
         | 
| 353 356 | 
             
                    // parsing successful
         | 
| 354 357 | 
             
                    if (eval_params->max_memory > 0) {
         | 
| @@ -374,41 +377,41 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context, | |
| 374 377 | 
             
                HandleScope scope(isolate);
         | 
| 375 378 |  | 
| 376 379 | 
             
                if (value->IsNull() || value->IsUndefined()){
         | 
| 377 | 
            -
             | 
| 380 | 
            +
                    return Qnil;
         | 
| 378 381 | 
             
                }
         | 
| 379 382 |  | 
| 380 383 | 
             
                if (value->IsInt32()) {
         | 
| 381 | 
            -
             | 
| 384 | 
            +
                    return INT2FIX(value->Int32Value());
         | 
| 382 385 | 
             
                }
         | 
| 383 386 |  | 
| 384 387 | 
             
                if (value->IsNumber()) {
         | 
| 385 | 
            -
             | 
| 388 | 
            +
                    return rb_float_new(value->NumberValue());
         | 
| 386 389 | 
             
                }
         | 
| 387 390 |  | 
| 388 391 | 
             
                if (value->IsTrue()) {
         | 
| 389 | 
            -
             | 
| 392 | 
            +
                    return Qtrue;
         | 
| 390 393 | 
             
                }
         | 
| 391 394 |  | 
| 392 395 | 
             
                if (value->IsFalse()) {
         | 
| 393 | 
            -
             | 
| 396 | 
            +
                    return Qfalse;
         | 
| 394 397 | 
             
                }
         | 
| 395 398 |  | 
| 396 399 | 
             
                if (value->IsArray()) {
         | 
| 397 400 | 
             
                  VALUE rb_array = rb_ary_new();
         | 
| 398 401 | 
             
                  Local<Array> arr = Local<Array>::Cast(value);
         | 
| 399 402 | 
             
                  for(uint32_t i=0; i < arr->Length(); i++) {
         | 
| 400 | 
            -
             | 
| 401 | 
            -
             | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 404 | 
            -
             | 
| 403 | 
            +
                      Local<Value> element = arr->Get(i);
         | 
| 404 | 
            +
                      VALUE rb_elem = convert_v8_to_ruby(isolate, context, element);
         | 
| 405 | 
            +
                      if (rb_funcall(rb_elem, rb_intern("class"), 0) == rb_cFailedV8Conversion) {
         | 
| 406 | 
            +
                        return rb_elem;
         | 
| 407 | 
            +
                      }
         | 
| 405 408 | 
             
                      rb_ary_push(rb_array, rb_elem);
         | 
| 406 409 | 
             
                  }
         | 
| 407 410 | 
             
                  return rb_array;
         | 
| 408 411 | 
             
                }
         | 
| 409 412 |  | 
| 410 413 | 
             
                if (value->IsFunction()){
         | 
| 411 | 
            -
             | 
| 414 | 
            +
                    return rb_funcall(rb_cJavaScriptFunction, rb_intern("new"), 0);
         | 
| 412 415 | 
             
                }
         | 
| 413 416 |  | 
| 414 417 | 
             
                if (value->IsDate()){
         | 
| @@ -420,30 +423,30 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context, | |
| 420 423 | 
             
                }
         | 
| 421 424 |  | 
| 422 425 | 
             
                if (value->IsObject()) {
         | 
| 423 | 
            -
             | 
| 424 | 
            -
             | 
| 425 | 
            -
             | 
| 426 | 
            -
             | 
| 427 | 
            -
             | 
| 428 | 
            -
             | 
| 429 | 
            -
             | 
| 430 | 
            -
             | 
| 431 | 
            -
             | 
| 432 | 
            -
             | 
| 433 | 
            -
             | 
| 434 | 
            -
             | 
| 435 | 
            -
             | 
| 436 | 
            -
             | 
| 437 | 
            -
             | 
| 438 | 
            -
             | 
| 439 | 
            -
             | 
| 440 | 
            -
             | 
| 441 | 
            -
             | 
| 442 | 
            -
             | 
| 443 | 
            -
             | 
| 444 | 
            -
             | 
| 445 | 
            -
             | 
| 446 | 
            -
             | 
| 426 | 
            +
                    VALUE rb_hash = rb_hash_new();
         | 
| 427 | 
            +
                    TryCatch trycatch(isolate);
         | 
| 428 | 
            +
             | 
| 429 | 
            +
                    Local<Object> object = value->ToObject();
         | 
| 430 | 
            +
                    auto maybe_props = object->GetOwnPropertyNames(context);
         | 
| 431 | 
            +
                    if (!maybe_props.IsEmpty()) {
         | 
| 432 | 
            +
                        Local<Array> props = maybe_props.ToLocalChecked();
         | 
| 433 | 
            +
                        for(uint32_t i=0; i < props->Length(); i++) {
         | 
| 434 | 
            +
                         Local<Value> key = props->Get(i);
         | 
| 435 | 
            +
                         VALUE rb_key = convert_v8_to_ruby(isolate, context, key);
         | 
| 436 | 
            +
                         Local<Value> prop_value = object->Get(key);
         | 
| 437 | 
            +
                         // this may have failed due to Get raising
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                         if (trycatch.HasCaught()) {
         | 
| 440 | 
            +
                         // TODO isolate code that translates execption to ruby
         | 
| 441 | 
            +
                         // exception so we can properly return it
         | 
| 442 | 
            +
                         return rb_funcall(rb_cFailedV8Conversion, rb_intern("new"), 1, rb_str_new2(""));
         | 
| 443 | 
            +
                         }
         | 
| 444 | 
            +
             | 
| 445 | 
            +
                         VALUE rb_value = convert_v8_to_ruby(isolate, context, prop_value);
         | 
| 446 | 
            +
                         rb_hash_aset(rb_hash, rb_key, rb_value);
         | 
| 447 | 
            +
                        }
         | 
| 448 | 
            +
                    }
         | 
| 449 | 
            +
                    return rb_hash;
         | 
| 447 450 | 
             
                }
         | 
| 448 451 |  | 
| 449 452 | 
             
                Local<String> rstr = value->ToString();
         | 
| @@ -468,7 +471,84 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, | |
| 468 471 | 
             
                                          Local<Value>::New(isolate, value));
         | 
| 469 472 | 
             
            }
         | 
| 470 473 |  | 
| 471 | 
            -
            static  | 
| 474 | 
            +
            static VALUE encode_as_utf8(VALUE string)
         | 
| 475 | 
            +
            {
         | 
| 476 | 
            +
                return rb_funcall(string, rb_intern("encode"), 1, rb_str_new2("UTF-8"));
         | 
| 477 | 
            +
            }
         | 
| 478 | 
            +
             | 
| 479 | 
            +
            #ifdef __AVX2__
         | 
| 480 | 
            +
            static bool (*best_utf8_validate_func(void))(const char *, size_t)
         | 
| 481 | 
            +
            {
         | 
| 482 | 
            +
                __builtin_cpu_init();
         | 
| 483 | 
            +
                if (__builtin_cpu_supports("avx2")) {
         | 
| 484 | 
            +
                    return validate_utf8_fast_avx;
         | 
| 485 | 
            +
                } else {
         | 
| 486 | 
            +
                    return validate_utf8_fast;
         | 
| 487 | 
            +
                }
         | 
| 488 | 
            +
            }
         | 
| 489 | 
            +
            #endif
         | 
| 490 | 
            +
             | 
| 491 | 
            +
            static inline Local<Value> convert_ruby_str_to_v8(
         | 
| 492 | 
            +
                    HandleScope& scope, Isolate *isolate, VALUE value)
         | 
| 493 | 
            +
            {
         | 
| 494 | 
            +
                static const rb_encoding *utf8_enc = rb_utf8_encoding();
         | 
| 495 | 
            +
                static const rb_encoding *ascii8bit_enc = rb_ascii8bit_encoding();
         | 
| 496 | 
            +
                static const rb_encoding *usascii_enc = rb_usascii_encoding();
         | 
| 497 | 
            +
                static const rb_encoding *latin1_enc = rb_enc_find("ISO-8859-1");
         | 
| 498 | 
            +
                assert(latin1_enc != nullptr);
         | 
| 499 | 
            +
            #ifndef __AVX2__
         | 
| 500 | 
            +
            # define validate_utf8 validate_utf8_fast
         | 
| 501 | 
            +
            #else
         | 
| 502 | 
            +
                static const (*validate_utf8)(const char *, size_t) =
         | 
| 503 | 
            +
                        best_utf8_validate_func();
         | 
| 504 | 
            +
            #endif
         | 
| 505 | 
            +
             | 
| 506 | 
            +
                rb_encoding *enc = rb_enc_get(value);
         | 
| 507 | 
            +
                char *str = RSTRING_PTR(value);
         | 
| 508 | 
            +
                long len = RSTRING_LEN(value);
         | 
| 509 | 
            +
                if (len < 0 || len > INT_MAX) {
         | 
| 510 | 
            +
                    return Null(isolate);
         | 
| 511 | 
            +
                }
         | 
| 512 | 
            +
                bool is_valid_utf8 = enc == utf8_enc &&
         | 
| 513 | 
            +
                        validate_utf8(str, static_cast<size_t>(len));
         | 
| 514 | 
            +
             | 
| 515 | 
            +
                MaybeLocal<String> v8str;
         | 
| 516 | 
            +
                int int_len = static_cast<int>(len);
         | 
| 517 | 
            +
                if (is_valid_utf8) {
         | 
| 518 | 
            +
            convert_from_utf8:
         | 
| 519 | 
            +
                    v8str = String::NewFromUtf8(
         | 
| 520 | 
            +
                                isolate, str, NewStringType::kNormal, int_len);
         | 
| 521 | 
            +
                } else if (enc == utf8_enc || enc == ascii8bit_enc ||
         | 
| 522 | 
            +
                           enc == usascii_enc || enc == latin1_enc ||
         | 
| 523 | 
            +
                           rb_funcall(value, rb_intern("valid_encoding?"), 0) == Qfalse) {
         | 
| 524 | 
            +
            treat_as_latin1:
         | 
| 525 | 
            +
                    // if ASCII, it could be that the string is invalid
         | 
| 526 | 
            +
                    // ignore that possibility (effectively treat it as latin1)
         | 
| 527 | 
            +
                    v8str = String::NewFromOneByte(
         | 
| 528 | 
            +
                                isolate, reinterpret_cast<uint8_t *>(str),
         | 
| 529 | 
            +
                                NewStringType::kNormal, int_len);
         | 
| 530 | 
            +
                } else {
         | 
| 531 | 
            +
                    int state;
         | 
| 532 | 
            +
                    VALUE result = rb_protect(encode_as_utf8, value, &state);
         | 
| 533 | 
            +
             | 
| 534 | 
            +
                    //Ran into an exception!
         | 
| 535 | 
            +
                    if (state) {
         | 
| 536 | 
            +
                        rb_set_errinfo(Qnil);
         | 
| 537 | 
            +
                        goto treat_as_latin1;
         | 
| 538 | 
            +
                    } else if (rb_enc_get(result) != utf8_enc) {
         | 
| 539 | 
            +
                        // conversion did not result in UTF-8. Odd!
         | 
| 540 | 
            +
                        goto treat_as_latin1;
         | 
| 541 | 
            +
                    } else {
         | 
| 542 | 
            +
                        str = RSTRING_PTR(result);
         | 
| 543 | 
            +
                        int_len = RSTRING_LEN(result);
         | 
| 544 | 
            +
                        goto convert_from_utf8;
         | 
| 545 | 
            +
                    }
         | 
| 546 | 
            +
                }
         | 
| 547 | 
            +
                return v8str.ToLocalChecked();
         | 
| 548 | 
            +
            }
         | 
| 549 | 
            +
             | 
| 550 | 
            +
            static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value)
         | 
| 551 | 
            +
            {
         | 
| 472 552 | 
             
                EscapableHandleScope scope(isolate);
         | 
| 473 553 |  | 
| 474 554 | 
             
                Local<Array> array;
         | 
| @@ -481,67 +561,85 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) { | |
| 481 561 | 
             
                VALUE klass;
         | 
| 482 562 |  | 
| 483 563 | 
             
                switch (TYPE(value)) {
         | 
| 484 | 
            -
             | 
| 485 | 
            -
                     | 
| 486 | 
            -
             | 
| 564 | 
            +
                    case T_FIXNUM:
         | 
| 565 | 
            +
                    {
         | 
| 566 | 
            +
                        fixnum = NUM2LONG(value);
         | 
| 567 | 
            +
                        if (fixnum > INT_MAX)
         | 
| 568 | 
            +
                        {
         | 
| 569 | 
            +
                            return scope.Escape(Number::New(isolate, (double)fixnum));
         | 
| 570 | 
            +
                        }
         | 
| 571 | 
            +
                        return scope.Escape(Integer::New(isolate, (int)fixnum));
         | 
| 572 | 
            +
                    }
         | 
| 573 | 
            +
                    case T_FLOAT:
         | 
| 574 | 
            +
                        return scope.Escape(Number::New(isolate, NUM2DBL(value)));
         | 
| 575 | 
            +
                    case T_STRING:
         | 
| 576 | 
            +
                        return scope.Escape(convert_ruby_str_to_v8(scope, isolate, value));
         | 
| 577 | 
            +
                    case T_NIL:
         | 
| 578 | 
            +
                        return scope.Escape(Null(isolate));
         | 
| 579 | 
            +
                    case T_TRUE:
         | 
| 580 | 
            +
                        return scope.Escape(True(isolate));
         | 
| 581 | 
            +
                    case T_FALSE:
         | 
| 582 | 
            +
                        return scope.Escape(False(isolate));
         | 
| 583 | 
            +
                    case T_ARRAY:
         | 
| 487 584 | 
             
                    {
         | 
| 488 | 
            -
                         | 
| 585 | 
            +
                        length = RARRAY_LEN(value);
         | 
| 586 | 
            +
                        array = Array::New(isolate, (int)length);
         | 
| 587 | 
            +
                        for(i=0; i<length; i++) {
         | 
| 588 | 
            +
                            array->Set(i, convert_ruby_to_v8(isolate, rb_ary_entry(value, i)));
         | 
| 589 | 
            +
                        }
         | 
| 590 | 
            +
                        return scope.Escape(array);
         | 
| 591 | 
            +
                    }
         | 
| 592 | 
            +
                    case T_HASH:
         | 
| 593 | 
            +
                    {
         | 
| 594 | 
            +
                        object = Object::New(isolate);
         | 
| 595 | 
            +
                        hash_as_array = rb_funcall(value, rb_intern("to_a"), 0);
         | 
| 596 | 
            +
                        length = RARRAY_LEN(hash_as_array);
         | 
| 597 | 
            +
                        for(i=0; i<length; i++) {
         | 
| 598 | 
            +
                            pair = rb_ary_entry(hash_as_array, i);
         | 
| 599 | 
            +
                            object->Set(convert_ruby_to_v8(isolate, rb_ary_entry(pair, 0)),
         | 
| 600 | 
            +
                                        convert_ruby_to_v8(isolate, rb_ary_entry(pair, 1)));
         | 
| 601 | 
            +
                        }
         | 
| 602 | 
            +
                        return scope.Escape(object);
         | 
| 603 | 
            +
                    }
         | 
| 604 | 
            +
                    case T_SYMBOL:
         | 
| 605 | 
            +
                    {
         | 
| 606 | 
            +
                        value = rb_funcall(value, rb_intern("to_s"), 0);
         | 
| 607 | 
            +
                        return scope.Escape(convert_ruby_str_to_v8(scope, isolate, value));
         | 
| 489 608 | 
             
                    }
         | 
| 490 | 
            -
                     | 
| 491 | 
            -
                case T_FLOAT:
         | 
| 492 | 
            -
            	return scope.Escape(Number::New(isolate, NUM2DBL(value)));
         | 
| 493 | 
            -
                case T_STRING:
         | 
| 494 | 
            -
            	return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
         | 
| 495 | 
            -
                case T_NIL:
         | 
| 496 | 
            -
            	return scope.Escape(Null(isolate));
         | 
| 497 | 
            -
                case T_TRUE:
         | 
| 498 | 
            -
            	return scope.Escape(True(isolate));
         | 
| 499 | 
            -
                case T_FALSE:
         | 
| 500 | 
            -
            	return scope.Escape(False(isolate));
         | 
| 501 | 
            -
                case T_ARRAY:
         | 
| 502 | 
            -
            	length = RARRAY_LEN(value);
         | 
| 503 | 
            -
            	array = Array::New(isolate, (int)length);
         | 
| 504 | 
            -
            	for(i=0; i<length; i++) {
         | 
| 505 | 
            -
            	    array->Set(i, convert_ruby_to_v8(isolate, rb_ary_entry(value, i)));
         | 
| 506 | 
            -
            	}
         | 
| 507 | 
            -
            	return scope.Escape(array);
         | 
| 508 | 
            -
                case T_HASH:
         | 
| 509 | 
            -
            	object = Object::New(isolate);
         | 
| 510 | 
            -
            	hash_as_array = rb_funcall(value, rb_intern("to_a"), 0);
         | 
| 511 | 
            -
            	length = RARRAY_LEN(hash_as_array);
         | 
| 512 | 
            -
            	for(i=0; i<length; i++) {
         | 
| 513 | 
            -
            	    pair = rb_ary_entry(hash_as_array, i);
         | 
| 514 | 
            -
            	    object->Set(convert_ruby_to_v8(isolate, rb_ary_entry(pair, 0)),
         | 
| 515 | 
            -
            			convert_ruby_to_v8(isolate, rb_ary_entry(pair, 1)));
         | 
| 516 | 
            -
            	}
         | 
| 517 | 
            -
            	return scope.Escape(object);
         | 
| 518 | 
            -
                case T_SYMBOL:
         | 
| 519 | 
            -
            	value = rb_funcall(value, rb_intern("to_s"), 0);
         | 
| 520 | 
            -
            	return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
         | 
| 521 | 
            -
                case T_DATA:
         | 
| 522 | 
            -
                    klass = rb_funcall(value, rb_intern("class"), 0);
         | 
| 523 | 
            -
                    if (klass == rb_cTime || klass == rb_cDateTime)
         | 
| 609 | 
            +
                    case T_DATA:
         | 
| 524 610 | 
             
                    {
         | 
| 525 | 
            -
                         | 
| 611 | 
            +
                        klass = rb_funcall(value, rb_intern("class"), 0);
         | 
| 612 | 
            +
                        if (klass == rb_cTime || klass == rb_cDateTime)
         | 
| 526 613 | 
             
                        {
         | 
| 527 | 
            -
                             | 
| 614 | 
            +
                            if (klass == rb_cDateTime)
         | 
| 615 | 
            +
                            {
         | 
| 616 | 
            +
                                value = rb_funcall(value, rb_intern("to_time"), 0);
         | 
| 617 | 
            +
                            }
         | 
| 618 | 
            +
                            value = rb_funcall(value, rb_intern("to_f"), 0);
         | 
| 619 | 
            +
                            return scope.Escape(Date::New(isolate, NUM2DBL(value) * 1000));
         | 
| 620 | 
            +
                        }
         | 
| 621 | 
            +
                        // break intentionally missing
         | 
| 622 | 
            +
                    }
         | 
| 623 | 
            +
                    case T_OBJECT:
         | 
| 624 | 
            +
                    case T_CLASS:
         | 
| 625 | 
            +
                    case T_ICLASS:
         | 
| 626 | 
            +
                    case T_MODULE:
         | 
| 627 | 
            +
                    case T_REGEXP:
         | 
| 628 | 
            +
                    case T_MATCH:
         | 
| 629 | 
            +
                    case T_STRUCT:
         | 
| 630 | 
            +
                    case T_BIGNUM:
         | 
| 631 | 
            +
                    case T_FILE:
         | 
| 632 | 
            +
                    case T_UNDEF:
         | 
| 633 | 
            +
                    case T_NODE:
         | 
| 634 | 
            +
                    default:
         | 
| 635 | 
            +
                    {
         | 
| 636 | 
            +
                        if (rb_respond_to(value, rb_intern("to_s"))) {
         | 
| 637 | 
            +
                            // TODO: if this throws we're screwed
         | 
| 638 | 
            +
                            value = rb_funcall(value, rb_intern("to_s"), 0);
         | 
| 639 | 
            +
                            return scope.Escape(convert_ruby_str_to_v8(scope, isolate, value));
         | 
| 528 640 | 
             
                        }
         | 
| 529 | 
            -
                         | 
| 530 | 
            -
                        return scope.Escape(Date::New(isolate, NUM2DBL(value) * 1000));
         | 
| 641 | 
            +
                        return scope.Escape(String::NewFromUtf8(isolate, "Undefined Conversion"));
         | 
| 531 642 | 
             
                    }
         | 
| 532 | 
            -
                case T_OBJECT:
         | 
| 533 | 
            -
                case T_CLASS:
         | 
| 534 | 
            -
                case T_ICLASS:
         | 
| 535 | 
            -
                case T_MODULE:
         | 
| 536 | 
            -
                case T_REGEXP:
         | 
| 537 | 
            -
                case T_MATCH:
         | 
| 538 | 
            -
                case T_STRUCT:
         | 
| 539 | 
            -
                case T_BIGNUM:
         | 
| 540 | 
            -
                case T_FILE:
         | 
| 541 | 
            -
                case T_UNDEF:
         | 
| 542 | 
            -
                case T_NODE:
         | 
| 543 | 
            -
                default:
         | 
| 544 | 
            -
                  return scope.Escape(String::NewFromUtf8(isolate, "Undefined Conversion"));
         | 
| 545 643 | 
             
                }
         | 
| 546 644 |  | 
| 547 645 | 
             
            }
         | 
| @@ -690,13 +788,13 @@ static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) { | |
| 690 788 | 
             
                    // the ruby lock is needed if this isn't a new isolate
         | 
| 691 789 | 
             
                    IsolateInfo::Lock ruby_lock(isolate_info->mutex);
         | 
| 692 790 | 
             
                    Locker lock(isolate_info->isolate);
         | 
| 693 | 
            -
             | 
| 694 | 
            -
             | 
| 791 | 
            +
                    Isolate::Scope isolate_scope(isolate_info->isolate);
         | 
| 792 | 
            +
                    HandleScope handle_scope(isolate_info->isolate);
         | 
| 695 793 |  | 
| 696 | 
            -
             | 
| 794 | 
            +
                    Local<Context> context = Context::New(isolate_info->isolate);
         | 
| 697 795 |  | 
| 698 | 
            -
             | 
| 699 | 
            -
             | 
| 796 | 
            +
                    context_info->context = new Persistent<Context>();
         | 
| 797 | 
            +
                    context_info->context->Reset(isolate_info->isolate, context);
         | 
| 700 798 | 
             
                }
         | 
| 701 799 |  | 
| 702 800 | 
             
                if (Qnil == rb_cDateTime && rb_funcall(rb_cObject, rb_intern("const_defined?"), 1, rb_str_new2("DateTime")) == Qtrue)
         | 
| @@ -818,45 +916,45 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) { | |
| 818 916 | 
             
                }
         | 
| 819 917 |  | 
| 820 918 | 
             
                {
         | 
| 821 | 
            -
             | 
| 822 | 
            -
             | 
| 823 | 
            -
             | 
| 824 | 
            -
             | 
| 825 | 
            -
             | 
| 826 | 
            -
             | 
| 827 | 
            -
             | 
| 828 | 
            -
             | 
| 829 | 
            -
             | 
| 830 | 
            -
             | 
| 831 | 
            -
             | 
| 832 | 
            -
             | 
| 833 | 
            -
             | 
| 834 | 
            -
             | 
| 835 | 
            -
             | 
| 836 | 
            -
             | 
| 837 | 
            -
             | 
| 838 | 
            -
             | 
| 839 | 
            -
             | 
| 840 | 
            -
             | 
| 841 | 
            -
             | 
| 842 | 
            -
             | 
| 843 | 
            -
             | 
| 844 | 
            -
             | 
| 845 | 
            -
             | 
| 846 | 
            -
             | 
| 847 | 
            -
             | 
| 848 | 
            -
             | 
| 849 | 
            -
             | 
| 850 | 
            -
             | 
| 851 | 
            -
             | 
| 852 | 
            -
             | 
| 853 | 
            -
             | 
| 854 | 
            -
             | 
| 919 | 
            +
                    Locker lock(isolate);
         | 
| 920 | 
            +
                    Isolate::Scope isolate_scope(isolate);
         | 
| 921 | 
            +
                    HandleScope handle_scope(isolate);
         | 
| 922 | 
            +
             | 
| 923 | 
            +
                    Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(str),
         | 
| 924 | 
            +
                                NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
         | 
| 925 | 
            +
             | 
| 926 | 
            +
                    Local<String> local_filename;
         | 
| 927 | 
            +
             | 
| 928 | 
            +
                    if (filename != Qnil) {
         | 
| 929 | 
            +
                        local_filename = String::NewFromUtf8(isolate, RSTRING_PTR(filename),
         | 
| 930 | 
            +
                            NewStringType::kNormal, (int)RSTRING_LEN(filename)).ToLocalChecked();
         | 
| 931 | 
            +
                        eval_params.filename = &local_filename;
         | 
| 932 | 
            +
                    } else {
         | 
| 933 | 
            +
                        eval_params.filename = NULL;
         | 
| 934 | 
            +
                    }
         | 
| 935 | 
            +
             | 
| 936 | 
            +
                    eval_params.context_info = context_info;
         | 
| 937 | 
            +
                    eval_params.eval = &eval;
         | 
| 938 | 
            +
                    eval_params.result = &eval_result;
         | 
| 939 | 
            +
                    eval_params.timeout = 0;
         | 
| 940 | 
            +
                    eval_params.max_memory = 0;
         | 
| 941 | 
            +
                    VALUE timeout = rb_iv_get(self, "@timeout");
         | 
| 942 | 
            +
                    if (timeout != Qnil) {
         | 
| 943 | 
            +
                        eval_params.timeout = (useconds_t)NUM2LONG(timeout);
         | 
| 944 | 
            +
                    }
         | 
| 945 | 
            +
             | 
| 946 | 
            +
                    VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
         | 
| 947 | 
            +
                    if (mem_softlimit != Qnil) {
         | 
| 948 | 
            +
                        eval_params.max_memory = (size_t)NUM2ULONG(mem_softlimit);
         | 
| 949 | 
            +
                    }
         | 
| 950 | 
            +
             | 
| 951 | 
            +
                    eval_result.message = NULL;
         | 
| 952 | 
            +
                    eval_result.backtrace = NULL;
         | 
| 855 953 |  | 
| 856 954 | 
             
            #if RUBY_API_VERSION_MAJOR > 1
         | 
| 857 | 
            -
             | 
| 955 | 
            +
                    rb_thread_call_without_gvl(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
         | 
| 858 956 | 
             
            #else
         | 
| 859 | 
            -
             | 
| 957 | 
            +
                    rb_thread_blocking_region(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
         | 
| 860 958 | 
             
            #endif
         | 
| 861 959 | 
             
                }
         | 
| 862 960 |  | 
| @@ -870,17 +968,16 @@ typedef struct { | |
| 870 968 | 
             
                bool failed;
         | 
| 871 969 | 
             
            } protected_callback_data;
         | 
| 872 970 |  | 
| 873 | 
            -
            static
         | 
| 874 | 
            -
            VALUE protected_callback(VALUE rdata) {
         | 
| 971 | 
            +
            static VALUE protected_callback(VALUE rdata) {
         | 
| 875 972 | 
             
                protected_callback_data* data = (protected_callback_data*)rdata;
         | 
| 876 973 | 
             
                VALUE result;
         | 
| 877 974 |  | 
| 878 975 | 
             
                if (data->length > 0) {
         | 
| 879 | 
            -
             | 
| 880 | 
            -
             | 
| 881 | 
            -
             | 
| 976 | 
            +
                    result = rb_funcall2(data->callback, rb_intern("call"), data->length,
         | 
| 977 | 
            +
                                 RARRAY_PTR(data->ruby_args));
         | 
| 978 | 
            +
                    RB_GC_GUARD(data->ruby_args);
         | 
| 882 979 | 
             
                } else {
         | 
| 883 | 
            -
             | 
| 980 | 
            +
                    result = rb_funcall(data->callback, rb_intern("call"), 0);
         | 
| 884 981 | 
             
                }
         | 
| 885 982 | 
             
                return result;
         | 
| 886 983 | 
             
            }
         | 
| @@ -917,16 +1014,16 @@ gvl_ruby_callback(void* data) { | |
| 917 1014 | 
             
                    ContextInfo* context_info;
         | 
| 918 1015 | 
             
                    Data_Get_Struct(parent, ContextInfo, context_info);
         | 
| 919 1016 |  | 
| 920 | 
            -
             | 
| 921 | 
            -
             | 
| 922 | 
            -
             | 
| 1017 | 
            +
                    if (length > 0) {
         | 
| 1018 | 
            +
                        ruby_args = rb_ary_tmp_new(length);
         | 
| 1019 | 
            +
                    }
         | 
| 923 1020 |  | 
| 924 | 
            -
             | 
| 925 | 
            -
             | 
| 926 | 
            -
             | 
| 927 | 
            -
             | 
| 928 | 
            -
             | 
| 929 | 
            -
             | 
| 1021 | 
            +
                    for (int i = 0; i < length; i++) {
         | 
| 1022 | 
            +
                        Local<Value> value = ((*args)[i]).As<Value>();
         | 
| 1023 | 
            +
                        VALUE tmp = convert_v8_to_ruby(args->GetIsolate(),
         | 
| 1024 | 
            +
                                          *context_info->context, value);
         | 
| 1025 | 
            +
                        rb_ary_push(ruby_args, tmp);
         | 
| 1026 | 
            +
                    }
         | 
| 930 1027 | 
             
                }
         | 
| 931 1028 |  | 
| 932 1029 | 
             
                // may raise exception stay clear of handle scope
         | 
| @@ -937,31 +1034,31 @@ gvl_ruby_callback(void* data) { | |
| 937 1034 | 
             
                callback_data.failed = false;
         | 
| 938 1035 |  | 
| 939 1036 | 
             
                if ((bool)args->GetIsolate()->GetData(DO_TERMINATE) == true) {
         | 
| 940 | 
            -
             | 
| 941 | 
            -
             | 
| 942 | 
            -
             | 
| 943 | 
            -
             | 
| 944 | 
            -
             | 
| 945 | 
            -
             | 
| 946 | 
            -
             | 
| 1037 | 
            +
                    args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Terminated execution during transition from Ruby to JS"));
         | 
| 1038 | 
            +
                    args->GetIsolate()->TerminateExecution();
         | 
| 1039 | 
            +
                    if (length > 0) {
         | 
| 1040 | 
            +
                        rb_ary_clear(ruby_args);
         | 
| 1041 | 
            +
                        rb_gc_force_recycle(ruby_args);
         | 
| 1042 | 
            +
                    }
         | 
| 1043 | 
            +
                    return NULL;
         | 
| 947 1044 | 
             
                }
         | 
| 948 1045 |  | 
| 949 1046 | 
             
                result = rb_rescue2((VALUE(*)(...))&protected_callback, (VALUE)(&callback_data),
         | 
| 950 | 
            -
             | 
| 1047 | 
            +
                        (VALUE(*)(...))&rescue_callback, (VALUE)(&callback_data), rb_eException, (VALUE)0);
         | 
| 951 1048 |  | 
| 952 1049 | 
             
                if(callback_data.failed) {
         | 
| 953 | 
            -
             | 
| 954 | 
            -
             | 
| 1050 | 
            +
                    rb_iv_set(parent, "@current_exception", result);
         | 
| 1051 | 
            +
                    args->GetIsolate()->ThrowException(String::NewFromUtf8(args->GetIsolate(), "Ruby exception"));
         | 
| 955 1052 | 
             
                }
         | 
| 956 1053 | 
             
                else {
         | 
| 957 | 
            -
             | 
| 958 | 
            -
             | 
| 959 | 
            -
             | 
| 1054 | 
            +
                    HandleScope scope(args->GetIsolate());
         | 
| 1055 | 
            +
                    Handle<Value> v8_result = convert_ruby_to_v8(args->GetIsolate(), result);
         | 
| 1056 | 
            +
                    args->GetReturnValue().Set(v8_result);
         | 
| 960 1057 | 
             
                }
         | 
| 961 1058 |  | 
| 962 1059 | 
             
                if (length > 0) {
         | 
| 963 | 
            -
             | 
| 964 | 
            -
             | 
| 1060 | 
            +
                    rb_ary_clear(ruby_args);
         | 
| 1061 | 
            +
                    rb_gc_force_recycle(ruby_args);
         | 
| 965 1062 | 
             
                }
         | 
| 966 1063 |  | 
| 967 1064 | 
             
                if ((bool)args->GetIsolate()->GetData(DO_TERMINATE) == true) {
         | 
| @@ -980,11 +1077,11 @@ static void ruby_callback(const FunctionCallbackInfo<Value>& args) { | |
| 980 1077 | 
             
                bool has_gvl = (bool)args.GetIsolate()->GetData(IN_GVL);
         | 
| 981 1078 |  | 
| 982 1079 | 
             
                if(has_gvl) {
         | 
| 983 | 
            -
             | 
| 1080 | 
            +
                    gvl_ruby_callback((void*)&args);
         | 
| 984 1081 | 
             
                } else {
         | 
| 985 | 
            -
             | 
| 986 | 
            -
             | 
| 987 | 
            -
             | 
| 1082 | 
            +
                    args.GetIsolate()->SetData(IN_GVL, (void*)true);
         | 
| 1083 | 
            +
                    rb_thread_call_with_gvl(gvl_ruby_callback, (void*)(&args));
         | 
| 1084 | 
            +
                    args.GetIsolate()->SetData(IN_GVL, (void*)false);
         | 
| 988 1085 | 
             
                }
         | 
| 989 1086 | 
             
            }
         | 
| 990 1087 |  | 
| @@ -1005,46 +1102,46 @@ static VALUE rb_external_function_notify_v8(VALUE self) { | |
| 1005 1102 | 
             
                Isolate* isolate = context_info->isolate_info->isolate;
         | 
| 1006 1103 |  | 
| 1007 1104 | 
             
                {
         | 
| 1008 | 
            -
             | 
| 1009 | 
            -
             | 
| 1010 | 
            -
             | 
| 1011 | 
            -
             | 
| 1012 | 
            -
            	Local<Context> context = context_info->context->Get(isolate);
         | 
| 1013 | 
            -
            	Context::Scope context_scope(context);
         | 
| 1105 | 
            +
                    Locker lock(isolate);
         | 
| 1106 | 
            +
                    Isolate::Scope isolate_scope(isolate);
         | 
| 1107 | 
            +
                    HandleScope handle_scope(isolate);
         | 
| 1014 1108 |  | 
| 1015 | 
            -
             | 
| 1016 | 
            -
             | 
| 1109 | 
            +
                    Local<Context> context = context_info->context->Get(isolate);
         | 
| 1110 | 
            +
                    Context::Scope context_scope(context);
         | 
| 1017 1111 |  | 
| 1018 | 
            -
             | 
| 1019 | 
            -
             | 
| 1020 | 
            -
            	Data_Get_Struct(self, VALUE, self_copy);
         | 
| 1021 | 
            -
            	*self_copy = self;
         | 
| 1112 | 
            +
                    Local<String> v8_str = String::NewFromUtf8(isolate, RSTRING_PTR(name),
         | 
| 1113 | 
            +
                                          NewStringType::kNormal, (int)RSTRING_LEN(name)).ToLocalChecked();
         | 
| 1022 1114 |  | 
| 1023 | 
            -
             | 
| 1115 | 
            +
                    // copy self so we can access from v8 external
         | 
| 1116 | 
            +
                    VALUE* self_copy;
         | 
| 1117 | 
            +
                    Data_Get_Struct(self, VALUE, self_copy);
         | 
| 1118 | 
            +
                    *self_copy = self;
         | 
| 1024 1119 |  | 
| 1025 | 
            -
             | 
| 1026 | 
            -
            	    context->Global()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
         | 
| 1027 | 
            -
            	} else {
         | 
| 1120 | 
            +
                    Local<Value> external = External::New(isolate, self_copy);
         | 
| 1028 1121 |  | 
| 1029 | 
            -
             | 
| 1030 | 
            -
             | 
| 1122 | 
            +
                    if (parent_object == Qnil) {
         | 
| 1123 | 
            +
                        context->Global()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
         | 
| 1124 | 
            +
                    } else {
         | 
| 1031 1125 |  | 
| 1032 | 
            -
             | 
| 1033 | 
            -
             | 
| 1034 | 
            -
            		parse_error = true;
         | 
| 1035 | 
            -
            	    } else {
         | 
| 1036 | 
            -
            		MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
         | 
| 1037 | 
            -
            		attach_error = true;
         | 
| 1126 | 
            +
                        Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
         | 
| 1127 | 
            +
                                              NewStringType::kNormal, (int)RSTRING_LEN(parent_object_eval)).ToLocalChecked();
         | 
| 1038 1128 |  | 
| 1039 | 
            -
             | 
| 1040 | 
            -
             | 
| 1041 | 
            -
             | 
| 1042 | 
            -
             | 
| 1043 | 
            -
             | 
| 1044 | 
            -
             | 
| 1045 | 
            -
             | 
| 1046 | 
            -
             | 
| 1047 | 
            -
             | 
| 1129 | 
            +
                        MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
         | 
| 1130 | 
            +
                        if (parsed_script.IsEmpty()) {
         | 
| 1131 | 
            +
                        parse_error = true;
         | 
| 1132 | 
            +
                        } else {
         | 
| 1133 | 
            +
                            MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
         | 
| 1134 | 
            +
                            attach_error = true;
         | 
| 1135 | 
            +
             | 
| 1136 | 
            +
                            if (!maybe_value.IsEmpty()) {
         | 
| 1137 | 
            +
                                Local<Value> value = maybe_value.ToLocalChecked();
         | 
| 1138 | 
            +
                                if (value->IsObject()){
         | 
| 1139 | 
            +
                                value.As<Object>()->Set(v8_str, FunctionTemplate::New(isolate, ruby_callback, external)->GetFunction());
         | 
| 1140 | 
            +
                                attach_error = false;
         | 
| 1141 | 
            +
                                }
         | 
| 1142 | 
            +
                            }
         | 
| 1143 | 
            +
                        }
         | 
| 1144 | 
            +
                    }
         | 
| 1048 1145 | 
             
                }
         | 
| 1049 1146 |  | 
| 1050 1147 | 
             
                // always raise out of V8 context
         | 
| @@ -1073,19 +1170,19 @@ static VALUE rb_context_isolate_mutex(VALUE self) { | |
| 1073 1170 | 
             
            void free_isolate(IsolateInfo* isolate_info) {
         | 
| 1074 1171 |  | 
| 1075 1172 | 
             
                if (isolate_info->isolate) {
         | 
| 1076 | 
            -
             | 
| 1173 | 
            +
                    Locker lock(isolate_info->isolate);
         | 
| 1077 1174 | 
             
                }
         | 
| 1078 1175 |  | 
| 1079 1176 | 
             
                if (isolate_info->isolate) {
         | 
| 1080 1177 | 
             
                    if (isolate_info->interrupted) {
         | 
| 1081 1178 | 
             
                        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");
         | 
| 1082 1179 | 
             
                    } else {
         | 
| 1083 | 
            -
             | 
| 1084 | 
            -
             | 
| 1085 | 
            -
             | 
| 1086 | 
            -
             | 
| 1087 | 
            -
             | 
| 1088 | 
            -
             | 
| 1180 | 
            +
                        
         | 
| 1181 | 
            +
                        if (isolate_info->pid != getpid()) {
         | 
| 1182 | 
            +
                            fprintf(stderr, "WARNING: V8 isolate was forked, it can not be disposed and memory will not be reclaimed till the Ruby process exits.\n");
         | 
| 1183 | 
            +
                        } else {
         | 
| 1184 | 
            +
                            isolate_info->isolate->Dispose();
         | 
| 1185 | 
            +
                        }
         | 
| 1089 1186 | 
             
                    }
         | 
| 1090 1187 | 
             
                    isolate_info->isolate = NULL;
         | 
| 1091 1188 | 
             
                }
         | 
| @@ -1128,17 +1225,17 @@ static void free_context(ContextInfo* context_info) { | |
| 1128 1225 | 
             
                context_info_copy->context = context_info->context;
         | 
| 1129 1226 |  | 
| 1130 1227 | 
             
                if (isolate_info && isolate_info->refs() > 1) {
         | 
| 1131 | 
            -
             | 
| 1132 | 
            -
             | 
| 1133 | 
            -
             | 
| 1134 | 
            -
             | 
| 1228 | 
            +
                pthread_t free_context_thread;
         | 
| 1229 | 
            +
                if (pthread_create(&free_context_thread, NULL, free_context_raw, (void*)context_info_copy)) {
         | 
| 1230 | 
            +
                    fprintf(stderr, "WARNING failed to release memory in MiniRacer, thread to release could not be created, process will leak memory\n");
         | 
| 1231 | 
            +
                }
         | 
| 1135 1232 |  | 
| 1136 1233 | 
             
                } else {
         | 
| 1137 | 
            -
             | 
| 1234 | 
            +
                    free_context_raw(context_info_copy);
         | 
| 1138 1235 | 
             
                }
         | 
| 1139 1236 |  | 
| 1140 1237 | 
             
                if (context_info->context && isolate_info && isolate_info->isolate) {
         | 
| 1141 | 
            -
             | 
| 1238 | 
            +
                    context_info->context = NULL;
         | 
| 1142 1239 | 
             
                }
         | 
| 1143 1240 |  | 
| 1144 1241 | 
             
                if (isolate_info) {
         | 
| @@ -1224,20 +1321,20 @@ rb_heap_stats(VALUE self) { | |
| 1224 1321 |  | 
| 1225 1322 | 
             
                if (!isolate) {
         | 
| 1226 1323 |  | 
| 1227 | 
            -
             | 
| 1228 | 
            -
             | 
| 1229 | 
            -
             | 
| 1230 | 
            -
             | 
| 1231 | 
            -
             | 
| 1324 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(0));
         | 
| 1325 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(0));
         | 
| 1326 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(0));
         | 
| 1327 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(0));
         | 
| 1328 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(0));
         | 
| 1232 1329 |  | 
| 1233 1330 | 
             
                } else {
         | 
| 1234 | 
            -
             | 
| 1331 | 
            +
                    isolate->GetHeapStatistics(&stats);
         | 
| 1235 1332 |  | 
| 1236 | 
            -
             | 
| 1237 | 
            -
             | 
| 1238 | 
            -
             | 
| 1239 | 
            -
             | 
| 1240 | 
            -
             | 
| 1333 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(stats.total_physical_size()));
         | 
| 1334 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(stats.total_heap_size_executable()));
         | 
| 1335 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(stats.total_heap_size()));
         | 
| 1336 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(stats.used_heap_size()));
         | 
| 1337 | 
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(stats.heap_size_limit()));
         | 
| 1241 1338 | 
             
                }
         | 
| 1242 1339 |  | 
| 1243 1340 | 
             
                return rval;
         | 
| @@ -1327,8 +1424,7 @@ static void unblock_function(void *args) { | |
| 1327 1424 | 
             
                call->context_info->isolate_info->interrupted = true;
         | 
| 1328 1425 | 
             
            }
         | 
| 1329 1426 |  | 
| 1330 | 
            -
            static VALUE
         | 
| 1331 | 
            -
            rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
         | 
| 1427 | 
            +
            static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
         | 
| 1332 1428 | 
             
                ContextInfo* context_info;
         | 
| 1333 1429 | 
             
                FunctionCall call;
         | 
| 1334 1430 | 
             
                VALUE *call_argv = NULL;
         | 
| @@ -1361,7 +1457,6 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { | |
| 1361 1457 | 
             
                }
         | 
| 1362 1458 |  | 
| 1363 1459 | 
             
                bool missingFunction = false;
         | 
| 1364 | 
            -
             | 
| 1365 1460 | 
             
                {
         | 
| 1366 1461 | 
             
                    Locker lock(isolate);
         | 
| 1367 1462 | 
             
                    Isolate::Scope isolate_scope(isolate);
         | 
| @@ -1372,38 +1467,38 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { | |
| 1372 1467 |  | 
| 1373 1468 | 
             
                    // examples of such usage can be found in
         | 
| 1374 1469 | 
             
                    // https://github.com/v8/v8/blob/36b32aa28db5e993312f4588d60aad5c8330c8a5/test/cctest/test-api.cc#L15711
         | 
| 1375 | 
            -
             | 
| 1376 | 
            -
             | 
| 1377 | 
            -
             | 
| 1378 | 
            -
             | 
| 1379 | 
            -
             | 
| 1380 | 
            -
             | 
| 1381 | 
            -
             | 
| 1382 | 
            -
             | 
| 1383 | 
            -
             | 
| 1384 | 
            -
             | 
| 1385 | 
            -
             | 
| 1386 | 
            -
            	    if (fun_argc > 0) {
         | 
| 1387 | 
            -
            		call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
         | 
| 1388 | 
            -
            		if (!call.argv) {
         | 
| 1389 | 
            -
            		    return Qnil;
         | 
| 1390 | 
            -
            		}
         | 
| 1391 | 
            -
            		for(int i=0; i < fun_argc; i++) {
         | 
| 1392 | 
            -
            		    call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
         | 
| 1393 | 
            -
            		}
         | 
| 1394 | 
            -
            	    }
         | 
| 1395 | 
            -
            #if RUBY_API_VERSION_MAJOR > 1
         | 
| 1396 | 
            -
            	    rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
         | 
| 1397 | 
            -
            #else
         | 
| 1398 | 
            -
            	    rb_thread_blocking_region(nogvl_context_call, &call, unblock_function, &call);
         | 
| 1399 | 
            -
            #endif
         | 
| 1400 | 
            -
            	    free(call.argv);
         | 
| 1470 | 
            +
                    Local<String> fname = String::NewFromUtf8(isolate, call.function_name);
         | 
| 1471 | 
            +
                    MaybeLocal<v8::Value> val = context->Global()->Get(fname);
         | 
| 1472 | 
            +
             | 
| 1473 | 
            +
                    if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) {
         | 
| 1474 | 
            +
                        missingFunction = true;
         | 
| 1475 | 
            +
                    } else {
         | 
| 1476 | 
            +
             | 
| 1477 | 
            +
                        Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
         | 
| 1478 | 
            +
                        call.fun = fun;
         | 
| 1479 | 
            +
                        int fun_argc = call.argc;
         | 
| 1401 1480 |  | 
| 1402 | 
            -
             | 
| 1481 | 
            +
                        if (fun_argc > 0) {
         | 
| 1482 | 
            +
                            call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
         | 
| 1483 | 
            +
                            if (!call.argv) {
         | 
| 1484 | 
            +
                                return Qnil;
         | 
| 1485 | 
            +
                            }
         | 
| 1486 | 
            +
                            for(int i=0; i < fun_argc; i++) {
         | 
| 1487 | 
            +
                                call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
         | 
| 1488 | 
            +
                            }
         | 
| 1489 | 
            +
                        }
         | 
| 1490 | 
            +
                #if RUBY_API_VERSION_MAJOR > 1
         | 
| 1491 | 
            +
                        rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
         | 
| 1492 | 
            +
                #else
         | 
| 1493 | 
            +
                        rb_thread_blocking_region(nogvl_context_call, &call, unblock_function, &call);
         | 
| 1494 | 
            +
                #endif
         | 
| 1495 | 
            +
                        free(call.argv);
         | 
| 1496 | 
            +
             | 
| 1497 | 
            +
                    }
         | 
| 1403 1498 | 
             
                }
         | 
| 1404 1499 |  | 
| 1405 1500 | 
             
                if (missingFunction) {
         | 
| 1406 | 
            -
             | 
| 1501 | 
            +
                rb_raise(rb_eScriptRuntimeError, "Unknown JavaScript method invoked");
         | 
| 1407 1502 | 
             
                }
         | 
| 1408 1503 |  | 
| 1409 1504 | 
             
                return convert_result_to_ruby(self, call.result);
         | 
| @@ -1428,53 +1523,52 @@ extern "C" { | |
| 1428 1523 | 
             
                {
         | 
| 1429 1524 | 
             
                    VALUE rb_mSqreen = rb_define_module("Sqreen");
         | 
| 1430 1525 | 
             
                    VALUE rb_mMiniRacer = rb_define_module_under(rb_mSqreen, "MiniRacer");
         | 
| 1431 | 
            -
             | 
| 1432 | 
            -
             | 
| 1433 | 
            -
             | 
| 1434 | 
            -
             | 
| 1435 | 
            -
             | 
| 1436 | 
            -
             | 
| 1437 | 
            -
             | 
| 1438 | 
            -
             | 
| 1439 | 
            -
             | 
| 1440 | 
            -
             | 
| 1441 | 
            -
             | 
| 1442 | 
            -
             | 
| 1443 | 
            -
             | 
| 1444 | 
            -
             | 
| 1445 | 
            -
             | 
| 1446 | 
            -
             | 
| 1447 | 
            -
             | 
| 1448 | 
            -
             | 
| 1449 | 
            -
             | 
| 1450 | 
            -
             | 
| 1451 | 
            -
             | 
| 1452 | 
            -
             | 
| 1453 | 
            -
             | 
| 1454 | 
            -
             | 
| 1455 | 
            -
             | 
| 1456 | 
            -
             | 
| 1457 | 
            -
             | 
| 1458 | 
            -
             | 
| 1459 | 
            -
             | 
| 1460 | 
            -
             | 
| 1461 | 
            -
             | 
| 1462 | 
            -
             | 
| 1463 | 
            -
             | 
| 1464 | 
            -
             | 
| 1465 | 
            -
             | 
| 1466 | 
            -
             | 
| 1467 | 
            -
             | 
| 1468 | 
            -
             | 
| 1469 | 
            -
             | 
| 1470 | 
            -
             | 
| 1471 | 
            -
             | 
| 1472 | 
            -
             | 
| 1473 | 
            -
             | 
| 1474 | 
            -
             | 
| 1475 | 
            -
             | 
| 1476 | 
            -
             | 
| 1477 | 
            -
             | 
| 1526 | 
            +
                    rb_cContext = rb_define_class_under(rb_mMiniRacer, "Context", rb_cObject);
         | 
| 1527 | 
            +
                    rb_cSnapshot = rb_define_class_under(rb_mMiniRacer, "Snapshot", rb_cObject);
         | 
| 1528 | 
            +
                    rb_cIsolate = rb_define_class_under(rb_mMiniRacer, "Isolate", rb_cObject);
         | 
| 1529 | 
            +
                    VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
         | 
| 1530 | 
            +
             | 
| 1531 | 
            +
                    VALUE rb_eError = rb_define_class_under(rb_mMiniRacer, "Error", rb_eStandardError);
         | 
| 1532 | 
            +
             | 
| 1533 | 
            +
                    VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
         | 
| 1534 | 
            +
                    rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
         | 
| 1535 | 
            +
                    rb_eV8OutOfMemoryError = rb_define_class_under(rb_mMiniRacer, "V8OutOfMemoryError", rb_eEvalError);
         | 
| 1536 | 
            +
                    rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
         | 
| 1537 | 
            +
                    rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
         | 
| 1538 | 
            +
             | 
| 1539 | 
            +
                    rb_cJavaScriptFunction = rb_define_class_under(rb_mMiniRacer, "JavaScriptFunction", rb_cObject);
         | 
| 1540 | 
            +
                    rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eError);
         | 
| 1541 | 
            +
                    rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eError);
         | 
| 1542 | 
            +
                    rb_cFailedV8Conversion = rb_define_class_under(rb_mMiniRacer, "FailedV8Conversion", rb_cObject);
         | 
| 1543 | 
            +
                    rb_mJSON = rb_define_module("JSON");
         | 
| 1544 | 
            +
             | 
| 1545 | 
            +
                    VALUE rb_cExternalFunction = rb_define_class_under(rb_cContext, "ExternalFunction", rb_cObject);
         | 
| 1546 | 
            +
             | 
| 1547 | 
            +
                    rb_define_method(rb_cContext, "stop", (VALUE(*)(...))&rb_context_stop, 0);
         | 
| 1548 | 
            +
                    rb_define_method(rb_cContext, "dispose_unsafe", (VALUE(*)(...))&rb_context_dispose, 0);
         | 
| 1549 | 
            +
                    rb_define_method(rb_cContext, "low_memory_notification", (VALUE(*)(...))&rb_context_low_memory_notification, 0);
         | 
| 1550 | 
            +
                    rb_define_method(rb_cContext, "heap_stats", (VALUE(*)(...))&rb_heap_stats, 0);
         | 
| 1551 | 
            +
                    rb_define_private_method(rb_cContext, "create_isolate_value",(VALUE(*)(...))&rb_context_create_isolate_value, 0);
         | 
| 1552 | 
            +
                    rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 2);
         | 
| 1553 | 
            +
                    rb_define_private_method(rb_cContext, "call_unsafe", (VALUE(*)(...))&rb_context_call_unsafe, -1);
         | 
| 1554 | 
            +
                    rb_define_private_method(rb_cContext, "isolate_mutex", (VALUE(*)(...))&rb_context_isolate_mutex, 0);
         | 
| 1555 | 
            +
                    rb_define_private_method(rb_cContext, "init_unsafe",(VALUE(*)(...))&rb_context_init_unsafe, 2);
         | 
| 1556 | 
            +
             | 
| 1557 | 
            +
                    rb_define_alloc_func(rb_cContext, allocate);
         | 
| 1558 | 
            +
                    rb_define_alloc_func(rb_cSnapshot, allocate_snapshot);
         | 
| 1559 | 
            +
                    rb_define_alloc_func(rb_cIsolate, allocate_isolate);
         | 
| 1560 | 
            +
             | 
| 1561 | 
            +
                    rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
         | 
| 1562 | 
            +
                    rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
         | 
| 1563 | 
            +
             | 
| 1564 | 
            +
                    rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
         | 
| 1565 | 
            +
                    rb_define_method(rb_cSnapshot, "dump", (VALUE(*)(...))&rb_snapshot_dump, 0);
         | 
| 1566 | 
            +
                    rb_define_method(rb_cSnapshot, "warmup_unsafe!", (VALUE(*)(...))&rb_snapshot_warmup_unsafe, 1);
         | 
| 1567 | 
            +
                    rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1);
         | 
| 1568 | 
            +
             | 
| 1569 | 
            +
                    rb_define_method(rb_cIsolate, "idle_notification", (VALUE(*)(...))&rb_isolate_idle_notification, 1);
         | 
| 1570 | 
            +
                    rb_define_private_method(rb_cIsolate, "init_with_snapshot",(VALUE(*)(...))&rb_isolate_init_with_snapshot, 1);
         | 
| 1571 | 
            +
             | 
| 1572 | 
            +
                    rb_define_singleton_method(rb_cPlatform, "set_flag_as_str!", (VALUE(*)(...))&rb_platform_set_flag_as_str, 1);
         | 
| 1478 1573 | 
             
                }
         | 
| 1479 | 
            -
             | 
| 1480 1574 | 
             
            }
         |