rusty_racer 0.1.1 → 0.1.3

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: ea693d067ec0ea289296493726bbecd72444e811218ca35a1beb44bbaf863e7d
4
- data.tar.gz: f1de072c0f64819c07708e47d385c345b7300e54a41c5186b79858ba73e3f7b7
3
+ metadata.gz: 746bc2e7e881d601b38f6052fb45f4f87d72d4580a46ea738e2c716af6641f82
4
+ data.tar.gz: 4fcc456589eabd593e506d7c941b7fe95635400225aac9807908a008f63e73ad
5
5
  SHA512:
6
- metadata.gz: bb7f4c71efcb143172a42c80898a9e10eeadc4c519e4f98e317907483ffd4565e751f7d0946b377964cb4b83b4e026cbe555449fac425b284572f088cb6d012e
7
- data.tar.gz: a859077b54ca976af9466271ada3cd094695b1f896ce09f3bc35d753912dc4e19743f589e322c0f438ca08cc4383bafa5faca16852831dbfd59e80dd74e61614
6
+ metadata.gz: 20aeb8c39cc3f321b5015b78ff2c4ae54553babd54735bbb256aeaea16c2428cccc03141a55c179ebad34822243d2d39508517df33f34d6236a7a368cbe274b5
7
+ data.tar.gz: 5ff495f94287dfd8464855d5e20c84c4743b91a3d320760decf17244dad5efa67c503b74dd2994792059e0f7236b10992157bfd5c4cb5681b02fe162b47a8a4d
data/README.md CHANGED
@@ -9,6 +9,38 @@ Embed [V8](https://v8.dev/) in Ruby, built on [rusty_v8](https://crates.io/crate
9
9
  > is **thread-confined**: every operation must happen on that owner thread, or it
10
10
  > raises. `Isolate#terminate` is the exception — it is safe from any thread.
11
11
 
12
+ ## Highlights
13
+
14
+ - **ES modules**, including dynamic `import()` with an embedder-owned resolver —
15
+ not just classic scripts.
16
+ - **Faithful value marshalling**: `BigInt`, `Date`, `Map`, `Set`, typed binary
17
+ (`Uint8Array`/`ArrayBuffer` ↔ binary `String`), and shared/cyclic object
18
+ graphs all round-trip — no lossy JSON hop.
19
+ - **In-thread execution** — V8 runs on the calling Ruby thread, with no dedicated
20
+ V8 thread and no per-op thread hop; fast when you run many small ops.
21
+ - **Drop-in [ExecJS](#execjs) runtime** — any ExecJS consumer switches with no
22
+ code change.
23
+ - **Snapshots, realms (`Context`s), host callbacks, and a bytecode cache.**
24
+ - **Resource limits on both axes** — a `timeout_ms` (time) and a `memory_limit`
25
+ (space), each catchable: a runaway script fails just its own `eval`, leaving
26
+ the isolate usable, instead of aborting the process.
27
+ - **Precompiled gems** bundle V8 for Linux/macOS × Ruby 3.3–4.0 — no V8 build,
28
+ no Rust toolchain.
29
+
30
+ ### Compared to mini_racer
31
+
32
+ [mini_racer](https://github.com/rubyjs/mini_racer) is the mature, widely-deployed
33
+ incumbent — if you want a battle-tested binding or **Windows** support, reach for
34
+ it. rusty_racer differs where it counts for some workloads: native **ES modules +
35
+ dynamic import** (mini_racer is eval/classic-script oriented); **richer
36
+ marshalling** (the types above round-trip natively instead of through a
37
+ JSON-shaped projection); and **in-thread execution** with no per-op thread hop,
38
+ which is faster for overhead-dominated workloads (lots of tiny `eval`/`call`) and
39
+ at parity once the per-op JS work dominates. Both axes of resource limiting are
40
+ covered — a `timeout_ms` (time) and a `memory_limit` (space), each catchable. It
41
+ is also younger and **experimental** — fewer miles, no Windows yet. Parity with
42
+ mini_racer is not a goal; the overlap is convergent evolution, not a port.
43
+
12
44
  ## What it can do
13
45
 
14
46
  Names follow V8's: an `Isolate` is the VM; it hands out `Context`s (v8::Context,
@@ -55,6 +87,25 @@ app.namespace["r"] # => 42
55
87
 
56
88
  Classic `<script>`s work the same way: `ctx.compile("1 + 1").run` # => 2.
57
89
 
90
+ ### Resource limits
91
+
92
+ An isolate can cap untrusted code on both axes. Each limit terminates the
93
+ offending op and raises a catchable error — the isolate stays usable afterward,
94
+ so one runaway script fails just its own `eval`, not the whole process.
95
+
96
+ ```ruby
97
+ # Time: timeout_ms caps each eval/call (per-call override on Context#eval).
98
+ iso = RustyRacer::Isolate.new(timeout_ms: 1000)
99
+ iso.context.eval("for (;;) {}") # raises RustyRacer::ScriptTerminatedError
100
+
101
+ # Space: memory_limit caps the V8 heap in bytes (a soft limit, enforced at GC
102
+ # granularity). The isolate forces a GC and resets the ceiling on recovery.
103
+ iso = RustyRacer::Isolate.new(memory_limit: 64 * 1024 * 1024)
104
+ iso.context.eval("a = []; for (;;) a.push(new Array(1e6))")
105
+ # raises RustyRacer::V8OutOfMemoryError
106
+ iso.context.eval("1 + 1") # => 2 (still usable)
107
+ ```
108
+
58
109
  ### Bytecode caching
59
110
 
60
111
  V8 compiles lazily: the top level up front, each function body on first call.
@@ -122,6 +173,28 @@ warm isolate — a per-visit reset that avoids rebuilding the VM. Its contract:
122
173
  suspended on the V8 stack (e.g. resetting a realm from inside one of its own
123
174
  host fns).
124
175
 
176
+ ## ExecJS
177
+
178
+ rusty_racer ships an optional [ExecJS](https://github.com/rails/execjs) runtime,
179
+ so any ExecJS consumer (asset pipelines, CoffeeScript/Babel/Uglify wrappers, …)
180
+ can run on V8-in-Ruby with no code change:
181
+
182
+ ```ruby
183
+ require "rusty_racer/execjs"
184
+ ExecJS.runtime = RustyRacer::ExecJSRuntime.new
185
+
186
+ ExecJS.eval("'foo bar'.toUpperCase()") # => "FOO BAR"
187
+ ctx = ExecJS.compile("function add(a, b) { return a + b }")
188
+ ctx.call("add", 1, 2) # => 3
189
+ ```
190
+
191
+ The adapter is **opt-in** — `rusty_racer` never requires `execjs` itself, so it
192
+ stays a non-dependency; `require "rusty_racer/execjs"` pulls it in only when you
193
+ ask. Values cross with ExecJS's JSON semantics (functions and `undefined` drop
194
+ out, Dates become ISO strings), matching what ExecJS's external runtimes give, so
195
+ results are identical whatever runtime a library picked. The integration is
196
+ verified against ExecJS's own runtime contract suite (`test/execjs_test.rb`).
197
+
125
198
  ## Threading
126
199
 
127
200
  An `Isolate` runs V8 **in-thread** on the Ruby thread that created it, and is
@@ -4,7 +4,7 @@
4
4
  # libv8-rusty needed under the cibuildgem native-per-platform model).
5
5
  [package]
6
6
  name = "rusty_racer"
7
- version = "0.1.1"
7
+ version = "0.1.3"
8
8
  edition = "2021"
9
9
  publish = false
10
10