Side Effect Isolation
The signal and lifecycle APIs can cause side effects such as tracking a signal access or registering a teardown hook.
The isolate
function can be used to run arbitrary code in isolation from signal access tracking and the current lifecycle.
import { isolate } from "rvx";
isolate(() => {
// Some code with side effects...
});
import { isolate } from "./rvx.js";
isolate(() => {
// Some code with side effects...
});
Lifecycle
Teardown hooks are leaked as if teardown
was called outside of any context:
import { capture, teardown, isolate } from "rvx";
capture(() => {
// This will be captured:
teardown(() => {});
isolate(() => {
// This will leak:
teardown(() => {});
});
});
import { capture, teardown, isolate } from "./rvx.js";
capture(() => {
// This will be captured:
teardown(() => {});
isolate(() => {
// This will leak:
teardown(() => {});
});
});
To isolate only the lifecycle, you can also use uncapture
, but this will not trigger leak detection.
Signals
Signal accesses are not tracked as if the signal was accessed outside of any observer.
import { effect, isolate, track } from "rvx";
effect(() => {
// This is tracked:
signalA.access();
isolate(() => {
// This is ignored:
signalB.access();
track(() => {
// This is also ignored:
signalC.access();
});
});
});
import { effect, isolate, track } from "./rvx.js";
effect(() => {
// This is tracked:
signalA.access();
isolate(() => {
// This is ignored:
signalB.access();
track(() => {
// This is also ignored:
signalC.access();
});
});
});
To only control if signal accesses are tracked, use track
and untrack
instead.
Non Isolated APIs
Batches are not isolated as this could lead to inconsistent signal access tracking:
import { batch, isolate } from "rvx";
batch(() => {
// This is part of the batch:
a.value++;
isolate(() => {
// This is also part of the batch:
b.value++;
});
});
The isolate
function is transparent to all contexts for performance reasons:
import { Context, isolate } from "rvx";
const EXAMPLE = new Context(42);
EXAMPLE.inject(77, () => {
isolate(() => {
EXAMPLE.value; // 77
});
});
import { Context, isolate } from "./rvx.js";
const EXAMPLE = new Context(42);
EXAMPLE.inject(77, () => {
isolate(() => {
EXAMPLE.value; // 77
});
});
In case you also need to isolate all contexts, isolate
can be combined with Context.window
:
import { Context, isolate } from "rvx";
isolate(Context.window, [], () => {
// ...
});
import { Context, isolate } from "./rvx.js";
isolate(Context.window, [], () => {
// ...
});