From 4504469fb9114be1912e089e9c6770ed69c015a9 Mon Sep 17 00:00:00 2001 From: Peter Marshall Date: Tue, 21 May 2024 16:45:43 +1000 Subject: [PATCH] Shrink ComputedValue using a bitfield --- .changeset/dirty-turtles-marry.md | 5 +++ packages/mobx/src/core/computedvalue.ts | 52 +++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 .changeset/dirty-turtles-marry.md diff --git a/.changeset/dirty-turtles-marry.md b/.changeset/dirty-turtles-marry.md new file mode 100644 index 000000000..696b077f1 --- /dev/null +++ b/.changeset/dirty-turtles-marry.md @@ -0,0 +1,5 @@ +--- +"mobx": patch +--- + +Shrink ComputedValue using a bitfield diff --git a/packages/mobx/src/core/computedvalue.ts b/packages/mobx/src/core/computedvalue.ts index a56d59525..dc8bed1eb 100644 --- a/packages/mobx/src/core/computedvalue.ts +++ b/packages/mobx/src/core/computedvalue.ts @@ -56,6 +56,18 @@ export type IComputedDidChange = { oldValue: T | undefined } +function getFlag(flags: number, mask: number) { + return !!(flags & mask) +} +function setFlag(flags: number, mask: number, newValue: boolean): number { + if (newValue) { + flags |= mask + } else { + flags &= ~mask + } + return flags +} + /** * A node in the state dependency root that observes other nodes, and can be observed itself. * @@ -79,8 +91,6 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva dependenciesState_ = IDerivationState_.NOT_TRACKING_ observing_: IObservable[] = [] // nodes we are looking at. Our value depends on these nodes newObserving_ = null // during tracking it's an array with new observed observers - isBeingObserved_ = false - isPendingUnobservation_: boolean = false observers_ = new Set() diffValue_ = 0 runId_ = 0 @@ -90,8 +100,13 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva protected value_: T | undefined | CaughtException = new CaughtException(null) name_: string triggeredBy_?: string - isComputing_: boolean = false // to check for cycles - isRunningSetter_: boolean = false + + private static readonly isComputingMask = 0b0001 + private static readonly isRunningSetterMask = 0b0010 + private static readonly isBeingObservedMask = 0b0100 + private static readonly isPendingUnobservationMask = 0b1000 + private flags = 0b0000 + derivation: () => T // N.B: unminified as it is used by MST setter_?: (value: T) => void isTracing_: TraceMode = TraceMode.NONE @@ -153,6 +168,35 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva } } + // to check for cycles + private get isComputing_(): boolean { + return getFlag(this.flags, ComputedValue.isComputingMask) + } + private set isComputing_(newValue: boolean) { + this.flags = setFlag(this.flags, ComputedValue.isComputingMask, newValue) + } + + private get isRunningSetter_(): boolean { + return getFlag(this.flags, ComputedValue.isRunningSetterMask) + } + private set isRunningSetter_(newValue: boolean) { + this.flags = setFlag(this.flags, ComputedValue.isRunningSetterMask, newValue) + } + + get isBeingObserved_(): boolean { + return getFlag(this.flags, ComputedValue.isBeingObservedMask) + } + set isBeingObserved_(newValue: boolean) { + this.flags = setFlag(this.flags, ComputedValue.isBeingObservedMask, newValue) + } + + get isPendingUnobservation_(): boolean { + return getFlag(this.flags, ComputedValue.isPendingUnobservationMask) + } + set isPendingUnobservation_(newValue: boolean) { + this.flags = setFlag(this.flags, ComputedValue.isPendingUnobservationMask, newValue) + } + /** * Returns the current value of this computed value. * Will evaluate its computation first if needed.