chore(quark): sync vendored keyed and layout with standalone

This commit is contained in:
Kit Langton 2026-07-17 22:53:35 -04:00
commit fc310da14d
2 changed files with 64 additions and 48 deletions

View file

@ -133,6 +133,7 @@ export namespace Keyed {
function publish(slot: Writable<A>, value: A) { function publish(slot: Writable<A>, value: A) {
const current = slot() const current = slot()
// alien-signals uses SameValueZero-compatible identity for primitive writes.
if (current === value || equivalent(current, value)) { if (current === value || equivalent(current, value)) {
if (options.metrics) options.metrics.equivalenceSuppressions++ if (options.metrics) options.metrics.equivalenceSuppressions++
return false return false

View file

@ -41,8 +41,10 @@ export namespace Layout {
readonly fields: StructFields readonly fields: StructFields
} }
export interface Union<Tag extends PropertyKey, Variants extends Readonly<Record<string, Field<unknown>>>> export interface Union<
extends Field<Variant<Tag, Variants>> { Tag extends PropertyKey,
Variants extends Readonly<Record<string, Field<unknown>>>,
> extends Field<Variant<Tag, Variants>> {
readonly type: "union" readonly type: "union"
readonly tag: Tag readonly tag: Tag
readonly variants: Variants readonly variants: Variants
@ -66,7 +68,7 @@ export namespace Layout {
readonly equivalent: (left: A, right: A) => boolean readonly equivalent: (left: A, right: A) => boolean
/** Bitmask of changed top-level fields; 0 means equivalent. Consistent with `equivalent`. */ /** Bitmask of changed top-level fields; 0 means equivalent. Consistent with `equivalent`. */
readonly diff: (left: A, right: A) => number readonly diff: (left: A, right: A) => number
/** Every known top-level property name to its change bit; immutable, key, and tag names map to 0. */ /** Every known top-level property name to its change bit; immutable and key names map to 0. */
readonly bits: ReadonlyMap<PropertyKey, number> readonly bits: ReadonlyMap<PropertyKey, number>
readonly keyOf: (value: A) => Key readonly keyOf: (value: A) => Key
make(initial?: readonly A[], options?: { readonly metrics?: Keyed.Metrics }): Keyed.Keyed<A, Key> make(initial?: readonly A[], options?: { readonly metrics?: Keyed.Metrics }): Keyed.Keyed<A, Key>
@ -215,8 +217,7 @@ export namespace Layout {
>(layout: KeyedUnion<Name, A, Tag, Variants>, options?: CompileOptions): Plan<KeyedVariant<Name, A, Tag, Variants>, A> >(layout: KeyedUnion<Name, A, Tag, Variants>, options?: CompileOptions): Plan<KeyedVariant<Name, A, Tag, Variants>, A>
export function compile(input: unknown, options: CompileOptions = {}): unknown { export function compile(input: unknown, options: CompileOptions = {}): unknown {
const layout = input as const layout = input as
| Struct<Fields> Struct<Fields> | KeyedUnion<PropertyKey, unknown, PropertyKey, Readonly<Record<string, Field<unknown>>>>
| KeyedUnion<PropertyKey, unknown, PropertyKey, Readonly<Record<string, Field<unknown>>>>
if (layout.type === "keyed-union") { if (layout.type === "keyed-union") {
const model = unionDiffModel(layout.key.name, layout.tag, layout.variants) const model = unionDiffModel(layout.key.name, layout.tag, layout.variants)
return makePlan( return makePlan(
@ -311,17 +312,14 @@ export namespace Layout {
initial: readonly A[], initial: readonly A[],
options?: { readonly metrics?: Keyed.Metrics }, options?: { readonly metrics?: Keyed.Metrics },
): Collection<A, Key, Definitions> { ): Collection<A, Key, Definitions> {
// The most recent publication's field diff, captured from the equivalence // `pending` hands a diff the collection already computed for a staged
// callback so index refresh can gate projections on it. `pending` hands a // mutation to the comparator, so equivalence costs one comparison, not two.
// diff the collection already computed for a staged mutation to the let pending: number | ReadonlyMap<Key, number> | undefined
// comparator, so equivalence costs one comparison, not two.
let lastDiff = -1
let pending = -1
const values = Keyed.make<A, Key>({ const values = Keyed.make<A, Key>({
key: plan.keyOf, key: plan.keyOf,
equivalent(left, right) { equivalent(left, right) {
lastDiff = pending !== -1 ? pending : plan.diff(left, right) const mask = typeof pending === "number" ? pending : pending?.get(plan.keyOf(left))
return lastDiff === 0 return (mask ?? plan.diff(left, right)) === 0
}, },
metrics: options?.metrics, metrics: options?.metrics,
}) })
@ -348,15 +346,20 @@ export namespace Layout {
}, },
getOwnPropertyDescriptor(_, property) { getOwnPropertyDescriptor(_, property) {
trackMask = -1 trackMask = -1
return Reflect.getOwnPropertyDescriptor(trackTarget!, property) const descriptor = Reflect.getOwnPropertyDescriptor(trackTarget!, property)
return descriptor && { ...descriptor, configurable: true }
}, },
}) })
function tracked<T>(value: A, f: (value: A) => T) { function tracked<T>(value: A, f: (value: A) => T) {
trackTarget = value as Record<PropertyKey, unknown> trackTarget = value as Record<PropertyKey, unknown>
trackMask = 0 trackMask = 0
const result = f(trackProxy as A) try {
trackTarget = undefined const result = f(trackProxy as A)
return result return { result, reads: trackMask }
} finally {
trackTarget = undefined
trackMask = 0
}
} }
// Each index entry stages user-code projections before any state mutation // Each index entry stages user-code projections before any state mutation
@ -394,18 +397,22 @@ export namespace Layout {
name, name,
reads: (key) => readsByKey.get(key), reads: (key) => readsByKey.get(key),
stage(key, value) { stage(key, value) {
const source = tracked(value, extract)
const reads = trackMask
const previous = byKey.get(key) const previous = byKey.get(key)
const members = source === previous?.source ? previous.members : new Set(source) const trackedMembers = tracked(value, (candidate) => {
return () => { const source = extract(candidate)
readsByKey.set(key, reads) return {
if (!previous) members.forEach((member) => adjust(member, 1)) source,
if (previous && previous.members !== members) { members: source === previous?.source ? previous.members : new Set(source),
members.forEach((member) => !previous.members.has(member) && adjust(member, 1))
previous.members.forEach((member) => !members.has(member) && adjust(member, -1))
} }
byKey.set(key, { source, members }) })
return () => {
readsByKey.set(key, trackedMembers.reads)
if (!previous) trackedMembers.result.members.forEach((member) => adjust(member, 1))
if (previous && previous.members !== trackedMembers.result.members) {
trackedMembers.result.members.forEach((member) => !previous.members.has(member) && adjust(member, 1))
previous.members.forEach((member) => !trackedMembers.result.members.has(member) && adjust(member, -1))
}
byKey.set(key, trackedMembers.result)
} }
}, },
applyDelta(key, change) { applyDelta(key, change) {
@ -468,18 +475,17 @@ export namespace Layout {
reads: (key) => readsByKey.get(key), reads: (key) => readsByKey.get(key),
stage(key, value, mode) { stage(key, value, mode) {
const matched = tracked(value, matches) const matched = tracked(value, matches)
const reads = trackMask
return (valueSlot) => { return (valueSlot) => {
readsByKey.set(key, reads) readsByKey.set(key, matched.reads)
const previous = matching.has(key) const previous = matching.has(key)
if (matched) matching.add(key) if (matched.result) matching.add(key)
if (!matched) matching.delete(key) if (!matched.result) matching.delete(key)
if (mode === "add") return if (mode === "add") return
if (slot === valueSlot && !matched) { if (slot === valueSlot && !matched.result) {
findFirst() findFirst()
return return
} }
if (slot !== valueSlot && !previous && matched) afterPlacement(valueSlot) if (slot !== valueSlot && !previous && matched.result) afterPlacement(valueSlot)
} }
}, },
remove(key, removedSlot) { remove(key, removedSlot) {
@ -524,19 +530,25 @@ export namespace Layout {
// Indexes are plain data, not reactive state; the transaction exists so // Indexes are plain data, not reactive state; the transaction exists so
// subscribers cannot observe published values with stale indexes. With // subscribers cannot observe published values with stale indexes. With
// no staged commits there is nothing to observe out of order. // no staged commits there is nothing to observe out of order.
if (!staged) { if (!staged) return publishValue()
pending = mask
const changed = values.update(value)
pending = -1
return changed
}
return Transaction.run(() => { return Transaction.run(() => {
pending = mask const changed = publishValue()
const changed = values.update(value)
pending = -1
if (changed) staged.forEach((commit) => commit(slot)) if (changed) staged.forEach((commit) => commit(slot))
return changed return changed
}) })
function publishValue() {
return withPending(mask, () => values.update(value))
}
}
function withPending<T>(mask: number | ReadonlyMap<Key, number>, f: () => T) {
pending = mask
try {
return f()
} finally {
pending = undefined
}
} }
const collection: Collection<A, Key, Definitions> = { const collection: Collection<A, Key, Definitions> = {
@ -549,6 +561,7 @@ export namespace Layout {
const value = slot() const value = slot()
existing.set(plan.keyOf(value), value) existing.set(plan.keyOf(value), value)
}) })
const masks = new Map<Key, number>()
// Stage user-code projections for new and changed values only; // Stage user-code projections for new and changed values only;
// retained equivalent values keep their index state and reads. // retained equivalent values keep their index state and reads.
const staged: Array<{ readonly key: Key; readonly commits: readonly Commit[] }> = [] const staged: Array<{ readonly key: Key; readonly commits: readonly Commit[] }> = []
@ -559,13 +572,14 @@ export namespace Layout {
return return
} }
const mask = plan.diff(existing.get(key)!, value) const mask = plan.diff(existing.get(key)!, value)
masks.set(key, mask)
if (mask === 0) return if (mask === 0) return
const commits = stageRefresh(key, value, mask) const commits = stageRefresh(key, value, mask)
if (commits) staged.push({ key, commits }) if (commits) staged.push({ key, commits })
}) })
const retained = new Set(keys) const retained = new Set(keys)
return Transaction.run(() => { return Transaction.run(() => {
const changed = values.set(next) const changed = withPending(masks, () => values.set(next))
existing.forEach((_value, key) => { existing.forEach((_value, key) => {
if (!retained.has(key)) entries.forEach((entry) => entry.remove(key)) if (!retained.has(key)) entries.forEach((entry) => entry.remove(key))
}) })
@ -713,7 +727,7 @@ export namespace Layout {
variants: Readonly<Record<string, Field<unknown>>>, variants: Readonly<Record<string, Field<unknown>>>,
): UnionDiffModel { ): UnionDiffModel {
const bits = new Map<PropertyKey, number>() const bits = new Map<PropertyKey, number>()
bits.set(tag, 0) bits.set(tag, 1)
bits.set(keyName, 0) bits.set(keyName, 0)
const assigned = new Map<PropertyKey, number>() const assigned = new Map<PropertyKey, number>()
const perVariant = new Map<string, ReadonlyArray<DiffField> | undefined>() const perVariant = new Map<string, ReadonlyArray<DiffField> | undefined>()
@ -731,7 +745,7 @@ export namespace Layout {
if (!assigned.has(name) && !bits.has(name)) bits.set(name, 0) if (!assigned.has(name) && !bits.has(name)) bits.set(name, 0)
continue continue
} }
const bit = assigned.get(name) ?? 1 << Math.min(count++, 30) const bit = assigned.get(name) ?? 1 << Math.min(count++ + 1, 30)
assigned.set(name, bit) assigned.set(name, bit)
bits.set(name, bit) bits.set(name, bit)
fields.push({ name, field, bit }) fields.push({ name, field, bit })
@ -777,7 +791,8 @@ export namespace Layout {
const label = JSON.stringify(name) const label = JSON.stringify(name)
const fields = model.perVariant.get(name) const fields = model.perVariant.get(name)
if (!fields) { if (!fields) {
const index = emitter.custom.push(variants[name].equivalent) - 1 const variant = variants[name]
const index = emitter.custom.push((left, right) => variant.equivalent(left, right)) - 1
return `case ${label}: return custom[${index}](left, right) ? 0 : -1` return `case ${label}: return custom[${index}](left, right) ? 0 : -1`
} }
const statements = fields.map((field) => { const statements = fields.map((field) => {
@ -841,7 +856,7 @@ export namespace Layout {
function expression(emitter: Emitter, field: Field<unknown>, left: string, right: string): string { function expression(emitter: Emitter, field: Field<unknown>, left: string, right: string): string {
if (field.immutable) return "true" if (field.immutable) return "true"
if (field.primitive) return `Object.is(${left}, ${right})` if (field.primitive && field.equivalent === Object.is) return `Object.is(${left}, ${right})`
const layout = field as Field<unknown> & { const layout = field as Field<unknown> & {
readonly type?: "struct" | "union" | "keyed-union" | "array" readonly type?: "struct" | "union" | "keyed-union" | "array"
readonly fields?: Fields readonly fields?: Fields
@ -876,12 +891,12 @@ export namespace Layout {
const name = declare(emitter, layout, (fn) => { const name = declare(emitter, layout, (fn) => {
const property = JSON.stringify(String(layout.key!.name)) const property = JSON.stringify(String(layout.key!.name))
const key = expression(emitter, layout.key!.field, `l[${property}]`, `r[${property}]`) const key = expression(emitter, layout.key!.field, `l[${property}]`, `r[${property}]`)
const union = declareUnion(emitter, layout.variants, layout.tag!, layout.variants!) const union = declareUnion(emitter, {}, layout.tag!, layout.variants!)
return `function ${fn}(l, r) { return ${key === "true" ? "" : `${key} && `}${union}(l, r) }` return `function ${fn}(l, r) { return ${key === "true" ? "" : `${key} && `}${union}(l, r) }`
}) })
return `${name}(${left}, ${right})` return `${name}(${left}, ${right})`
} }
const index = emitter.custom.push(field.equivalent) - 1 const index = emitter.custom.push((left, right) => field.equivalent(left, right)) - 1
return `custom[${index}](${left}, ${right})` return `custom[${index}](${left}, ${right})`
} }