rusty_racer 0.1.4 → 0.1.6
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 +4 -4
- data/README.md +13 -0
- data/ext/rusty_racer/Cargo.toml +1 -1
- data/ext/rusty_racer/src/lib.rs +183 -25
- data/ext/rusty_racer/src/ops.rs +2 -2
- data/lib/rusty_racer/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d14d201ab91d7e00d99d448826a92ad13c5b082b3ebe4b9d1f03778f89abf04
|
|
4
|
+
data.tar.gz: 3dc4d0bb904458984b24e12806dd756f17ae9f541f479df277e218fe8cb70478
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 856d5dbbb8c3c70b1a4a574c85711c2bb89b3d343eaf4316d7714249ba5f6c04113187a728155627634a4eedcca0901cd427734e9fe9e89e9051fe0ffdaf4a6b
|
|
7
|
+
data.tar.gz: 07dd013c094a65e09e2e32ce97a2ac874b2b1dd357e440914a4fdd282612bae3afce4c41bfcc62302457573a7d8681e91117186f0d32cd0aefff27160032bdfa
|
data/README.md
CHANGED
|
@@ -154,6 +154,19 @@ Also available:
|
|
|
154
154
|
isolate's heap. All realms are mutually same-origin (with a host namespace,
|
|
155
155
|
`NS.contextGlobal(id)` reaches another realm's `globalThis`, like a same-origin
|
|
156
156
|
`iframe.contentWindow`), so this is **not** an isolation boundary.
|
|
157
|
+
- **Zero-copy buffer transfer between isolates** — with a host namespace,
|
|
158
|
+
`NS.transferOut(arrayBufferOrView)` detaches a buffer (its `byteLength` → 0) and
|
|
159
|
+
returns an integer token; `NS.transferIn(token)` rebuilds an `ArrayBuffer` over
|
|
160
|
+
the **same** memory in another isolate with no byte copy (the backing store is
|
|
161
|
+
heap-external and atomic-refcounted, so the token stays importable even after the
|
|
162
|
+
exporting isolate is disposed). `NS.transferOut` returns `0` for a non-buffer or
|
|
163
|
+
non-detachable argument — including a `SharedArrayBuffer`, which is *shared*, not
|
|
164
|
+
transferred — so the caller can fall back to a copy; `NS.transferIn` returns
|
|
165
|
+
`undefined` for an unknown token; `NS.transferDrop(token)` releases an exported
|
|
166
|
+
buffer that is never imported. This is the engine primitive for
|
|
167
|
+
implementing `postMessage` transferables; `RustyRacer.pending_transfer_count`
|
|
168
|
+
reports exported-but-not-yet-imported buffers so dropped messages don't leak
|
|
169
|
+
silently.
|
|
157
170
|
- **`Isolate#perform_microtask_checkpoint`** — manual microtask drain. The default
|
|
158
171
|
`microtasks: :auto` also drains at the end of each outermost eval/call/evaluate;
|
|
159
172
|
`microtasks: :explicit` leaves it fully manual. There is no event loop or timers
|
data/ext/rusty_racer/Cargo.toml
CHANGED
data/ext/rusty_racer/src/lib.rs
CHANGED
|
@@ -534,11 +534,6 @@ struct V8State {
|
|
|
534
534
|
promise_reject_handler: Option<(i32, v8::Global<v8::Function>)>,
|
|
535
535
|
}
|
|
536
536
|
|
|
537
|
-
// Context embedder-data slot holding the realm id (an Integer), stamped by
|
|
538
|
-
// new_realm so id_of_context is O(1). Slot 0 is the embedder's own first slot
|
|
539
|
-
// (the binding adds INTERNAL_SLOT_COUNT); nothing else here uses embedder data.
|
|
540
|
-
const REALM_ID_SLOT: i32 = 0;
|
|
541
|
-
|
|
542
537
|
// (STATE/MODULES/SCRIPTS/ACTIVE_REALMS/INSTANTIATING/WATCHDOG_FIRED/
|
|
543
538
|
// AUTO_MICROTASKS/DRAINING moved into IsolateState in the isolate slot, reached
|
|
544
539
|
// via istate!(scope). Their invariants are documented on IsolateState's fields.)
|
|
@@ -652,6 +647,44 @@ static NEXT_ISOLATE_ID: std::sync::atomic::AtomicU32 = std::sync::atomic::Atomic
|
|
|
652
647
|
// dispose isolates explicitly on their owner thread before that thread exits.
|
|
653
648
|
static LEAKED_ISOLATES: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
|
|
654
649
|
|
|
650
|
+
// ── zero-copy ArrayBuffer transfer registry ────────────────────────────────
|
|
651
|
+
//
|
|
652
|
+
// A SharedRef<BackingStore> parked here so a large ArrayBuffer can cross from one
|
|
653
|
+
// isolate to another with NO byte copy. A backing store is V8's own heap-external,
|
|
654
|
+
// atomic-refcounted allocation, designed to be co-owned by live ArrayBuffers "even
|
|
655
|
+
// across isolates" (rusty_v8 ArrayBuffer docs). The embedder (capybara-simulated's
|
|
656
|
+
// cross-isolate postMessage transport) exports a buffer from the source realm via
|
|
657
|
+
// NS.transferOut, ships the returned integer token through its normal message
|
|
658
|
+
// plumbing, and rebuilds an ArrayBuffer over the SAME memory in the destination
|
|
659
|
+
// realm via NS.transferIn — replacing the prior copy-out/copy-in of the bytes.
|
|
660
|
+
//
|
|
661
|
+
// SharedRef<BackingStore> is NOT auto-Send (BackingStore is Send but not Sync, so
|
|
662
|
+
// SharedPtrBase's `T: Sync` Send-bound is unmet). It rides in this newtype with a
|
|
663
|
+
// manual Send for the same reason as SendIso/IsoPtr: the registry only ever MOVES
|
|
664
|
+
// the handle between owner threads (insert on the exporter's thread, remove on the
|
|
665
|
+
// importer's) under the Mutex, never sharing &handle concurrently — and shared_ptr's
|
|
666
|
+
// refcount is atomic, so dropping it on either thread is sound. No Sync impl: the
|
|
667
|
+
// handle is never aliased across threads.
|
|
668
|
+
struct SendBackingStore(v8::SharedRef<v8::BackingStore>);
|
|
669
|
+
unsafe impl Send for SendBackingStore {}
|
|
670
|
+
|
|
671
|
+
// Exported-but-not-yet-imported backing stores, keyed by token. A GLOBAL (not
|
|
672
|
+
// per-isolate): the whole point is to bridge two isolates, and tokens are unique
|
|
673
|
+
// process-wide. An exported buffer that is never imported (a dropped message)
|
|
674
|
+
// pins its memory here until NS.transferDrop releases it — RustyRacer
|
|
675
|
+
// .pending_transfer_count makes that observable.
|
|
676
|
+
static TRANSFER_REGISTRY: std::sync::OnceLock<Mutex<HashMap<u64, SendBackingStore>>> =
|
|
677
|
+
std::sync::OnceLock::new();
|
|
678
|
+
|
|
679
|
+
fn transfer_registry() -> &'static Mutex<HashMap<u64, SendBackingStore>> {
|
|
680
|
+
TRANSFER_REGISTRY.get_or_init(|| Mutex::new(HashMap::new()))
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// Monotonic token source. Starts at 1 so 0 is free as the JS-side "not
|
|
684
|
+
// transferable — fall back to a copy" sentinel. A token is f64-exact for ~2^53
|
|
685
|
+
// transfers, which a process will never reach.
|
|
686
|
+
static NEXT_TRANSFER_TOKEN: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
|
|
687
|
+
|
|
655
688
|
// Run a microtask checkpoint with DRAINING set (nesting-safe via save/restore),
|
|
656
689
|
// so a nested Reset/DisposeContext issued by a drained microtask is refused.
|
|
657
690
|
fn checkpoint_draining(scope: &mut v8::PinScope<'_, '_>) {
|
|
@@ -1015,17 +1048,35 @@ fn finish_dynamic_import(
|
|
|
1015
1048
|
}
|
|
1016
1049
|
}
|
|
1017
1050
|
|
|
1018
|
-
// The id of |context
|
|
1019
|
-
//
|
|
1020
|
-
//
|
|
1021
|
-
//
|
|
1051
|
+
// The id of |context| among this isolate's LIVE realms, or None when it isn't
|
|
1052
|
+
// one (e.g. a context that was reset or disposed away). Scans the realm table:
|
|
1053
|
+
// realm counts are small (a handful of frames) and this only runs off the hot
|
|
1054
|
+
// path (promise rejection, dynamic import, contextOf), so the scan is cheap.
|
|
1055
|
+
//
|
|
1056
|
+
// We deliberately do NOT stamp the id into the context's embedder data. Using a
|
|
1057
|
+
// context slot makes V8 attach a ContextAnnex carrying a guaranteed-finalizer
|
|
1058
|
+
// weak handle to every realm, and that finalizer has crashed the process at
|
|
1059
|
+
// isolate teardown (a first-pass weak callback re-fired during disposal,
|
|
1060
|
+
// panicking on an already-taken handle). Keeping realms free of context slots
|
|
1061
|
+
// keeps teardown clear of that hazard.
|
|
1022
1062
|
fn id_of_context(scope: &mut v8::PinScope<'_, '_>, context: v8::Local<v8::Context>) -> Option<i32> {
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1063
|
+
// The main realm (id 0) is overwhelmingly the common case — check it first,
|
|
1064
|
+
// without cloning the whole table.
|
|
1065
|
+
let main = istate!(scope).realms.main_context.clone();
|
|
1066
|
+
if main.is_some_and(|g| v8::Local::new(scope, &g) == context) {
|
|
1067
|
+
return Some(0);
|
|
1068
|
+
}
|
|
1069
|
+
// Extra realms: snapshot the (cloned) Globals so no IsolateState borrow is
|
|
1070
|
+
// held while we mint Locals from `scope`.
|
|
1071
|
+
let extras: Vec<(i32, v8::Global<v8::Context>)> = istate!(scope)
|
|
1072
|
+
.realms
|
|
1073
|
+
.contexts
|
|
1074
|
+
.iter()
|
|
1075
|
+
.map(|(id, g)| (*id, g.clone()))
|
|
1076
|
+
.collect();
|
|
1077
|
+
extras
|
|
1078
|
+
.into_iter()
|
|
1079
|
+
.find_map(|(id, g)| (v8::Local::new(scope, &g) == context).then_some(id))
|
|
1029
1080
|
}
|
|
1030
1081
|
|
|
1031
1082
|
// Pick the Global context for a realm id: 0 = main, N = an extra realm (None
|
|
@@ -1304,6 +1355,105 @@ fn set_promise_reject_handler(
|
|
|
1304
1355
|
}
|
|
1305
1356
|
}
|
|
1306
1357
|
|
|
1358
|
+
// NS.transferOut(arrayBufferOrView) -> a positive integer token, or 0 when the
|
|
1359
|
+
// argument can't be zero-copy transferred so the caller falls back to a copy.
|
|
1360
|
+
// Grabs the buffer's backing store, DETACHES the source (transfer semantics: its
|
|
1361
|
+
// byteLength -> 0, like a structured-clone transfer list), and parks the store
|
|
1362
|
+
// under the returned token. The bytes are untouched — only the source realm
|
|
1363
|
+
// loses access. A view transfers its whole underlying ArrayBuffer.
|
|
1364
|
+
//
|
|
1365
|
+
// Returns 0 (copy fallback) for: a non-buffer argument; a non-detachable buffer
|
|
1366
|
+
// (WebAssembly/asm.js memory); and a SharedArrayBuffer or SAB-backed view — a
|
|
1367
|
+
// SAB is *shared*, not transferred (detaching it would be a category error), so
|
|
1368
|
+
// it has no place in this transfer primitive; sharing it zero-copy across
|
|
1369
|
+
// isolates would be a separate feature.
|
|
1370
|
+
fn transfer_out(
|
|
1371
|
+
scope: &mut v8::PinScope<'_, '_>,
|
|
1372
|
+
args: v8::FunctionCallbackArguments<'_>,
|
|
1373
|
+
mut rv: v8::ReturnValue<'_, v8::Value>,
|
|
1374
|
+
) {
|
|
1375
|
+
let value = args.get(0);
|
|
1376
|
+
let ab = if value.is_array_buffer() {
|
|
1377
|
+
v8::Local::<v8::ArrayBuffer>::try_from(value).ok()
|
|
1378
|
+
} else if value.is_array_buffer_view() {
|
|
1379
|
+
v8::Local::<v8::ArrayBufferView>::try_from(value)
|
|
1380
|
+
.ok()
|
|
1381
|
+
.and_then(|view| view.buffer(scope))
|
|
1382
|
+
} else {
|
|
1383
|
+
None
|
|
1384
|
+
};
|
|
1385
|
+
// Only transfer what we can neuter: zero-copy sharing a buffer the source
|
|
1386
|
+
// realm keeps live would alias mutable memory across isolates. Caller copies.
|
|
1387
|
+
let Some(ab) = ab.filter(|ab| ab.is_detachable()) else {
|
|
1388
|
+
rv.set(v8::Number::new(scope, 0.0).into());
|
|
1389
|
+
return;
|
|
1390
|
+
};
|
|
1391
|
+
// Grab the store BEFORE detaching — detach severs the buffer from it; the
|
|
1392
|
+
// SharedRef then keeps the memory alive on its own via the atomic refcount.
|
|
1393
|
+
let store = ab.get_backing_store();
|
|
1394
|
+
// is_detachable() does NOT guarantee detach succeeds: a buffer carrying an
|
|
1395
|
+
// [[ArrayBufferDetachKey]] returns None here and stays live. Register only
|
|
1396
|
+
// once the source is genuinely neutered, else both realms would alias one
|
|
1397
|
+
// backing store. (rusty_racer sets no detach keys today, so this is belt-and-
|
|
1398
|
+
// braces against the safety invariant ever silently breaking.)
|
|
1399
|
+
if ab.detach(None) != Some(true) {
|
|
1400
|
+
rv.set(v8::Number::new(scope, 0.0).into());
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
let token = NEXT_TRANSFER_TOKEN.fetch_add(1, Ordering::Relaxed);
|
|
1404
|
+
transfer_registry()
|
|
1405
|
+
.lock()
|
|
1406
|
+
.unwrap()
|
|
1407
|
+
.insert(token, SendBackingStore(store));
|
|
1408
|
+
rv.set(v8::Number::new(scope, token as f64).into());
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// Parse a transfer-token argument: a finite, integral JS number >= 1 (0 is the
|
|
1412
|
+
// "not transferable" sentinel transferOut never issues, and tokens are f64-exact
|
|
1413
|
+
// only up to 2^53). Rejects NaN / Infinity / fractional / negative / out-of-range
|
|
1414
|
+
// values — which a bare `as u64` would truncate or saturate into a COLLISION with
|
|
1415
|
+
// a live token, stealing an unrelated transfer — so a malformed token instead
|
|
1416
|
+
// reads as "unknown" (transferIn -> undefined, transferDrop -> no-op). Must run
|
|
1417
|
+
// before locking the registry: number_value can invoke a user valueOf/
|
|
1418
|
+
// Symbol.toPrimitive, i.e. re-enter these callbacks.
|
|
1419
|
+
fn transfer_token(scope: &mut v8::PinScope<'_, '_>, value: v8::Local<v8::Value>) -> Option<u64> {
|
|
1420
|
+
let n = value.number_value(scope)?;
|
|
1421
|
+
(n.is_finite() && n.fract() == 0.0 && (1.0..=9_007_199_254_740_992.0).contains(&n))
|
|
1422
|
+
.then_some(n as u64)
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// NS.transferIn(token) -> a fresh ArrayBuffer over the transferred backing store
|
|
1426
|
+
// (no byte copy), or undefined for an unknown token (already imported, or the
|
|
1427
|
+
// message was dropped). Consumes the token: the new buffer co-owns the store, so
|
|
1428
|
+
// the registry's reference is released.
|
|
1429
|
+
fn transfer_in(
|
|
1430
|
+
scope: &mut v8::PinScope<'_, '_>,
|
|
1431
|
+
args: v8::FunctionCallbackArguments<'_>,
|
|
1432
|
+
mut rv: v8::ReturnValue<'_, v8::Value>,
|
|
1433
|
+
) {
|
|
1434
|
+
let Some(token) = transfer_token(scope, args.get(0)) else {
|
|
1435
|
+
return;
|
|
1436
|
+
};
|
|
1437
|
+
let entry = transfer_registry().lock().unwrap().remove(&token);
|
|
1438
|
+
if let Some(SendBackingStore(store)) = entry {
|
|
1439
|
+
rv.set(v8::ArrayBuffer::with_backing_store(scope, &store).into());
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// NS.transferDrop(token): release a transferred backing store WITHOUT importing
|
|
1444
|
+
// it — for when the embedder discards a message whose buffer was exported.
|
|
1445
|
+
// A no-op for an unknown token. Without this, an exported-but-never-imported
|
|
1446
|
+
// buffer would pin its memory until process exit.
|
|
1447
|
+
fn transfer_drop(
|
|
1448
|
+
scope: &mut v8::PinScope<'_, '_>,
|
|
1449
|
+
args: v8::FunctionCallbackArguments<'_>,
|
|
1450
|
+
_rv: v8::ReturnValue<'_, v8::Value>,
|
|
1451
|
+
) {
|
|
1452
|
+
if let Some(token) = transfer_token(scope, args.get(0)) {
|
|
1453
|
+
transfer_registry().lock().unwrap().remove(&token);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1307
1457
|
// V8 calls this synchronously on promise rejections with no handler (and the
|
|
1308
1458
|
// later revocations when a handler IS added). Forwards
|
|
1309
1459
|
// (event, contextId, promise, reason) to the registered JS recorder — the
|
|
@@ -1363,18 +1513,11 @@ unsafe extern "C" fn promise_reject_cb(message: v8::PromiseRejectMessage) {
|
|
|
1363
1513
|
// Build a fresh v8::Context and install the host namespace (from STATE) into
|
|
1364
1514
|
// it — the single definition of "a realm of this isolate", shared by boot,
|
|
1365
1515
|
// reset and create_context so realms can't drift apart.
|
|
1366
|
-
fn new_realm(scope: &mut v8::PinScope<'_, '_, ()
|
|
1516
|
+
fn new_realm(scope: &mut v8::PinScope<'_, '_, ()>) -> v8::Global<v8::Context> {
|
|
1367
1517
|
let fresh = {
|
|
1368
1518
|
let context = v8::Context::new(scope, Default::default());
|
|
1369
1519
|
v8::Global::new(scope, context)
|
|
1370
1520
|
};
|
|
1371
|
-
// Stamp the realm id into the context so id_of_context is O(1) (it would
|
|
1372
|
-
// otherwise scan every realm on every promise rejection / contextOf call).
|
|
1373
|
-
{
|
|
1374
|
-
let context = v8::Local::new(scope, &fresh);
|
|
1375
|
-
let id_val: v8::Local<v8::Value> = v8::Integer::new(scope, id).into();
|
|
1376
|
-
context.set_embedder_data(REALM_ID_SLOT, id_val);
|
|
1377
|
-
}
|
|
1378
1521
|
// DESIGN DECISION: every realm of an isolate shares ONE security token, so
|
|
1379
1522
|
// they are all mutually same-origin — the model is "a group of same-origin
|
|
1380
1523
|
// frames sharing one heap", and NS.contextGlobal gives full cross-realm
|
|
@@ -1427,7 +1570,7 @@ fn install_host_namespace(
|
|
|
1427
1570
|
let context = v8::Local::new(scope, ctx);
|
|
1428
1571
|
let scope = &mut v8::ContextScope::new(scope, context);
|
|
1429
1572
|
let ns = v8::Object::new(scope);
|
|
1430
|
-
let members: [(&str, Option<v8::Local<v8::Function>>);
|
|
1573
|
+
let members: [(&str, Option<v8::Local<v8::Function>>); 7] = [
|
|
1431
1574
|
("drainMicrotasks", v8::Function::new(scope, drain_microtasks)),
|
|
1432
1575
|
("contextGlobal", v8::Function::new(scope, context_global)),
|
|
1433
1576
|
("contextOf", v8::Function::new(scope, context_of)),
|
|
@@ -1435,6 +1578,9 @@ fn install_host_namespace(
|
|
|
1435
1578
|
"setPromiseRejectHandler",
|
|
1436
1579
|
v8::Function::new(scope, set_promise_reject_handler),
|
|
1437
1580
|
),
|
|
1581
|
+
("transferOut", v8::Function::new(scope, transfer_out)),
|
|
1582
|
+
("transferIn", v8::Function::new(scope, transfer_in)),
|
|
1583
|
+
("transferDrop", v8::Function::new(scope, transfer_drop)),
|
|
1438
1584
|
];
|
|
1439
1585
|
for (member, function) in members {
|
|
1440
1586
|
if let (Some(f), Some(k)) = (function, v8::String::new(scope, member)) {
|
|
@@ -1620,7 +1766,7 @@ impl Isolate {
|
|
|
1620
1766
|
// namespace from the slot (seeded above).
|
|
1621
1767
|
{
|
|
1622
1768
|
v8::scope!(let scope, &mut isolate);
|
|
1623
|
-
let main_context = new_realm(scope
|
|
1769
|
+
let main_context = new_realm(scope);
|
|
1624
1770
|
istate!(scope).realms.main_context = Some(main_context);
|
|
1625
1771
|
}
|
|
1626
1772
|
// Box the OwnedIsolate so it has a STABLE address, then capture a raw ptr
|
|
@@ -2278,6 +2424,17 @@ fn leaked_isolate_count() -> usize {
|
|
|
2278
2424
|
LEAKED_ISOLATES.load(Ordering::Relaxed)
|
|
2279
2425
|
}
|
|
2280
2426
|
|
|
2427
|
+
// RustyRacer.pending_transfer_count -> Integer: backing stores exported via
|
|
2428
|
+
// NS.transferOut but not yet imported (NS.transferIn) or released
|
|
2429
|
+
// (NS.transferDrop). PROCESS-WIDE (the registry bridges isolates, so the count
|
|
2430
|
+
// aggregates every isolate's outstanding transfers — compare deltas, not the
|
|
2431
|
+
// absolute value, when isolates run concurrently). A transport that always pairs
|
|
2432
|
+
// an export with one of those keeps its own contribution at 0; a rising count
|
|
2433
|
+
// means dropped messages are leaking transferred memory.
|
|
2434
|
+
fn pending_transfer_count() -> usize {
|
|
2435
|
+
transfer_registry().lock().unwrap().len()
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2281
2438
|
// Thin magnus-method wrappers.
|
|
2282
2439
|
// Isolate = the VM and its isolate-level operations; it hands out Contexts.
|
|
2283
2440
|
impl Isolate {
|
|
@@ -2812,5 +2969,6 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
2812
2969
|
// Observability for the thread-confined lifecycle (see Drop for Core).
|
|
2813
2970
|
module.define_singleton_method("live_isolate_count", function!(live_isolate_count, 0))?;
|
|
2814
2971
|
module.define_singleton_method("leaked_isolate_count", function!(leaked_isolate_count, 0))?;
|
|
2972
|
+
module.define_singleton_method("pending_transfer_count", function!(pending_transfer_count, 0))?;
|
|
2815
2973
|
Ok(())
|
|
2816
2974
|
}
|
data/ext/rusty_racer/src/ops.rs
CHANGED
|
@@ -574,7 +574,7 @@ fn op_reset(scope: &mut v8::PinScope<'_, '_, ()>, context_id: i32) -> VmReply {
|
|
|
574
574
|
.into(),
|
|
575
575
|
)))
|
|
576
576
|
} else {
|
|
577
|
-
let fresh = new_realm(scope
|
|
577
|
+
let fresh = new_realm(scope);
|
|
578
578
|
{
|
|
579
579
|
let realms = &mut istate!(scope).realms;
|
|
580
580
|
if context_id == 0 {
|
|
@@ -596,7 +596,7 @@ fn op_create_context(scope: &mut v8::PinScope<'_, '_, ()>) -> VmReply {
|
|
|
596
596
|
realms.next_context_id += 1;
|
|
597
597
|
id
|
|
598
598
|
};
|
|
599
|
-
let fresh = new_realm(scope
|
|
599
|
+
let fresh = new_realm(scope);
|
|
600
600
|
istate!(scope).realms.contexts.insert(id, fresh);
|
|
601
601
|
VmReply::Done(Ok(JsVal::Int(id as i64)))
|
|
602
602
|
}
|
data/lib/rusty_racer/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rusty_racer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keita Urashima
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 2026-06-14 00:00:00.000000000 Z
|
|
@@ -54,7 +54,7 @@ metadata:
|
|
|
54
54
|
source_code_uri: https://github.com/ursm/rusty_racer
|
|
55
55
|
bug_tracker_uri: https://github.com/ursm/rusty_racer/issues
|
|
56
56
|
rubygems_mfa_required: 'true'
|
|
57
|
-
post_install_message:
|
|
57
|
+
post_install_message:
|
|
58
58
|
rdoc_options: []
|
|
59
59
|
require_paths:
|
|
60
60
|
- lib
|
|
@@ -70,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
70
70
|
version: '0'
|
|
71
71
|
requirements: []
|
|
72
72
|
rubygems_version: 3.5.22
|
|
73
|
-
signing_key:
|
|
73
|
+
signing_key:
|
|
74
74
|
specification_version: 4
|
|
75
75
|
summary: Embed V8 in Ruby via rusty_v8 + Magnus (rb-sys)
|
|
76
76
|
test_files: []
|