From 327c1c590795ad3f89c15785be0a1870f2c628d4 Mon Sep 17 00:00:00 2001 From: daishi Date: Mon, 9 Aug 2021 10:03:16 +0900 Subject: [PATCH] refactor(core): useMutableSource emulation without symbol and any --- .size-snapshot.json | 14 +++++------ src/core/Provider.ts | 5 ++-- src/core/contexts.ts | 43 ++++++-------------------------- src/core/useAtom.ts | 4 +-- src/core/useMutableSource.ts | 24 ++++++++++++------ src/devtools/useAtomsSnapshot.ts | 4 +-- 6 files changed, 38 insertions(+), 56 deletions(-) diff --git a/.size-snapshot.json b/.size-snapshot.json index 2e88209f47..f25b468beb 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -1,15 +1,15 @@ { "index.js": { - "bundled": 21268, - "minified": 10175, - "gzipped": 3361, + "bundled": 21267, + "minified": 10148, + "gzipped": 3367, "treeshaked": { "rollup": { "code": 14, "import_statements": 14 }, "webpack": { - "code": 1220 + "code": 1202 } } }, @@ -29,15 +29,15 @@ }, "devtools.js": { "bundled": 19122, - "minified": 9544, - "gzipped": 3281, + "minified": 9537, + "gzipped": 3288, "treeshaked": { "rollup": { "code": 28, "import_statements": 28 }, "webpack": { - "code": 1259 + "code": 1241 } } }, diff --git a/src/core/Provider.ts b/src/core/Provider.ts index d708f16522..0a59bc3009 100644 --- a/src/core/Provider.ts +++ b/src/core/Provider.ts @@ -68,7 +68,8 @@ export const getDebugStateAndAtoms = ({ }: { atoms: Atom[] state: State -}) => [state, atoms] +}) => [state, atoms] as const + export const subscribeDebugStore = ( { listeners }: { listeners: Set<() => void> }, callback: () => void @@ -81,7 +82,7 @@ export const subscribeDebugStore = ( // so atoms aren't garbage collected by the WeakMap of mounted atoms const useDebugState = (store: StoreForDevelopment) => { const debugMutableSource = store[3] - const [state, atoms]: [State, Atom[]] = useMutableSource( + const [state, atoms] = useMutableSource( debugMutableSource, getDebugStateAndAtoms, subscribeDebugStore diff --git a/src/core/contexts.ts b/src/core/contexts.ts index 3a970c21fc..650cff3c38 100644 --- a/src/core/contexts.ts +++ b/src/core/contexts.ts @@ -3,41 +3,10 @@ import type { Context } from 'react' import type { Atom, Scope, WritableAtom } from './atom' import { createMutableSource } from './useMutableSource' import { createState, flushPending, restoreAtoms, writeAtom } from './vanilla' -import type { State } from './vanilla' - -type MutableSource<_Target> = ReturnType - -type UpdateAtom = ( - atom: WritableAtom, - update: Update -) => void - -type CommitCallback = () => void - -type StoreForProduction = [ - stateMutableSource: MutableSource, - updateAtom: UpdateAtom, - commitCallback: CommitCallback -] - -export type StoreForDevelopment = [ - stateMutableSource: MutableSource, - updateAtom: UpdateAtom, - commitCallback: CommitCallback, - debugMutableSource: MutableSource<{ - version: number - atoms: Atom[] - state: State - listeners: Set<() => void> - }>, - restore: (values: Iterable, unknown]>) => void -] - -export type Store = StoreForProduction | StoreForDevelopment const createStoreForProduction = ( initialValues?: Iterable, unknown]> -): StoreForProduction => { +) => { const state = createState(initialValues) const stateMutableSource = createMutableSource(state, () => state.v) const commitCallback = () => flushPending(state) @@ -45,12 +14,12 @@ const createStoreForProduction = ( atom: WritableAtom, update: Update ) => writeAtom(state, atom, update) - return [stateMutableSource, updateAtom, commitCallback] + return [stateMutableSource, updateAtom, commitCallback] as const } const createStoreForDevelopment = ( initialValues?: Iterable, unknown]> -): StoreForDevelopment => { +) => { const stateListener = (updatedAtom: Atom, isNewAtom: boolean) => { ++debugStore.version if (isNewAtom) { @@ -87,9 +56,13 @@ const createStoreForDevelopment = ( commitCallback, debugMutableSource, restore, - ] + ] as const } +type StoreForProduction = ReturnType +export type StoreForDevelopment = ReturnType +export type Store = StoreForProduction | StoreForDevelopment + type CreateStore = ( initialValues?: Iterable, unknown]> ) => Store diff --git a/src/core/useAtom.ts b/src/core/useAtom.ts index 4f5c748bbb..fbd0decac2 100644 --- a/src/core/useAtom.ts +++ b/src/core/useAtom.ts @@ -46,7 +46,7 @@ export function useAtom( throw atomState.w // write promise } if ('v' in atomState) { - return atomState.v + return atomState.v as Value } throw new Error('no atom value') }, @@ -61,7 +61,7 @@ export function useAtom( const StoreContext = getStoreContext(atom.scope) const [mutableSource, updateAtom, commitCallback] = useContext(StoreContext) - const value: Value = useMutableSource(mutableSource, getAtomValue, subscribe) + const value = useMutableSource(mutableSource, getAtomValue, subscribe) useEffect(() => { commitCallback() }) diff --git a/src/core/useMutableSource.ts b/src/core/useMutableSource.ts index b33c364713..2b1599e21e 100644 --- a/src/core/useMutableSource.ts +++ b/src/core/useMutableSource.ts @@ -9,20 +9,28 @@ export { import { useEffect, useRef, useState } from 'react' -const TARGET = Symbol() -const GET_VERSION = Symbol() +const TARGET = '_uMS_T' +const GET_VERSION = '_uMS_V' -export const createMutableSource = (target: any, getVersion: any): any => ({ +type MutableSource = { + [TARGET]: T + [GET_VERSION]: (target: T) => V +} + +export const createMutableSource = ( + target: T, + getVersion: (target: T) => V +): MutableSource => ({ [TARGET]: target, [GET_VERSION]: getVersion, }) -export const useMutableSource = ( - source: any, - getSnapshot: any, - subscribe: any +export const useMutableSource = ( + source: MutableSource, + getSnapshot: (target: T) => S, + subscribe: (target: T, callback: () => void) => () => void ) => { - const lastVersion = useRef(0) + const lastVersion = useRef() const currentVersion = source[GET_VERSION](source[TARGET]) const [state, setState] = useState( () => diff --git a/src/devtools/useAtomsSnapshot.ts b/src/devtools/useAtomsSnapshot.ts index 37d15a9637..961270fd42 100644 --- a/src/devtools/useAtomsSnapshot.ts +++ b/src/devtools/useAtomsSnapshot.ts @@ -5,7 +5,7 @@ import { } from 'jotai' import type { Atom, Scope } from '../core/atom' import { getDebugStateAndAtoms, subscribeDebugStore } from '../core/Provider' -import type { AtomState, State } from '../core/vanilla' +import type { AtomState } from '../core/vanilla' // NOTE importing from '../core/Provider' is across bundles and actually copying code type AtomsSnapshot = Map, unknown> @@ -18,7 +18,7 @@ export function useAtomsSnapshot(scope?: Scope): AtomsSnapshot { throw Error('useAtomsSnapshot can only be used in dev mode.') } - const [state, atoms]: [State, Atom[]] = useMutableSource( + const [state, atoms] = useMutableSource( debugMutableSource, getDebugStateAndAtoms, subscribeDebugStore