mini_racer_rs 1.0.0 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41191c7e0a6bf53c0371de7ba31f7067b3d83b0095579d6955a75a9021c4a5b0
4
- data.tar.gz: 7b0424bbabd9fcd45122dc81b6b449e3c30d7ffb218ec43eff973ae4d8c70772
3
+ metadata.gz: aeb35a422c03ec1f8366cc6794daefa2cbacd69d8e113c0e1cb1d369a274cf07
4
+ data.tar.gz: e672b7b588ec4eb10e95317af8eea2a5d03aaf7340200b70c307f6a74e988606
5
5
  SHA512:
6
- metadata.gz: b864cac2b4d1f3108deea75e4bc5a10de16c94ce73be5c5824f7443922a86d94f6d1ff933a1008632c971f1eafdef57a452631661bc82807799b339ff7e15ca5
7
- data.tar.gz: '0391a874e20db2b91f6c1916efa0c39f05178b68e9223dc2709aeb2fa6ad6026de9bba898f8bea5f8764193df36c0291fb8af8afab738029db3ef4a537354bb4'
6
+ metadata.gz: 95f7422df0c8a5f74675fdcdcf9ba1d9e9c3e7278a67b1bd57a4964ee38a022570b2b968db0a3b81af8e6320b2d2bbb9d98489bdfd87b3a8f78edb5971a595f9
7
+ data.tar.gz: 5288702eb114fe82c194a5071e15c99f36e6d2dbfb7c6541813074b89fb774a446dd84f4198c494306401a26cfda8932a082d8904f28bd468f01cda11bc29dcd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.1](https://github.com/andymai/mini_racer_rs/compare/v1.0.0...v1.0.1) (2026-10-18)
4
+
5
+
6
+ ### Performance
7
+
8
+ * **engine:** build small call arguments in the runner and write primitive results directly ([#83](https://github.com/andymai/mini_racer_rs/issues/83)) ([76afcbd](https://github.com/andymai/mini_racer_rs/commit/76afcbd7bb5df36da6797b95d8dae7049ee80f53))
9
+
3
10
  ## 1.0.0 (2026-10-18)
4
11
 
5
12
 
data/Cargo.lock CHANGED
@@ -458,7 +458,7 @@ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
458
458
 
459
459
  [[package]]
460
460
  name = "mini_racer_engine"
461
- version = "1.0.0"
461
+ version = "1.0.1"
462
462
  dependencies = [
463
463
  "deno_core_icudata",
464
464
  "libc",
@@ -470,7 +470,7 @@ dependencies = [
470
470
 
471
471
  [[package]]
472
472
  name = "mini_racer_rs"
473
- version = "1.0.0"
473
+ version = "1.0.1"
474
474
  dependencies = [
475
475
  "magnus",
476
476
  "mini_racer_engine",
@@ -481,7 +481,7 @@ dependencies = [
481
481
 
482
482
  [[package]]
483
483
  name = "mini_racer_sync"
484
- version = "1.0.0"
484
+ version = "1.0.1"
485
485
  dependencies = [
486
486
  "loom",
487
487
  "thiserror",
@@ -489,7 +489,7 @@ dependencies = [
489
489
 
490
490
  [[package]]
491
491
  name = "mini_racer_wire"
492
- version = "1.0.0"
492
+ version = "1.0.1"
493
493
  dependencies = [
494
494
  "proptest",
495
495
  "thiserror",
data/Cargo.toml CHANGED
@@ -14,7 +14,7 @@ license = "MIT"
14
14
  publish = false
15
15
  repository = "https://github.com/andymai/mini_racer_rs"
16
16
  rust-version = "1.91"
17
- version = "1.0.0"
17
+ version = "1.0.1"
18
18
 
19
19
  [workspace.dependencies]
20
20
  deno_core_icudata = "=0.78.0"
data/README.md CHANGED
@@ -17,7 +17,7 @@ A drop-in replacement for mini_racer, implemented in Rust on V8 15.2.
17
17
 
18
18
  mini_racer_rs implements the `MiniRacer` Ruby API from mini_racer 0.22.1, with faster Ruby and JavaScript round trips, V8 15.2, prebuilt native gems, fiber scheduler support, and safer handling of difficult values. It defines the `MiniRacer` namespace and ships `lib/mini_racer.rb`, so `require "mini_racer"` and ExecJS continue to work.
19
19
 
20
- > **Pre-release:** Nothing is published to RubyGems.org yet, and the release workflow is held. Install from the repository until the first release. mini_racer_rs is an independent project and is not affiliated with the Discourse staff who maintain mini_racer.
20
+ > mini_racer_rs is an independent project and is not affiliated with the Discourse staff who maintain mini_racer.
21
21
 
22
22
  ## Highlights
23
23
 
@@ -46,7 +46,7 @@ The package switch is one Gemfile line:
46
46
 
47
47
  Run `bundle install`. Bundler is required because RubyGems may otherwise activate the original `mini_racer` first. Loading both gems raises a `LoadError` that names the conflict. Reverse the Gemfile change to switch back.
48
48
 
49
- Until the first release publishes native gems, build from a checkout as described in [CONTRIBUTING.md](CONTRIBUTING.md). Run `bin/setup`. Source builds require Rust 1.91 or newer and libclang. Once published, installing a native gem will compile nothing.
49
+ On x86_64-linux-gnu, aarch64-linux-gnu, arm64-darwin, and x86_64-darwin, `bundle install` installs a native gem and compiles nothing. Elsewhere, the source gem builds the extension and requires Rust 1.91 or newer and libclang. To build from a checkout, follow [CONTRIBUTING.md](CONTRIBUTING.md) and run `bin/setup`.
50
50
 
51
51
  ## Quick start
52
52
 
@@ -143,8 +143,6 @@ See [COMPATIBILITY.md](COMPATIBILITY.md) for every difference.
143
143
 
144
144
  - You deploy on musl-based Linux such as Alpine. mini_racer supports it through libv8-node's musl gems, while mini_racer_rs does not install there. Neither gem supports Windows.
145
145
 
146
- - You need a gem from RubyGems.org today. mini_racer_rs is pre-release, while mini_racer is the established gem maintained by Discourse staff.
147
-
148
146
  - Download size matters more than compile time. The largest mini_racer_rs native gem is 65.6 MB because it includes extensions for three Ruby versions. The mini_racer download on x86_64 Linux is 47.1 MB, followed by compilation.
149
147
 
150
148
  ### Gems that depend on mini_racer
@@ -8,7 +8,9 @@ use mini_racer_sync::{
8
8
  Channel, ChannelError, DispatchKind, Inherited, Interrupt, Phase, Side, TermError, ToRuby, lock,
9
9
  };
10
10
 
11
- use crate::control::{CallbackReply, ContextConfig, ControlBlock, Depth, JsText, Request, Wire};
11
+ use crate::control::{
12
+ CallRequest, CallbackReply, ContextConfig, ControlBlock, Depth, JsText, Request, Wire,
13
+ };
12
14
  use crate::notify::NotifyFd;
13
15
  use crate::process::fork::{self, Generation};
14
16
  use crate::process::platform::Mode;
@@ -287,16 +289,14 @@ impl ContextHandle {
287
289
  )
288
290
  }
289
291
 
290
- /// `request` is the wire form `mini_racer` sends: one array holding the
291
- /// function's dotted path, then its arguments.
292
- pub fn call(&self, request: Vec<u8>, host: &mut impl Host) -> Result<Vec<u8>, EngineError> {
292
+ pub fn call(&self, request: CallRequest, host: &mut impl Host) -> Result<Vec<u8>, EngineError> {
293
293
  self.invoke(request, false, host)
294
294
  }
295
295
 
296
296
  /// `call`, then awaits a promise result, as `eval_await` does.
297
297
  pub fn call_await(
298
298
  &self,
299
- request: Vec<u8>,
299
+ request: CallRequest,
300
300
  host: &mut impl Host,
301
301
  ) -> Result<Vec<u8>, EngineError> {
302
302
  self.invoke(request, true, host)
@@ -304,7 +304,7 @@ impl ContextHandle {
304
304
 
305
305
  fn invoke(
306
306
  &self,
307
- request: Vec<u8>,
307
+ request: CallRequest,
308
308
  awaited: bool,
309
309
  host: &mut impl Host,
310
310
  ) -> Result<Vec<u8>, EngineError> {
@@ -784,6 +784,11 @@ fn adopt(inherited: &ControlBlock, carried: Inherited) -> Held {
784
784
  let block = Arc::new(ControlBlock::with_tasks(inherited.config.clone(), tasks));
785
785
  *lock(&block.custody) = Some(isolate);
786
786
  block.term.adopt(carried);
787
+ // The isolate keeps whatever termination V8 still held for it.
788
+ block.termination_requested.store(
789
+ inherited.termination_requested.load(Ordering::Acquire),
790
+ Ordering::Release,
791
+ );
787
792
  match start(&block, generation, Start::Adopted) {
788
793
  Ok(()) => Held::Block(block),
789
794
  Err(_) => orphaned(true, false),
@@ -1,3 +1,4 @@
1
+ use std::sync::atomic::{AtomicBool, Ordering};
1
2
  use std::sync::{Arc, Mutex, OnceLock};
2
3
  use std::time::{Duration, Instant};
3
4
 
@@ -66,6 +67,17 @@ impl From<&str> for JsText {
66
67
  }
67
68
  }
68
69
 
70
+ /// A call in the wire form `mini_racer` sends: one array holding the
71
+ /// function's dotted path, then its arguments.
72
+ ///
73
+ /// `objects` and `properties` count the objects the arguments hold and their
74
+ /// properties in all, which decide whether the runner builds the arguments.
75
+ pub struct CallRequest {
76
+ pub bytes: Vec<u8>,
77
+ pub objects: usize,
78
+ pub properties: usize,
79
+ }
80
+
69
81
  pub enum Request {
70
82
  Init {
71
83
  depth: Depth,
@@ -78,7 +90,7 @@ pub enum Request {
78
90
  awaited: bool,
79
91
  },
80
92
  Call {
81
- request: Vec<u8>,
93
+ request: CallRequest,
82
94
  depth: Depth,
83
95
  awaited: bool,
84
96
  },
@@ -117,13 +129,15 @@ pub enum Request {
117
129
  pub struct IsolateTerminator {
118
130
  handle: v8::IsolateHandle,
119
131
  tasks: Arc<Tasks>,
132
+ requested: Arc<AtomicBool>,
120
133
  }
121
134
 
122
135
  impl IsolateTerminator {
123
- pub fn new(handle: v8::IsolateHandle, tasks: &Arc<Tasks>) -> Self {
136
+ pub fn new(block: &ControlBlock, handle: v8::IsolateHandle) -> Self {
124
137
  Self {
125
138
  handle,
126
- tasks: Arc::clone(tasks),
139
+ tasks: Arc::clone(&block.tasks),
140
+ requested: Arc::clone(&block.termination_requested),
127
141
  }
128
142
  }
129
143
  }
@@ -132,12 +146,14 @@ impl Terminator for IsolateTerminator {
132
146
  // A runner awaiting a promise sleeps until a task is due; the ring wakes
133
147
  // it to find the termination.
134
148
  fn terminate(&self) {
149
+ self.requested.store(true, Ordering::Release);
135
150
  self.handle.terminate_execution();
136
151
  self.tasks.ring();
137
152
  }
138
153
 
139
154
  fn cancel(&self) {
140
155
  self.handle.cancel_terminate_execution();
156
+ self.requested.store(false, Ordering::Release);
141
157
  }
142
158
  }
143
159
 
@@ -178,6 +194,10 @@ pub struct ControlBlock {
178
194
  // V8's foreground tasks for this context's isolate, which the runner runs
179
195
  // while awaiting a promise or pumping.
180
196
  pub tasks: Arc<Tasks>,
197
+ /// Set before anything asks V8 to terminate this context's script, and
198
+ /// cleared only once V8 has cancelled every such request, so a runner
199
+ /// building values itself knows when V8's own reader would stop instead.
200
+ pub termination_requested: Arc<AtomicBool>,
181
201
  pub phase: RunnerPhase,
182
202
  pub isolate: OnceLock<v8::IsolateHandle>,
183
203
  // The isolate a snapshot is being built in on this runner, if any.
@@ -230,6 +250,7 @@ impl ControlBlock {
230
250
  timer: Mutex::default(),
231
251
  notify: NotifyFd::default(),
232
252
  tasks: Arc::new(tasks),
253
+ termination_requested: Arc::default(),
233
254
  phase: RunnerPhase::default(),
234
255
  isolate: OnceLock::new(),
235
256
  building: Mutex::new(None),
@@ -4,6 +4,7 @@ mod error;
4
4
  mod fast_calls;
5
5
  mod notify;
6
6
  pub mod process;
7
+ mod request;
7
8
  mod runner;
8
9
  mod serialize;
9
10
  mod snapshot;
@@ -15,6 +16,6 @@ mod spin;
15
16
  mod sys;
16
17
 
17
18
  pub use context::{ContextHandle, Host, Unparker, WaitHandle, WaitOutcome};
18
- pub use control::{CallbackReply, ContextConfig, JsText};
19
+ pub use control::{CallRequest, CallbackReply, ContextConfig, JsText};
19
20
  pub use error::{EngineError, FlagError, InvalidSnapshot, JsError, JsErrorKind, TerminationCause};
20
21
  pub use snapshot::{SnapshotBlob, WeakSnapshotBlob};