diff --git a/README.md b/README.md index e750d7f..a0e0289 100644 --- a/README.md +++ b/README.md @@ -97,19 +97,6 @@ context.eval("var a = new Array(10000); while(true) {a = a.concat(new Array(1000 # => V8OutOfMemoryError is raised ``` -### Object marshal max Stack Ddepth Support - -Contexts can specify a stack depth limit for object marshalling. Max depth is unbounded by default. - -```ruby -# terminates script if stack depth exceeds max during marshal -context = MiniRacer::Context.new(marshal_stack_depth: 500) -context.attach("a", proc{|a| a}) - -context.eval("let arr = []; arr.push(arr); a(arr)") -# => RuntimeError is raised -``` - ### Rich Debugging with File Name in Stack Trace Support You can provide `filename:` to `#eval` which will be used in stack traces produced by V8: @@ -208,25 +195,7 @@ context.eval("counter") ### Garbage collection -Re-using the same context over and over again means V8's garbage collector will have to run to clean it up every now and then; it's possible to trigger a _blocking_ V8 GC run inside your context by running the `idle_notification` method on it, which takes a single argument: the amount of time (in milliseconds) that V8 should use at most for garbage collecting: - -```ruby -context = MiniRacer::Context.new - -# do stuff with that context... - -# give up to 100ms for V8 garbage collection -context.idle_notification(100) - -# force V8 to perform a full GC -context.low_memory_notification -``` - -This can come in handy to force V8 GC runs for example in between requests if you use MiniRacer on a web application. - -Note that this method maps directly to [`v8::Isolate::IdleNotification`](http://bespin.cz/~ondras/html/classv8_1_1Isolate.html#aea16cbb2e351de9a3ae7be2b7cb48297), and that in particular its return value is the same (true if there is no further garbage to collect, false otherwise) and the same caveats apply, in particular that `there is no guarantee that the [call will return] within the time limit.` - -Additionally you may automate this process on a context by defining it with `MiniRacer::Context.new(ensure_gc_after_idle: 1000)`. Using this will ensure V8 will run a full GC using `context.low_memory_notification` 1 second after the last eval on the context. Low memory notification is both slower and more aggressive than an idle_notification and will ensure long living contexts use minimal amounts of memory. +You can make the garbage collector more aggressive by defining the context with `MiniRacer::Context.new(ensure_gc_after_idle: 1000)`. Using this will ensure V8 will run a full GC using `context.low_memory_notification` 1 second after the last eval on the context. Low memory notifications ensure long living contexts use minimal amounts of memory. ### V8 Runtime flags @@ -395,7 +364,8 @@ Or install it yourself as: $ gem install mini_racer ``` -**Note** using v8.h and compiling MiniRacer requires a C++11 standard compiler, more specifically clang 3.5 (or later) or GCC 6.3 (or later). +**Note** using v8.h and compiling MiniRacer requires a C++20 capable compiler. +gcc >= 12.2 and Xcode >= 13 are, at the time of writing, known to work. ## Similar Projects diff --git a/ext/mini_racer_extension/extconf.rb b/ext/mini_racer_extension/extconf.rb index 93ef03c..a8e09c8 100644 --- a/ext/mini_racer_extension/extconf.rb +++ b/ext/mini_racer_extension/extconf.rb @@ -19,7 +19,7 @@ $CXXFLAGS += " -g" unless $CXXFLAGS.split.include? "-g" $CXXFLAGS += " -rdynamic" unless $CXXFLAGS.split.include? "-rdynamic" $CXXFLAGS += " -fPIC" unless $CXXFLAGS.split.include? "-rdynamic" or IS_DARWIN -$CXXFLAGS += " -std=c++17" +$CXXFLAGS += " -std=c++20" $CXXFLAGS += " -fpermissive" $CXXFLAGS += " -fno-rtti" $CXXFLAGS += " -fno-exceptions" @@ -47,28 +47,6 @@ CONFIG['CXX'] = ENV['CXX'] end -CXX11_TEST = <pst); - case 'I': return v8_idle_notification(c->pst, p+1, n-1); case 'P': return v8_pump_message_loop(c->pst); case 'S': return v8_heap_stats(c->pst); case 'T': return v8_snapshot(c->pst, p+1, n-1); @@ -1301,20 +1300,6 @@ static VALUE context_pump_message_loop(VALUE self) return rendezvous(c, &b); // takes ownership of |b| } -static VALUE context_idle_notification(VALUE self, VALUE arg) -{ - Context *c; - Ser s; - - Check_Type(arg, T_FIXNUM); - TypedData_Get_Struct(self, Context, &context_type, c); - // request is (I)dle notification, idle_time_in_seconds - ser_init1(&s, 'I'); - ser_num(&s, LONG2FIX(arg) / 1e3); - // response is |undefined| - return rendezvous(c, &s.b); // takes ownership of |s.b| -} - static VALUE context_low_memory_notification(VALUE self) { Buf req, res; @@ -1638,7 +1623,6 @@ void Init_mini_racer_extension(void) rb_define_method(c, "heap_stats", context_heap_stats, 0); rb_define_method(c, "heap_snapshot", context_heap_snapshot, 0); rb_define_method(c, "pump_message_loop", context_pump_message_loop, 0); - rb_define_method(c, "idle_notification", context_idle_notification, 1); rb_define_method(c, "low_memory_notification", context_low_memory_notification, 0); rb_define_alloc_func(c, context_alloc); diff --git a/ext/mini_racer_extension/mini_racer_v8.cc b/ext/mini_racer_extension/mini_racer_v8.cc index 64d4870..f8c1946 100644 --- a/ext/mini_racer_extension/mini_racer_v8.cc +++ b/ext/mini_racer_extension/mini_racer_v8.cc @@ -834,26 +834,6 @@ extern "C" void v8_warmup(State *pst, const uint8_t *p, size_t n) } } -extern "C" void v8_idle_notification(State *pst, const uint8_t *p, size_t n) -{ - State& st = *pst; - v8::TryCatch try_catch(st.isolate); - v8::HandleScope handle_scope(st.isolate); - v8::ValueDeserializer des(st.isolate, p, n); - des.ReadHeader(st.context).Check(); - double idle_time_in_seconds = .01; - { - v8::Local idle_time_in_seconds_v; - if (!des.ReadValue(st.context).ToLocal(&idle_time_in_seconds_v)) goto fail; - if (!idle_time_in_seconds_v->NumberValue(st.context).To(&idle_time_in_seconds)) goto fail; - } -fail: - double now = platform->MonotonicallyIncreasingTime(); - bool stop = st.isolate->IdleNotificationDeadline(now + idle_time_in_seconds); - auto result = v8::Boolean::New(st.isolate, stop); - if (!reply(st, result)) abort(); -} - extern "C" void v8_low_memory_notification(State *pst) { pst->isolate->LowMemoryNotification(); diff --git a/ext/mini_racer_extension/mini_racer_v8.h b/ext/mini_racer_extension/mini_racer_v8.h index 2ed3f07..5bd47ba 100644 --- a/ext/mini_racer_extension/mini_racer_v8.h +++ b/ext/mini_racer_extension/mini_racer_v8.h @@ -45,7 +45,6 @@ void v8_heap_snapshot(struct State *pst); void v8_pump_message_loop(struct State *pst); void v8_snapshot(struct State *pst, const uint8_t *p, size_t n); void v8_warmup(struct State *pst, const uint8_t *p, size_t n); -void v8_idle_notification(struct State *pst, const uint8_t *p, size_t n); void v8_low_memory_notification(struct State *pst); void v8_terminate_execution(struct State *pst); // called from ruby or watchdog thread void v8_single_threaded_enter(struct State *pst, struct Context *c, void (*f)(struct Context *c)); diff --git a/lib/mini_racer/truffleruby.rb b/lib/mini_racer/truffleruby.rb index 5beed70..1540085 100644 --- a/lib/mini_racer/truffleruby.rb +++ b/lib/mini_racer/truffleruby.rb @@ -67,10 +67,6 @@ def low_memory_notification GC.start end - def idle_notification(idle_time) - true - end - private @context_initialized = false diff --git a/lib/mini_racer/version.rb b/lib/mini_racer/version.rb index 068aff1..2d7bce1 100644 --- a/lib/mini_racer/version.rb +++ b/lib/mini_racer/version.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true module MiniRacer - VERSION = "0.17.0.pre13" - LIBV8_NODE_VERSION = "~> 22.7.0.4" + VERSION = "0.18.0.pre1" + LIBV8_NODE_VERSION = "~> 23.6.1.0" end diff --git a/test/mini_racer_test.rb b/test/mini_racer_test.rb index 00eaa44..c387138 100644 --- a/test/mini_racer_test.rb +++ b/test/mini_racer_test.rb @@ -594,13 +594,6 @@ def test_isolates_from_snapshot_dont_get_corrupted_if_the_snapshot_gets_warmed_u assert_equal "function", context2.eval("typeof(Math.sin)") end - def test_isolate_can_be_notified_of_idle_time - context = MiniRacer::Context.new - - # returns true if embedder should stop calling - assert(context.idle_notification(1000)) - end - def test_platform_set_flags_raises_an_exception_if_already_initialized # makes sure it's initialized MiniRacer::Snapshot.new