From 3c6832c07b2c6073e547de79da5badc00041ddad Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 27 Jun 2018 12:15:03 +1000 Subject: [PATCH] correct tests, repair snapshot in debug mode --- .../mini_racer_extension.cc | 12 +++++-- lib/mini_racer.rb | 31 ++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/ext/mini_racer_extension/mini_racer_extension.cc b/ext/mini_racer_extension/mini_racer_extension.cc index b6a1700..2bf5bef 100644 --- a/ext/mini_racer_extension/mini_racer_extension.cc +++ b/ext/mini_racer_extension/mini_racer_extension.cc @@ -562,7 +562,7 @@ static VALUE rb_snapshot_load(VALUE self, VALUE str) { return Qnil; } -static VALUE rb_snapshot_warmup(VALUE self, VALUE str) { +static VALUE rb_snapshot_warmup_unsafe(VALUE self, VALUE str) { SnapshotInfo* snapshot_info; Data_Get_Struct(self, SnapshotInfo, snapshot_info); @@ -1275,6 +1275,8 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { call_argv = argv + 1; } + bool missingFunction = false; + { Locker lock(isolate); Isolate::Scope isolate_scope(isolate); @@ -1289,7 +1291,7 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { MaybeLocal val = context->Global()->Get(fname); if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) { - return Qnil; + missingFunction = true; } else { Local fun = Local::Cast(val.ToLocalChecked()); @@ -1312,6 +1314,10 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) { } } + if (missingFunction) { + rb_raise(rb_eScriptRuntimeError, "Unknown JavaScript method invoked"); + } + return convert_result_to_ruby(self, call.result); } @@ -1371,7 +1377,7 @@ extern "C" { rb_define_alloc_func(rb_cExternalFunction, allocate_external_function); rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0); - rb_define_method(rb_cSnapshot, "warmup!", (VALUE(*)(...))&rb_snapshot_warmup, 1); + rb_define_method(rb_cSnapshot, "warmup_unsafe!", (VALUE(*)(...))&rb_snapshot_warmup_unsafe, 1); rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1); rb_define_method(rb_cIsolate, "idle_notification", (VALUE(*)(...))&rb_isolate_idle_notification, 1); diff --git a/lib/mini_racer.rb b/lib/mini_racer.rb index 85c7a8d..74ffefa 100644 --- a/lib/mini_racer.rb +++ b/lib/mini_racer.rb @@ -212,11 +212,13 @@ module MiniRacer wrapped = lambda do |*args| begin + r = nil + begin @callback_mutex.synchronize{ @callback_running = true } - callback.call(*args) + r = callback.call(*args) ensure @callback_mutex.synchronize{ @callback_running = false @@ -232,6 +234,8 @@ module MiniRacer end } + r + ensure @callback_mutex.synchronize { @thread_raise_called = false @@ -311,8 +315,33 @@ module MiniRacer # `size` and `warmup!` public methods are defined in the C class class Snapshot def initialize(str = '') + # ensure it first can load + begin + ctx = MiniRacer::Context.new + ctx.eval(str) + rescue MiniRacer::RuntimeError => e + raise MiniRacer::SnapshotError.new, e.message + end + + @source = str + # defined in the C class load(str) end + + def warmup!(src) + # we have to do something here + # we are bloating memory a bit but it is more correct + # than hitting an exception when attempty to compile invalid source + begin + ctx = MiniRacer::Context.new + ctx.eval(@source) + ctx.eval(src) + rescue MiniRacer::RuntimeError => e + raise MiniRacer::SnapshotError.new, e.message + end + + warmup_unsafe!(src) + end end end