Skip to content

Commit

Permalink
fix solidjs#1850 untrack in external source
Browse files Browse the repository at this point in the history
  • Loading branch information
ryansolid committed Jan 3, 2024
1 parent 292aba4 commit 8d2de12
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/popular-birds-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"solid-js": patch
---

fix #1850 untrack in external source
48 changes: 29 additions & 19 deletions packages/solid/src/reactive/signal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ const NO_INIT = {};
export var Owner: Owner | null = null;
export let Transition: TransitionState | null = null;
let Scheduler: ((fn: () => void) => any) | null = null;
let ExternalSourceFactory: ExternalSourceFactory | null = null;
let ExternalSourceConfig: {
factory: ExternalSourceFactory;
untrack: <V>(fn: () => V) => V;
} | null = null;
let Listener: Computation<any> | null = null;
let Updates: Computation<any>[] | null = null;
let Effects: Computation<any>[] | null = null;
Expand Down Expand Up @@ -865,11 +868,12 @@ export function batch<T>(fn: Accessor<T>): T {
* @description https://www.solidjs.com/docs/latest/api#untrack
*/
export function untrack<T>(fn: Accessor<T>): T {
if (Listener === null) return fn();
if (!ExternalSourceConfig && Listener === null) return fn();

const listener = Listener;
Listener = null;
try {
if (ExternalSourceConfig) return ExternalSourceConfig.untrack(fn);
return fn();
} finally {
Listener = listener;
Expand Down Expand Up @@ -1231,22 +1235,28 @@ export function getSuspenseContext() {
}

// Interop
export function enableExternalSource(factory: ExternalSourceFactory) {
if (ExternalSourceFactory) {
const oldFactory = ExternalSourceFactory;
ExternalSourceFactory = (fn, trigger) => {
const oldSource = oldFactory(fn, trigger);
const source = factory(x => oldSource.track(x), trigger);
return {
track: x => source.track(x),
dispose() {
source.dispose();
oldSource.dispose();
}
};
export function enableExternalSource(
factory: ExternalSourceFactory,
untrack: <V>(fn: () => V) => V = fn => fn()
) {
if (ExternalSourceConfig) {
const { factory: oldFactory, untrack: oldUntrack } = ExternalSourceConfig;
ExternalSourceConfig = {
factory: (fn, trigger) => {
const oldSource = oldFactory(fn, trigger);
const source = factory(x => oldSource.track(x), trigger);
return {
track: x => source.track(x),
dispose() {
source.dispose();
oldSource.dispose();
}
};
},
untrack: fn => oldUntrack(() => untrack(fn))
};
} else {
ExternalSourceFactory = factory;
ExternalSourceConfig = { factory, untrack };
}
}

Expand Down Expand Up @@ -1428,13 +1438,13 @@ function createComputation<Next, Init = unknown>(

if ("_SOLID_DEV_" && options && options.name) c.name = options.name;

if (ExternalSourceFactory && c.fn) {
if (ExternalSourceConfig && c.fn) {
const [track, trigger] = createSignal<void>(undefined, { equals: false });
const ordinary = ExternalSourceFactory(c.fn, trigger);
const ordinary = ExternalSourceConfig.factory(c.fn, trigger);
onCleanup(() => ordinary.dispose());
const triggerInTransition: () => void = () =>
startTransition(trigger).then(() => inTransition.dispose());
const inTransition = ExternalSourceFactory(c.fn, triggerInTransition);
const inTransition = ExternalSourceConfig.factory(c.fn, triggerInTransition);
c.fn = x => {
track();
return Transition && Transition.running ? inTransition.track(x) : ordinary.track(x);
Expand Down
19 changes: 17 additions & 2 deletions packages/solid/test/external-source.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createRoot, createMemo, enableExternalSource } from "../src";
import { createRoot, createMemo, untrack, enableExternalSource } from "../src";

import "./MessageChannel";

Expand Down Expand Up @@ -27,6 +27,16 @@ class ExternalSource<T = any> {

let listener: (() => void) | null = null;

function untrackSource<T>(fn: () => T) {
const tmp = listener;
listener = null;
try {
return fn();
} finally {
listener = tmp;
}
}

let sources: Map<() => void, Set<ExternalSource>> = new Map();

describe("external source", () => {
Expand All @@ -49,7 +59,7 @@ describe("external source", () => {
sources.delete(trigger);
}
};
});
}, untrackSource);

enableExternalSource(fn => {
return {
Expand All @@ -64,9 +74,14 @@ describe("external source", () => {
const memo = createMemo(() => {
return e.get();
});
const memo2 = createMemo(() => {
return untrack(() => e.get());
});
expect(memo()).toBe(0);
expect(memo2()).toBe(0);
e.update(1);
expect(memo()).toBe(1);
expect(memo2()).toBe(0);
fn();
});
});
Expand Down

0 comments on commit 8d2de12

Please sign in to comment.