Save prism effects in the prism scope, rather than a WeakMap
... for easier debugging, but there is a perf regression which I can't yet quantify as the benchmark suit doesn't support comparisons.
This commit is contained in:
parent
ae8be59366
commit
1c69cb7055
1 changed files with 11 additions and 20 deletions
|
@ -107,6 +107,7 @@ export class PrismDerivation<V> extends AbstractDerivation<V> {
|
||||||
class PrismScope {
|
class PrismScope {
|
||||||
isPrismScope = true
|
isPrismScope = true
|
||||||
private _subs: Record<string, PrismScope> = {}
|
private _subs: Record<string, PrismScope> = {}
|
||||||
|
readonly effects: Map<string, IEffect> = new Map()
|
||||||
|
|
||||||
sub(key: string) {
|
sub(key: string) {
|
||||||
if (!this._subs[key]) {
|
if (!this._subs[key]) {
|
||||||
|
@ -118,23 +119,20 @@ class PrismScope {
|
||||||
get subs() {
|
get subs() {
|
||||||
return this._subs
|
return this._subs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanupEffects() {
|
||||||
|
for (const effect of this.effects.values()) {
|
||||||
|
safelyRun(effect.cleanup, undefined)
|
||||||
|
}
|
||||||
|
this.effects.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupScopeStack(scope: PrismScope) {
|
function cleanupScopeStack(scope: PrismScope) {
|
||||||
for (const sub of Object.values(scope.subs)) {
|
for (const sub of Object.values(scope.subs)) {
|
||||||
cleanupScopeStack(sub)
|
cleanupScopeStack(sub)
|
||||||
}
|
}
|
||||||
cleanupEffects(scope)
|
scope.cleanupEffects()
|
||||||
}
|
|
||||||
|
|
||||||
function cleanupEffects(scope: PrismScope) {
|
|
||||||
const effects = effectsWeakMap.get(scope)
|
|
||||||
if (effects) {
|
|
||||||
for (const effect of effects.values()) {
|
|
||||||
safelyRun(effect.cleanup, undefined)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
effectsWeakMap.delete(scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function safelyRun<T, U>(
|
function safelyRun<T, U>(
|
||||||
|
@ -160,7 +158,6 @@ const refsWeakMap = new WeakMap<PrismScope, Map<string, IRef<unknown>>>()
|
||||||
type IRef<T> = {
|
type IRef<T> = {
|
||||||
current: T
|
current: T
|
||||||
}
|
}
|
||||||
const effectsWeakMap = new WeakMap<PrismScope, Map<string, IEffect>>()
|
|
||||||
|
|
||||||
type IEffect = {
|
type IEffect = {
|
||||||
deps: undefined | unknown[]
|
deps: undefined | unknown[]
|
||||||
|
@ -209,20 +206,14 @@ function effect(key: string, cb: () => () => void, deps?: unknown[]): void {
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
throw new Error(`prism.effect() is called outside of a prism() call.`)
|
throw new Error(`prism.effect() is called outside of a prism() call.`)
|
||||||
}
|
}
|
||||||
let effects = effectsWeakMap.get(scope)
|
|
||||||
|
|
||||||
if (effects === undefined) {
|
let effect = scope.effects.get(key)
|
||||||
effects = new Map()
|
|
||||||
effectsWeakMap.set(scope, effects)
|
|
||||||
}
|
|
||||||
|
|
||||||
let effect = effects.get(key)
|
|
||||||
if (effect === undefined) {
|
if (effect === undefined) {
|
||||||
effect = {
|
effect = {
|
||||||
cleanup: voidFn,
|
cleanup: voidFn,
|
||||||
deps: undefined,
|
deps: undefined,
|
||||||
}
|
}
|
||||||
effects.set(key, effect)
|
scope.effects.set(key, effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depsHaveChanged(effect.deps, deps)) {
|
if (depsHaveChanged(effect.deps, deps)) {
|
||||||
|
|
Loading…
Reference in a new issue