mini_racer 0.2.4 → 0.4.0
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/.dockerignore +12 -0
 - data/.github/workflows/ci.yml +80 -0
 - data/.gitignore +1 -0
 - data/.travis.yml +17 -9
 - data/CHANGELOG +98 -0
 - data/Dockerfile +21 -0
 - data/LICENSE.txt +1 -1
 - data/README.md +44 -4
 - data/Rakefile +42 -0
 - data/ext/mini_racer_extension/extconf.rb +16 -3
 - data/ext/mini_racer_extension/mini_racer_extension.cc +611 -318
 - data/ext/mini_racer_loader/extconf.rb +8 -0
 - data/ext/mini_racer_loader/mini_racer_loader.c +123 -0
 - data/lib/mini_racer/version.rb +4 -1
 - data/lib/mini_racer.rb +113 -16
 - data/mini_racer.gemspec +13 -6
 - metadata +43 -20
 
| 
         @@ -1,7 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include <stdio.h>
         
     | 
| 
       2 
2 
     | 
    
         
             
            #include <ruby.h>
         
     | 
| 
       3 
3 
     | 
    
         
             
            #include <ruby/thread.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #include <ruby/io.h>
         
     | 
| 
       4 
5 
     | 
    
         
             
            #include <v8.h>
         
     | 
| 
      
 6 
     | 
    
         
            +
            #include <v8-profiler.h>
         
     | 
| 
       5 
7 
     | 
    
         
             
            #include <libplatform/libplatform.h>
         
     | 
| 
       6 
8 
     | 
    
         
             
            #include <ruby/encoding.h>
         
     | 
| 
       7 
9 
     | 
    
         
             
            #include <pthread.h>
         
     | 
| 
         @@ -23,6 +25,7 @@ public: 
     | 
|
| 
       23 
25 
     | 
    
         
             
                ArrayBuffer::Allocator* allocator;
         
     | 
| 
       24 
26 
     | 
    
         
             
                StartupData* startup_data;
         
     | 
| 
       25 
27 
     | 
    
         
             
                bool interrupted;
         
     | 
| 
      
 28 
     | 
    
         
            +
                bool added_gc_cb;
         
     | 
| 
       26 
29 
     | 
    
         
             
                pid_t pid;
         
     | 
| 
       27 
30 
     | 
    
         
             
                VALUE mutex;
         
     | 
| 
       28 
31 
     | 
    
         | 
| 
         @@ -40,15 +43,12 @@ public: 
     | 
|
| 
       40 
43 
     | 
    
         | 
| 
       41 
44 
     | 
    
         | 
| 
       42 
45 
     | 
    
         
             
                IsolateInfo() : isolate(nullptr), allocator(nullptr), startup_data(nullptr),
         
     | 
| 
       43 
     | 
    
         
            -
                    interrupted(false), pid(getpid()), refs_count(0) {
         
     | 
| 
      
 46 
     | 
    
         
            +
                    interrupted(false), added_gc_cb(false), pid(getpid()), refs_count(0) {
         
     | 
| 
       44 
47 
     | 
    
         
             
                    VALUE cMutex = rb_const_get(rb_cThread, rb_intern("Mutex"));
         
     | 
| 
       45 
48 
     | 
    
         
             
                    mutex = rb_class_new_instance(0, nullptr, cMutex);
         
     | 
| 
       46 
49 
     | 
    
         
             
                }
         
     | 
| 
       47 
50 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                ~IsolateInfo() 
     | 
| 
       49 
     | 
    
         
            -
                    void free_isolate(IsolateInfo*);
         
     | 
| 
       50 
     | 
    
         
            -
                    free_isolate(this);
         
     | 
| 
       51 
     | 
    
         
            -
                }
         
     | 
| 
      
 51 
     | 
    
         
            +
                ~IsolateInfo();
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
53 
     | 
    
         
             
                void init(SnapshotInfo* snapshot_info = nullptr);
         
     | 
| 
       54 
54 
     | 
    
         | 
| 
         @@ -71,7 +71,7 @@ public: 
     | 
|
| 
       71 
71 
     | 
    
         
             
                }
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
73 
     | 
    
         
             
                int refs() {
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
      
 74 
     | 
    
         
            +
                    return refs_count;
         
     | 
| 
       75 
75 
     | 
    
         
             
                }
         
     | 
| 
       76 
76 
     | 
    
         | 
| 
       77 
77 
     | 
    
         
             
                static void* operator new(size_t size) {
         
     | 
| 
         @@ -125,6 +125,7 @@ typedef struct { 
     | 
|
| 
       125 
125 
     | 
    
         
             
                Local<Function> fun;
         
     | 
| 
       126 
126 
     | 
    
         
             
                Local<Value> *argv;
         
     | 
| 
       127 
127 
     | 
    
         
             
                EvalResult result;
         
     | 
| 
      
 128 
     | 
    
         
            +
                size_t max_memory;
         
     | 
| 
       128 
129 
     | 
    
         
             
            } FunctionCall;
         
     | 
| 
       129 
130 
     | 
    
         | 
| 
       130 
131 
     | 
    
         
             
            enum IsolateFlags {
         
     | 
| 
         @@ -150,9 +151,14 @@ static VALUE rb_mJSON; 
     | 
|
| 
       150 
151 
     | 
    
         
             
            static VALUE rb_cFailedV8Conversion;
         
     | 
| 
       151 
152 
     | 
    
         
             
            static VALUE rb_cDateTime = Qnil;
         
     | 
| 
       152 
153 
     | 
    
         | 
| 
       153 
     | 
    
         
            -
            static Platform 
     | 
| 
      
 154 
     | 
    
         
            +
            static std::unique_ptr<Platform> current_platform = NULL;
         
     | 
| 
       154 
155 
     | 
    
         
             
            static std::mutex platform_lock;
         
     | 
| 
       155 
156 
     | 
    
         | 
| 
      
 157 
     | 
    
         
            +
            static pthread_attr_t *thread_attr_p;
         
     | 
| 
      
 158 
     | 
    
         
            +
            static pthread_rwlock_t exit_lock = PTHREAD_RWLOCK_INITIALIZER;
         
     | 
| 
      
 159 
     | 
    
         
            +
            static bool ruby_exiting = false; // guarded by exit_lock
         
     | 
| 
      
 160 
     | 
    
         
            +
            static bool single_threaded = false;
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
       156 
162 
     | 
    
         
             
            static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
         
     | 
| 
       157 
163 
     | 
    
         
             
                bool platform_already_initialized = false;
         
     | 
| 
       158 
164 
     | 
    
         | 
| 
         @@ -164,6 +170,9 @@ static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) { 
     | 
|
| 
       164 
170 
     | 
    
         
             
                platform_lock.lock();
         
     | 
| 
       165 
171 
     | 
    
         | 
| 
       166 
172 
     | 
    
         
             
                if (current_platform == NULL) {
         
     | 
| 
      
 173 
     | 
    
         
            +
            	if (!strcmp(RSTRING_PTR(flag_as_str), "--single_threaded")) {
         
     | 
| 
      
 174 
     | 
    
         
            +
            	   single_threaded = true;
         
     | 
| 
      
 175 
     | 
    
         
            +
            	}
         
     | 
| 
       167 
176 
     | 
    
         
             
                    V8::SetFlagsFromString(RSTRING_PTR(flag_as_str), (int)RSTRING_LEN(flag_as_str));
         
     | 
| 
       168 
177 
     | 
    
         
             
                } else {
         
     | 
| 
       169 
178 
     | 
    
         
             
                    platform_already_initialized = true;
         
     | 
| 
         @@ -187,8 +196,8 @@ static void init_v8() { 
     | 
|
| 
       187 
196 
     | 
    
         | 
| 
       188 
197 
     | 
    
         
             
                if (current_platform == NULL) {
         
     | 
| 
       189 
198 
     | 
    
         
             
                    V8::InitializeICU();
         
     | 
| 
       190 
     | 
    
         
            -
                    current_platform = platform:: 
     | 
| 
       191 
     | 
    
         
            -
                    V8::InitializePlatform(current_platform);
         
     | 
| 
      
 199 
     | 
    
         
            +
                    current_platform = platform::NewDefaultPlatform();
         
     | 
| 
      
 200 
     | 
    
         
            +
                    V8::InitializePlatform(current_platform.get());
         
     | 
| 
       192 
201 
     | 
    
         
             
                    V8::Initialize();
         
     | 
| 
       193 
202 
     | 
    
         
             
                }
         
     | 
| 
       194 
203 
     | 
    
         | 
| 
         @@ -200,9 +209,9 @@ static void gc_callback(Isolate *isolate, GCType type, GCCallbackFlags flags) { 
     | 
|
| 
       200 
209 
     | 
    
         | 
| 
       201 
210 
     | 
    
         
             
                size_t softlimit = *(size_t*) isolate->GetData(MEM_SOFTLIMIT_VALUE);
         
     | 
| 
       202 
211 
     | 
    
         | 
| 
       203 
     | 
    
         
            -
                HeapStatistics 
     | 
| 
       204 
     | 
    
         
            -
                isolate->GetHeapStatistics(stats);
         
     | 
| 
       205 
     | 
    
         
            -
                size_t used = stats 
     | 
| 
      
 212 
     | 
    
         
            +
                HeapStatistics stats;
         
     | 
| 
      
 213 
     | 
    
         
            +
                isolate->GetHeapStatistics(&stats);
         
     | 
| 
      
 214 
     | 
    
         
            +
                size_t used = stats.used_heap_size();
         
     | 
| 
       206 
215 
     | 
    
         | 
| 
       207 
216 
     | 
    
         
             
                if(used > softlimit) {
         
     | 
| 
       208 
217 
     | 
    
         
             
                    isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)true);
         
     | 
| 
         @@ -231,15 +240,17 @@ static void prepare_result(MaybeLocal<Value> v8res, 
     | 
|
| 
       231 
240 
     | 
    
         
             
                    if ((local_value->IsObject() || local_value->IsArray()) &&
         
     | 
| 
       232 
241 
     | 
    
         
             
                            !local_value->IsDate() && !local_value->IsFunction()) {
         
     | 
| 
       233 
242 
     | 
    
         
             
                        Local<Object> JSON = context->Global()->Get(
         
     | 
| 
       234 
     | 
    
         
            -
                                    String:: 
     | 
| 
      
 243 
     | 
    
         
            +
                                    context, String::NewFromUtf8Literal(isolate, "JSON"))
         
     | 
| 
      
 244 
     | 
    
         
            +
                                .ToLocalChecked().As<Object>();
         
     | 
| 
       235 
245 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
                        Local<Function> stringify = JSON->Get( 
     | 
| 
       237 
     | 
    
         
            -
             
     | 
| 
      
 246 
     | 
    
         
            +
                        Local<Function> stringify = JSON->Get(
         
     | 
| 
      
 247 
     | 
    
         
            +
                                    context, v8::String::NewFromUtf8Literal(isolate, "stringify"))
         
     | 
| 
      
 248 
     | 
    
         
            +
                                .ToLocalChecked().As<Function>();
         
     | 
| 
       238 
249 
     | 
    
         | 
| 
       239 
     | 
    
         
            -
                        Local<Object> object = local_value->ToObject();
         
     | 
| 
      
 250 
     | 
    
         
            +
                        Local<Object> object = local_value->ToObject(context).ToLocalChecked();
         
     | 
| 
       240 
251 
     | 
    
         
             
                        const unsigned argc = 1;
         
     | 
| 
       241 
252 
     | 
    
         
             
                        Local<Value> argv[argc] = { object };
         
     | 
| 
       242 
     | 
    
         
            -
                        MaybeLocal<Value> json = stringify->Call(JSON, argc, argv);
         
     | 
| 
      
 253 
     | 
    
         
            +
                        MaybeLocal<Value> json = stringify->Call(context, JSON, argc, argv);
         
     | 
| 
       243 
254 
     | 
    
         | 
| 
       244 
255 
     | 
    
         
             
                        if (json.IsEmpty()) {
         
     | 
| 
       245 
256 
     | 
    
         
             
                            evalRes.executed = false;
         
     | 
| 
         @@ -263,11 +274,21 @@ static void prepare_result(MaybeLocal<Value> v8res, 
     | 
|
| 
       263 
274 
     | 
    
         
             
                            evalRes.message = new Persistent<Value>();
         
     | 
| 
       264 
275 
     | 
    
         
             
                            Local<Message> message = trycatch.Message();
         
     | 
| 
       265 
276 
     | 
    
         
             
                            char buf[1000];
         
     | 
| 
       266 
     | 
    
         
            -
                            int len;
         
     | 
| 
       267 
     | 
    
         
            -
             
     | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
      
 277 
     | 
    
         
            +
                            int len, line, column;
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
      
 279 
     | 
    
         
            +
                            if (!message->GetLineNumber(context).To(&line)) {
         
     | 
| 
      
 280 
     | 
    
         
            +
                              line = 0;
         
     | 
| 
      
 281 
     | 
    
         
            +
                            }
         
     | 
| 
      
 282 
     | 
    
         
            +
             
     | 
| 
      
 283 
     | 
    
         
            +
                            if (!message->GetStartColumn(context).To(&column)) {
         
     | 
| 
      
 284 
     | 
    
         
            +
                              column = 0;
         
     | 
| 
      
 285 
     | 
    
         
            +
                            }
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                            len = snprintf(buf, sizeof(buf), "%s at %s:%i:%i", *String::Utf8Value(isolate, message->Get()),
         
     | 
| 
      
 288 
     | 
    
         
            +
                                           *String::Utf8Value(isolate, message->GetScriptResourceName()->ToString(context).ToLocalChecked()),
         
     | 
| 
      
 289 
     | 
    
         
            +
                                           line,
         
     | 
| 
      
 290 
     | 
    
         
            +
                                           column);
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
       271 
292 
     | 
    
         
             
                            if ((size_t) len >= sizeof(buf)) {
         
     | 
| 
       272 
293 
     | 
    
         
             
                                len = sizeof(buf) - 1;
         
     | 
| 
       273 
294 
     | 
    
         
             
                                buf[len] = '\0';
         
     | 
| 
         @@ -278,12 +299,13 @@ static void prepare_result(MaybeLocal<Value> v8res, 
     | 
|
| 
       278 
299 
     | 
    
         
             
                        } else if(trycatch.HasTerminated()) {
         
     | 
| 
       279 
300 
     | 
    
         
             
                            evalRes.terminated = true;
         
     | 
| 
       280 
301 
     | 
    
         
             
                            evalRes.message = new Persistent<Value>();
         
     | 
| 
       281 
     | 
    
         
            -
                            Local<String> tmp = String:: 
     | 
| 
      
 302 
     | 
    
         
            +
                            Local<String> tmp = String::NewFromUtf8Literal(isolate, "JavaScript was terminated (either by timeout or explicitly)");
         
     | 
| 
       282 
303 
     | 
    
         
             
                            evalRes.message->Reset(isolate, tmp);
         
     | 
| 
       283 
304 
     | 
    
         
             
                        }
         
     | 
| 
       284 
     | 
    
         
            -
                        if (!trycatch.StackTrace().IsEmpty()) {
         
     | 
| 
      
 305 
     | 
    
         
            +
                        if (!trycatch.StackTrace(context).IsEmpty()) {
         
     | 
| 
       285 
306 
     | 
    
         
             
                            evalRes.backtrace = new Persistent<Value>();
         
     | 
| 
       286 
     | 
    
         
            -
                            evalRes.backtrace->Reset(isolate, 
     | 
| 
      
 307 
     | 
    
         
            +
                            evalRes.backtrace->Reset(isolate,
         
     | 
| 
      
 308 
     | 
    
         
            +
                                                     trycatch.StackTrace(context).ToLocalChecked()->ToString(context).ToLocalChecked());
         
     | 
| 
       287 
309 
     | 
    
         
             
                        }
         
     | 
| 
       288 
310 
     | 
    
         
             
                    }
         
     | 
| 
       289 
311 
     | 
    
         
             
                }
         
     | 
| 
         @@ -294,7 +316,8 @@ nogvl_context_eval(void* arg) { 
     | 
|
| 
       294 
316 
     | 
    
         | 
| 
       295 
317 
     | 
    
         
             
                EvalParams* eval_params = (EvalParams*)arg;
         
     | 
| 
       296 
318 
     | 
    
         
             
                EvalResult* result = eval_params->result;
         
     | 
| 
       297 
     | 
    
         
            -
                 
     | 
| 
      
 319 
     | 
    
         
            +
                IsolateInfo* isolate_info = eval_params->context_info->isolate_info;
         
     | 
| 
      
 320 
     | 
    
         
            +
                Isolate* isolate = isolate_info->isolate;
         
     | 
| 
       298 
321 
     | 
    
         | 
| 
       299 
322 
     | 
    
         
             
                Isolate::Scope isolate_scope(isolate);
         
     | 
| 
       300 
323 
     | 
    
         
             
                HandleScope handle_scope(isolate);
         
     | 
| 
         @@ -315,13 +338,13 @@ nogvl_context_eval(void* arg) { 
     | 
|
| 
       315 
338 
     | 
    
         
             
                MaybeLocal<Script> parsed_script;
         
     | 
| 
       316 
339 
     | 
    
         | 
| 
       317 
340 
     | 
    
         
             
                if (eval_params->filename) {
         
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
      
 341 
     | 
    
         
            +
                    origin = new v8::ScriptOrigin(*eval_params->filename);
         
     | 
| 
       319 
342 
     | 
    
         
             
                }
         
     | 
| 
       320 
343 
     | 
    
         | 
| 
       321 
344 
     | 
    
         
             
                parsed_script = Script::Compile(context, *eval_params->eval, origin);
         
     | 
| 
       322 
345 
     | 
    
         | 
| 
       323 
346 
     | 
    
         
             
                if (origin) {
         
     | 
| 
       324 
     | 
    
         
            -
             
     | 
| 
      
 347 
     | 
    
         
            +
                    delete origin;
         
     | 
| 
       325 
348 
     | 
    
         
             
                }
         
     | 
| 
       326 
349 
     | 
    
         | 
| 
       327 
350 
     | 
    
         
             
                result->parsed = !parsed_script.IsEmpty();
         
     | 
| 
         @@ -332,13 +355,16 @@ nogvl_context_eval(void* arg) { 
     | 
|
| 
       332 
355 
     | 
    
         | 
| 
       333 
356 
     | 
    
         
             
                MaybeLocal<Value> maybe_value;
         
     | 
| 
       334 
357 
     | 
    
         
             
                if (!result->parsed) {
         
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
       336 
     | 
    
         
            -
             
     | 
| 
      
 358 
     | 
    
         
            +
                    result->message = new Persistent<Value>();
         
     | 
| 
      
 359 
     | 
    
         
            +
                    result->message->Reset(isolate, trycatch.Exception());
         
     | 
| 
       337 
360 
     | 
    
         
             
                } else {
         
     | 
| 
       338 
361 
     | 
    
         
             
                    // parsing successful
         
     | 
| 
       339 
362 
     | 
    
         
             
                    if (eval_params->max_memory > 0) {
         
     | 
| 
       340 
363 
     | 
    
         
             
                        isolate->SetData(MEM_SOFTLIMIT_VALUE, &eval_params->max_memory);
         
     | 
| 
      
 364 
     | 
    
         
            +
                        if (!isolate_info->added_gc_cb) {
         
     | 
| 
       341 
365 
     | 
    
         
             
                        isolate->AddGCEpilogueCallback(gc_callback);
         
     | 
| 
      
 366 
     | 
    
         
            +
                            isolate_info->added_gc_cb = true;
         
     | 
| 
      
 367 
     | 
    
         
            +
                        }
         
     | 
| 
       342 
368 
     | 
    
         
             
                    }
         
     | 
| 
       343 
369 
     | 
    
         | 
| 
       344 
370 
     | 
    
         
             
                    maybe_value = parsed_script.ToLocalChecked()->Run(context);
         
     | 
| 
         @@ -351,6 +377,12 @@ nogvl_context_eval(void* arg) { 
     | 
|
| 
       351 
377 
     | 
    
         
             
                return NULL;
         
     | 
| 
       352 
378 
     | 
    
         
             
            }
         
     | 
| 
       353 
379 
     | 
    
         | 
| 
      
 380 
     | 
    
         
            +
            static VALUE new_empty_failed_conv_obj() {
         
     | 
| 
      
 381 
     | 
    
         
            +
                // TODO isolate code that translates execption to ruby
         
     | 
| 
      
 382 
     | 
    
         
            +
                // exception so we can properly return it
         
     | 
| 
      
 383 
     | 
    
         
            +
                return rb_funcall(rb_cFailedV8Conversion, rb_intern("new"), 1, rb_str_new2(""));
         
     | 
| 
      
 384 
     | 
    
         
            +
            }
         
     | 
| 
      
 385 
     | 
    
         
            +
             
     | 
| 
       354 
386 
     | 
    
         
             
            // assumes isolate locking is in place
         
     | 
| 
       355 
387 
     | 
    
         
             
            static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context,
         
     | 
| 
       356 
388 
     | 
    
         
             
                                            Local<Value> value) {
         
     | 
| 
         @@ -359,41 +391,44 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context, 
     | 
|
| 
       359 
391 
     | 
    
         
             
                HandleScope scope(isolate);
         
     | 
| 
       360 
392 
     | 
    
         | 
| 
       361 
393 
     | 
    
         
             
                if (value->IsNull() || value->IsUndefined()){
         
     | 
| 
       362 
     | 
    
         
            -
             
     | 
| 
      
 394 
     | 
    
         
            +
                    return Qnil;
         
     | 
| 
       363 
395 
     | 
    
         
             
                }
         
     | 
| 
       364 
396 
     | 
    
         | 
| 
       365 
397 
     | 
    
         
             
                if (value->IsInt32()) {
         
     | 
| 
       366 
     | 
    
         
            -
             
     | 
| 
      
 398 
     | 
    
         
            +
                    return INT2FIX(value->Int32Value(context).ToChecked());
         
     | 
| 
       367 
399 
     | 
    
         
             
                }
         
     | 
| 
       368 
400 
     | 
    
         | 
| 
       369 
401 
     | 
    
         
             
                if (value->IsNumber()) {
         
     | 
| 
       370 
     | 
    
         
            -
             
     | 
| 
      
 402 
     | 
    
         
            +
                    return rb_float_new(value->NumberValue(context).ToChecked());
         
     | 
| 
       371 
403 
     | 
    
         
             
                }
         
     | 
| 
       372 
404 
     | 
    
         | 
| 
       373 
405 
     | 
    
         
             
                if (value->IsTrue()) {
         
     | 
| 
       374 
     | 
    
         
            -
             
     | 
| 
      
 406 
     | 
    
         
            +
                    return Qtrue;
         
     | 
| 
       375 
407 
     | 
    
         
             
                }
         
     | 
| 
       376 
408 
     | 
    
         | 
| 
       377 
409 
     | 
    
         
             
                if (value->IsFalse()) {
         
     | 
| 
       378 
     | 
    
         
            -
             
     | 
| 
      
 410 
     | 
    
         
            +
                    return Qfalse;
         
     | 
| 
       379 
411 
     | 
    
         
             
                }
         
     | 
| 
       380 
412 
     | 
    
         | 
| 
       381 
413 
     | 
    
         
             
                if (value->IsArray()) {
         
     | 
| 
       382 
414 
     | 
    
         
             
                  VALUE rb_array = rb_ary_new();
         
     | 
| 
       383 
415 
     | 
    
         
             
                  Local<Array> arr = Local<Array>::Cast(value);
         
     | 
| 
       384 
416 
     | 
    
         
             
                  for(uint32_t i=0; i < arr->Length(); i++) {
         
     | 
| 
       385 
     | 
    
         
            -
             
     | 
| 
       386 
     | 
    
         
            -
             
     | 
| 
       387 
     | 
    
         
            -
             
     | 
| 
       388 
     | 
    
         
            -
             
     | 
| 
       389 
     | 
    
         
            -
             
     | 
| 
      
 417 
     | 
    
         
            +
                      MaybeLocal<Value> element = arr->Get(context, i);
         
     | 
| 
      
 418 
     | 
    
         
            +
                      if (element.IsEmpty()) {
         
     | 
| 
      
 419 
     | 
    
         
            +
                          continue;
         
     | 
| 
      
 420 
     | 
    
         
            +
                      }
         
     | 
| 
      
 421 
     | 
    
         
            +
                      VALUE rb_elem = convert_v8_to_ruby(isolate, context, element.ToLocalChecked());
         
     | 
| 
      
 422 
     | 
    
         
            +
                      if (rb_funcall(rb_elem, rb_intern("class"), 0) == rb_cFailedV8Conversion) {
         
     | 
| 
      
 423 
     | 
    
         
            +
                        return rb_elem;
         
     | 
| 
      
 424 
     | 
    
         
            +
                      }
         
     | 
| 
       390 
425 
     | 
    
         
             
                      rb_ary_push(rb_array, rb_elem);
         
     | 
| 
       391 
426 
     | 
    
         
             
                  }
         
     | 
| 
       392 
427 
     | 
    
         
             
                  return rb_array;
         
     | 
| 
       393 
428 
     | 
    
         
             
                }
         
     | 
| 
       394 
429 
     | 
    
         | 
| 
       395 
430 
     | 
    
         
             
                if (value->IsFunction()){
         
     | 
| 
       396 
     | 
    
         
            -
             
     | 
| 
      
 431 
     | 
    
         
            +
                    return rb_funcall(rb_cJavaScriptFunction, rb_intern("new"), 0);
         
     | 
| 
       397 
432 
     | 
    
         
             
                }
         
     | 
| 
       398 
433 
     | 
    
         | 
| 
       399 
434 
     | 
    
         
             
                if (value->IsDate()){
         
     | 
| 
         @@ -405,34 +440,55 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Local<Context> context, 
     | 
|
| 
       405 
440 
     | 
    
         
             
                }
         
     | 
| 
       406 
441 
     | 
    
         | 
| 
       407 
442 
     | 
    
         
             
                if (value->IsObject()) {
         
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
             
     | 
| 
       410 
     | 
    
         
            -
             
     | 
| 
       411 
     | 
    
         
            -
             
     | 
| 
       412 
     | 
    
         
            -
             
     | 
| 
       413 
     | 
    
         
            -
             
     | 
| 
       414 
     | 
    
         
            -
             
     | 
| 
       415 
     | 
    
         
            -
             
     | 
| 
       416 
     | 
    
         
            -
             
     | 
| 
       417 
     | 
    
         
            -
             
     | 
| 
       418 
     | 
    
         
            -
             
     | 
| 
       419 
     | 
    
         
            -
             
     | 
| 
       420 
     | 
    
         
            -
             
     | 
| 
       421 
     | 
    
         
            -
             
     | 
| 
       422 
     | 
    
         
            -
             
     | 
| 
       423 
     | 
    
         
            -
             
     | 
| 
       424 
     | 
    
         
            -
             
     | 
| 
       425 
     | 
    
         
            -
             
     | 
| 
       426 
     | 
    
         
            -
             
     | 
| 
       427 
     | 
    
         
            -
             
     | 
| 
       428 
     | 
    
         
            -
             
     | 
| 
       429 
     | 
    
         
            -
             
     | 
| 
       430 
     | 
    
         
            -
             
     | 
| 
       431 
     | 
    
         
            -
             
     | 
| 
      
 443 
     | 
    
         
            +
                    VALUE rb_hash = rb_hash_new();
         
     | 
| 
      
 444 
     | 
    
         
            +
                    TryCatch trycatch(isolate);
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                    Local<Object> object = value->ToObject(context).ToLocalChecked();
         
     | 
| 
      
 447 
     | 
    
         
            +
                    auto maybe_props = object->GetOwnPropertyNames(context);
         
     | 
| 
      
 448 
     | 
    
         
            +
                    if (!maybe_props.IsEmpty()) {
         
     | 
| 
      
 449 
     | 
    
         
            +
                        Local<Array> props = maybe_props.ToLocalChecked();
         
     | 
| 
      
 450 
     | 
    
         
            +
                        for(uint32_t i=0; i < props->Length(); i++) {
         
     | 
| 
      
 451 
     | 
    
         
            +
                         MaybeLocal<Value> key = props->Get(context, i);
         
     | 
| 
      
 452 
     | 
    
         
            +
                         if (key.IsEmpty()) {
         
     | 
| 
      
 453 
     | 
    
         
            +
                            return rb_funcall(rb_cFailedV8Conversion, rb_intern("new"), 1, rb_str_new2(""));
         
     | 
| 
      
 454 
     | 
    
         
            +
                         }
         
     | 
| 
      
 455 
     | 
    
         
            +
                         VALUE rb_key = convert_v8_to_ruby(isolate, context, key.ToLocalChecked());
         
     | 
| 
      
 456 
     | 
    
         
            +
             
     | 
| 
      
 457 
     | 
    
         
            +
                         MaybeLocal<Value> prop_value = object->Get(context, key.ToLocalChecked());
         
     | 
| 
      
 458 
     | 
    
         
            +
                         // this may have failed due to Get raising
         
     | 
| 
      
 459 
     | 
    
         
            +
                         if (prop_value.IsEmpty() || trycatch.HasCaught()) {
         
     | 
| 
      
 460 
     | 
    
         
            +
                             return new_empty_failed_conv_obj();
         
     | 
| 
      
 461 
     | 
    
         
            +
                         }
         
     | 
| 
      
 462 
     | 
    
         
            +
             
     | 
| 
      
 463 
     | 
    
         
            +
                         VALUE rb_value = convert_v8_to_ruby(
         
     | 
| 
      
 464 
     | 
    
         
            +
                                     isolate, context, prop_value.ToLocalChecked());
         
     | 
| 
      
 465 
     | 
    
         
            +
                         rb_hash_aset(rb_hash, rb_key, rb_value);
         
     | 
| 
      
 466 
     | 
    
         
            +
                        }
         
     | 
| 
      
 467 
     | 
    
         
            +
                    }
         
     | 
| 
      
 468 
     | 
    
         
            +
                    return rb_hash;
         
     | 
| 
       432 
469 
     | 
    
         
             
                }
         
     | 
| 
       433 
470 
     | 
    
         | 
| 
       434 
     | 
    
         
            -
                 
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
      
 471 
     | 
    
         
            +
                if (value->IsSymbol()) {
         
     | 
| 
      
 472 
     | 
    
         
            +
            	v8::String::Utf8Value symbol_name(isolate,
         
     | 
| 
      
 473 
     | 
    
         
            +
            	    Local<Symbol>::Cast(value)->Name());
         
     | 
| 
      
 474 
     | 
    
         
            +
             
     | 
| 
      
 475 
     | 
    
         
            +
            	VALUE str_symbol = rb_enc_str_new(
         
     | 
| 
      
 476 
     | 
    
         
            +
            	    *symbol_name,
         
     | 
| 
      
 477 
     | 
    
         
            +
            	    symbol_name.length(),
         
     | 
| 
      
 478 
     | 
    
         
            +
            	    rb_enc_find("utf-8")
         
     | 
| 
      
 479 
     | 
    
         
            +
            	);
         
     | 
| 
      
 480 
     | 
    
         
            +
             
     | 
| 
      
 481 
     | 
    
         
            +
            	return ID2SYM(rb_intern_str(str_symbol));
         
     | 
| 
      
 482 
     | 
    
         
            +
                }
         
     | 
| 
      
 483 
     | 
    
         
            +
             
     | 
| 
      
 484 
     | 
    
         
            +
                MaybeLocal<String> rstr_maybe = value->ToString(context);
         
     | 
| 
      
 485 
     | 
    
         
            +
             
     | 
| 
      
 486 
     | 
    
         
            +
                if (rstr_maybe.IsEmpty()) {
         
     | 
| 
      
 487 
     | 
    
         
            +
            	return Qnil;
         
     | 
| 
      
 488 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 489 
     | 
    
         
            +
            	Local<String> rstr = rstr_maybe.ToLocalChecked();
         
     | 
| 
      
 490 
     | 
    
         
            +
            	return rb_enc_str_new(*String::Utf8Value(isolate, rstr), rstr->Utf8Length(isolate), rb_enc_find("utf-8"));
         
     | 
| 
      
 491 
     | 
    
         
            +
                }
         
     | 
| 
       436 
492 
     | 
    
         
             
            }
         
     | 
| 
       437 
493 
     | 
    
         | 
| 
       438 
494 
     | 
    
         
             
            static VALUE convert_v8_to_ruby(Isolate* isolate,
         
     | 
| 
         @@ -453,7 +509,7 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, 
     | 
|
| 
       453 
509 
     | 
    
         
             
                                          Local<Value>::New(isolate, value));
         
     | 
| 
       454 
510 
     | 
    
         
             
            }
         
     | 
| 
       455 
511 
     | 
    
         | 
| 
       456 
     | 
    
         
            -
            static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) {
         
     | 
| 
      
 512 
     | 
    
         
            +
            static Local<Value> convert_ruby_to_v8(Isolate* isolate, Local<Context> context, VALUE value) {
         
     | 
| 
       457 
513 
     | 
    
         
             
                EscapableHandleScope scope(isolate);
         
     | 
| 
       458 
514 
     | 
    
         | 
| 
       459 
515 
     | 
    
         
             
                Local<Array> array;
         
     | 
| 
         @@ -487,7 +543,7 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) { 
     | 
|
| 
       487 
543 
     | 
    
         
             
            	length = RARRAY_LEN(value);
         
     | 
| 
       488 
544 
     | 
    
         
             
            	array = Array::New(isolate, (int)length);
         
     | 
| 
       489 
545 
     | 
    
         
             
            	for(i=0; i<length; i++) {
         
     | 
| 
       490 
     | 
    
         
            -
             
     | 
| 
      
 546 
     | 
    
         
            +
                        array->Set(context, i, convert_ruby_to_v8(isolate, context, rb_ary_entry(value, i)));
         
     | 
| 
       491 
547 
     | 
    
         
             
            	}
         
     | 
| 
       492 
548 
     | 
    
         
             
            	return scope.Escape(array);
         
     | 
| 
       493 
549 
     | 
    
         
             
                case T_HASH:
         
     | 
| 
         @@ -496,8 +552,8 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) { 
     | 
|
| 
       496 
552 
     | 
    
         
             
            	length = RARRAY_LEN(hash_as_array);
         
     | 
| 
       497 
553 
     | 
    
         
             
            	for(i=0; i<length; i++) {
         
     | 
| 
       498 
554 
     | 
    
         
             
            	    pair = rb_ary_entry(hash_as_array, i);
         
     | 
| 
       499 
     | 
    
         
            -
             
     | 
| 
       500 
     | 
    
         
            -
             
     | 
| 
      
 555 
     | 
    
         
            +
                        object->Set(context, convert_ruby_to_v8(isolate, context, rb_ary_entry(pair, 0)),
         
     | 
| 
      
 556 
     | 
    
         
            +
                              convert_ruby_to_v8(isolate, context, rb_ary_entry(pair, 1)));
         
     | 
| 
       501 
557 
     | 
    
         
             
            	}
         
     | 
| 
       502 
558 
     | 
    
         
             
            	return scope.Escape(object);
         
     | 
| 
       503 
559 
     | 
    
         
             
                case T_SYMBOL:
         
     | 
| 
         @@ -512,7 +568,7 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) { 
     | 
|
| 
       512 
568 
     | 
    
         
             
                            value = rb_funcall(value, rb_intern("to_time"), 0);
         
     | 
| 
       513 
569 
     | 
    
         
             
                        }
         
     | 
| 
       514 
570 
     | 
    
         
             
                        value = rb_funcall(value, rb_intern("to_f"), 0);
         
     | 
| 
       515 
     | 
    
         
            -
                        return scope.Escape(Date::New( 
     | 
| 
      
 571 
     | 
    
         
            +
                        return scope.Escape(Date::New(context, NUM2DBL(value) * 1000).ToLocalChecked());
         
     | 
| 
       516 
572 
     | 
    
         
             
                    }
         
     | 
| 
       517 
573 
     | 
    
         
             
                case T_OBJECT:
         
     | 
| 
       518 
574 
     | 
    
         
             
                case T_CLASS:
         
     | 
| 
         @@ -526,16 +582,90 @@ static Local<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) { 
     | 
|
| 
       526 
582 
     | 
    
         
             
                case T_UNDEF:
         
     | 
| 
       527 
583 
     | 
    
         
             
                case T_NODE:
         
     | 
| 
       528 
584 
     | 
    
         
             
                default:
         
     | 
| 
       529 
     | 
    
         
            -
                  return scope.Escape(String:: 
     | 
| 
      
 585 
     | 
    
         
            +
                  return scope.Escape(String::NewFromUtf8Literal(isolate, "Undefined Conversion"));
         
     | 
| 
      
 586 
     | 
    
         
            +
                }
         
     | 
| 
       530 
587 
     | 
    
         
             
                }
         
     | 
| 
       531 
     | 
    
         
            -
             
     | 
| 
       532 
     | 
    
         
            -
            }
         
     | 
| 
       533 
588 
     | 
    
         | 
| 
       534 
589 
     | 
    
         
             
            static void unblock_eval(void *ptr) {
         
     | 
| 
       535 
590 
     | 
    
         
             
                EvalParams* eval = (EvalParams*)ptr;
         
     | 
| 
       536 
591 
     | 
    
         
             
                eval->context_info->isolate_info->interrupted = true;
         
     | 
| 
       537 
592 
     | 
    
         
             
            }
         
     | 
| 
       538 
593 
     | 
    
         | 
| 
      
 594 
     | 
    
         
            +
            /*
         
     | 
| 
      
 595 
     | 
    
         
            +
             * The implementations of the run_extra_code(), create_snapshot_data_blob() and
         
     | 
| 
      
 596 
     | 
    
         
            +
             * warm_up_snapshot_data_blob() functions have been derived from V8's test suite.
         
     | 
| 
      
 597 
     | 
    
         
            +
             */
         
     | 
| 
      
 598 
     | 
    
         
            +
            static bool run_extra_code(Isolate *isolate, Local<v8::Context> context,
         
     | 
| 
      
 599 
     | 
    
         
            +
                                const char *utf8_source, const char *name) {
         
     | 
| 
      
 600 
     | 
    
         
            +
                Context::Scope context_scope(context);
         
     | 
| 
      
 601 
     | 
    
         
            +
                TryCatch try_catch(isolate);
         
     | 
| 
      
 602 
     | 
    
         
            +
                Local<String> source_string;
         
     | 
| 
      
 603 
     | 
    
         
            +
                if (!String::NewFromUtf8(isolate, utf8_source).ToLocal(&source_string)) {
         
     | 
| 
      
 604 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 605 
     | 
    
         
            +
                }
         
     | 
| 
      
 606 
     | 
    
         
            +
                Local<String> resource_name =
         
     | 
| 
      
 607 
     | 
    
         
            +
                        String::NewFromUtf8(isolate, name).ToLocalChecked();
         
     | 
| 
      
 608 
     | 
    
         
            +
                ScriptOrigin origin(resource_name);
         
     | 
| 
      
 609 
     | 
    
         
            +
                ScriptCompiler::Source source(source_string, origin);
         
     | 
| 
      
 610 
     | 
    
         
            +
                Local<Script> script;
         
     | 
| 
      
 611 
     | 
    
         
            +
                if (!ScriptCompiler::Compile(context, &source).ToLocal(&script))
         
     | 
| 
      
 612 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 613 
     | 
    
         
            +
                if (script->Run(context).IsEmpty()) return false;
         
     | 
| 
      
 614 
     | 
    
         
            +
                return true;
         
     | 
| 
      
 615 
     | 
    
         
            +
            }
         
     | 
| 
      
 616 
     | 
    
         
            +
             
     | 
| 
      
 617 
     | 
    
         
            +
            static StartupData
         
     | 
| 
      
 618 
     | 
    
         
            +
            create_snapshot_data_blob(const char *embedded_source = nullptr) {
         
     | 
| 
      
 619 
     | 
    
         
            +
                Isolate *isolate = Isolate::Allocate();
         
     | 
| 
      
 620 
     | 
    
         
            +
             
     | 
| 
      
 621 
     | 
    
         
            +
                // Optionally run a script to embed, and serialize to create a snapshot blob.
         
     | 
| 
      
 622 
     | 
    
         
            +
                SnapshotCreator snapshot_creator(isolate);
         
     | 
| 
      
 623 
     | 
    
         
            +
                    {
         
     | 
| 
      
 624 
     | 
    
         
            +
                        HandleScope scope(isolate);
         
     | 
| 
      
 625 
     | 
    
         
            +
                    Local<v8::Context> context = v8::Context::New(isolate);
         
     | 
| 
      
 626 
     | 
    
         
            +
                        if (embedded_source != nullptr &&
         
     | 
| 
      
 627 
     | 
    
         
            +
                            !run_extra_code(isolate, context, embedded_source, "<embedded>")) {
         
     | 
| 
      
 628 
     | 
    
         
            +
                       return {};
         
     | 
| 
      
 629 
     | 
    
         
            +
                        }
         
     | 
| 
      
 630 
     | 
    
         
            +
                        snapshot_creator.SetDefaultContext(context);
         
     | 
| 
      
 631 
     | 
    
         
            +
                    }
         
     | 
| 
      
 632 
     | 
    
         
            +
                return snapshot_creator.CreateBlob(
         
     | 
| 
      
 633 
     | 
    
         
            +
                        SnapshotCreator::FunctionCodeHandling::kClear);
         
     | 
| 
      
 634 
     | 
    
         
            +
                }
         
     | 
| 
      
 635 
     | 
    
         
            +
             
     | 
| 
      
 636 
     | 
    
         
            +
            StartupData warm_up_snapshot_data_blob(StartupData cold_snapshot_blob,
         
     | 
| 
      
 637 
     | 
    
         
            +
                                                   const char *warmup_source) {
         
     | 
| 
      
 638 
     | 
    
         
            +
                // Use following steps to create a warmed up snapshot blob from a cold one:
         
     | 
| 
      
 639 
     | 
    
         
            +
                //  - Create a new isolate from the cold snapshot.
         
     | 
| 
      
 640 
     | 
    
         
            +
                //  - Create a new context to run the warmup script. This will trigger
         
     | 
| 
      
 641 
     | 
    
         
            +
                //    compilation of executed functions.
         
     | 
| 
      
 642 
     | 
    
         
            +
                //  - Create a new context. This context will be unpolluted.
         
     | 
| 
      
 643 
     | 
    
         
            +
                //  - Serialize the isolate and the second context into a new snapshot blob.
         
     | 
| 
      
 644 
     | 
    
         
            +
                StartupData result = {nullptr, 0};
         
     | 
| 
      
 645 
     | 
    
         
            +
             
     | 
| 
      
 646 
     | 
    
         
            +
                if (cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != nullptr &&
         
     | 
| 
      
 647 
     | 
    
         
            +
                    warmup_source != NULL) {
         
     | 
| 
      
 648 
     | 
    
         
            +
                    SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob);
         
     | 
| 
      
 649 
     | 
    
         
            +
                    Isolate *isolate = snapshot_creator.GetIsolate();
         
     | 
| 
      
 650 
     | 
    
         
            +
                    {
         
     | 
| 
      
 651 
     | 
    
         
            +
                        HandleScope scope(isolate);
         
     | 
| 
      
 652 
     | 
    
         
            +
                        Local<Context> context = Context::New(isolate);
         
     | 
| 
      
 653 
     | 
    
         
            +
                        if (!run_extra_code(isolate, context, warmup_source, "<warm-up>")) {
         
     | 
| 
      
 654 
     | 
    
         
            +
                            return result;
         
     | 
| 
      
 655 
     | 
    
         
            +
                        }
         
     | 
| 
      
 656 
     | 
    
         
            +
                    }
         
     | 
| 
      
 657 
     | 
    
         
            +
                    {
         
     | 
| 
      
 658 
     | 
    
         
            +
                        HandleScope handle_scope(isolate);
         
     | 
| 
      
 659 
     | 
    
         
            +
                        isolate->ContextDisposedNotification(false);
         
     | 
| 
      
 660 
     | 
    
         
            +
                        Local<Context> context = Context::New(isolate);
         
     | 
| 
      
 661 
     | 
    
         
            +
                        snapshot_creator.SetDefaultContext(context);
         
     | 
| 
      
 662 
     | 
    
         
            +
                    }
         
     | 
| 
      
 663 
     | 
    
         
            +
                    result = snapshot_creator.CreateBlob(
         
     | 
| 
      
 664 
     | 
    
         
            +
                        SnapshotCreator::FunctionCodeHandling::kKeep);
         
     | 
| 
      
 665 
     | 
    
         
            +
                }
         
     | 
| 
      
 666 
     | 
    
         
            +
                return result;
         
     | 
| 
      
 667 
     | 
    
         
            +
            }
         
     | 
| 
      
 668 
     | 
    
         
            +
             
     | 
| 
       539 
669 
     | 
    
         
             
            static VALUE rb_snapshot_size(VALUE self, VALUE str) {
         
     | 
| 
       540 
670 
     | 
    
         
             
                SnapshotInfo* snapshot_info;
         
     | 
| 
       541 
671 
     | 
    
         
             
                Data_Get_Struct(self, SnapshotInfo, snapshot_info);
         
     | 
| 
         @@ -554,7 +684,7 @@ static VALUE rb_snapshot_load(VALUE self, VALUE str) { 
     | 
|
| 
       554 
684 
     | 
    
         | 
| 
       555 
685 
     | 
    
         
             
                init_v8();
         
     | 
| 
       556 
686 
     | 
    
         | 
| 
       557 
     | 
    
         
            -
                StartupData startup_data =  
     | 
| 
      
 687 
     | 
    
         
            +
                StartupData startup_data = create_snapshot_data_blob(RSTRING_PTR(str));
         
     | 
| 
       558 
688 
     | 
    
         | 
| 
       559 
689 
     | 
    
         
             
                if (startup_data.data == NULL && startup_data.raw_size == 0) {
         
     | 
| 
       560 
690 
     | 
    
         
             
                    rb_raise(rb_eSnapshotError, "Could not create snapshot, most likely the source is incorrect");
         
     | 
| 
         @@ -585,7 +715,7 @@ static VALUE rb_snapshot_warmup_unsafe(VALUE self, VALUE str) { 
     | 
|
| 
       585 
715 
     | 
    
         
             
                init_v8();
         
     | 
| 
       586 
716 
     | 
    
         | 
| 
       587 
717 
     | 
    
         
             
                StartupData cold_startup_data = {snapshot_info->data, snapshot_info->raw_size};
         
     | 
| 
       588 
     | 
    
         
            -
                StartupData warm_startup_data =  
     | 
| 
      
 718 
     | 
    
         
            +
                StartupData warm_startup_data = warm_up_snapshot_data_blob(cold_startup_data, RSTRING_PTR(str));
         
     | 
| 
       589 
719 
     | 
    
         | 
| 
       590 
720 
     | 
    
         
             
                if (warm_startup_data.data == NULL && warm_startup_data.raw_size == 0) {
         
     | 
| 
       591 
721 
     | 
    
         
             
                    rb_raise(rb_eSnapshotError, "Could not warm up snapshot, most likely the source is incorrect");
         
     | 
| 
         @@ -648,6 +778,29 @@ static VALUE rb_isolate_idle_notification(VALUE self, VALUE idle_time_in_ms) { 
     | 
|
| 
       648 
778 
     | 
    
         
             
                return isolate_info->isolate->IdleNotificationDeadline(now + duration) ? Qtrue : Qfalse;
         
     | 
| 
       649 
779 
     | 
    
         
             
            }
         
     | 
| 
       650 
780 
     | 
    
         | 
| 
      
 781 
     | 
    
         
            +
            static VALUE rb_isolate_low_memory_notification(VALUE self) {
         
     | 
| 
      
 782 
     | 
    
         
            +
                IsolateInfo* isolate_info;
         
     | 
| 
      
 783 
     | 
    
         
            +
                Data_Get_Struct(self, IsolateInfo, isolate_info);
         
     | 
| 
      
 784 
     | 
    
         
            +
             
     | 
| 
      
 785 
     | 
    
         
            +
                if (current_platform == NULL) return Qfalse;
         
     | 
| 
      
 786 
     | 
    
         
            +
             
     | 
| 
      
 787 
     | 
    
         
            +
                isolate_info->isolate->LowMemoryNotification();
         
     | 
| 
      
 788 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 789 
     | 
    
         
            +
            }
         
     | 
| 
      
 790 
     | 
    
         
            +
             
     | 
| 
      
 791 
     | 
    
         
            +
            static VALUE rb_isolate_pump_message_loop(VALUE self) {
         
     | 
| 
      
 792 
     | 
    
         
            +
                IsolateInfo* isolate_info;
         
     | 
| 
      
 793 
     | 
    
         
            +
                Data_Get_Struct(self, IsolateInfo, isolate_info);
         
     | 
| 
      
 794 
     | 
    
         
            +
             
     | 
| 
      
 795 
     | 
    
         
            +
                if (current_platform == NULL) return Qfalse;
         
     | 
| 
      
 796 
     | 
    
         
            +
             
     | 
| 
      
 797 
     | 
    
         
            +
                if (platform::PumpMessageLoop(current_platform.get(), isolate_info->isolate)){
         
     | 
| 
      
 798 
     | 
    
         
            +
            	return Qtrue;
         
     | 
| 
      
 799 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 800 
     | 
    
         
            +
            	return Qfalse;
         
     | 
| 
      
 801 
     | 
    
         
            +
                }
         
     | 
| 
      
 802 
     | 
    
         
            +
            }
         
     | 
| 
      
 803 
     | 
    
         
            +
             
     | 
| 
       651 
804 
     | 
    
         
             
            static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) {
         
     | 
| 
       652 
805 
     | 
    
         
             
                ContextInfo* context_info;
         
     | 
| 
       653 
806 
     | 
    
         
             
                Data_Get_Struct(self, ContextInfo, context_info);
         
     | 
| 
         @@ -675,13 +828,13 @@ static VALUE rb_context_init_unsafe(VALUE self, VALUE isolate, VALUE snap) { 
     | 
|
| 
       675 
828 
     | 
    
         
             
                    // the ruby lock is needed if this isn't a new isolate
         
     | 
| 
       676 
829 
     | 
    
         
             
                    IsolateInfo::Lock ruby_lock(isolate_info->mutex);
         
     | 
| 
       677 
830 
     | 
    
         
             
                    Locker lock(isolate_info->isolate);
         
     | 
| 
       678 
     | 
    
         
            -
             
     | 
| 
       679 
     | 
    
         
            -
             
     | 
| 
      
 831 
     | 
    
         
            +
                    Isolate::Scope isolate_scope(isolate_info->isolate);
         
     | 
| 
      
 832 
     | 
    
         
            +
                    HandleScope handle_scope(isolate_info->isolate);
         
     | 
| 
       680 
833 
     | 
    
         | 
| 
       681 
     | 
    
         
            -
             
     | 
| 
      
 834 
     | 
    
         
            +
                    Local<Context> context = Context::New(isolate_info->isolate);
         
     | 
| 
       682 
835 
     | 
    
         | 
| 
       683 
     | 
    
         
            -
             
     | 
| 
       684 
     | 
    
         
            -
             
     | 
| 
      
 836 
     | 
    
         
            +
                    context_info->context = new Persistent<Context>();
         
     | 
| 
      
 837 
     | 
    
         
            +
                    context_info->context->Reset(isolate_info->isolate, context);
         
     | 
| 
       685 
838 
     | 
    
         
             
                }
         
     | 
| 
       686 
839 
     | 
    
         | 
| 
       687 
840 
     | 
    
         
             
                if (Qnil == rb_cDateTime && rb_funcall(rb_cObject, rb_intern("const_defined?"), 1, rb_str_new2("DateTime")) == Qtrue)
         
     | 
| 
         @@ -764,8 +917,8 @@ static VALUE convert_result_to_ruby(VALUE self /* context */, 
     | 
|
| 
       764 
917 
     | 
    
         
             
                    Local<Value> tmp = Local<Value>::New(isolate, *result.value);
         
     | 
| 
       765 
918 
     | 
    
         | 
| 
       766 
919 
     | 
    
         
             
                    if (result.json) {
         
     | 
| 
       767 
     | 
    
         
            -
                        Local<String> rstr = tmp->ToString();
         
     | 
| 
       768 
     | 
    
         
            -
                        VALUE json_string = rb_enc_str_new(*String::Utf8Value(rstr), rstr->Utf8Length(), rb_enc_find("utf-8"));
         
     | 
| 
      
 920 
     | 
    
         
            +
                        Local<String> rstr = tmp->ToString(p_ctx->Get(isolate)).ToLocalChecked();
         
     | 
| 
      
 921 
     | 
    
         
            +
                        VALUE json_string = rb_enc_str_new(*String::Utf8Value(isolate, rstr), rstr->Utf8Length(isolate), rb_enc_find("utf-8"));
         
     | 
| 
       769 
922 
     | 
    
         
             
                        ret = rb_funcall(rb_mJSON, rb_intern("parse"), 1, json_string);
         
     | 
| 
       770 
923 
     | 
    
         
             
                    } else {
         
     | 
| 
       771 
924 
     | 
    
         
             
                        ret = convert_v8_to_ruby(isolate, *p_ctx, tmp);
         
     | 
| 
         @@ -803,42 +956,42 @@ static VALUE rb_context_eval_unsafe(VALUE self, VALUE str, VALUE filename) { 
     | 
|
| 
       803 
956 
     | 
    
         
             
                }
         
     | 
| 
       804 
957 
     | 
    
         | 
| 
       805 
958 
     | 
    
         
             
                {
         
     | 
| 
       806 
     | 
    
         
            -
             
     | 
| 
       807 
     | 
    
         
            -
             
     | 
| 
       808 
     | 
    
         
            -
             
     | 
| 
      
 959 
     | 
    
         
            +
                    Locker lock(isolate);
         
     | 
| 
      
 960 
     | 
    
         
            +
                    Isolate::Scope isolate_scope(isolate);
         
     | 
| 
      
 961 
     | 
    
         
            +
                    HandleScope handle_scope(isolate);
         
     | 
| 
       809 
962 
     | 
    
         | 
| 
       810 
     | 
    
         
            -
             
     | 
| 
       811 
     | 
    
         
            -
             
     | 
| 
      
 963 
     | 
    
         
            +
                    Local<String> eval = String::NewFromUtf8(isolate, RSTRING_PTR(str),
         
     | 
| 
      
 964 
     | 
    
         
            +
                                NewStringType::kNormal, (int)RSTRING_LEN(str)).ToLocalChecked();
         
     | 
| 
       812 
965 
     | 
    
         | 
| 
       813 
     | 
    
         
            -
             
     | 
| 
      
 966 
     | 
    
         
            +
                    Local<String> local_filename;
         
     | 
| 
       814 
967 
     | 
    
         | 
| 
       815 
     | 
    
         
            -
             
     | 
| 
       816 
     | 
    
         
            -
             
     | 
| 
       817 
     | 
    
         
            -
             
     | 
| 
       818 
     | 
    
         
            -
             
     | 
| 
       819 
     | 
    
         
            -
             
     | 
| 
       820 
     | 
    
         
            -
             
     | 
| 
       821 
     | 
    
         
            -
             
     | 
| 
      
 968 
     | 
    
         
            +
                    if (filename != Qnil) {
         
     | 
| 
      
 969 
     | 
    
         
            +
                        local_filename = String::NewFromUtf8(isolate, RSTRING_PTR(filename),
         
     | 
| 
      
 970 
     | 
    
         
            +
                            NewStringType::kNormal, (int)RSTRING_LEN(filename)).ToLocalChecked();
         
     | 
| 
      
 971 
     | 
    
         
            +
                        eval_params.filename = &local_filename;
         
     | 
| 
      
 972 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 973 
     | 
    
         
            +
                        eval_params.filename = NULL;
         
     | 
| 
      
 974 
     | 
    
         
            +
                    }
         
     | 
| 
       822 
975 
     | 
    
         | 
| 
       823 
     | 
    
         
            -
             
     | 
| 
       824 
     | 
    
         
            -
             
     | 
| 
       825 
     | 
    
         
            -
             
     | 
| 
       826 
     | 
    
         
            -
             
     | 
| 
       827 
     | 
    
         
            -
             
     | 
| 
       828 
     | 
    
         
            -
             
     | 
| 
       829 
     | 
    
         
            -
             
     | 
| 
       830 
     | 
    
         
            -
             
     | 
| 
       831 
     | 
    
         
            -
             
     | 
| 
      
 976 
     | 
    
         
            +
                    eval_params.context_info = context_info;
         
     | 
| 
      
 977 
     | 
    
         
            +
                    eval_params.eval = &eval;
         
     | 
| 
      
 978 
     | 
    
         
            +
                    eval_params.result = &eval_result;
         
     | 
| 
      
 979 
     | 
    
         
            +
                    eval_params.timeout = 0;
         
     | 
| 
      
 980 
     | 
    
         
            +
                    eval_params.max_memory = 0;
         
     | 
| 
      
 981 
     | 
    
         
            +
                    VALUE timeout = rb_iv_get(self, "@timeout");
         
     | 
| 
      
 982 
     | 
    
         
            +
                    if (timeout != Qnil) {
         
     | 
| 
      
 983 
     | 
    
         
            +
                        eval_params.timeout = (useconds_t)NUM2LONG(timeout);
         
     | 
| 
      
 984 
     | 
    
         
            +
                    }
         
     | 
| 
       832 
985 
     | 
    
         | 
| 
       833 
     | 
    
         
            -
             
     | 
| 
       834 
     | 
    
         
            -
             
     | 
| 
       835 
     | 
    
         
            -
             
     | 
| 
       836 
     | 
    
         
            -
             
     | 
| 
      
 986 
     | 
    
         
            +
                    VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
         
     | 
| 
      
 987 
     | 
    
         
            +
                    if (mem_softlimit != Qnil) {
         
     | 
| 
      
 988 
     | 
    
         
            +
                        eval_params.max_memory = (size_t)NUM2ULONG(mem_softlimit);
         
     | 
| 
      
 989 
     | 
    
         
            +
                    }
         
     | 
| 
       837 
990 
     | 
    
         | 
| 
       838 
     | 
    
         
            -
             
     | 
| 
       839 
     | 
    
         
            -
             
     | 
| 
      
 991 
     | 
    
         
            +
                    eval_result.message = NULL;
         
     | 
| 
      
 992 
     | 
    
         
            +
                    eval_result.backtrace = NULL;
         
     | 
| 
       840 
993 
     | 
    
         | 
| 
       841 
     | 
    
         
            -
             
     | 
| 
      
 994 
     | 
    
         
            +
                    rb_thread_call_without_gvl(nogvl_context_eval, &eval_params, unblock_eval, &eval_params);
         
     | 
| 
       842 
995 
     | 
    
         
             
                }
         
     | 
| 
       843 
996 
     | 
    
         | 
| 
       844 
997 
     | 
    
         
             
                return convert_result_to_ruby(self, eval_result);
         
     | 
| 
         @@ -851,17 +1004,16 @@ typedef struct { 
     | 
|
| 
       851 
1004 
     | 
    
         
             
                bool failed;
         
     | 
| 
       852 
1005 
     | 
    
         
             
            } protected_callback_data;
         
     | 
| 
       853 
1006 
     | 
    
         | 
| 
       854 
     | 
    
         
            -
            static
         
     | 
| 
       855 
     | 
    
         
            -
            VALUE protected_callback(VALUE rdata) {
         
     | 
| 
      
 1007 
     | 
    
         
            +
            static VALUE protected_callback(VALUE rdata) {
         
     | 
| 
       856 
1008 
     | 
    
         
             
                protected_callback_data* data = (protected_callback_data*)rdata;
         
     | 
| 
       857 
1009 
     | 
    
         
             
                VALUE result;
         
     | 
| 
       858 
1010 
     | 
    
         | 
| 
       859 
1011 
     | 
    
         
             
                if (data->length > 0) {
         
     | 
| 
       860 
     | 
    
         
            -
             
     | 
| 
       861 
     | 
    
         
            -
             
     | 
| 
       862 
     | 
    
         
            -
             
     | 
| 
      
 1012 
     | 
    
         
            +
                    result = rb_funcall2(data->callback, rb_intern("call"), data->length,
         
     | 
| 
      
 1013 
     | 
    
         
            +
                                 RARRAY_PTR(data->ruby_args));
         
     | 
| 
      
 1014 
     | 
    
         
            +
                    RB_GC_GUARD(data->ruby_args);
         
     | 
| 
       863 
1015 
     | 
    
         
             
                } else {
         
     | 
| 
       864 
     | 
    
         
            -
             
     | 
| 
      
 1016 
     | 
    
         
            +
                    result = rb_funcall(data->callback, rb_intern("call"), 0);
         
     | 
| 
       865 
1017 
     | 
    
         
             
                }
         
     | 
| 
       866 
1018 
     | 
    
         
             
                return result;
         
     | 
| 
       867 
1019 
     | 
    
         
             
            }
         
     | 
| 
         @@ -883,6 +1035,8 @@ gvl_ruby_callback(void* data) { 
     | 
|
| 
       883 
1035 
     | 
    
         
             
                VALUE result;
         
     | 
| 
       884 
1036 
     | 
    
         
             
                VALUE self;
         
     | 
| 
       885 
1037 
     | 
    
         
             
                VALUE parent;
         
     | 
| 
      
 1038 
     | 
    
         
            +
                ContextInfo* context_info;
         
     | 
| 
      
 1039 
     | 
    
         
            +
             
     | 
| 
       886 
1040 
     | 
    
         
             
                {
         
     | 
| 
       887 
1041 
     | 
    
         
             
                    HandleScope scope(args->GetIsolate());
         
     | 
| 
       888 
1042 
     | 
    
         
             
                    Local<External> external = Local<External>::Cast(args->Data());
         
     | 
| 
         @@ -895,19 +1049,18 @@ gvl_ruby_callback(void* data) { 
     | 
|
| 
       895 
1049 
     | 
    
         
             
                        return NULL;
         
     | 
| 
       896 
1050 
     | 
    
         
             
                    }
         
     | 
| 
       897 
1051 
     | 
    
         | 
| 
       898 
     | 
    
         
            -
                    ContextInfo* context_info;
         
     | 
| 
       899 
1052 
     | 
    
         
             
                    Data_Get_Struct(parent, ContextInfo, context_info);
         
     | 
| 
       900 
1053 
     | 
    
         | 
| 
       901 
     | 
    
         
            -
             
     | 
| 
       902 
     | 
    
         
            -
             
     | 
| 
       903 
     | 
    
         
            -
             
     | 
| 
      
 1054 
     | 
    
         
            +
                    if (length > 0) {
         
     | 
| 
      
 1055 
     | 
    
         
            +
                        ruby_args = rb_ary_tmp_new(length);
         
     | 
| 
      
 1056 
     | 
    
         
            +
                    }
         
     | 
| 
       904 
1057 
     | 
    
         | 
| 
       905 
     | 
    
         
            -
             
     | 
| 
       906 
     | 
    
         
            -
             
     | 
| 
       907 
     | 
    
         
            -
             
     | 
| 
       908 
     | 
    
         
            -
             
     | 
| 
       909 
     | 
    
         
            -
             
     | 
| 
       910 
     | 
    
         
            -
             
     | 
| 
      
 1058 
     | 
    
         
            +
                    for (int i = 0; i < length; i++) {
         
     | 
| 
      
 1059 
     | 
    
         
            +
                        Local<Value> value = ((*args)[i]).As<Value>();
         
     | 
| 
      
 1060 
     | 
    
         
            +
                        VALUE tmp = convert_v8_to_ruby(args->GetIsolate(),
         
     | 
| 
      
 1061 
     | 
    
         
            +
                                                       *context_info->context, value);
         
     | 
| 
      
 1062 
     | 
    
         
            +
                        rb_ary_push(ruby_args, tmp);
         
     | 
| 
      
 1063 
     | 
    
         
            +
                    }
         
     | 
| 
       911 
1064 
     | 
    
         
             
                }
         
     | 
| 
       912 
1065 
     | 
    
         | 
| 
       913 
1066 
     | 
    
         
             
                // may raise exception stay clear of handle scope
         
     | 
| 
         @@ -918,31 +1071,33 @@ gvl_ruby_callback(void* data) { 
     | 
|
| 
       918 
1071 
     | 
    
         
             
                callback_data.failed = false;
         
     | 
| 
       919 
1072 
     | 
    
         | 
| 
       920 
1073 
     | 
    
         
             
                if ((bool)args->GetIsolate()->GetData(DO_TERMINATE) == true) {
         
     | 
| 
       921 
     | 
    
         
            -
             
     | 
| 
       922 
     | 
    
         
            -
             
     | 
| 
       923 
     | 
    
         
            -
             
     | 
| 
       924 
     | 
    
         
            -
             
     | 
| 
       925 
     | 
    
         
            -
             
     | 
| 
       926 
     | 
    
         
            -
             
     | 
| 
       927 
     | 
    
         
            -
             
     | 
| 
      
 1074 
     | 
    
         
            +
                    args->GetIsolate()->ThrowException(
         
     | 
| 
      
 1075 
     | 
    
         
            +
                                String::NewFromUtf8Literal(args->GetIsolate(),
         
     | 
| 
      
 1076 
     | 
    
         
            +
                                                           "Terminated execution during transition from Ruby to JS"));
         
     | 
| 
      
 1077 
     | 
    
         
            +
                    args->GetIsolate()->TerminateExecution();
         
     | 
| 
      
 1078 
     | 
    
         
            +
                    if (length > 0) {
         
     | 
| 
      
 1079 
     | 
    
         
            +
                        rb_ary_clear(ruby_args);
         
     | 
| 
      
 1080 
     | 
    
         
            +
                        rb_gc_force_recycle(ruby_args);
         
     | 
| 
      
 1081 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1082 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
       928 
1083 
     | 
    
         
             
                }
         
     | 
| 
       929 
1084 
     | 
    
         | 
| 
       930 
1085 
     | 
    
         
             
                result = rb_rescue2((VALUE(*)(...))&protected_callback, (VALUE)(&callback_data),
         
     | 
| 
       931 
     | 
    
         
            -
             
     | 
| 
      
 1086 
     | 
    
         
            +
                        (VALUE(*)(...))&rescue_callback, (VALUE)(&callback_data), rb_eException, (VALUE)0);
         
     | 
| 
       932 
1087 
     | 
    
         | 
| 
       933 
1088 
     | 
    
         
             
                if(callback_data.failed) {
         
     | 
| 
       934 
     | 
    
         
            -
             
     | 
| 
       935 
     | 
    
         
            -
             
     | 
| 
      
 1089 
     | 
    
         
            +
                    rb_iv_set(parent, "@current_exception", result);
         
     | 
| 
      
 1090 
     | 
    
         
            +
                    args->GetIsolate()->ThrowException(String::NewFromUtf8Literal(args->GetIsolate(), "Ruby exception"));
         
     | 
| 
       936 
1091 
     | 
    
         
             
                }
         
     | 
| 
       937 
1092 
     | 
    
         
             
                else {
         
     | 
| 
       938 
     | 
    
         
            -
             
     | 
| 
       939 
     | 
    
         
            -
             
     | 
| 
       940 
     | 
    
         
            -
             
     | 
| 
      
 1093 
     | 
    
         
            +
                    HandleScope scope(args->GetIsolate());
         
     | 
| 
      
 1094 
     | 
    
         
            +
                    Handle<Value> v8_result = convert_ruby_to_v8(args->GetIsolate(), context_info->context->Get(args->GetIsolate()), result);
         
     | 
| 
      
 1095 
     | 
    
         
            +
                    args->GetReturnValue().Set(v8_result);
         
     | 
| 
       941 
1096 
     | 
    
         
             
                }
         
     | 
| 
       942 
1097 
     | 
    
         | 
| 
       943 
1098 
     | 
    
         
             
                if (length > 0) {
         
     | 
| 
       944 
     | 
    
         
            -
             
     | 
| 
       945 
     | 
    
         
            -
             
     | 
| 
      
 1099 
     | 
    
         
            +
                    rb_ary_clear(ruby_args);
         
     | 
| 
      
 1100 
     | 
    
         
            +
                    rb_gc_force_recycle(ruby_args);
         
     | 
| 
       946 
1101 
     | 
    
         
             
                }
         
     | 
| 
       947 
1102 
     | 
    
         | 
| 
       948 
1103 
     | 
    
         
             
                if ((bool)args->GetIsolate()->GetData(DO_TERMINATE) == true) {
         
     | 
| 
         @@ -957,11 +1112,11 @@ static void ruby_callback(const FunctionCallbackInfo<Value>& args) { 
     | 
|
| 
       957 
1112 
     | 
    
         
             
                bool has_gvl = (bool)args.GetIsolate()->GetData(IN_GVL);
         
     | 
| 
       958 
1113 
     | 
    
         | 
| 
       959 
1114 
     | 
    
         
             
                if(has_gvl) {
         
     | 
| 
       960 
     | 
    
         
            -
             
     | 
| 
      
 1115 
     | 
    
         
            +
                    gvl_ruby_callback((void*)&args);
         
     | 
| 
       961 
1116 
     | 
    
         
             
                } else {
         
     | 
| 
       962 
     | 
    
         
            -
             
     | 
| 
       963 
     | 
    
         
            -
             
     | 
| 
       964 
     | 
    
         
            -
             
     | 
| 
      
 1117 
     | 
    
         
            +
                    args.GetIsolate()->SetData(IN_GVL, (void*)true);
         
     | 
| 
      
 1118 
     | 
    
         
            +
                    rb_thread_call_with_gvl(gvl_ruby_callback, (void*)(&args));
         
     | 
| 
      
 1119 
     | 
    
         
            +
                    args.GetIsolate()->SetData(IN_GVL, (void*)false);
         
     | 
| 
       965 
1120 
     | 
    
         
             
                }
         
     | 
| 
       966 
1121 
     | 
    
         
             
            }
         
     | 
| 
       967 
1122 
     | 
    
         | 
| 
         @@ -982,55 +1137,71 @@ static VALUE rb_external_function_notify_v8(VALUE self) { 
     | 
|
| 
       982 
1137 
     | 
    
         
             
                Isolate* isolate = context_info->isolate_info->isolate;
         
     | 
| 
       983 
1138 
     | 
    
         | 
| 
       984 
1139 
     | 
    
         
             
                {
         
     | 
| 
       985 
     | 
    
         
            -
             
     | 
| 
       986 
     | 
    
         
            -
             
     | 
| 
       987 
     | 
    
         
            -
             
     | 
| 
       988 
     | 
    
         
            -
             
     | 
| 
       989 
     | 
    
         
            -
             
     | 
| 
       990 
     | 
    
         
            -
             
     | 
| 
       991 
     | 
    
         
            -
             
     | 
| 
       992 
     | 
    
         
            -
             
     | 
| 
       993 
     | 
    
         
            -
             
     | 
| 
       994 
     | 
    
         
            -
             
     | 
| 
       995 
     | 
    
         
            -
             
     | 
| 
       996 
     | 
    
         
            -
             
     | 
| 
       997 
     | 
    
         
            -
             
     | 
| 
       998 
     | 
    
         
            -
             
     | 
| 
       999 
     | 
    
         
            -
             
     | 
| 
       1000 
     | 
    
         
            -
             
     | 
| 
       1001 
     | 
    
         
            -
             
     | 
| 
       1002 
     | 
    
         
            -
             
     | 
| 
       1003 
     | 
    
         
            -
             
     | 
| 
       1004 
     | 
    
         
            -
             
     | 
| 
       1005 
     | 
    
         
            -
             
     | 
| 
       1006 
     | 
    
         
            -
             
     | 
| 
       1007 
     | 
    
         
            -
             
     | 
| 
       1008 
     | 
    
         
            -
             
     | 
| 
       1009 
     | 
    
         
            -
             
     | 
| 
       1010 
     | 
    
         
            -
             
     | 
| 
       1011 
     | 
    
         
            -
             
     | 
| 
       1012 
     | 
    
         
            -
             
     | 
| 
       1013 
     | 
    
         
            -
             
     | 
| 
       1014 
     | 
    
         
            -
             
     | 
| 
       1015 
     | 
    
         
            -
             
     | 
| 
       1016 
     | 
    
         
            -
             
     | 
| 
       1017 
     | 
    
         
            -
             
     | 
| 
       1018 
     | 
    
         
            -
             
     | 
| 
       1019 
     | 
    
         
            -
             
     | 
| 
       1020 
     | 
    
         
            -
             
     | 
| 
       1021 
     | 
    
         
            -
             
     | 
| 
       1022 
     | 
    
         
            -
             
     | 
| 
       1023 
     | 
    
         
            -
             
     | 
| 
       1024 
     | 
    
         
            -
             
     | 
| 
      
 1140 
     | 
    
         
            +
                    Locker lock(isolate);
         
     | 
| 
      
 1141 
     | 
    
         
            +
                    Isolate::Scope isolate_scope(isolate);
         
     | 
| 
      
 1142 
     | 
    
         
            +
                    HandleScope handle_scope(isolate);
         
     | 
| 
      
 1143 
     | 
    
         
            +
             
     | 
| 
      
 1144 
     | 
    
         
            +
                    Local<Context> context = context_info->context->Get(isolate);
         
     | 
| 
      
 1145 
     | 
    
         
            +
                    Context::Scope context_scope(context);
         
     | 
| 
      
 1146 
     | 
    
         
            +
             
     | 
| 
      
 1147 
     | 
    
         
            +
                    Local<String> v8_str =
         
     | 
| 
      
 1148 
     | 
    
         
            +
                        String::NewFromUtf8(isolate, RSTRING_PTR(name),
         
     | 
| 
      
 1149 
     | 
    
         
            +
                                            NewStringType::kNormal, (int)RSTRING_LEN(name))
         
     | 
| 
      
 1150 
     | 
    
         
            +
                            .ToLocalChecked();
         
     | 
| 
      
 1151 
     | 
    
         
            +
             
     | 
| 
      
 1152 
     | 
    
         
            +
                    // copy self so we can access from v8 external
         
     | 
| 
      
 1153 
     | 
    
         
            +
                    VALUE* self_copy;
         
     | 
| 
      
 1154 
     | 
    
         
            +
                    Data_Get_Struct(self, VALUE, self_copy);
         
     | 
| 
      
 1155 
     | 
    
         
            +
                    *self_copy = self;
         
     | 
| 
      
 1156 
     | 
    
         
            +
             
     | 
| 
      
 1157 
     | 
    
         
            +
                    Local<Value> external = External::New(isolate, self_copy);
         
     | 
| 
      
 1158 
     | 
    
         
            +
             
     | 
| 
      
 1159 
     | 
    
         
            +
                    if (parent_object == Qnil) {
         
     | 
| 
      
 1160 
     | 
    
         
            +
                        context->Global()->Set(
         
     | 
| 
      
 1161 
     | 
    
         
            +
                                    context,
         
     | 
| 
      
 1162 
     | 
    
         
            +
                                    v8_str,
         
     | 
| 
      
 1163 
     | 
    
         
            +
                                    FunctionTemplate::New(isolate, ruby_callback, external)
         
     | 
| 
      
 1164 
     | 
    
         
            +
                                        ->GetFunction(context)
         
     | 
| 
      
 1165 
     | 
    
         
            +
                                        .ToLocalChecked());
         
     | 
| 
      
 1166 
     | 
    
         
            +
             
     | 
| 
      
 1167 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 1168 
     | 
    
         
            +
                        Local<String> eval =
         
     | 
| 
      
 1169 
     | 
    
         
            +
                            String::NewFromUtf8(isolate, RSTRING_PTR(parent_object_eval),
         
     | 
| 
      
 1170 
     | 
    
         
            +
                                                NewStringType::kNormal,
         
     | 
| 
      
 1171 
     | 
    
         
            +
                                                (int)RSTRING_LEN(parent_object_eval))
         
     | 
| 
      
 1172 
     | 
    
         
            +
                                .ToLocalChecked();
         
     | 
| 
      
 1173 
     | 
    
         
            +
             
     | 
| 
      
 1174 
     | 
    
         
            +
                        MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
         
     | 
| 
      
 1175 
     | 
    
         
            +
                        if (parsed_script.IsEmpty()) {
         
     | 
| 
      
 1176 
     | 
    
         
            +
                        parse_error = true;
         
     | 
| 
      
 1177 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 1178 
     | 
    
         
            +
                            MaybeLocal<Value> maybe_value =
         
     | 
| 
      
 1179 
     | 
    
         
            +
                                parsed_script.ToLocalChecked()->Run(context);
         
     | 
| 
      
 1180 
     | 
    
         
            +
                            attach_error = true;
         
     | 
| 
      
 1181 
     | 
    
         
            +
             
     | 
| 
      
 1182 
     | 
    
         
            +
                            if (!maybe_value.IsEmpty()) {
         
     | 
| 
      
 1183 
     | 
    
         
            +
                                Local<Value> value = maybe_value.ToLocalChecked();
         
     | 
| 
      
 1184 
     | 
    
         
            +
                                if (value->IsObject()) {
         
     | 
| 
      
 1185 
     | 
    
         
            +
                                    value.As<Object>()->Set(
         
     | 
| 
      
 1186 
     | 
    
         
            +
                                                context,
         
     | 
| 
      
 1187 
     | 
    
         
            +
                                                v8_str,
         
     | 
| 
      
 1188 
     | 
    
         
            +
                                                FunctionTemplate::New(isolate, ruby_callback, external)
         
     | 
| 
      
 1189 
     | 
    
         
            +
                                                    ->GetFunction(context)
         
     | 
| 
      
 1190 
     | 
    
         
            +
                                                    .ToLocalChecked());
         
     | 
| 
      
 1191 
     | 
    
         
            +
                                attach_error = false;
         
     | 
| 
      
 1192 
     | 
    
         
            +
                                }
         
     | 
| 
      
 1193 
     | 
    
         
            +
                            }
         
     | 
| 
      
 1194 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1195 
     | 
    
         
            +
                    }
         
     | 
| 
       1025 
1196 
     | 
    
         
             
                }
         
     | 
| 
       1026 
1197 
     | 
    
         | 
| 
       1027 
1198 
     | 
    
         
             
                // always raise out of V8 context
         
     | 
| 
       1028 
1199 
     | 
    
         
             
                if (parse_error) {
         
     | 
| 
       1029 
     | 
    
         
            -
             
     | 
| 
      
 1200 
     | 
    
         
            +
                    rb_raise(rb_eParseError, "Invalid object %" PRIsVALUE, parent_object);
         
     | 
| 
       1030 
1201 
     | 
    
         
             
                }
         
     | 
| 
       1031 
1202 
     | 
    
         | 
| 
       1032 
1203 
     | 
    
         
             
                if (attach_error) {
         
     | 
| 
       1033 
     | 
    
         
            -
             
     | 
| 
      
 1204 
     | 
    
         
            +
                    rb_raise(rb_eParseError, "Was expecting %" PRIsVALUE" to be an object", parent_object);
         
     | 
| 
       1034 
1205 
     | 
    
         
             
                }
         
     | 
| 
       1035 
1206 
     | 
    
         | 
| 
       1036 
1207 
     | 
    
         
             
                return Qnil;
         
     | 
| 
         @@ -1047,35 +1218,39 @@ static VALUE rb_context_isolate_mutex(VALUE self) { 
     | 
|
| 
       1047 
1218 
     | 
    
         
             
                return context_info->isolate_info->mutex;
         
     | 
| 
       1048 
1219 
     | 
    
         
             
            }
         
     | 
| 
       1049 
1220 
     | 
    
         | 
| 
       1050 
     | 
    
         
            -
             
     | 
| 
       1051 
     | 
    
         
            -
             
     | 
| 
       1052 
     | 
    
         
            -
             
     | 
| 
       1053 
     | 
    
         
            -
             
     | 
| 
       1054 
     | 
    
         
            -
             
     | 
| 
       1055 
     | 
    
         
            -
             
     | 
| 
       1056 
     | 
    
         
            -
                if (isolate_info->isolate) {
         
     | 
| 
       1057 
     | 
    
         
            -
                    if (isolate_info->interrupted) {
         
     | 
| 
       1058 
     | 
    
         
            -
                        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");
         
     | 
| 
      
 1221 
     | 
    
         
            +
            IsolateInfo::~IsolateInfo() {
         
     | 
| 
      
 1222 
     | 
    
         
            +
                if (isolate) {
         
     | 
| 
      
 1223 
     | 
    
         
            +
                    if (this->interrupted) {
         
     | 
| 
      
 1224 
     | 
    
         
            +
                        fprintf(stderr, "WARNING: V8 isolate was interrupted by Ruby, "
         
     | 
| 
      
 1225 
     | 
    
         
            +
                                        "it can not be disposed and memory will not be "
         
     | 
| 
      
 1226 
     | 
    
         
            +
                                        "reclaimed till the Ruby process exits.\n");
         
     | 
| 
       1059 
1227 
     | 
    
         
             
                    } else {
         
     | 
| 
       1060 
     | 
    
         
            -
             
     | 
| 
       1061 
     | 
    
         
            -
             
     | 
| 
       1062 
     | 
    
         
            -
             
     | 
| 
       1063 
     | 
    
         
            -
             
     | 
| 
       1064 
     | 
    
         
            -
             
     | 
| 
       1065 
     | 
    
         
            -
             
     | 
| 
      
 1228 
     | 
    
         
            +
                        if (this->pid != getpid() && !single_threaded) {
         
     | 
| 
      
 1229 
     | 
    
         
            +
                            fprintf(stderr, "WARNING: V8 isolate was forked, "
         
     | 
| 
      
 1230 
     | 
    
         
            +
                                            "it can not be disposed and "
         
     | 
| 
      
 1231 
     | 
    
         
            +
                                            "memory will not be reclaimed "
         
     | 
| 
      
 1232 
     | 
    
         
            +
                                            "till the Ruby process exits.\n"
         
     | 
| 
      
 1233 
     | 
    
         
            +
            				"It is VERY likely your process will hang.\n"
         
     | 
| 
      
 1234 
     | 
    
         
            +
            				"If you wish to use v8 in forked environment "
         
     | 
| 
      
 1235 
     | 
    
         
            +
            				"please ensure the platform is initialized with:\n"
         
     | 
| 
      
 1236 
     | 
    
         
            +
            				"MiniRacer::Platform.set_flags! :single_threaded\n"
         
     | 
| 
      
 1237 
     | 
    
         
            +
            				);
         
     | 
| 
      
 1238 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 1239 
     | 
    
         
            +
                            isolate->Dispose();
         
     | 
| 
      
 1240 
     | 
    
         
            +
                        }
         
     | 
| 
       1066 
1241 
     | 
    
         
             
                    }
         
     | 
| 
       1067 
     | 
    
         
            -
                     
     | 
| 
      
 1242 
     | 
    
         
            +
                    isolate = nullptr;
         
     | 
| 
       1068 
1243 
     | 
    
         
             
                }
         
     | 
| 
       1069 
1244 
     | 
    
         | 
| 
       1070 
     | 
    
         
            -
                if ( 
     | 
| 
       1071 
     | 
    
         
            -
                    delete[]  
     | 
| 
       1072 
     | 
    
         
            -
                    delete  
     | 
| 
      
 1245 
     | 
    
         
            +
                if (startup_data) {
         
     | 
| 
      
 1246 
     | 
    
         
            +
                    delete[] startup_data->data;
         
     | 
| 
      
 1247 
     | 
    
         
            +
                    delete startup_data;
         
     | 
| 
       1073 
1248 
     | 
    
         
             
                }
         
     | 
| 
       1074 
1249 
     | 
    
         | 
| 
       1075 
     | 
    
         
            -
                delete  
     | 
| 
      
 1250 
     | 
    
         
            +
                delete allocator;
         
     | 
| 
       1076 
1251 
     | 
    
         
             
            }
         
     | 
| 
       1077 
1252 
     | 
    
         | 
| 
       1078 
     | 
    
         
            -
            static void  
     | 
| 
      
 1253 
     | 
    
         
            +
            static void free_context_raw(void *arg) {
         
     | 
| 
       1079 
1254 
     | 
    
         
             
                ContextInfo* context_info = (ContextInfo*)arg;
         
     | 
| 
       1080 
1255 
     | 
    
         
             
                IsolateInfo* isolate_info = context_info->isolate_info;
         
     | 
| 
       1081 
1256 
     | 
    
         
             
                Persistent<Context>* context = context_info->context;
         
     | 
| 
         @@ -1092,6 +1267,20 @@ static void *free_context_raw(void* arg) { 
     | 
|
| 
       1092 
1267 
     | 
    
         
             
                }
         
     | 
| 
       1093 
1268 
     | 
    
         | 
| 
       1094 
1269 
     | 
    
         
             
                xfree(context_info);
         
     | 
| 
      
 1270 
     | 
    
         
            +
            }
         
     | 
| 
      
 1271 
     | 
    
         
            +
             
     | 
| 
      
 1272 
     | 
    
         
            +
            static void *free_context_thr(void* arg) {
         
     | 
| 
      
 1273 
     | 
    
         
            +
                if (pthread_rwlock_tryrdlock(&exit_lock) != 0) {
         
     | 
| 
      
 1274 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
      
 1275 
     | 
    
         
            +
                }
         
     | 
| 
      
 1276 
     | 
    
         
            +
                if (ruby_exiting) {
         
     | 
| 
      
 1277 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
      
 1278 
     | 
    
         
            +
                }
         
     | 
| 
      
 1279 
     | 
    
         
            +
             
     | 
| 
      
 1280 
     | 
    
         
            +
                free_context_raw(arg);
         
     | 
| 
      
 1281 
     | 
    
         
            +
             
     | 
| 
      
 1282 
     | 
    
         
            +
                pthread_rwlock_unlock(&exit_lock);
         
     | 
| 
      
 1283 
     | 
    
         
            +
             
     | 
| 
       1095 
1284 
     | 
    
         
             
                return NULL;
         
     | 
| 
       1096 
1285 
     | 
    
         
             
            }
         
     | 
| 
       1097 
1286 
     | 
    
         | 
| 
         @@ -1105,22 +1294,17 @@ static void free_context(ContextInfo* context_info) { 
     | 
|
| 
       1105 
1294 
     | 
    
         
             
                context_info_copy->context = context_info->context;
         
     | 
| 
       1106 
1295 
     | 
    
         | 
| 
       1107 
1296 
     | 
    
         
             
                if (isolate_info && isolate_info->refs() > 1) {
         
     | 
| 
       1108 
     | 
    
         
            -
             
     | 
| 
       1109 
     | 
    
         
            -
             
     | 
| 
      
 1297 
     | 
    
         
            +
                    pthread_t free_context_thread;
         
     | 
| 
      
 1298 
     | 
    
         
            +
                    if (pthread_create(&free_context_thread, thread_attr_p,
         
     | 
| 
      
 1299 
     | 
    
         
            +
                                       free_context_thr, (void*)context_info_copy)) {
         
     | 
| 
       1110 
1300 
     | 
    
         
             
                        fprintf(stderr, "WARNING failed to release memory in MiniRacer, thread to release could not be created, process will leak memory\n");
         
     | 
| 
       1111 
     | 
    
         
            -
             
     | 
| 
       1112 
     | 
    
         
            -
             
     | 
| 
      
 1301 
     | 
    
         
            +
                    }
         
     | 
| 
       1113 
1302 
     | 
    
         
             
                } else {
         
     | 
| 
       1114 
     | 
    
         
            -
             
     | 
| 
      
 1303 
     | 
    
         
            +
                    free_context_raw(context_info_copy);
         
     | 
| 
       1115 
1304 
     | 
    
         
             
                }
         
     | 
| 
       1116 
1305 
     | 
    
         | 
| 
       1117 
     | 
    
         
            -
                 
     | 
| 
       1118 
     | 
    
         
            -
             
     | 
| 
       1119 
     | 
    
         
            -
                }
         
     | 
| 
       1120 
     | 
    
         
            -
             
     | 
| 
       1121 
     | 
    
         
            -
                if (isolate_info) {
         
     | 
| 
       1122 
     | 
    
         
            -
                    context_info->isolate_info = NULL;
         
     | 
| 
       1123 
     | 
    
         
            -
                }
         
     | 
| 
      
 1306 
     | 
    
         
            +
                context_info->context = NULL;
         
     | 
| 
      
 1307 
     | 
    
         
            +
                context_info->isolate_info = NULL;
         
     | 
| 
       1124 
1308 
     | 
    
         
             
            }
         
     | 
| 
       1125 
1309 
     | 
    
         | 
| 
       1126 
1310 
     | 
    
         
             
            static void deallocate_isolate(void* data) {
         
     | 
| 
         @@ -1135,7 +1319,7 @@ static void mark_isolate(void* data) { 
     | 
|
| 
       1135 
1319 
     | 
    
         
             
                isolate_info->mark();
         
     | 
| 
       1136 
1320 
     | 
    
         
             
            }
         
     | 
| 
       1137 
1321 
     | 
    
         | 
| 
       1138 
     | 
    
         
            -
            void deallocate(void* data) {
         
     | 
| 
      
 1322 
     | 
    
         
            +
            static void deallocate(void* data) {
         
     | 
| 
       1139 
1323 
     | 
    
         
             
                ContextInfo* context_info = (ContextInfo*)data;
         
     | 
| 
       1140 
1324 
     | 
    
         | 
| 
       1141 
1325 
     | 
    
         
             
                free_context(context_info);
         
     | 
| 
         @@ -1150,22 +1334,22 @@ static void mark_context(void* data) { 
     | 
|
| 
       1150 
1334 
     | 
    
         
             
                }
         
     | 
| 
       1151 
1335 
     | 
    
         
             
            }
         
     | 
| 
       1152 
1336 
     | 
    
         | 
| 
       1153 
     | 
    
         
            -
            void deallocate_external_function(void * data) {
         
     | 
| 
      
 1337 
     | 
    
         
            +
            static void deallocate_external_function(void * data) {
         
     | 
| 
       1154 
1338 
     | 
    
         
             
                xfree(data);
         
     | 
| 
       1155 
1339 
     | 
    
         
             
            }
         
     | 
| 
       1156 
1340 
     | 
    
         | 
| 
       1157 
     | 
    
         
            -
            void deallocate_snapshot(void * data) {
         
     | 
| 
      
 1341 
     | 
    
         
            +
            static void deallocate_snapshot(void * data) {
         
     | 
| 
       1158 
1342 
     | 
    
         
             
                SnapshotInfo* snapshot_info = (SnapshotInfo*)data;
         
     | 
| 
       1159 
1343 
     | 
    
         
             
                delete[] snapshot_info->data;
         
     | 
| 
       1160 
1344 
     | 
    
         
             
                xfree(snapshot_info);
         
     | 
| 
       1161 
1345 
     | 
    
         
             
            }
         
     | 
| 
       1162 
1346 
     | 
    
         | 
| 
       1163 
     | 
    
         
            -
            VALUE allocate_external_function(VALUE klass) {
         
     | 
| 
      
 1347 
     | 
    
         
            +
            static VALUE allocate_external_function(VALUE klass) {
         
     | 
| 
       1164 
1348 
     | 
    
         
             
                VALUE* self = ALLOC(VALUE);
         
     | 
| 
       1165 
1349 
     | 
    
         
             
                return Data_Wrap_Struct(klass, NULL, deallocate_external_function, (void*)self);
         
     | 
| 
       1166 
1350 
     | 
    
         
             
            }
         
     | 
| 
       1167 
1351 
     | 
    
         | 
| 
       1168 
     | 
    
         
            -
            VALUE allocate(VALUE klass) {
         
     | 
| 
      
 1352 
     | 
    
         
            +
            static VALUE allocate(VALUE klass) {
         
     | 
| 
       1169 
1353 
     | 
    
         
             
                ContextInfo* context_info = ALLOC(ContextInfo);
         
     | 
| 
       1170 
1354 
     | 
    
         
             
                context_info->isolate_info = NULL;
         
     | 
| 
       1171 
1355 
     | 
    
         
             
                context_info->context = NULL;
         
     | 
| 
         @@ -1173,7 +1357,7 @@ VALUE allocate(VALUE klass) { 
     | 
|
| 
       1173 
1357 
     | 
    
         
             
                return Data_Wrap_Struct(klass, mark_context, deallocate, (void*)context_info);
         
     | 
| 
       1174 
1358 
     | 
    
         
             
            }
         
     | 
| 
       1175 
1359 
     | 
    
         | 
| 
       1176 
     | 
    
         
            -
            VALUE allocate_snapshot(VALUE klass) {
         
     | 
| 
      
 1360 
     | 
    
         
            +
            static VALUE allocate_snapshot(VALUE klass) {
         
     | 
| 
       1177 
1361 
     | 
    
         
             
                SnapshotInfo* snapshot_info = ALLOC(SnapshotInfo);
         
     | 
| 
       1178 
1362 
     | 
    
         
             
                snapshot_info->data = NULL;
         
     | 
| 
       1179 
1363 
     | 
    
         
             
                snapshot_info->raw_size = 0;
         
     | 
| 
         @@ -1181,7 +1365,7 @@ VALUE allocate_snapshot(VALUE klass) { 
     | 
|
| 
       1181 
1365 
     | 
    
         
             
                return Data_Wrap_Struct(klass, NULL, deallocate_snapshot, (void*)snapshot_info);
         
     | 
| 
       1182 
1366 
     | 
    
         
             
            }
         
     | 
| 
       1183 
1367 
     | 
    
         | 
| 
       1184 
     | 
    
         
            -
            VALUE allocate_isolate(VALUE klass) {
         
     | 
| 
      
 1368 
     | 
    
         
            +
            static VALUE allocate_isolate(VALUE klass) {
         
     | 
| 
       1185 
1369 
     | 
    
         
             
                IsolateInfo* isolate_info = new IsolateInfo();
         
     | 
| 
       1186 
1370 
     | 
    
         | 
| 
       1187 
1371 
     | 
    
         
             
                return Data_Wrap_Struct(klass, mark_isolate, deallocate_isolate, (void*)isolate_info);
         
     | 
| 
         @@ -1201,25 +1385,90 @@ rb_heap_stats(VALUE self) { 
     | 
|
| 
       1201 
1385 
     | 
    
         | 
| 
       1202 
1386 
     | 
    
         
             
                if (!isolate) {
         
     | 
| 
       1203 
1387 
     | 
    
         | 
| 
       1204 
     | 
    
         
            -
             
     | 
| 
       1205 
     | 
    
         
            -
             
     | 
| 
       1206 
     | 
    
         
            -
             
     | 
| 
       1207 
     | 
    
         
            -
             
     | 
| 
       1208 
     | 
    
         
            -
             
     | 
| 
      
 1388 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(0));
         
     | 
| 
      
 1389 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(0));
         
     | 
| 
      
 1390 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(0));
         
     | 
| 
      
 1391 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(0));
         
     | 
| 
      
 1392 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(0));
         
     | 
| 
       1209 
1393 
     | 
    
         | 
| 
       1210 
1394 
     | 
    
         
             
                } else {
         
     | 
| 
       1211 
     | 
    
         
            -
             
     | 
| 
      
 1395 
     | 
    
         
            +
                    isolate->GetHeapStatistics(&stats);
         
     | 
| 
       1212 
1396 
     | 
    
         | 
| 
       1213 
     | 
    
         
            -
             
     | 
| 
       1214 
     | 
    
         
            -
             
     | 
| 
       1215 
     | 
    
         
            -
             
     | 
| 
       1216 
     | 
    
         
            -
             
     | 
| 
       1217 
     | 
    
         
            -
             
     | 
| 
      
 1397 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_physical_size")), ULONG2NUM(stats.total_physical_size()));
         
     | 
| 
      
 1398 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size_executable")), ULONG2NUM(stats.total_heap_size_executable()));
         
     | 
| 
      
 1399 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("total_heap_size")), ULONG2NUM(stats.total_heap_size()));
         
     | 
| 
      
 1400 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("used_heap_size")), ULONG2NUM(stats.used_heap_size()));
         
     | 
| 
      
 1401 
     | 
    
         
            +
                    rb_hash_aset(rval, ID2SYM(rb_intern("heap_size_limit")), ULONG2NUM(stats.heap_size_limit()));
         
     | 
| 
       1218 
1402 
     | 
    
         
             
                }
         
     | 
| 
       1219 
1403 
     | 
    
         | 
| 
       1220 
1404 
     | 
    
         
             
                return rval;
         
     | 
| 
       1221 
1405 
     | 
    
         
             
            }
         
     | 
| 
       1222 
1406 
     | 
    
         | 
| 
      
 1407 
     | 
    
         
            +
            // https://github.com/bnoordhuis/node-heapdump/blob/master/src/heapdump.cc
         
     | 
| 
      
 1408 
     | 
    
         
            +
            class FileOutputStream : public OutputStream {
         
     | 
| 
      
 1409 
     | 
    
         
            +
             public:
         
     | 
| 
      
 1410 
     | 
    
         
            +
              FileOutputStream(FILE* stream) : stream_(stream) {}
         
     | 
| 
      
 1411 
     | 
    
         
            +
             
     | 
| 
      
 1412 
     | 
    
         
            +
              virtual int GetChunkSize() {
         
     | 
| 
      
 1413 
     | 
    
         
            +
                return 65536;
         
     | 
| 
      
 1414 
     | 
    
         
            +
              }
         
     | 
| 
      
 1415 
     | 
    
         
            +
             
     | 
| 
      
 1416 
     | 
    
         
            +
              virtual void EndOfStream() {}
         
     | 
| 
      
 1417 
     | 
    
         
            +
             
     | 
| 
      
 1418 
     | 
    
         
            +
              virtual WriteResult WriteAsciiChunk(char* data, int size) {
         
     | 
| 
      
 1419 
     | 
    
         
            +
                const size_t len = static_cast<size_t>(size);
         
     | 
| 
      
 1420 
     | 
    
         
            +
                size_t off = 0;
         
     | 
| 
      
 1421 
     | 
    
         
            +
             
     | 
| 
      
 1422 
     | 
    
         
            +
                while (off < len && !feof(stream_) && !ferror(stream_))
         
     | 
| 
      
 1423 
     | 
    
         
            +
                  off += fwrite(data + off, 1, len - off, stream_);
         
     | 
| 
      
 1424 
     | 
    
         
            +
             
     | 
| 
      
 1425 
     | 
    
         
            +
                return off == len ? kContinue : kAbort;
         
     | 
| 
      
 1426 
     | 
    
         
            +
              }
         
     | 
| 
      
 1427 
     | 
    
         
            +
             
     | 
| 
      
 1428 
     | 
    
         
            +
             private:
         
     | 
| 
      
 1429 
     | 
    
         
            +
              FILE* stream_;
         
     | 
| 
      
 1430 
     | 
    
         
            +
            };
         
     | 
| 
      
 1431 
     | 
    
         
            +
             
     | 
| 
      
 1432 
     | 
    
         
            +
             
     | 
| 
      
 1433 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 1434 
     | 
    
         
            +
            rb_heap_snapshot(VALUE self, VALUE file) {
         
     | 
| 
      
 1435 
     | 
    
         
            +
             
     | 
| 
      
 1436 
     | 
    
         
            +
                rb_io_t *fptr;
         
     | 
| 
      
 1437 
     | 
    
         
            +
             
     | 
| 
      
 1438 
     | 
    
         
            +
                fptr = RFILE(file)->fptr;
         
     | 
| 
      
 1439 
     | 
    
         
            +
             
     | 
| 
      
 1440 
     | 
    
         
            +
                if (!fptr) return Qfalse;
         
     | 
| 
      
 1441 
     | 
    
         
            +
             
     | 
| 
      
 1442 
     | 
    
         
            +
                FILE* fp;
         
     | 
| 
      
 1443 
     | 
    
         
            +
                fp = fdopen(fptr->fd, "w");
         
     | 
| 
      
 1444 
     | 
    
         
            +
                if (fp == NULL) return Qfalse;
         
     | 
| 
      
 1445 
     | 
    
         
            +
             
     | 
| 
      
 1446 
     | 
    
         
            +
             
     | 
| 
      
 1447 
     | 
    
         
            +
                ContextInfo* context_info;
         
     | 
| 
      
 1448 
     | 
    
         
            +
                Data_Get_Struct(self, ContextInfo, context_info);
         
     | 
| 
      
 1449 
     | 
    
         
            +
                Isolate* isolate;
         
     | 
| 
      
 1450 
     | 
    
         
            +
                isolate = context_info->isolate_info ? context_info->isolate_info->isolate : NULL;
         
     | 
| 
      
 1451 
     | 
    
         
            +
             
     | 
| 
      
 1452 
     | 
    
         
            +
                if (!isolate) return Qfalse;
         
     | 
| 
      
 1453 
     | 
    
         
            +
             
     | 
| 
      
 1454 
     | 
    
         
            +
                Locker lock(isolate);
         
     | 
| 
      
 1455 
     | 
    
         
            +
                Isolate::Scope isolate_scope(isolate);
         
     | 
| 
      
 1456 
     | 
    
         
            +
                HandleScope handle_scope(isolate);
         
     | 
| 
      
 1457 
     | 
    
         
            +
             
     | 
| 
      
 1458 
     | 
    
         
            +
                HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
         
     | 
| 
      
 1459 
     | 
    
         
            +
             
     | 
| 
      
 1460 
     | 
    
         
            +
                const HeapSnapshot* const snap = heap_profiler->TakeHeapSnapshot();
         
     | 
| 
      
 1461 
     | 
    
         
            +
             
     | 
| 
      
 1462 
     | 
    
         
            +
                FileOutputStream stream(fp);
         
     | 
| 
      
 1463 
     | 
    
         
            +
                snap->Serialize(&stream, HeapSnapshot::kJSON);
         
     | 
| 
      
 1464 
     | 
    
         
            +
             
     | 
| 
      
 1465 
     | 
    
         
            +
                fflush(fp);
         
     | 
| 
      
 1466 
     | 
    
         
            +
             
     | 
| 
      
 1467 
     | 
    
         
            +
                const_cast<HeapSnapshot*>(snap)->Delete();
         
     | 
| 
      
 1468 
     | 
    
         
            +
             
     | 
| 
      
 1469 
     | 
    
         
            +
                return Qtrue;
         
     | 
| 
      
 1470 
     | 
    
         
            +
            }
         
     | 
| 
      
 1471 
     | 
    
         
            +
             
     | 
| 
       1223 
1472 
     | 
    
         
             
            static VALUE
         
     | 
| 
       1224 
1473 
     | 
    
         
             
            rb_context_stop(VALUE self) {
         
     | 
| 
       1225 
1474 
     | 
    
         | 
| 
         @@ -1255,13 +1504,23 @@ nogvl_context_call(void *args) { 
     | 
|
| 
       1255 
1504 
     | 
    
         
             
                if (!call) {
         
     | 
| 
       1256 
1505 
     | 
    
         
             
                    return NULL;
         
     | 
| 
       1257 
1506 
     | 
    
         
             
                }
         
     | 
| 
       1258 
     | 
    
         
            -
                 
     | 
| 
      
 1507 
     | 
    
         
            +
                IsolateInfo *isolate_info = call->context_info->isolate_info;
         
     | 
| 
      
 1508 
     | 
    
         
            +
                Isolate* isolate = isolate_info->isolate;
         
     | 
| 
       1259 
1509 
     | 
    
         | 
| 
       1260 
1510 
     | 
    
         
             
                // in gvl flag
         
     | 
| 
       1261 
1511 
     | 
    
         
             
                isolate->SetData(IN_GVL, (void*)false);
         
     | 
| 
       1262 
1512 
     | 
    
         
             
                // terminate ASAP
         
     | 
| 
       1263 
1513 
     | 
    
         
             
                isolate->SetData(DO_TERMINATE, (void*)false);
         
     | 
| 
       1264 
1514 
     | 
    
         | 
| 
      
 1515 
     | 
    
         
            +
                if (call->max_memory > 0) {
         
     | 
| 
      
 1516 
     | 
    
         
            +
                    isolate->SetData(MEM_SOFTLIMIT_VALUE, &call->max_memory);
         
     | 
| 
      
 1517 
     | 
    
         
            +
                    isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)false);
         
     | 
| 
      
 1518 
     | 
    
         
            +
                    if (!isolate_info->added_gc_cb) {
         
     | 
| 
      
 1519 
     | 
    
         
            +
                    isolate->AddGCEpilogueCallback(gc_callback);
         
     | 
| 
      
 1520 
     | 
    
         
            +
                        isolate_info->added_gc_cb = true;
         
     | 
| 
      
 1521 
     | 
    
         
            +
                }
         
     | 
| 
      
 1522 
     | 
    
         
            +
                }
         
     | 
| 
      
 1523 
     | 
    
         
            +
             
     | 
| 
       1265 
1524 
     | 
    
         
             
                Isolate::Scope isolate_scope(isolate);
         
     | 
| 
       1266 
1525 
     | 
    
         
             
                EscapableHandleScope handle_scope(isolate);
         
     | 
| 
       1267 
1526 
     | 
    
         
             
                TryCatch trycatch(isolate);
         
     | 
| 
         @@ -1287,8 +1546,7 @@ static void unblock_function(void *args) { 
     | 
|
| 
       1287 
1546 
     | 
    
         
             
                call->context_info->isolate_info->interrupted = true;
         
     | 
| 
       1288 
1547 
     | 
    
         
             
            }
         
     | 
| 
       1289 
1548 
     | 
    
         | 
| 
       1290 
     | 
    
         
            -
            static VALUE
         
     | 
| 
       1291 
     | 
    
         
            -
            rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
         
     | 
| 
      
 1549 
     | 
    
         
            +
            static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
         
     | 
| 
       1292 
1550 
     | 
    
         
             
                ContextInfo* context_info;
         
     | 
| 
       1293 
1551 
     | 
    
         
             
                FunctionCall call;
         
     | 
| 
       1294 
1552 
     | 
    
         
             
                VALUE *call_argv = NULL;
         
     | 
| 
         @@ -1320,8 +1578,14 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1320 
1578 
     | 
    
         
             
                    call_argv = argv + 1;
         
     | 
| 
       1321 
1579 
     | 
    
         
             
                }
         
     | 
| 
       1322 
1580 
     | 
    
         | 
| 
       1323 
     | 
    
         
            -
                 
     | 
| 
      
 1581 
     | 
    
         
            +
                call.max_memory = 0;
         
     | 
| 
      
 1582 
     | 
    
         
            +
                VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
         
     | 
| 
      
 1583 
     | 
    
         
            +
                if (mem_softlimit != Qnil) {
         
     | 
| 
      
 1584 
     | 
    
         
            +
                    unsigned long sl_int = NUM2ULONG(mem_softlimit);
         
     | 
| 
      
 1585 
     | 
    
         
            +
                    call.max_memory = (size_t)sl_int;
         
     | 
| 
      
 1586 
     | 
    
         
            +
                }
         
     | 
| 
       1324 
1587 
     | 
    
         | 
| 
      
 1588 
     | 
    
         
            +
                bool missingFunction = false;
         
     | 
| 
       1325 
1589 
     | 
    
         
             
                {
         
     | 
| 
       1326 
1590 
     | 
    
         
             
                    Locker lock(isolate);
         
     | 
| 
       1327 
1591 
     | 
    
         
             
                    Isolate::Scope isolate_scope(isolate);
         
     | 
| 
         @@ -1332,35 +1596,37 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1332 
1596 
     | 
    
         | 
| 
       1333 
1597 
     | 
    
         
             
                    // examples of such usage can be found in
         
     | 
| 
       1334 
1598 
     | 
    
         
             
                    // https://github.com/v8/v8/blob/36b32aa28db5e993312f4588d60aad5c8330c8a5/test/cctest/test-api.cc#L15711
         
     | 
| 
       1335 
     | 
    
         
            -
             
     | 
| 
       1336 
     | 
    
         
            -
             
     | 
| 
       1337 
     | 
    
         
            -
             
     | 
| 
       1338 
     | 
    
         
            -
             
     | 
| 
       1339 
     | 
    
         
            -
             
     | 
| 
       1340 
     | 
    
         
            -
            	} else {
         
     | 
| 
       1341 
     | 
    
         
            -
             
     | 
| 
       1342 
     | 
    
         
            -
            	    Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
         
     | 
| 
       1343 
     | 
    
         
            -
            	    call.fun = fun;
         
     | 
| 
       1344 
     | 
    
         
            -
            	    int fun_argc = call.argc;
         
     | 
| 
       1345 
     | 
    
         
            -
             
     | 
| 
       1346 
     | 
    
         
            -
            	    if (fun_argc > 0) {
         
     | 
| 
       1347 
     | 
    
         
            -
            		call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
         
     | 
| 
       1348 
     | 
    
         
            -
            		if (!call.argv) {
         
     | 
| 
       1349 
     | 
    
         
            -
            		    return Qnil;
         
     | 
| 
       1350 
     | 
    
         
            -
            		}
         
     | 
| 
       1351 
     | 
    
         
            -
            		for(int i=0; i < fun_argc; i++) {
         
     | 
| 
       1352 
     | 
    
         
            -
            		    call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
         
     | 
| 
       1353 
     | 
    
         
            -
            		}
         
     | 
| 
       1354 
     | 
    
         
            -
            	    }
         
     | 
| 
       1355 
     | 
    
         
            -
             
     | 
| 
       1356 
     | 
    
         
            -
            	    rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
         
     | 
| 
       1357 
     | 
    
         
            -
            	    free(call.argv);
         
     | 
| 
      
 1599 
     | 
    
         
            +
                    MaybeLocal<String> fname = String::NewFromUtf8(isolate, call.function_name);
         
     | 
| 
      
 1600 
     | 
    
         
            +
                    MaybeLocal<v8::Value> val;
         
     | 
| 
      
 1601 
     | 
    
         
            +
                    if (!fname.IsEmpty()) {
         
     | 
| 
      
 1602 
     | 
    
         
            +
                        val = context->Global()->Get(context, fname.ToLocalChecked());
         
     | 
| 
      
 1603 
     | 
    
         
            +
                    }
         
     | 
| 
       1358 
1604 
     | 
    
         | 
| 
       1359 
     | 
    
         
            -
             
     | 
| 
      
 1605 
     | 
    
         
            +
                    if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) {
         
     | 
| 
      
 1606 
     | 
    
         
            +
                        missingFunction = true;
         
     | 
| 
      
 1607 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 1608 
     | 
    
         
            +
             
     | 
| 
      
 1609 
     | 
    
         
            +
                        Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
         
     | 
| 
      
 1610 
     | 
    
         
            +
                        call.fun = fun;
         
     | 
| 
      
 1611 
     | 
    
         
            +
                        int fun_argc = call.argc;
         
     | 
| 
      
 1612 
     | 
    
         
            +
             
     | 
| 
      
 1613 
     | 
    
         
            +
                        if (fun_argc > 0) {
         
     | 
| 
      
 1614 
     | 
    
         
            +
                            call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
         
     | 
| 
      
 1615 
     | 
    
         
            +
                            if (!call.argv) {
         
     | 
| 
      
 1616 
     | 
    
         
            +
                                return Qnil;
         
     | 
| 
      
 1617 
     | 
    
         
            +
                            }
         
     | 
| 
      
 1618 
     | 
    
         
            +
                            for(int i=0; i < fun_argc; i++) {
         
     | 
| 
      
 1619 
     | 
    
         
            +
                                call.argv[i] = convert_ruby_to_v8(isolate, context, call_argv[i]);
         
     | 
| 
      
 1620 
     | 
    
         
            +
                            }
         
     | 
| 
      
 1621 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1622 
     | 
    
         
            +
                        rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
         
     | 
| 
      
 1623 
     | 
    
         
            +
                        free(call.argv);
         
     | 
| 
      
 1624 
     | 
    
         
            +
             
     | 
| 
      
 1625 
     | 
    
         
            +
                    }
         
     | 
| 
       1360 
1626 
     | 
    
         
             
                }
         
     | 
| 
       1361 
1627 
     | 
    
         | 
| 
       1362 
1628 
     | 
    
         
             
                if (missingFunction) {
         
     | 
| 
       1363 
     | 
    
         
            -
             
     | 
| 
      
 1629 
     | 
    
         
            +
                rb_raise(rb_eScriptRuntimeError, "Unknown JavaScript method invoked");
         
     | 
| 
       1364 
1630 
     | 
    
         
             
                }
         
     | 
| 
       1365 
1631 
     | 
    
         | 
| 
       1366 
1632 
     | 
    
         
             
                return convert_result_to_ruby(self, call.result);
         
     | 
| 
         @@ -1379,57 +1645,84 @@ static VALUE rb_context_create_isolate_value(VALUE self) { 
     | 
|
| 
       1379 
1645 
     | 
    
         
             
                return Data_Wrap_Struct(rb_cIsolate, NULL, &deallocate_isolate, isolate_info);
         
     | 
| 
       1380 
1646 
     | 
    
         
             
            }
         
     | 
| 
       1381 
1647 
     | 
    
         | 
| 
       1382 
     | 
    
         
            -
             
     | 
| 
       1383 
     | 
    
         
            -
             
     | 
| 
       1384 
     | 
    
         
            -
                void Init_mini_racer_extension ( void )
         
     | 
| 
       1385 
     | 
    
         
            -
                {
         
     | 
| 
       1386 
     | 
    
         
            -
            	VALUE rb_mMiniRacer = rb_define_module("MiniRacer");
         
     | 
| 
       1387 
     | 
    
         
            -
            	rb_cContext = rb_define_class_under(rb_mMiniRacer, "Context", rb_cObject);
         
     | 
| 
       1388 
     | 
    
         
            -
            	rb_cSnapshot = rb_define_class_under(rb_mMiniRacer, "Snapshot", rb_cObject);
         
     | 
| 
       1389 
     | 
    
         
            -
            	rb_cIsolate = rb_define_class_under(rb_mMiniRacer, "Isolate", rb_cObject);
         
     | 
| 
       1390 
     | 
    
         
            -
            	VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
         
     | 
| 
       1391 
     | 
    
         
            -
             
     | 
| 
       1392 
     | 
    
         
            -
            	VALUE rb_eError = rb_define_class_under(rb_mMiniRacer, "Error", rb_eStandardError);
         
     | 
| 
       1393 
     | 
    
         
            -
             
     | 
| 
       1394 
     | 
    
         
            -
            	VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
         
     | 
| 
       1395 
     | 
    
         
            -
            	rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
         
     | 
| 
       1396 
     | 
    
         
            -
            	rb_eV8OutOfMemoryError = rb_define_class_under(rb_mMiniRacer, "V8OutOfMemoryError", rb_eEvalError);
         
     | 
| 
       1397 
     | 
    
         
            -
            	rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
         
     | 
| 
       1398 
     | 
    
         
            -
            	rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
         
     | 
| 
      
 1648 
     | 
    
         
            +
            static void set_ruby_exiting(VALUE value) {
         
     | 
| 
      
 1649 
     | 
    
         
            +
                (void)value;
         
     | 
| 
       1399 
1650 
     | 
    
         | 
| 
       1400 
     | 
    
         
            -
             
     | 
| 
       1401 
     | 
    
         
            -
            	rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eError);
         
     | 
| 
       1402 
     | 
    
         
            -
            	rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eError);
         
     | 
| 
       1403 
     | 
    
         
            -
            	rb_cFailedV8Conversion = rb_define_class_under(rb_mMiniRacer, "FailedV8Conversion", rb_cObject);
         
     | 
| 
       1404 
     | 
    
         
            -
            	rb_mJSON = rb_define_module("JSON");
         
     | 
| 
      
 1651 
     | 
    
         
            +
                int res = pthread_rwlock_wrlock(&exit_lock);
         
     | 
| 
       1405 
1652 
     | 
    
         | 
| 
       1406 
     | 
    
         
            -
             
     | 
| 
       1407 
     | 
    
         
            -
             
     | 
| 
       1408 
     | 
    
         
            -
             
     | 
| 
       1409 
     | 
    
         
            -
             
     | 
| 
       1410 
     | 
    
         
            -
             
     | 
| 
       1411 
     | 
    
         
            -
            	rb_define_private_method(rb_cContext, "create_isolate_value",(VALUE(*)(...))&rb_context_create_isolate_value, 0);
         
     | 
| 
       1412 
     | 
    
         
            -
            	rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 2);
         
     | 
| 
       1413 
     | 
    
         
            -
            	rb_define_private_method(rb_cContext, "call_unsafe", (VALUE(*)(...))&rb_context_call_unsafe, -1);
         
     | 
| 
       1414 
     | 
    
         
            -
            	rb_define_private_method(rb_cContext, "isolate_mutex", (VALUE(*)(...))&rb_context_isolate_mutex, 0);
         
     | 
| 
       1415 
     | 
    
         
            -
            	rb_define_private_method(rb_cContext, "init_unsafe",(VALUE(*)(...))&rb_context_init_unsafe, 2);
         
     | 
| 
       1416 
     | 
    
         
            -
             
     | 
| 
       1417 
     | 
    
         
            -
            	rb_define_alloc_func(rb_cContext, allocate);
         
     | 
| 
       1418 
     | 
    
         
            -
            	rb_define_alloc_func(rb_cSnapshot, allocate_snapshot);
         
     | 
| 
       1419 
     | 
    
         
            -
            	rb_define_alloc_func(rb_cIsolate, allocate_isolate);
         
     | 
| 
       1420 
     | 
    
         
            -
             
     | 
| 
       1421 
     | 
    
         
            -
            	rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
         
     | 
| 
       1422 
     | 
    
         
            -
            	rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
         
     | 
| 
       1423 
     | 
    
         
            -
             
     | 
| 
       1424 
     | 
    
         
            -
            	rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
         
     | 
| 
       1425 
     | 
    
         
            -
            	rb_define_method(rb_cSnapshot, "dump", (VALUE(*)(...))&rb_snapshot_dump, 0);
         
     | 
| 
       1426 
     | 
    
         
            -
            	rb_define_method(rb_cSnapshot, "warmup_unsafe!", (VALUE(*)(...))&rb_snapshot_warmup_unsafe, 1);
         
     | 
| 
       1427 
     | 
    
         
            -
            	rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1);
         
     | 
| 
      
 1653 
     | 
    
         
            +
                ruby_exiting  = true;
         
     | 
| 
      
 1654 
     | 
    
         
            +
                if (res == 0) {
         
     | 
| 
      
 1655 
     | 
    
         
            +
                    pthread_rwlock_unlock(&exit_lock);
         
     | 
| 
      
 1656 
     | 
    
         
            +
                }
         
     | 
| 
      
 1657 
     | 
    
         
            +
            }
         
     | 
| 
       1428 
1658 
     | 
    
         | 
| 
       1429 
     | 
    
         
            -
             
     | 
| 
       1430 
     | 
    
         
            -
            	rb_define_private_method(rb_cIsolate, "init_with_snapshot",(VALUE(*)(...))&rb_isolate_init_with_snapshot, 1);
         
     | 
| 
      
 1659 
     | 
    
         
            +
            extern "C" {
         
     | 
| 
       1431 
1660 
     | 
    
         | 
| 
       1432 
     | 
    
         
            -
             
     | 
| 
      
 1661 
     | 
    
         
            +
                __attribute__((visibility("default"))) void Init_mini_racer_extension ( void )
         
     | 
| 
      
 1662 
     | 
    
         
            +
                {
         
     | 
| 
      
 1663 
     | 
    
         
            +
                    VALUE rb_mMiniRacer = rb_define_module("MiniRacer");
         
     | 
| 
      
 1664 
     | 
    
         
            +
                    rb_cContext = rb_define_class_under(rb_mMiniRacer, "Context", rb_cObject);
         
     | 
| 
      
 1665 
     | 
    
         
            +
                    rb_cSnapshot = rb_define_class_under(rb_mMiniRacer, "Snapshot", rb_cObject);
         
     | 
| 
      
 1666 
     | 
    
         
            +
                    rb_cIsolate = rb_define_class_under(rb_mMiniRacer, "Isolate", rb_cObject);
         
     | 
| 
      
 1667 
     | 
    
         
            +
                    VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
         
     | 
| 
      
 1668 
     | 
    
         
            +
             
     | 
| 
      
 1669 
     | 
    
         
            +
                    VALUE rb_eError = rb_define_class_under(rb_mMiniRacer, "Error", rb_eStandardError);
         
     | 
| 
      
 1670 
     | 
    
         
            +
             
     | 
| 
      
 1671 
     | 
    
         
            +
                    VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eError);
         
     | 
| 
      
 1672 
     | 
    
         
            +
                    rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
         
     | 
| 
      
 1673 
     | 
    
         
            +
                    rb_eV8OutOfMemoryError = rb_define_class_under(rb_mMiniRacer, "V8OutOfMemoryError", rb_eEvalError);
         
     | 
| 
      
 1674 
     | 
    
         
            +
                    rb_eParseError = rb_define_class_under(rb_mMiniRacer, "ParseError", rb_eEvalError);
         
     | 
| 
      
 1675 
     | 
    
         
            +
                    rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
         
     | 
| 
      
 1676 
     | 
    
         
            +
             
     | 
| 
      
 1677 
     | 
    
         
            +
                    rb_cJavaScriptFunction = rb_define_class_under(rb_mMiniRacer, "JavaScriptFunction", rb_cObject);
         
     | 
| 
      
 1678 
     | 
    
         
            +
                    rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eError);
         
     | 
| 
      
 1679 
     | 
    
         
            +
                    rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eError);
         
     | 
| 
      
 1680 
     | 
    
         
            +
                    rb_cFailedV8Conversion = rb_define_class_under(rb_mMiniRacer, "FailedV8Conversion", rb_cObject);
         
     | 
| 
      
 1681 
     | 
    
         
            +
                    rb_mJSON = rb_define_module("JSON");
         
     | 
| 
      
 1682 
     | 
    
         
            +
             
     | 
| 
      
 1683 
     | 
    
         
            +
                    VALUE rb_cExternalFunction = rb_define_class_under(rb_cContext, "ExternalFunction", rb_cObject);
         
     | 
| 
      
 1684 
     | 
    
         
            +
             
     | 
| 
      
 1685 
     | 
    
         
            +
                    rb_define_method(rb_cContext, "stop", (VALUE(*)(...))&rb_context_stop, 0);
         
     | 
| 
      
 1686 
     | 
    
         
            +
                    rb_define_method(rb_cContext, "dispose_unsafe", (VALUE(*)(...))&rb_context_dispose, 0);
         
     | 
| 
      
 1687 
     | 
    
         
            +
                    rb_define_method(rb_cContext, "heap_stats", (VALUE(*)(...))&rb_heap_stats, 0);
         
     | 
| 
      
 1688 
     | 
    
         
            +
            	rb_define_method(rb_cContext, "write_heap_snapshot_unsafe", (VALUE(*)(...))&rb_heap_snapshot, 1);
         
     | 
| 
      
 1689 
     | 
    
         
            +
             
     | 
| 
      
 1690 
     | 
    
         
            +
                    rb_define_private_method(rb_cContext, "create_isolate_value",(VALUE(*)(...))&rb_context_create_isolate_value, 0);
         
     | 
| 
      
 1691 
     | 
    
         
            +
                    rb_define_private_method(rb_cContext, "eval_unsafe",(VALUE(*)(...))&rb_context_eval_unsafe, 2);
         
     | 
| 
      
 1692 
     | 
    
         
            +
                    rb_define_private_method(rb_cContext, "call_unsafe", (VALUE(*)(...))&rb_context_call_unsafe, -1);
         
     | 
| 
      
 1693 
     | 
    
         
            +
                    rb_define_private_method(rb_cContext, "isolate_mutex", (VALUE(*)(...))&rb_context_isolate_mutex, 0);
         
     | 
| 
      
 1694 
     | 
    
         
            +
                    rb_define_private_method(rb_cContext, "init_unsafe",(VALUE(*)(...))&rb_context_init_unsafe, 2);
         
     | 
| 
      
 1695 
     | 
    
         
            +
             
     | 
| 
      
 1696 
     | 
    
         
            +
                    rb_define_alloc_func(rb_cContext, allocate);
         
     | 
| 
      
 1697 
     | 
    
         
            +
                    rb_define_alloc_func(rb_cSnapshot, allocate_snapshot);
         
     | 
| 
      
 1698 
     | 
    
         
            +
                    rb_define_alloc_func(rb_cIsolate, allocate_isolate);
         
     | 
| 
      
 1699 
     | 
    
         
            +
             
     | 
| 
      
 1700 
     | 
    
         
            +
                    rb_define_private_method(rb_cExternalFunction, "notify_v8", (VALUE(*)(...))&rb_external_function_notify_v8, 0);
         
     | 
| 
      
 1701 
     | 
    
         
            +
                    rb_define_alloc_func(rb_cExternalFunction, allocate_external_function);
         
     | 
| 
      
 1702 
     | 
    
         
            +
             
     | 
| 
      
 1703 
     | 
    
         
            +
                    rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
         
     | 
| 
      
 1704 
     | 
    
         
            +
                    rb_define_method(rb_cSnapshot, "dump", (VALUE(*)(...))&rb_snapshot_dump, 0);
         
     | 
| 
      
 1705 
     | 
    
         
            +
                    rb_define_method(rb_cSnapshot, "warmup_unsafe!", (VALUE(*)(...))&rb_snapshot_warmup_unsafe, 1);
         
     | 
| 
      
 1706 
     | 
    
         
            +
                    rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1);
         
     | 
| 
      
 1707 
     | 
    
         
            +
             
     | 
| 
      
 1708 
     | 
    
         
            +
                    rb_define_method(rb_cIsolate, "idle_notification", (VALUE(*)(...))&rb_isolate_idle_notification, 1);
         
     | 
| 
      
 1709 
     | 
    
         
            +
                    rb_define_method(rb_cIsolate, "low_memory_notification", (VALUE(*)(...))&rb_isolate_low_memory_notification, 0);
         
     | 
| 
      
 1710 
     | 
    
         
            +
                    rb_define_method(rb_cIsolate, "pump_message_loop", (VALUE(*)(...))&rb_isolate_pump_message_loop, 0);
         
     | 
| 
      
 1711 
     | 
    
         
            +
                    rb_define_private_method(rb_cIsolate, "init_with_snapshot",(VALUE(*)(...))&rb_isolate_init_with_snapshot, 1);
         
     | 
| 
      
 1712 
     | 
    
         
            +
             
     | 
| 
      
 1713 
     | 
    
         
            +
                    rb_define_singleton_method(rb_cPlatform, "set_flag_as_str!", (VALUE(*)(...))&rb_platform_set_flag_as_str, 1);
         
     | 
| 
      
 1714 
     | 
    
         
            +
             
     | 
| 
      
 1715 
     | 
    
         
            +
                    rb_set_end_proc(set_ruby_exiting, Qnil);
         
     | 
| 
      
 1716 
     | 
    
         
            +
             
     | 
| 
      
 1717 
     | 
    
         
            +
                    static pthread_attr_t attr;
         
     | 
| 
      
 1718 
     | 
    
         
            +
                    if (pthread_attr_init(&attr) == 0) {
         
     | 
| 
      
 1719 
     | 
    
         
            +
                        if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0) {
         
     | 
| 
      
 1720 
     | 
    
         
            +
                            thread_attr_p = &attr;
         
     | 
| 
      
 1721 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1722 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1723 
     | 
    
         
            +
                    auto on_fork_for_child = []() {
         
     | 
| 
      
 1724 
     | 
    
         
            +
                        exit_lock = PTHREAD_RWLOCK_INITIALIZER;
         
     | 
| 
      
 1725 
     | 
    
         
            +
                    };
         
     | 
| 
      
 1726 
     | 
    
         
            +
                    pthread_atfork(nullptr, nullptr, on_fork_for_child);
         
     | 
| 
       1433 
1727 
     | 
    
         
             
                }
         
     | 
| 
       1434 
     | 
    
         
            -
             
     | 
| 
       1435 
1728 
     | 
    
         
             
            }
         
     |