Skip to content

Commit

Permalink
Shrink ComputedValue using a bitfield
Browse files Browse the repository at this point in the history
  • Loading branch information
peterm-canva committed May 30, 2024
1 parent 00748d5 commit 6b15203
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-turtles-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"mobx": patch
---

Shrink ComputedValue using a bitfield
52 changes: 48 additions & 4 deletions packages/mobx/src/core/computedvalue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ export type IComputedDidChange<T = any> = {
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.
*
Expand All @@ -79,8 +91,6 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, 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<IDerivation>()
diffValue_ = 0
runId_ = 0
Expand All @@ -90,8 +100,13 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, 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
Expand Down Expand Up @@ -153,6 +168,35 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, 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.
Expand Down

0 comments on commit 6b15203

Please sign in to comment.