-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5fc2c12
commit d448792
Showing
1 changed file
with
73 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,77 @@ | ||
import { trackedData } from '@glimmer/validator'; | ||
|
||
interface Storage<Value> { | ||
/** | ||
* This is not a real property. Don't use it. | ||
* This is functioning as a brand-type for use with | ||
* - createStorage | ||
* - getValue | ||
* - setValue | ||
* | ||
* from @glimmer/trcking/primitives/storage | ||
*/ | ||
__storage: Value; | ||
import type { UpdatableTag } from '@glimmer/interfaces'; | ||
|
||
import { consumeTag } from './tracking'; | ||
Check failure on line 3 in packages/@ember/-internals/metal/lib/storage.ts GitHub Actions / Linting
|
||
import { createUpdatableTag, DIRTY_TAG } from './validators'; | ||
Check failure on line 4 in packages/@ember/-internals/metal/lib/storage.ts GitHub Actions / Linting
|
||
import { assert } from '@ember/debug'; | ||
|
||
const SET = Symbol.for('TrackedStorage.set'); | ||
const READ = Symbol.for('TrackedStorage.read'); | ||
|
||
function tripleEq<Value>(a: Value, b: Value): boolean { | ||
return a === b; | ||
} | ||
|
||
class Storage<Value> { | ||
#tag: UpdatableTag; | ||
#value: Value; | ||
#lastValue: Value; | ||
#isEqual: (a: Value, b: Value) => boolean; | ||
|
||
get #current() { | ||
consumeTag(this.#tag); | ||
return this.#value; | ||
} | ||
set #current(value) { | ||
if (this.#isEqual(this.#value, this.#lastValue)) { | ||
return; | ||
} | ||
|
||
this.#value = this.#lastValue = value; | ||
|
||
DIRTY_TAG(this.#tag); | ||
} | ||
|
||
constructor(initialValue: Value, isEqual?: (a: Value, b: Value) => boolean) { | ||
this.#tag = createUpdatableTag(); | ||
this.#value = this.#lastValue = initialValue; | ||
this.#isEqual = isEqual ?? tripleEq; | ||
} | ||
|
||
[READ]() { | ||
return this.#current; | ||
} | ||
|
||
[SET](value: Value) { | ||
this.#current = value; | ||
} | ||
} | ||
|
||
export function createStorage<Value>( | ||
initialValue?: Value, | ||
initialValue: Value, | ||
isEqual?: (oldValue: Value, newValue: Value) => boolean | ||
): Storage<Value> {} | ||
export function getValue<Value>(storage: Storage<Value>): Value {} | ||
export function setValue<Value>(storage: Storage<Value>, value: Value): void {} | ||
): Storage<Value> { | ||
assert( | ||
'the second parameter to `createStorage` must be an equality function or undefined', | ||
isEqual === undefined || typeof isEqual === 'function' | ||
); | ||
|
||
return new Storage(initialValue, isEqual); | ||
} | ||
|
||
export function getValue<Value>(storage: Storage<Value>): Value { | ||
assert( | ||
'getValue must be passed a tracked store created with `createStorage`.', | ||
storage instanceof Storage | ||
); | ||
|
||
return storage[READ](); | ||
} | ||
|
||
export function setValue<Value>(storage: Storage<Value>, value: Value): void { | ||
assert( | ||
'setValue must be passed a tracked store created with `createStorage`.', | ||
storage instanceof Storage | ||
); | ||
|
||
storage[SET](value); | ||
} |