Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/store-family-mangled-fields.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Smaller store bundles: the store family field (`_fam`) and its `_overlaid`, `_asked`, `_woke` and `_shallow` fields are now `_`-prefixed internals, so the prod and observe builds mangle them (no behavior change).
10 changes: 10 additions & 0 deletions packages/signals/scripts/mangle-props.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"_acted": "nt",
"_armLane": "B",
"_armed": "h",
"_asked": "dn",
"_blocked": "fe",
"_born": "ro",
"_boundRunEffect": "W",
Expand Down Expand Up @@ -32,6 +33,7 @@
"_evaluating": "gt",
"_extraConfig": "xe",
"_fallback": "L",
"_fam": "rr",
"_fb": "re",
"_firstChild": "pe",
"_flags": "R",
Expand Down Expand Up @@ -82,6 +84,7 @@
"_open": "tt",
"_order": "yt",
"_output": "j",
"_overlaid": "cn",
"_owned": "Mt",
"_owner": "H",
"_parentComputed": "Ke",
Expand Down Expand Up @@ -110,6 +113,7 @@
"_runs": "M",
"_scope": "oo",
"_served": "$e",
"_shallow": "It",
"_show": "ne",
"_shown": "Ue",
"_shownError": "Te",
Expand Down Expand Up @@ -138,12 +142,14 @@
"_verdictLane": "J",
"_witness": "io",
"_witnessMark": "rt",
"_woke": "Tt",
"_x": "T"
},
"observe": {
"_acted": "nt",
"_armLane": "B",
"_armed": "h",
"_asked": "dn",
"_blocked": "fe",
"_born": "ro",
"_boundRunEffect": "W",
Expand Down Expand Up @@ -199,6 +205,7 @@
"_evaluating": "rs",
"_extraConfig": "ct",
"_fallback": "L",
"_fam": "rr",
"_fb": "re",
"_firstChild": "ze",
"_flags": "R",
Expand Down Expand Up @@ -251,6 +258,7 @@
"_open": "tt",
"_order": "Zt",
"_output": "j",
"_overlaid": "cn",
"_owned": "ls",
"_owner": "H",
"_parentComputed": "Pt",
Expand Down Expand Up @@ -280,6 +288,7 @@
"_runs": "M",
"_scope": "oo",
"_served": "Ut",
"_shallow": "nr",
"_show": "ne",
"_shown": "Nt",
"_shownError": "Te",
Expand Down Expand Up @@ -308,6 +317,7 @@
"_verdictLane": "J",
"_witness": "io",
"_witnessMark": "bt",
"_woke": "tr",
"_x": "T"
}
}
4 changes: 2 additions & 2 deletions packages/signals/src/affects-marks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function repoll(
if (!(sub as any)._type) repoll(sub, seen, readers);
// A derived store's derive: its leaves' readers derive from it too
// (store/projection.ts; a live target's property, has and keys nodes).
const fam = (sub as any).fam;
const fam = (sub as any)._fam;
if (fam)
for (const t of fam.live)
for (const o of [t.n, t.h, { k: t.k, d: t.dk }])
Expand All @@ -69,7 +69,7 @@ function marked(el: Marked, seen: Set<Marked>): boolean {
if (c._statusFlags & STATUS_ERROR || seen.has(el)) return false;
seen.add(el);
if (c._config & CONFIG_SLOT_NODE) {
const derive: Marked | null | undefined = (c as any)._host?.fam?.node;
const derive: Marked | null | undefined = (c as any)._host?._fam?.node;
return derive != null && marked(derive, seen);
}
const tail = c._flags & REACTIVE_RECOMPUTING_DEPS ? c._depsTail : undefined;
Expand Down
8 changes: 4 additions & 4 deletions packages/signals/src/core/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export function stageError(el: Computed<any>, error: any, inPass?: boolean): boo
if (
!(
el._config & CONFIG_HELD ||
(inPass && el._flags & REACTIVE_STAGED_READ && globalQueue._running && !(el as any).fam)
(inPass && el._flags & REACTIVE_STAGED_READ && globalQueue._running && !(el as any)._fam)
) ||
passLane
)
Expand Down Expand Up @@ -249,7 +249,7 @@ function stageMark(node: Computed<any>, el: Computed<any>): void {
queuePendingNode(node);
// A derived store's readers are its family's (store/projection.ts): they
// re-derive from the staging, as from the derive's status (#4189).
(node as any).fam?.st(STATUS_ERROR);
(node as any)._fam?.st(STATUS_ERROR);
settlePendingSource(node);
}
}
Expand Down Expand Up @@ -387,7 +387,7 @@ export function settlePendingSource(el: Computed<any>, source: Computed<any> = e
// its readers wait on the derive itself, not on this source, so they
// settle with it, as a memo's would through its dependents (F-9, A9).
// Only a store build has one (`storeParkHook`).
else if (storeParkHook) (node as any).fam?.st();
else if (storeParkHook) (node as any)._fam?.st();
if (node._x !== null) node._x._blocked = false;
// Fully settled with nobody watching: release candidate (#2934). Checked
// again at release time — deferred so unobserved() can't unlink subs
Expand Down Expand Up @@ -1135,7 +1135,7 @@ export function propagateStatus(el: Computed<any>, status: number, error: any):
notifyStatus(sub, status, error);
// A derived store's derive (store/projection.ts): marked, not re-run —
// its leaves' readers are not its dependents, so the family walks them.
(sub as any).fam?.st(status, error);
(sub as any)._fam?.st(status, error);
}
});
}
2 changes: 1 addition & 1 deletion packages/signals/src/core/seat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ export function slot(
const laneHas = !laneNP(el, guess, staged, uninit) && !flying;
// A folded lane (D-34): a deriving pass outside the lane reads the
// hold's world and joins it; lane work and leaves keep the guess.
if (l.folded && guess && !inLane && !leaf && (el as any)._host?.fam?.node !== c)
if (l.folded && guess && !inLane && !leaf && (el as any)._host?._fam?.node !== c)
return pred(rowBase + "D4'", staged ? SLOT_P : SLOT_C, RAISE_H, resolveTx(l._parent ?? l));
if (!tracked) {
// An untracked read outside lane work: the screen (D4''); inside, the
Expand Down
2 changes: 1 addition & 1 deletion packages/signals/src/core/verdict.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ function observeFlight(c: Computed<any>, el: Computed<any>): boolean {
// A derived store's derive whose store has no reader (`fam.live` empty:
// no leaf has a node) is no display: it observes nothing and holds nothing
// (F-3, D-11) — it stays live only to keep the store's data.
if (globalQueue._running && (c as any).fam?.live.size !== 0) {
if (globalQueue._running && (c as any)._fam?.live.size !== 0) {
joinFuture(null);
if (!(el._config & CONFIG_HELD)) queuePendingNode(el);
verdictRead(c, flushTransaction!, true);
Expand Down
2 changes: 1 addition & 1 deletion packages/signals/src/deferred.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function lagOf(c: Computed<any>, seen: Set<Computed<any>>): Computed<any> | unde
if (lagging.has(c)) return c;
if (seen.has(c)) return;
seen.add(c);
if (c._config & CONFIG_SLOT_NODE) return lagOf((c as any)._host?.fam?.node ?? c, seen);
if (c._config & CONFIG_SLOT_NODE) return lagOf((c as any)._host?._fam?.node ?? c, seen);
const tail = c._flags & REACTIVE_RECOMPUTING_DEPS ? c._depsTail : undefined;
if (tail !== null)
for (let d = c._deps ?? null; d !== null; d = d._nextDep) {
Expand Down
6 changes: 3 additions & 3 deletions packages/signals/src/store/affects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function storeMarks(t: StoreTarget, key: PropertyKey | undefined): Marked
const entry = scopeOf(node, key);
if (key === undefined) {
const found: Marked[] = [node];
walk(t.px, entry, found, t.fam, new Set());
walk(t.px, entry, found, t._fam, new Set());
return found;
}
entry._scope.add(t.v);
Expand Down Expand Up @@ -87,7 +87,7 @@ function walk(
if (t !== undefined) {
if (t.pb !== null) entry._scope.add(t.v);
// The writer's view: the tick's own unflushed guesses are in motion too.
if (optHooks && t.fam?.opt === true) raw = optHooks.view(t, raw, true);
if (optHooks && t._fam?.opt === true) raw = optHooks.view(t, raw, true);
const nodes = t.n;
if (nodes !== null)
for (const k of Reflect.ownKeys(nodes))
Expand All @@ -98,7 +98,7 @@ function walk(
if (has !== null) for (const k of Reflect.ownKeys(has)) found.push(has[k as any]);
if (t.k !== null) found.push(t.k);
if (t.dk !== null) found.push(t.dk);
fam = t.fam ?? fam;
fam = t._fam ?? fam;
}
for (const k of Reflect.ownKeys(raw))
if (k !== $OWNER) {
Expand Down
4 changes: 2 additions & 2 deletions packages/signals/src/store/edges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export function storeName(x: object | undefined): string | undefined {
// Up to the root; a target on the way named as a root of its own is one
// object in two stores.
while (t.u !== null) {
if (t.fam !== null || t.ch || signalName(t) !== undefined) return undefined;
if (t._fam !== null || t.ch || signalName(t) !== undefined) return undefined;
t = t.u;
}
if (t.fam !== null || t.ch) return undefined;
if (t._fam !== null || t.ch) return undefined;
return signalName(t) || undefined;
}
2 changes: 1 addition & 1 deletion packages/signals/src/store/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface OptHooks {
has(t: StoreTarget, key: PropertyKey): boolean | undefined;
/** A guessed key's descriptor (`null`: removed; `undefined`: no guess). */
descriptor(t: StoreTarget, key: PropertyKey): PropertyDescriptor | null | undefined;
/** The flush's commit: targets no lane holds leave `overlaid`. */
/** The flush's commit: targets no lane holds leave `_overlaid`. */
sweep(): void;
/** The container comparator's lane arm: an arrangement guess against a
* landing (or another arrangement), by row identity. */
Expand Down
48 changes: 24 additions & 24 deletions packages/signals/src/store/optimistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function notifyOptimisticWrites(
// are the guesses' own: their landings judge them. A set (empty or not)
// marks a keyed arrangement guess (`fold`).
let removed: Set<unknown> | null = null;
const keyFn = t.fam!.key;
const keyFn = t._fam!.key;
if (isArr && keyFn !== null && keyFn !== undefined) {
removed = new Set();
const kept = new Set<unknown>();
Expand Down Expand Up @@ -206,7 +206,7 @@ function arrangement(t: StoreTarget, a: any, b: any): boolean {
const av = a instanceof LaneView;
const bv = b instanceof LaneView;
if (!av && !bv) return false;
return arrangementEqual(av ? a.rows : a, bv ? b.rows : b, t.fam!);
return arrangementEqual(av ? a.rows : a, bv ? b.rows : b, t._fam!);
}

function rowSame(a: any, b: any, fam: StoreFamily): boolean {
Expand Down Expand Up @@ -338,7 +338,7 @@ GlobalQueue._slotTake = (n, back) => {
? getHasNode(t!, k)
: getNode(t!, k);
}
const d = t?.fam?.node?._x?._transaction;
const d = t?._fam?.node?._x?._transaction;
const g = txOf(n);
if (!d?._lane || sameAction(d, g)) return false;
// The re-ask takes the target's guess whole: the slot is the lane's
Expand Down Expand Up @@ -375,7 +375,7 @@ GlobalQueue._laneRebase = (el: Signal<any>, truth: unknown, older: boolean) => {
view.base = truth as Record<PropertyKey, any>;
return;
}
const keyFn = t.fam?.key ?? null;
const keyFn = t._fam?.key ?? null;
if (keyFn === null) return;
const byKey = new Map<unknown, any>();
for (let i = 0; i < truth.length; i++) {
Expand Down Expand Up @@ -472,7 +472,7 @@ function foldedRead(c: Computed<any> | null, el: Signal<any> | Computed<any>): u
passLane !== null ||
(c as any)._type === EFFECT_RENDER ||
c._config & CONFIG_CHILDREN_FORBIDDEN ||
(el as any)._host?.fam?.node === c
(el as any)._host?._fam?.node === c
)
return NOT_PENDING;
const l = txOf(el);
Expand Down Expand Up @@ -513,8 +513,8 @@ function laneSet(node: Signal<any>, value: unknown, lane: ReturnType<typeof txOf
* a guessed row keeps its target, and its leaves are judged against their
* guesses. Rows nothing guessed are left as the draft wrote them. */
function pairRows(t: StoreTarget, pb: Record<PropertyKey, any>): void {
const keyFn = t.fam!.key;
for (let c of t.fam!.overlaid ?? []) {
const keyFn = t._fam!.key;
for (let c of t._fam!._overlaid ?? []) {
// The guessed row, or its ancestor directly under `t` (none: skip).
while (c.u !== t) if ((c = c.u!) === null) break;
if (c === null) continue;
Expand All @@ -524,7 +524,7 @@ function pairRows(t: StoreTarget, pb: Record<PropertyKey, any>): void {
: pb[c.pk!];
// A new object only: not `c`'s own, nor one another row serves
// (pairing it would alias the two).
if (isWrappable(nv) && !lookupTarget(nv, t.fam)) reconcileState(nv, c.px, keyFn, true);
if (isWrappable(nv) && !lookupTarget(nv, t._fam)) reconcileState(nv, c.px, keyFn, true);
}
}

Expand All @@ -540,7 +540,7 @@ installOptHooks({
descriptor: optimisticOwnDescriptor,
sweep: sweepOverlaid,
// A new question (not a `refresh()`) asked over guesses an earlier frame
// opened, which answer the old one (D-34, #4336). Stamped on `fam.asked`
// opened, which answer the old one (D-34, #4336). Stamped on `fam._asked`
// with this flush's `clock`, so it lapses when the flush ends: `clock + 1`
// from mainline over a live guess — a frame still reading a guess at the
// seam shows it beside the new input, so the flush holds with the guess's
Expand All @@ -549,35 +549,35 @@ installOptHooks({
// guessed `createOptimistic` (lanes `laneStage`). The guess's own lane
// asks nothing new and stamps nothing.
ask: fam => {
if (fam.node!._flags & REACTIVE_REASK || !fam.overlaid?.size) return;
if (fam.node!._flags & REACTIVE_REASK || !fam._overlaid?.size) return;
// Stamped with the flush (`clock`): it lapses when the flush ends.
let a = ~clock;
for (const g of fam.overlaid) {
for (const g of fam._overlaid) {
const n = laneNodeOf(g);
if (n) {
if (passLane === null) a = clock + 1;
else if (sameAction(txOf(n), passLane)) return;
}
}
if ((fam.asked = a) > 0) joinFuture(null);
if ((fam._asked = a) > 0) joinFuture(null);
},
// Over a new question the guesses do not answer (`asked`): from mainline
// Over a new question the guesses do not answer (`_asked`): from mainline
// only a target carrying a guess stands in — a read of one with none is an
// ordinary pending read (F-2), so a keyed store's other keys wait for their
// answer, not for the guess's action; in a lane with no guess of its own,
// or with no live guess left, none does (F-6).
stands: t => {
const o = t.fam!.overlaid;
const a = t.fam!.asked;
const o = t._fam!._overlaid;
const a = t._fam!._asked;
return !!o?.size && (a !== clock + 1 || passLane !== null || o.has(t)) && a !== ~clock;
},
// Mainline hold (`clock + 1`): the flush joins the action of each guess a
// reader still reads at the seam; a reader that moved off it (a keyed
// store's other key) holds nothing.
park: t => {
for (const fam of overlaidFamilies)
if (fam.asked === clock + 1)
for (const g of fam.overlaid!) {
if (fam._asked === clock + 1)
for (const g of fam._overlaid!) {
const n = laneNodeOf(g, true);
if (n) merge(txOf(n)._parent!, t);
}
Expand All @@ -597,21 +597,21 @@ function shallowKeys(o: Record<PropertyKey, any>): Record<PropertyKey, any> {

/** Families with a target carrying a lane value — swept at the flush's
* commit (`sweepOverlaid`): a target none of whose nodes is a lane's any
* more leaves its family's `overlaid`. (Not on the read path: a guess is
* more leaves its family's `_overlaid`. (Not on the read path: a guess is
* pending between the setter and the seam, and a read in between must not
* take the target for clean.) */
const overlaidFamilies: Set<StoreFamily> = new Set();

function markOverlaid(t: StoreTarget): void {
const fam = t.fam!;
(fam.overlaid ??= new Set()).add(t);
const fam = t._fam!;
(fam._overlaid ??= new Set()).add(t);
overlaidFamilies.add(fam);
}

export function sweepOverlaid(): void {
if (overlaidFamilies.size === 0) return;
for (const fam of overlaidFamilies) {
const set = fam.overlaid!;
const set = fam._overlaid!;
for (const t of set)
if (!laneNodeOf(t)) {
set.delete(t);
Expand Down Expand Up @@ -669,7 +669,7 @@ function rebaseChained(t: StoreTarget): void {
k._notifiedAt !== notifyEpoch
) {
const rows = Array.isArray(inner) ? untrack(() => (inner as any[]).map(unwrapValue)) : inner;
if (!arrangementEqual(k._value.rows, rows, t.fam!)) {
if (!arrangementEqual(k._value.rows, rows, t._fam!)) {
insertSubs(k);
changed = true;
}
Expand All @@ -695,8 +695,8 @@ function laneNodeOf(t: StoreTarget, read?: boolean): Signal<any> | undefined {
}

function overlaid(t: StoreTarget): boolean {
const fam = t.fam;
return fam !== null && fam.opt === true && fam.overlaid !== undefined && fam.overlaid.has(t);
const fam = t._fam;
return fam !== null && fam.opt === true && fam._overlaid !== undefined && fam._overlaid.has(t);
}

/** What a lane node shows an untracked reader here: core's rule (`read`
Expand Down
Loading
Loading