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 27, 2024
1 parent 00748d5 commit c437bf7
Showing 1 changed file with 60 additions and 4 deletions.
64 changes: 60 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 getBitFieldMember(bitField: number, mask: number) {
return !!(bitField & mask)
}
function setBitFieldMember(bitField: number, mask: number, newValue: boolean): number {
if (newValue) {
bitField |= mask
} else {
bitField &= ~mask
}
return bitField
}

/**
* 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 bitField = 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,47 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
}
}

// to check for cycles
private get isComputing_(): boolean {
return getBitFieldMember(this.bitField, ComputedValue.isComputingMask)
}
private set isComputing_(newValue: boolean) {
this.bitField = setBitFieldMember(this.bitField, ComputedValue.isComputingMask, newValue)
}

private get isRunningSetter_(): boolean {
return getBitFieldMember(this.bitField, ComputedValue.isRunningSetterMask)
}
private set isRunningSetter_(newValue: boolean) {
this.bitField = setBitFieldMember(
this.bitField,
ComputedValue.isRunningSetterMask,
newValue
)
}

get isBeingObserved_(): boolean {
return getBitFieldMember(this.bitField, ComputedValue.isBeingObservedMask)
}
set isBeingObserved_(newValue: boolean) {
this.bitField = setBitFieldMember(
this.bitField,
ComputedValue.isBeingObservedMask,
newValue
)
}

get isPendingUnobservation_(): boolean {
return getBitFieldMember(this.bitField, ComputedValue.isPendingUnobservationMask)
}
set isPendingUnobservation_(newValue: boolean) {
this.bitField = setBitFieldMember(
this.bitField,
ComputedValue.isPendingUnobservationMask,
newValue
)
}

/**
* Returns the current value of this computed value.
* Will evaluate its computation first if needed.
Expand Down

0 comments on commit c437bf7

Please sign in to comment.