mini_racer_rs 1.0.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.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/AI-DISCLOSURE.md +13 -0
  3. data/CHANGELOG.md +45 -0
  4. data/COMPATIBILITY.md +235 -0
  5. data/Cargo.lock +1263 -0
  6. data/Cargo.toml +62 -0
  7. data/LICENSE +21 -0
  8. data/README.md +254 -0
  9. data/THIRD_PARTY_NOTICES.md +4501 -0
  10. data/crates/mini_racer_engine/Cargo.toml +25 -0
  11. data/crates/mini_racer_engine/build.rs +13 -0
  12. data/crates/mini_racer_engine/src/context.rs +802 -0
  13. data/crates/mini_racer_engine/src/control.rs +239 -0
  14. data/crates/mini_racer_engine/src/error.rs +88 -0
  15. data/crates/mini_racer_engine/src/fast_calls.rs +681 -0
  16. data/crates/mini_racer_engine/src/lib.rs +20 -0
  17. data/crates/mini_racer_engine/src/notify.rs +107 -0
  18. data/crates/mini_racer_engine/src/process/code_cache.rs +412 -0
  19. data/crates/mini_racer_engine/src/process/fork.rs +261 -0
  20. data/crates/mini_racer_engine/src/process/platform.rs +194 -0
  21. data/crates/mini_racer_engine/src/process/tasks.rs +96 -0
  22. data/crates/mini_racer_engine/src/process/watchdog.rs +185 -0
  23. data/crates/mini_racer_engine/src/process/workers.rs +165 -0
  24. data/crates/mini_racer_engine/src/process.rs +69 -0
  25. data/crates/mini_racer_engine/src/runner.rs +1560 -0
  26. data/crates/mini_racer_engine/src/serialize.rs +253 -0
  27. data/crates/mini_racer_engine/src/snapshot.rs +221 -0
  28. data/crates/mini_racer_engine/src/spin.rs +23 -0
  29. data/crates/mini_racer_engine/src/sys.rs +566 -0
  30. data/crates/mini_racer_sync/Cargo.toml +18 -0
  31. data/crates/mini_racer_sync/src/channel.rs +621 -0
  32. data/crates/mini_racer_sync/src/fork.rs +116 -0
  33. data/crates/mini_racer_sync/src/lib.rs +20 -0
  34. data/crates/mini_racer_sync/src/lock.rs +49 -0
  35. data/crates/mini_racer_sync/src/parker.rs +44 -0
  36. data/crates/mini_racer_sync/src/primitives.rs +10 -0
  37. data/crates/mini_racer_sync/src/tasks.rs +345 -0
  38. data/crates/mini_racer_sync/src/termination.rs +1234 -0
  39. data/crates/mini_racer_sync/src/workers.rs +283 -0
  40. data/crates/mini_racer_wire/Cargo.toml +18 -0
  41. data/crates/mini_racer_wire/src/decode.rs +926 -0
  42. data/crates/mini_racer_wire/src/lib.rs +67 -0
  43. data/crates/mini_racer_wire/src/marker.rs +43 -0
  44. data/crates/mini_racer_wire/src/text.rs +106 -0
  45. data/crates/mini_racer_wire/src/write.rs +187 -0
  46. data/ext/mini_racer_rs/Cargo.toml +26 -0
  47. data/ext/mini_racer_rs/build.rs +16 -0
  48. data/ext/mini_racer_rs/extconf.rb +78 -0
  49. data/ext/mini_racer_rs/src/context.rs +485 -0
  50. data/ext/mini_racer_rs/src/decode.rs +450 -0
  51. data/ext/mini_racer_rs/src/encode.rs +333 -0
  52. data/ext/mini_racer_rs/src/errors.rs +156 -0
  53. data/ext/mini_racer_rs/src/fork.rs +31 -0
  54. data/ext/mini_racer_rs/src/gc_root.rs +117 -0
  55. data/ext/mini_racer_rs/src/guard.rs +7 -0
  56. data/ext/mini_racer_rs/src/host.rs +339 -0
  57. data/ext/mini_racer_rs/src/lib.rs +44 -0
  58. data/ext/mini_racer_rs/src/options.rs +269 -0
  59. data/ext/mini_racer_rs/src/platform.rs +42 -0
  60. data/ext/mini_racer_rs/src/rb_raw.rs +368 -0
  61. data/ext/mini_racer_rs/src/snapshot.rs +149 -0
  62. data/ext/mini_racer_rs/v8-archives.sha256 +8 -0
  63. data/lib/mini_racer/shared.rb +420 -0
  64. data/lib/mini_racer/truffleruby.rb +439 -0
  65. data/lib/mini_racer/version.rb +6 -0
  66. data/lib/mini_racer.rb +3 -0
  67. data/lib/mini_racer_rs/internal_error.rb +7 -0
  68. data/lib/mini_racer_rs/version.rb +5 -0
  69. data/lib/mini_racer_rs/vocabulary.rb +105 -0
  70. data/lib/mini_racer_rs.rb +33 -0
  71. data/licenses/mini_racer.txt +21 -0
  72. data/licenses/rust/SOURCES.tsv +6 -0
  73. data/licenses/rust/std/COPYRIGHT +34 -0
  74. data/licenses/rust/std/COPYRIGHT-library.html +29357 -0
  75. data/licenses/rust/std/LICENSE-APACHE +176 -0
  76. data/licenses/rust/std/LICENSE-MIT +25 -0
  77. data/licenses/v8/SOURCES.tsv +20 -0
  78. data/licenses/v8/abseil-cpp/LICENSE +203 -0
  79. data/licenses/v8/chromium-build/LICENSE +27 -0
  80. data/licenses/v8/components.tsv +29 -0
  81. data/licenses/v8/dragonbox/LICENSE-Boost +23 -0
  82. data/licenses/v8/fast_float/LICENSE-MIT +27 -0
  83. data/licenses/v8/highway/LICENSE +371 -0
  84. data/licenses/v8/icu/LICENSE +568 -0
  85. data/licenses/v8/inspector_protocol/LICENSE +27 -0
  86. data/licenses/v8/libc++/LICENSE.TXT +311 -0
  87. data/licenses/v8/libc++abi/LICENSE.TXT +311 -0
  88. data/licenses/v8/llvm-libc/LICENSE.TXT +278 -0
  89. data/licenses/v8/rapidhash/LICENSE +34 -0
  90. data/licenses/v8/simdutf/LICENSE +18 -0
  91. data/licenses/v8/siphash/LICENSE +116 -0
  92. data/licenses/v8/utf8-decoder/LICENSE +19 -0
  93. data/licenses/v8/v8/LICENSE +61 -0
  94. data/licenses/v8/v8/LICENSE.fdlibm +6 -0
  95. data/licenses/v8/v8/LICENSE.strongtalk +29 -0
  96. data/licenses/v8/v8/LICENSE.v8 +26 -0
  97. metadata +156 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 41191c7e0a6bf53c0371de7ba31f7067b3d83b0095579d6955a75a9021c4a5b0
4
+ data.tar.gz: 7b0424bbabd9fcd45122dc81b6b449e3c30d7ffb218ec43eff973ae4d8c70772
5
+ SHA512:
6
+ metadata.gz: b864cac2b4d1f3108deea75e4bc5a10de16c94ce73be5c5824f7443922a86d94f6d1ff933a1008632c971f1eafdef57a452631661bc82807799b339ff7e15ca5
7
+ data.tar.gz: '0391a874e20db2b91f6c1916efa0c39f05178b68e9223dc2709aeb2fa6ad6026de9bba898f8bea5f8764193df36c0291fb8af8afab738029db3ef4a537354bb4'
data/AI-DISCLOSURE.md ADDED
@@ -0,0 +1,13 @@
1
+ I solemnly swear that this opening sentence is the only thing here written by myself with absolutely no AI assistance or even proofreading. The rest of the project? Different story.
2
+
3
+ Most, if not all, of this project has been created with the assistance of AI tooling. I am a builder / software engineer at heart with decades of experience and I genuinely love what AI has enabled me to pursue.
4
+
5
+ It’s allowed me to spend more time with my family while still building (what I think is) cool shit. AI has helped tremendously with the “how” but I am still firmly in control of the “what” and the “why”. I apologize in advance whenever you see a piece of code or text that does not pass your Turing test. This is not because of a lack of care or laziness, but instead a doctrine of getting things into a state of reasonable context and clarity so that I can continue iterating without getting bogged down by semantics.
6
+
7
+ I hope you read this knowing there is still a human behind all this AI generated work (although I completely understand that the state of things often doesn’t make it feel like so).
8
+
9
+ I genuinely hope that you find value in the work that was created here and not be dissuaded by the means in which it was created.
10
+
11
+ Thanks for taking the time to read this.
12
+
13
+ - Andy
data/CHANGELOG.md ADDED
@@ -0,0 +1,45 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 (2026-10-18)
4
+
5
+
6
+ ### Features
7
+
8
+ * **engine:** add async promise dispatch and V8 task queues ([#37](https://github.com/andymai/mini_racer_rs/issues/37)) ([c23986a](https://github.com/andymai/mini_racer_rs/commit/c23986a407e94864dfa35343cd7579e2e99c905c))
9
+ * **engine:** add heap stats and snapshot support ([#39](https://github.com/andymai/mini_racer_rs/issues/39)) ([38072fb](https://github.com/andymai/mini_racer_rs/commit/38072fba06c249a9a7e72d39b97a3f4fb979cb62))
10
+ * **engine:** carry idle single-threaded contexts across fork ([#27](https://github.com/andymai/mini_racer_rs/issues/27)) ([c1251bc](https://github.com/andymai/mini_racer_rs/commit/c1251bcce60eb05627d616564cae73df90a622d7))
11
+ * **engine:** dispatch through the channel and termination cell ([#14](https://github.com/andymai/mini_racer_rs/issues/14)) ([77c05bd](https://github.com/andymai/mini_racer_rs/commit/77c05bd77c29c063561078edd11903b54fb3c6db))
12
+ * **engine:** enforce max_memory after garbage collection ([#41](https://github.com/andymai/mini_racer_rs/issues/41)) ([ba3dced](https://github.com/andymai/mini_racer_rs/commit/ba3dced1e862b0964d6d6a3a02d448f6a3de1347))
13
+ * **engine:** support garbage collection after idle ([#43](https://github.com/andymai/mini_racer_rs/issues/43)) ([a835159](https://github.com/andymai/mini_racer_rs/commit/a835159799e3cc918d486f4a9f0288a67f96f6fb))
14
+ * **engine:** support verbose exceptions ([#45](https://github.com/andymai/mini_racer_rs/issues/45)) ([5adf6b6](https://github.com/andymai/mini_racer_rs/commit/5adf6b64b52235822657359aeb0545f674759c2a))
15
+ * **ext:** attach ruby callables as javascript functions with context#attach ([#20](https://github.com/andymai/mini_racer_rs/issues/20)) ([1c84836](https://github.com/andymai/mini_racer_rs/commit/1c8483680518f8346aa8ee58f285b32d10d7c9f7))
16
+ * **ext:** build, load and warm up startup snapshots with mini_racer::snapshot ([#21](https://github.com/andymai/mini_racer_rs/issues/21)) ([441a8f5](https://github.com/andymai/mini_racer_rs/commit/441a8f58f856099b2c2771cbd5b3937b804d0ed2))
17
+ * **ext:** call javascript functions from ruby with context#call ([#18](https://github.com/andymai/mini_racer_rs/issues/18)) ([bf144c6](https://github.com/andymai/mini_racer_rs/commit/bf144c6e38c2848b4e69267f89b0c804189708a0))
18
+ * **ext:** context low_memory_notification, answered after the collection as in mini_racer ([#26](https://github.com/andymai/mini_racer_rs/issues/26)) ([d9b11e2](https://github.com/andymai/mini_racer_rs/commit/d9b11e28837e9727f85ebe95d023355c8d55f258))
19
+ * **ext:** park only the waiting fiber under a fiber scheduler ([#25](https://github.com/andymai/mini_racer_rs/issues/25)) ([6d16553](https://github.com/andymai/mini_racer_rs/commit/6d16553a13b2100951e2dcc41324d32bd4ff57c1))
20
+ * **ext:** return every javascript value from eval as mini_racer does ([#17](https://github.com/andymai/mini_racer_rs/issues/17)) ([8c59e07](https://github.com/andymai/mini_racer_rs/commit/8c59e07cb2abbfe92d9197bf64d653419fdbc8f6))
21
+ * **sync:** turn-taking channel and termination cell with loom models ([#9](https://github.com/andymai/mini_racer_rs/issues/9)) ([353abb7](https://github.com/andymai/mini_racer_rs/commit/353abb763b7e3407c6da869db5d04a63950d91cb))
22
+ * **wire:** decode every V8 wire tag and write mini_racer's encoding ([#16](https://github.com/andymai/mini_racer_rs/issues/16)) ([24d8a85](https://github.com/andymai/mini_racer_rs/commit/24d8a85243c9c4acf515ec12fa03f96211f39a8c))
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **engine:** attach under a pending stop raises mini_racer's internal error ([#47](https://github.com/andymai/mini_racer_rs/issues/47)) ([e68d8ce](https://github.com/andymai/mini_racer_rs/commit/e68d8ced83faa122e77e667c754bfb872d2436e4))
28
+ * **engine:** model mini_racer's one-shot stop interrupt ([#49](https://github.com/andymai/mini_racer_rs/issues/49)) ([649ff1a](https://github.com/andymai/mini_racer_rs/commit/649ff1a40b94564bd5d07141e1fa526c23006fa2))
29
+ * **engine:** preserve callback exceptions during termination ([#42](https://github.com/andymai/mini_racer_rs/issues/42)) ([3a92918](https://github.com/andymai/mini_racer_rs/commit/3a92918460b71cc5cf564221c40b839442e34721))
30
+ * **engine:** preserve results after late timeouts ([#38](https://github.com/andymai/mini_racer_rs/issues/38)) ([1d8038d](https://github.com/andymai/mini_racer_rs/commit/1d8038d4ba13859552c1c8dac7bf2595ef28b069))
31
+ * **engine:** raise disposed error for in-flight work ([#40](https://github.com/andymai/mini_racer_rs/issues/40)) ([fbd37f1](https://github.com/andymai/mini_racer_rs/commit/fbd37f1dde7288658e190bb2c6d5976942980016))
32
+ * **fork:** hold the single-threaded platform's worker across a fork ([#70](https://github.com/andymai/mini_racer_rs/issues/70)) ([78c94e3](https://github.com/andymai/mini_racer_rs/commit/78c94e3685b35a5b90f37c02e336de2e25feccd4))
33
+ * **fork:** quiesce runners and hold V8's workers across a multi-threaded fork ([#68](https://github.com/andymai/mini_racer_rs/issues/68)) ([95b69bc](https://github.com/andymai/mini_racer_rs/commit/95b69bc625c248e0af263353b3e413540726672c))
34
+
35
+
36
+ ### Performance
37
+
38
+ * **decode:** decode arrays of numbers in runs ([#72](https://github.com/andymai/mini_racer_rs/issues/72)) ([2513a48](https://github.com/andymai/mini_racer_rs/commit/2513a481f3c84a026091b1f77dad41b299cdf8c2))
39
+ * **engine:** compile ExecJS calls and react-rails renders once per context ([#77](https://github.com/andymai/mini_racer_rs/issues/77)) ([774be16](https://github.com/andymai/mini_racer_rs/commit/774be1609816d7027986578a594f03fb00e0de61))
40
+ * **engine:** compile large scripts from a process-wide code cache ([#69](https://github.com/andymai/mini_racer_rs/issues/69)) ([ca3ce70](https://github.com/andymai/mini_racer_rs/commit/ca3ce705febb3b92c5f62879faffbd5e725fee8b))
41
+ * **engine:** hand freed malloc memory back after a large eval ([#67](https://github.com/andymai/mini_racer_rs/issues/67)) ([81b21cc](https://github.com/andymai/mini_racer_rs/commit/81b21ccb68d9f0d3c69c7f9594d1f3a027d39bbf))
42
+ * **engine:** run V8's worker tasks on a pool each process owns ([#75](https://github.com/andymai/mini_racer_rs/issues/75)) ([a090a9f](https://github.com/andymai/mini_racer_rs/commit/a090a9fb6dfe3ae9e42e864e8a084bd67aaa7485))
43
+ * **engine:** share each snapshot's blob across its contexts and refuse blobs V8 would abort on ([#79](https://github.com/andymai/mini_racer_rs/issues/79)) ([470da4a](https://github.com/andymai/mini_racer_rs/commit/470da4a2f73791c0f0610a0c41b102dc7e31fcfd))
44
+ * **ext:** decode arrays and objects in batches under one rb_protect each ([#23](https://github.com/andymai/mini_racer_rs/issues/23)) ([77f44ab](https://github.com/andymai/mini_racer_rs/commit/77f44ab1d09b49944dd480bdc6e9dff9781ad366))
45
+ * **wire:** copy ascii spans in bulk when transcoding latin-1 text ([#19](https://github.com/andymai/mini_racer_rs/issues/19)) ([c7e4a7a](https://github.com/andymai/mini_racer_rs/commit/c7e4a7acbeac56af80422ce8774c6e43035232a9))
data/COMPATIBILITY.md ADDED
@@ -0,0 +1,235 @@
1
+ # Compatibility with mini_racer 0.22.1
2
+
3
+ <!-- Generated by `rake compat:render` from compat.toml and compat/surface.json; do not edit. -->
4
+
5
+ | Engine | Done | Planned | Deviation |
6
+ |---|---|---|---|
7
+ | CRuby | 54 | 0 | 25 |
8
+ | TruffleRuby | 58 | 0 | 0 |
9
+
10
+ ## Surface
11
+
12
+ | Id | CRuby | TruffleRuby |
13
+ |---|---|---|
14
+ | `class:MiniRacer::Binary < Object` | done | done |
15
+ | `class:MiniRacer::Context < Object` | done | done |
16
+ | `class:MiniRacer::Context::ExternalFunction < Object` | n/a | done |
17
+ | `class:MiniRacer::ContextDisposedError < MiniRacer::Error` | done | done |
18
+ | `class:MiniRacer::Error < StandardError` | done | done |
19
+ | `class:MiniRacer::EvalError < MiniRacer::Error` | done | done |
20
+ | `class:MiniRacer::FailedV8Conversion < Object` | n/a | done |
21
+ | `class:MiniRacer::InternalError < MiniRacer::EvalError` | done | n/a |
22
+ | `class:MiniRacer::Isolate < Object` | n/a | done |
23
+ | `class:MiniRacer::JavaScriptFunction < Object` | done | done |
24
+ | `class:MiniRacer::ParseError < MiniRacer::EvalError` | done | done |
25
+ | `class:MiniRacer::Platform < Object` | done | done |
26
+ | `class:MiniRacer::PlatformAlreadyInitialized < MiniRacer::Error` | done | done |
27
+ | `class:MiniRacer::RuntimeError < MiniRacer::EvalError` | done | done |
28
+ | `class:MiniRacer::ScriptError < MiniRacer::EvalError` | done | done |
29
+ | `class:MiniRacer::ScriptTerminatedError < MiniRacer::EvalError` | done | done |
30
+ | `class:MiniRacer::Snapshot < Object` | done | done |
31
+ | `class:MiniRacer::SnapshotError < MiniRacer::Error` | done | done |
32
+ | `class:MiniRacer::V8OutOfMemoryError < MiniRacer::EvalError` | done | done |
33
+ | `const:MiniRacer::LIBV8_NODE_VERSION` | done | done |
34
+ | `const:MiniRacer::MARSHAL_STACKDEPTH_DEFAULT` | n/a | done |
35
+ | `const:MiniRacer::MARSHAL_STACKDEPTH_MAX_VALUE` | n/a | done |
36
+ | `const:MiniRacer::VERSION` | done | done |
37
+ | `feature:io/wait` | done | done |
38
+ | `feature:json` | done | done |
39
+ | `feature:pathname` | done | done |
40
+ | `imethod:MiniRacer::Binary#data` | done | done |
41
+ | `imethod:MiniRacer::Context#attach` | done | done |
42
+ | `imethod:MiniRacer::Context#call` | done | done |
43
+ | `imethod:MiniRacer::Context#call_await` | done | done |
44
+ | `imethod:MiniRacer::Context#dispose` | done | done |
45
+ | `imethod:MiniRacer::Context#eval` | done | done |
46
+ | `imethod:MiniRacer::Context#eval_await` | done | done |
47
+ | `imethod:MiniRacer::Context#eval_in_context` | n/a | done |
48
+ | `imethod:MiniRacer::Context#heap_snapshot` | done | n/a |
49
+ | `imethod:MiniRacer::Context#heap_stats` | done | done |
50
+ | `imethod:MiniRacer::Context#isolate` | n/a | done |
51
+ | `imethod:MiniRacer::Context#load` | done | done |
52
+ | `imethod:MiniRacer::Context#low_memory_notification` | done | done |
53
+ | `imethod:MiniRacer::Context#perform_microtask_checkpoint` | done | n/a |
54
+ | `imethod:MiniRacer::Context#pump_message_loop` | done | n/a |
55
+ | `imethod:MiniRacer::Context#stop` | done | done |
56
+ | `imethod:MiniRacer::Context#write_heap_snapshot` | done | done |
57
+ | `imethod:MiniRacer::FailedV8Conversion#info` | n/a | done |
58
+ | `imethod:MiniRacer::Isolate#init_with_snapshot` | n/a | done |
59
+ | `imethod:MiniRacer::JavaScriptFunction#to_s` | n/a | done |
60
+ | `imethod:MiniRacer::RuntimeError#backtrace` | done | done |
61
+ | `imethod:MiniRacer::ScriptError#backtrace` | done | done |
62
+ | `imethod:MiniRacer::ScriptError#cause` | done | n/a |
63
+ | `imethod:MiniRacer::Snapshot#dump` | done | n/a |
64
+ | `imethod:MiniRacer::Snapshot#load` | n/a | done |
65
+ | `imethod:MiniRacer::Snapshot#size` | done | n/a |
66
+ | `imethod:MiniRacer::Snapshot#warmup!` | done | done |
67
+ | `imethod:MiniRacer::Snapshot#warmup_unsafe!` | n/a | done |
68
+ | `imethod:MiniRacer::SnapshotError#backtrace` | done | done |
69
+ | `kwarg:MiniRacer::Context#eval:filename` | done | done |
70
+ | `kwarg:MiniRacer::Context#eval_await:filename` | done | n/a |
71
+ | `kwarg:MiniRacer::Context#initialize:ensure_gc_after_idle` | done | done |
72
+ | `kwarg:MiniRacer::Context#initialize:isolate` | n/a | done |
73
+ | `kwarg:MiniRacer::Context#initialize:marshal_stack_depth` | done | done |
74
+ | `kwarg:MiniRacer::Context#initialize:max_memory` | done | done |
75
+ | `kwarg:MiniRacer::Context#initialize:snapshot` | done | done |
76
+ | `kwarg:MiniRacer::Context#initialize:timeout` | done | done |
77
+ | `kwarg:MiniRacer::Context#initialize:verbose_exceptions` | done | n/a |
78
+ | `module:MiniRacer` | done | done |
79
+ | `module:MiniRacer::Loader` | deviation | n/a |
80
+ | `smethod:MiniRacer::Loader.load` | deviation | n/a |
81
+ | `smethod:MiniRacer::Platform.set_flag_as_str!` | n/a | done |
82
+ | `smethod:MiniRacer::Platform.set_flags!` | done | done |
83
+ | `smethod:MiniRacer::Snapshot.load` | done | n/a |
84
+
85
+ ## Deviations
86
+
87
+ ### `behavior:bigint-objects@ruby`
88
+
89
+ mini_racer_rs returns a BigInt wrapper object's wrapped value as an Integer: `Object(1n)` returns `1`, and `[Object(-5n)]` returns `[-5]`. mini_racer 0.22.1 instead raises `MiniRacer::RuntimeError` with the message `bad tag: z`. Returning the primitive value makes BigInt wrappers consistent with Boolean, Number, and String wrapper objects, which both gems already return as their primitive values.
90
+
91
+ Approved 2026-10-16.
92
+
93
+ ### `behavior:callback-error-text@ruby`
94
+
95
+ When an attached Ruby callback raises, JavaScript receives an `Error` whose message is the exception’s `to_s`. mini_racer_rs gives V8 that text using the same rules as `eval` source: ISO-8859-1 as Latin-1, UTF-16LE as two-byte text, and other encodings as UTF-8, with invalid sequences replaced by U+FFFD. mini_racer 0.22.1 treats the string’s bytes as Latin-1 regardless of encoding. With `t` raising `"café"`, `try { t() } catch (e) { e.message }` returns `"café"` from mini_racer_rs and `"café"` from mini_racer 0.22.1. UTF-16LE produces a NUL after each letter in mini_racer. ASCII messages match. If JavaScript does not catch the exception, both gems raise the original Ruby exception from `eval` or `call` with its message unchanged.
96
+
97
+ Approved 2026-10-16.
98
+
99
+ ### `behavior:callback-jump@ruby`
100
+
101
+ mini_racer_rs terminates the script with `Error: terminated` when a callback attached with `Context#attach` leaves by `throw`, by `return` out of a proc whose method is still running, or by `Thread#kill`. The jump continues after `Context#eval` or `Context#call` returns, and the context stays usable. For example, `catch(:out) { context.eval("thrower(); 'not reached'") }` returns `5` when `thrower` executes `throw :out, 5`. With mini_racer 0.22.1, that `throw` never returns, and neither does `proc { return :x }` when called from the method that created it. The process hangs until killed. A callback calling `Thread.current.kill` instead makes `eval` raise `TypeError` with `exception class/object expected`, without killing the thread. In mini_racer_rs, the thread ends. `break` out of a proc raises `LocalJumpError` in both gems.
102
+
103
+ Approved 2026-10-16.
104
+
105
+ ### `behavior:callback-reentry@ruby`
106
+
107
+ Both gems allow an attached callback to call `eval`, `call`, or `attach` on its own context, running the nested call inside the script that invoked the callback. mini_racer_rs accepts the call only from the fiber running the callback. A call from another fiber on the same thread, such as code inside `Enumerator#next`, raises `ThreadError` (`deadlock; lock already owned by another fiber belonging to the same thread`). mini_racer 0.22.1 accepts it: `Enumerator.new { |y| y << context.eval("1") }.next` inside a callback returns `1`. A signal trap that calls the context while a callback waits on a nested `eval` gets `ThreadError` in mini_racer_rs; when rescued, the script completes. With mini_racer 0.22.1, the same program hangs until killed. mini_racer_rs refuses these calls because each nested call must finish before its callback replies, preventing out-of-order replies from being paired with the wrong callback.
108
+
109
+ Approved 2026-10-16.
110
+
111
+ ### `behavior:dispose-in-flight@ruby`
112
+
113
+ `MiniRacer::Context#dispose` in mini_racer_rs returns only after the runner has finished any eval or call in flight and dropped the isolate, on both platforms, so the isolate and its memory cannot outlive disposal. On mini_racer 0.22.1’s default platform, `dispose` returns once the context’s V8 thread has taken the eval or call in flight, and that thread finishes the work and frees the isolate afterward (`context_dispose_do` in `mini_racer_extension.c`). With `:single_threaded`, mini_racer joins the runner and waits. When `dispose` was called 10 ms into serialization of a 64 MiB snapshot string, default mini_racer returned at 10 ms and mini_racer_rs at about 60 ms, after serialization finished. With `:single_threaded`, they returned at 85 ms and 62 ms, respectively. For busy loops, both returned within milliseconds. The in-flight operation always raises `MiniRacer::ContextDisposedError` in mini_racer_rs. mini_racer 0.22.1 usually raises that class, but raised `MiniRacer::ScriptTerminatedError` in 2 of 12 busy-loop runs; its test accepts either class.
114
+
115
+ Approved 2026-10-16.
116
+
117
+ ### `behavior:fast-calls@ruby`
118
+
119
+ Unlike mini_racer 0.22.1, which compiles every source, mini_racer_rs recognizes ExecJS 2.10.2 `call` sources and react-rails 3.2.1 and 3.3.1 server render sources evaluated without a file name, then runs a template compiled once by the context. The template remains a top-level script and replaces each JSON literal with a native function call stored in a randomly named global `const`; V8's JSON parser reads the values. Results, error classes and messages, `this`, and stack frame line and column numbers remain those of the source. The approved `behavior:fast-calls@ruby` deviation is limited to V8 stack reflection: `CallSite#getScriptHash` reports the template hash, and render `CallSite#getPosition` can report a different raw offset after hoisted literals, such as 260 instead of 185. A reflected render wrapper shows template reads instead of literals, and invoking it again receives no values outside a fast call or the current call's values during one, while mini_racer supplies the literals each time. Heap snapshots expose the hidden `const`. Set `MINI_RACER_RS_FAST_CALLS` to `off` before the first context is created to send every eval down the normal path.
120
+
121
+ Approved 2026-10-18.
122
+
123
+ ### `behavior:fiber-scheduler@ruby`
124
+
125
+ mini_racer_rs parks only a non-blocking fiber waiting for a context under a fiber scheduler, so the thread's other fibers keep running during `Context.new`, `eval`, `call`, `attach`, `dispose`, and nested callback calls. mini_racer 0.22.1 releases the GVL and blocks the whole thread until JavaScript returns. Three 100 ms busy loops in separate contexts and fibers inside `Sync` finish in 100 ms with mini_racer_rs, with a 10 ms ticker ticking 9 times; mini_racer takes 300 ms, with 3 ticks. With mini_racer_rs, `task.with_timeout(0.05) { context.call("busy", 300) }` raises `Async::TimeoutError` after 50 ms and terminates JavaScript; mini_racer returns `300` after 300 ms. In both gems the context stays usable afterward. Fibers sharing a context take turns in both gems. Without a scheduler or in a blocking fiber, mini_racer_rs blocks the thread while waiting, as mini_racer does. `Snapshot.new` also blocks the thread.
126
+
127
+ Approved 2026-10-16.
128
+
129
+ ### `behavior:fork-from-callback@ruby`
130
+
131
+ With an attached callback that calls `fork` under the `:single_threaded` platform flag, the parent's `eval` returns `"parent"` in both gems, and its later `context.eval("1 + 1")` returns `2`. mini_racer 0.22.1's child is still running five seconds later, when the test kills it. In mini_racer_rs's child, the `eval` that invokes the callback raises `MiniRacer::RuntimeError` with `single-threaded runner: Device or resource busy` when the callback returns, because the JavaScript thread stays with the parent. A call on the same context from inside the child callback, and every later call, raises the same error. A new child context works: `MiniRacer::Context.new.eval("6 * 7")` returns `42`.
132
+
133
+ Approved 2026-10-16.
134
+
135
+ ### `behavior:fork-quiesce-bound@ruby`
136
+
137
+ With the `:single_threaded` platform flag, mini_racer_rs waits up to 500 ms inside Ruby's `fork` or `Process.daemon` for every context's runner to become idle or parked. If another thread runs an operation V8 does not interrupt, such as `JSON.parse` of a large string, the child refuses every inherited context: calling an idle one raises `MiniRacer::RuntimeError` with `single-threaded runner: Device or resource busy`. New contexts created in the child work. mini_racer 0.22.1 does not wait for its runners. With `JSON.parse` of a 3,000,000-element array's JSON, its fork took 15 ms and its child's idle context returned `42`; mini_racer_rs took 523 ms and refused that context.
138
+
139
+ Approved 2026-10-16.
140
+
141
+ ### `behavior:fork-wait@ruby`
142
+
143
+ For forks made through Ruby's `fork`, `IO.popen("-")` or `Process.daemon`, mini_racer_rs waits for context runners, pauses its worker pool and waits for running worker tasks in both modes; mini_racer 0.22.1 waits for neither. Idle pool threads wait on a Rust standard library condition variable that keeps no records on their stacks, so a child does not inherit records that refer to discarded stacks. mini_racer 0.22.1 creates its `:single_threaded` platform with `NewSingleThreadedDefaultPlatform`, which has no V8 worker threads. mini_racer_rs creates V8's platform with one worker thread, which never receives a task, and routes worker tasks to a process-owned pool with one thread under `:single_threaded`. On Ubuntu 24.04 with glibc 2.39, 20 of 20 mini_racer children aborted with signal 6 after loading and rendering React, whether or not two parent threads kept rendering. With mini_racer_rs, 20 of 20 children exited cleanly in both cases. On Fedora, mini_racer children hung within the first 50 forks in `test/stress/fork_busy.rb`; mini_racer_rs completed 300 forks per run on Fedora and Ubuntu. On one Fedora machine, with four threads evaluating and 50 forks per run, fork latency was 0.90 to 0.94 ms at the median across three runs, versus 0.73 to 0.78 ms with mini_racer 0.22.1. The waits are best effort: the fork proceeds after the 500 ms runner bound or the following 100 ms worker bound expires.
144
+
145
+ Approved 2026-10-17.
146
+
147
+ ### `behavior:invalid-snapshot@ruby`
148
+
149
+ mini_racer_rs raises `MiniRacer::SnapshotError` instead of letting V8 terminate the process. `Snapshot.load` rejects a blob that is too short for its header, was made by another V8 version, or is truncated. `Context.new(snapshot:)` and `#warmup!` reject the same corruption if the String returned by `dump` has since been changed, and `#warmup!` rejects an empty snapshot. The messages are `invalid snapshot: truncated or corrupt`, `invalid snapshot: not made by V8 <version>`, and `invalid snapshot: empty`. Context option errors still raise first. mini_racer 0.22.1 accepts any String, then dies with a V8 fatal error (SIGTRAP), or with SIGSEGV when the blob is cut short in its last section. As in mini_racer, an empty blob starts a context without a snapshot, trailing bytes are accepted, and damaged payload bytes that V8 can read are accepted. Damage to a section's 8-byte header is rejected.
150
+
151
+ Approved 2026-10-18.
152
+
153
+ ### `behavior:multi-threaded-fork@ruby`
154
+
155
+ In a child forked from a process using V8's default multi-threaded platform, mini_racer 0.22.1 hangs when an inherited context runs `context.eval("1 + 1")`; the observed child was still waiting after 3 seconds. mini_racer_rs instead raises `MiniRacer::RuntimeError` at once with `single-threaded runner: Device or resource busy`, while the parent's contexts remain unaffected. The child inherits none of the context runner or V8 worker threads. A new `MiniRacer::Context` in the child can evaluate `eval("2")` to `2` and runs V8 worker work on the child's own pool. An async `WebAssembly.compile` in a new context completes. With mini_racer 0.22.1, the same case hung in 2 of 2 runs on Fedora; on Ubuntu 24.04, it aborted with signal 6 in 2 of 3 runs and hung in 1 of 3. Contexts intended to keep working in a child should use `:single_threaded`.
156
+
157
+ Approved 2026-10-16.
158
+
159
+ ### `behavior:native-fork@ruby`
160
+
161
+ With the `:single_threaded` platform flag, mini_racer_rs refuses every context inherited by a child of a fork that bypasses Ruby's `fork`, including idle contexts: calls raise `MiniRacer::RuntimeError` with `single-threaded runner: Device or resource busy`. In a libc `fork()` test through Fiddle, mini_racer 0.22.1's child returned `42` from an inherited idle context holding `var answer = 42`, while mini_racer_rs raised that error. In both gems, new child contexts and the parent's context work. Calling `dispose` on an inherited child context returns `nil`, after which calls raise `MiniRacer::ContextDisposedError`. mini_racer_rs cannot rule out an in-progress V8 state change without the runner wait used by Ruby's `fork`, `IO.popen("-")`, and `Process.daemon`.
162
+
163
+ Approved 2026-10-16.
164
+
165
+ ### `behavior:object-ids@ruby`
166
+
167
+ mini_racer_rs preserves repeated-object identity in both directions by numbering every object as V8 does, including dates, regular expressions, typed arrays, ArrayBuffers, wrapper objects, and errors. Serialized repeats refer back by number. From JavaScript to Ruby, `(() => { const d = new Date(0); const o = {}; return [d, d, o, o] })()` returns `[Time, Time, {}, {}]`, with each pair the same Ruby object. mini_racer 0.22.1 counts only decoded arrays, objects, maps, sets, and errors, so it returns `[Time, nil, {}, nil]`; a repeated error, including one that is its own cause, becomes `[]` instead of the same `MiniRacer::ScriptError`. From Ruby to JavaScript, mini_racer 0.22.1 counts only Arrays and Hashes, so `context.call("f", time, hash, hash)` gives `f` a Date, an object, and the same Date. mini_racer_rs gives `f` the same object twice. For call arguments and callback results, it also sends a repeated `Time`, `DateTime`, object whose `to_time` returns a `Time`, or `MiniRacer::Binary` as one Date or Uint8Array, calling `to_time` once per object. Thus, with `same = (a, b) => a === b`, `context.call("same", time, time)` returns `true`, while mini_racer returns `false`; distinct equal `Time` objects remain distinct in both.
168
+
169
+ Approved 2026-10-16.
170
+
171
+ ### `behavior:padded-two-byte-text@ruby`
172
+
173
+ mini_racer_rs returns a regular expression as its pattern String and a String object as its String, including `[1, new RegExp('東')]`, `new RegExp('東')`, and `[new String('東')]` as `[1, "東"]`, `"東"`, and `["東"]`. It skips V8's optional alignment byte before two-byte text, as V8's own deserializer does. mini_racer 0.22.1 does not accept that byte and raises `MiniRacer::RuntimeError` with `bad regexp` or `bad string object` for these examples, although `({ab: new RegExp('東')})` returns `{"ab" => "東"}` because its serialized position requires no alignment byte.
174
+
175
+ Approved 2026-10-16.
176
+
177
+ ### `behavior:platforms@ruby`
178
+
179
+ mini_racer_rs supports glibc Linux on x86_64 and aarch64, plus macOS on arm64 and x86_64. Installation stops on musl-based Linux, including Alpine, and on Windows, with a message naming the supported platforms.
180
+
181
+ Approved 2026-10-16.
182
+
183
+ ### `behavior:snapshot-filter-context@ruby`
184
+
185
+ mini_racer_rs returns the same filtered results from a snapshot-based context as from a context without a snapshot. In a context made from `MiniRacer::Snapshot.new("Object.getOwnPropertyDescriptors = () => ({})")`, `({a: 1, f() {}})` returns `{"a" => 1}`, and `[1, function() {}]` returns `[1]`. mini_racer 0.22.1 returns `nil` for both. Both gems copy results that V8 refuses to serialize as is through a filter in a separate safe context. mini_racer_rs keeps an untouched context in each snapshot blob and uses it for that filter, while mini_racer 0.22.1 builds the safe context from the snapshot, exposing the filter's built-ins to snapshot code. User code still sees the replacement in both gems: `Object.getOwnPropertyDescriptors({a: 1})` returns `{}`.
186
+
187
+ Approved 2026-10-16.
188
+
189
+ ### `behavior:timeout-bounds-leftover-microtasks@ruby`
190
+
191
+ mini_racer_rs applies the context’s timeout once more while running microtasks left by a script that reached its own timeout. Both gems run leftover microtasks before returning, but mini_racer 0.22.1's watchdog has already fired for that call, so it runs them without a time limit. For example, with `timeout: 200`, evaluating `Promise.resolve().then(() => { while (true) {} }); while (true) {}` never returns in mini_racer. In mini_racer_rs it raises `MiniRacer::ScriptTerminatedError` after about 400 ms, and the context remains usable. This also means mini_racer_rs cuts short a finite leftover microtask that needs more than the second 200 ms, while mini_racer finishes it. Microtasks left by a script ended another way, such as by `stop`, a memory limit, or an interrupt, keep the original deadline in both gems. Without `timeout:`, both run leftover microtasks without a limit. mini_racer_rs differs because `timeout:` often bounds untrusted JavaScript, and an endless microtask should not remove that bound.
192
+
193
+ Approved 2026-10-17.
194
+
195
+ ### `behavior:timeout-watchdog@ruby`
196
+
197
+ mini_racer_rs raises MiniRacer::InternalError when its single process-wide watchdog thread cannot start, and the timed script does not run. mini_racer 0.22.1 starts a watchdog thread for each eval or call on a context created with timeout:; if creation fails, it prints mini_racer: watchdog: pthread_create: <error> to stderr and runs the script without a time limit. This difference prevents a failed watchdog from silently removing the bound often placed on untrusted JavaScript.
198
+
199
+ Approved 2026-10-16.
200
+
201
+ ### `behavior:typed-array-offsets@ruby`
202
+
203
+ mini_racer_rs returns a typed array or DataView at any byte offset as a binary (`ASCII-8BIT`) String containing the view's whole ArrayBuffer, consistent with both gems at offset 0. mini_racer 0.22.1 instead raises `MiniRacer::RuntimeError` with `bad typed array` for offsets such as those in `new Uint8Array(new ArrayBuffer(8), 4)` and `new DataView(new ArrayBuffer(4), 1, 2)`. Its decoder checks the byte after the view type, so offsets whose first encoded byte matches a view type letter can pass, including offset 66 for `B`.
204
+
205
+ Approved 2026-10-16.
206
+
207
+ ### `behavior:uncloneable-after-filter@ruby`
208
+
209
+ mini_racer_rs returns an error Hash when a result remains uncloneable after both gems copy it through mini_racer's filter function, which keeps enumerable data and drops functions. For example, `({a: Symbol("s")})` returns `{"error" => "Error: Symbol(s) could not be cloned."}`. A Map with a function key is another such case. mini_racer 0.22.1 aborts the Ruby process with signal 6 (SIGABRT), although its code contains the fallback that returns V8's message in a Hash. mini_racer_rs uses that fallback.
210
+
211
+ Approved 2026-10-16.
212
+
213
+ ### `behavior:v8-version@ruby`
214
+
215
+ On CRuby, `mini_racer_rs` embeds V8 15.2.124.1 through the `v8` crate 152.2.0, while `mini_racer` 0.22.1 uses V8 13.6.233.17 through `libv8-node` 24.12.0.1. V8-generated text, including parse and runtime error messages and locale formatting, can therefore differ. So can the nesting depth at which V8 stops reading a value: with the default stack limit, `Context#call` accepts arguments about 6,250 levels deep in `mini_racer_rs` and about 3,100 in `mini_racer` 0.22.1, and both limits halve with half the stack. In single-threaded mode, after `low_memory_notification` on a new context, `pump_message_loop` returns `true` in `mini_racer_rs` and `false` in `mini_racer` 0.22.1 because V8 15.2 posts a zero-delay foreground task during collection. Later pumps return `false` in both, as they do in the default multi-threaded mode. Affected upstream tests are marked `deviation:behavior:v8-version@ruby` in `test/upstream/mini_racer.status.toml`. This difference does not apply on TruffleRuby, where both gems use upstream's GraalJS backend.
216
+
217
+ Approved 2026-10-16.
218
+
219
+ ### `behavior:warmup-discards-context@ruby`
220
+
221
+ mini_racer_rs completes `Snapshot#warmup!` when the warmup script creates an object V8 cannot serialize, while mini_racer 0.22.1 stops the process with a `global handle not serialized` trap. mini_racer_rs releases the warmup context before writing the new snapshot blob, so its objects are not written. mini_racer 0.22.1 still holds that context while writing the blob. For `snapshot = MiniRacer::Snapshot.new("function f() { return 1 }")`, `snapshot.warmup!("var formatter = new Intl.DateTimeFormat('en'); f()")` succeeds in mini_racer_rs, and a context created from the snapshot evaluates `[f(), typeof formatter]` to `[1, "undefined"]`. Both gems use a fresh default context, so warmup variables are never part of the result.
222
+
223
+ Approved 2026-10-16.
224
+
225
+ ### `module:MiniRacer::Loader@ruby`
226
+
227
+ `MiniRacer::Loader` and `MiniRacer::Loader.load` do not exist in mini_racer_rs, whose single native extension uses a plain `require`. Its dynamic exports are limited to per-platform allowlists, CI fails if any C++ or Rust symbol is exported, and on Linux it links with `-Bsymbolic` so its references bind to its own definitions. mini_racer 0.22.1 uses `mini_racer_loader` with `RTLD_LOCAL` and `RTLD_DEEPBIND`, except when `LD_PRELOAD` contains `malloc`; `LD_PRELOAD` does not change mini_racer_rs loading.
228
+
229
+ Approved 2026-10-16.
230
+
231
+ ### `smethod:MiniRacer::Loader.load@ruby`
232
+
233
+ `MiniRacer::Loader` and `MiniRacer::Loader.load` do not exist in mini_racer_rs, whose single native extension uses a plain `require`. Its dynamic exports are limited to per-platform allowlists, CI fails if any C++ or Rust symbol is exported, and on Linux it links with `-Bsymbolic` so its references bind to its own definitions. mini_racer 0.22.1 uses `mini_racer_loader` with `RTLD_LOCAL` and `RTLD_DEEPBIND`, except when `LD_PRELOAD` contains `malloc`; `LD_PRELOAD` does not change mini_racer_rs loading.
234
+
235
+ Approved 2026-10-16.