ptrs
Version:
Manage your state with pointers.
1 lines • 34 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/hooks.ts","../src/mutate.ts","../src/ptrs.ts","../src/subscriber.ts","../src/pointer.ts"],"sourcesContent":["import { useMemoPointer, usePointer, useStatePointer } from \"./hooks\";\nimport { createPointer, pointerSchema, NoPointer, Pointer, PointerValue } from \"./pointer\";\nimport { ptrs } from \"./ptrs\";\nimport { subscribe } from \"./subscriber\";\n\nexport {\n createPointer,\n pointerSchema,\n ptrs,\n subscribe,\n useMemoPointer,\n usePointer,\n useStatePointer,\n}\n\nexport type {\n NoPointer,\n Pointer,\n PointerValue,\n}","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPointer, NoPointer, Pointer, PointerValue } from \"./pointer\";\nimport { subscribersAdd, subscribersRemove } from \"./subscriber\";\nimport { usedPointers, watchUsedPointers } from \"./ptrs\";\n\n/**\n * Creates a pointer to a new state.\n * @param initialValue The initial value of the pointer/state.\n * @param usePointerHook If true, the pointer will be registered with the usePointer hook.\n */\nexport const useStatePointer = <T>(initialValue: PointerValue<T>, usePointerHook = true) => {\n const ptr = useMemo(() => createPointer(initialValue), []);\n\n if (usePointerHook) {\n // most of the time the user wants to re-render the state owner when the pointer changes\n // so we register by default\n\n if (watchUsedPointers) {\n // far more efficient than using usePointer\n usedPointers.add(ptr);\n } else {\n usePointer(ptr);\n }\n }\n\n return ptr\n}\n\n/**\n * Basically like useStatePointer, but the pointer value updates if the given value changes.\n * @param value The value which the pointer holds.\n * @param usePointerHook If true, the pointer will be registered with the usePointer hook.\n */\nexport const useMemoPointer = <T>(value: PointerValue<T>, usePointerHook = true) => {\n const ptr = useStatePointer(value, usePointerHook);\n useEffect(() => { ptr(value as NoPointer<typeof value>) }, [ptr, value]);\n return ptr;\n}\n\n/**\n * Pointers are stable, which means that e.g. a component with a pointer prop will not re-render\n * when the pointer value changes. If re-rendering is needed, this hook can be used.\n * A re-render will happen when the value of one pointer changes.\n * The list of pointers can be different on each call/render (the order or count can change).\n * As an alternative, the `ptrs` component can be used, which will automatically\n * re-render when any pointer used in the component changes.\n * @param pointers A list of pointers that should cause a re-render when their value changes.\n */\nexport const usePointer = (...pointers: Pointer<any>[]) => {\n\n type VersionPointerMap = Map<Pointer<any>, { version: number }> & { version: number };\n\n if (watchUsedPointers) {\n // we don't need to manage a own subscriber, just use the current running ptrs component \n for (const p of pointers) {\n usedPointers.add(p);\n }\n return;\n }\n\n const [, subscriber] = useState(0)\n const pointerMap = useRef<VersionPointerMap>(null);\n\n const pm = pointerMap.current ?? (pointerMap.current = new Map() as VersionPointerMap);\n const newVersion = pm.version = (pm.version ?? 0) + 1;\n\n for (const p of pointers) {\n const entry = pm.get(p)\n\n if (entry) {\n entry.version = newVersion\n } else {\n pm.set(p, { version: newVersion })\n subscribersAdd(p, subscriber)\n }\n }\n\n // remove pointers with old version => they were not \n // provided in the current pointer list\n for (const entry of pm.entries()) {\n const [p, { version }] = entry;\n\n if (version !== newVersion) {\n subscribersRemove(p, subscriber);\n pm.delete(p);\n }\n }\n\n useEffect(() => (() => {\n // component won't be used anymore, clean up subscribers\n const pm = pointerMap.current!;\n for (const p of pm.keys()) {\n subscribersRemove(p, subscriber);\n }\n pm.clear();\n }), [])\n}","/**\n * Safely mutate an object with an action function.\n * It is possible that more objects are created than necessary.\n * All accessed descendants of the object are cloned. If something referenced\n * a descendant, it from now on references a potential outdated version.\n * Newly created objects are frozen, but not assigned objects.\n * @param value Value to mutate\n * @param action Mutation action\n * @returns New mutated value\n */\nexport const mutate = <T extends object>(value: T, action: (value: T) => void) => {\n const mutatedObjects = new Map<object, object>();\n const mappedProps = new Map<object, Set<() => any>>();\n\n // If currently the action is running\n let inAction = false\n\n // Every element that is touched by the action gets recreated.\n // This is a bit wasteful, because many/most elements will not be updated, just read.\n // However, this makes it much simpler.\n // Also, we don't use proxies, because if a value would be assigned to something\n // outside of the action, it could never get rid of the proxy.\n\n const shallowCloneObject = <T extends object>(value: T): T => {\n\n if (mutatedObjects.has(value)) {\n return mutatedObjects.get(value)! as T;\n }\n\n const props = Object.getOwnPropertyDescriptors(value)\n const getters = new Set<() => any>();\n\n // We can't simply use Object.entries, because that skips symbols.\n\n proxyGetter(props, Object.getOwnPropertyNames(props), getters);\n proxyGetter(props, Object.getOwnPropertySymbols(props), getters);\n\n const isArray = Array.isArray(value);\n\n if (isArray) {\n // length is not configurable\n delete props.length;\n }\n\n const obj = isArray\n ? Object.defineProperties([], props) as T\n : Object.create(Object.getPrototypeOf(value), props);\n\n mutatedObjects.set(value, obj);\n mappedProps.set(obj, getters);\n\n if (isArray) {\n // Make sure for sparse arrays that the length is correct.\n obj.length = value.length;\n }\n\n return obj;\n }\n\n const proxyGetter = (\n descriptors: Record<PropertyKey, PropertyDescriptor>,\n props: PropertyKey[], getters: Set<() => any>) => {\n\n // Replace all value props with a getter.\n // This getter will clone objects on access, so that they can be mutated.\n\n for (const p of props) {\n const prop = descriptors[p];\n\n if (prop.writable !== undefined) {\n // Whether the action changed the value.\n let changed = false\n\n const getter = () => {\n const value = prop.value\n\n if (inAction && !changed && typeof value === \"object\") {\n changed = true\n return prop.value = shallowCloneObject(value)\n }\n\n return value;\n }\n\n descriptors[p] = {\n configurable: true,\n enumerable: prop.enumerable,\n get: getter,\n set: (v: any) => (changed = true, prop.value = v),\n }\n\n getters.add(getter);\n }\n }\n }\n\n const cloned = shallowCloneObject(value);\n\n inAction = true;\n action(cloned);\n inAction = false;\n\n // Finalize all objects, mutation is done\n for (const obj of mutatedObjects.values()) {\n finalizeMutation(obj, mappedProps.get(obj)!);\n }\n\n return cloned;\n}\n\nconst finalizeMutation = (value: object, getters: Set<() => any>) => {\n const props = Object.getOwnPropertyDescriptors(value)\n\n finalizeMutationProp(value, props, Object.getOwnPropertyNames(props), getters);\n finalizeMutationProp(value, props, Object.getOwnPropertySymbols(props), getters);\n\n // Freeze the object, so it can't be mutated anymore.\n Object.freeze(value);\n}\n\nconst finalizeMutationProp = (\n obj: object, descriptors: Record<PropertyKey, PropertyDescriptor>,\n props: PropertyKey[], getters: Set<() => any>) => {\n\n for (const p of props) {\n const prop = descriptors[p];\n\n if (prop.get && getters.has(prop.get)) {\n // change to an regular value prop\n Object.defineProperty(obj, p, { value: prop.get() });\n }\n }\n}","import { usePointer } from \"./hooks\";\nimport { Pointer } from \"./pointer\";\n\nexport const usedPointers: Set<Pointer<any>> = new Set();\nexport let watchUsedPointers = false;\n\n/**\n * ptrs watches for pointer usage in the component.\n * Conditional usage is no problem, unlike with usePointer (can't be used in ifs, like any other hook).\n * The component will re-render if the component used a pointer's value during rendering, that now changed.\n * It only watches for itself, not for pointer usage in its children.\n * \n * Conditional rendering works like:\n * ```\n * if (pointerA()) {\n * console.log(pointerB()); // change of pointerB will only re-render if pointerA was truthy\n * }\n * ```\n * @param component The component to watch\n * @returns A wrapped component that behaves like the original component, but watches for pointer usage.\n */\nexport const ptrs = <P extends {}>(component: React.FunctionComponent<P>) => ((props: P): ReturnType<typeof component> => {\n\n if (watchUsedPointers) {\n throw new Error(\"There should never run two ptrs components at the same time. If they do, it breaks general assumptions about the ptrs component.\");\n }\n watchUsedPointers = true;\n\n try {\n\n // render the actual component\n return component(props);\n\n } finally {\n // the usePointer hook can use usedPointers itself, if we are in a ptrs component\n // so we have to disable it, so that usePointer will create a subscriber\n watchUsedPointers = false;\n\n // register all used pointers\n usePointer(...usedPointers);\n\n usedPointers.clear();\n }\n\n})","import { Pointer } from './pointer';\n\ntype Subscriber = React.Dispatch<React.SetStateAction<number>>;\n\n/**\n * A global state where we store all currently subscribed pointers.\n * There should usually be no memory leaks, because we use WeakMap and WeakRef.\n */\nconst subscribers = new WeakMap<Pointer<any>, WeakRef<Subscriber>[]>()\n\n/**\n * Subscribes to pointer changes.\n * @param subscriber The subscriber function that will be called when the pointer changes.\n * @param pointer One or more pointers to subscribe to.\n * @returns Function that can be used to unsubscribe from pointers. No argument -> all pointers will be unsubscribed.\n */\nexport const subscribe = <T>(subscriber: (p: Pointer<T>) => void, ...pointer: Pointer<T>[]) => {\n const wrappers = new Map<Pointer<T>, () => void>()\n\n for (const p of pointer) {\n\n const subWrapper = () => {\n subscriber(p)\n }\n\n wrappers.set(p, subWrapper);\n subscribersAdd(p, subWrapper)\n }\n\n return (...pointers: Pointer<T>[]) => {\n const unSub = pointers.length === 0 ? wrappers.keys() : pointers\n\n for (const p of unSub) {\n const wrapper = wrappers.get(p);\n\n if (wrapper) {\n subscribersRemove(p, wrapper);\n wrappers.delete(p);\n }\n }\n }\n}\n\nexport const subscribersAdd = (pointer: Pointer<any>, subscriber: Subscriber) => {\n\n const subs = subscribers.get(pointer)?.filter(s => {\n const d = s.deref();\n return d && d !== subscriber;\n }) ?? [];\n\n subs.push(new WeakRef(subscriber));\n subscribers.set(pointer, subs);\n}\n\nexport const subscribersRemove = (pointer: Pointer<any>, subscriber: Subscriber) => {\n\n const subs = subscribers.get(pointer);\n\n if (!subs) return;\n\n const newSubs = subs.filter(s => {\n const d = s.deref();\n return d && d !== subscriber;\n })\n\n if (newSubs.length === 0) {\n subscribers.delete(pointer);\n } else {\n subscribers.set(pointer, newSubs);\n }\n}\n\n/**\n * Triggers the subscribers for a given pointer.\n * @param pointer The pointer to trigger the subscribers for.\n */\nexport const subscriberTrigger = (pointer: Pointer<any>) => {\n const subs = subscribers.get(pointer)\n if (!subs) return\n\n for (const sub of subs) {\n sub.deref()?.((old: number) => old + 1)\n }\n}","import { mutate } from \"./mutate\";\nimport { usedPointers, watchUsedPointers } from \"./ptrs\";\nimport { subscriberTrigger } from \"./subscriber\";\n\n/**\n * A pointer references to an actual value. A pointer is stable and won't change\n * when the value changes. The value of a pointer can be accessed and changed.\n * \n * ```\n * pointer() // gets the value\n * pointer(newValue) // sets a new value\n * ```\n */\nexport type Pointer<T> =\n (NonNullable<T> extends object ? (PointerFunc<T> & ComplexPointer<NonNullable<T>>) : PointerFunc<T>)\n & NeverFunctionProp<T>\n\n/**\n * Defines a valid pointer value.\n */\nexport type PointerValue<T> = T extends UndefinedToOptional<T> ? T : UndefinedToOptional<T>;\n\n/**\n * Makes sure that a type is not a pointer.\n */\nexport type NoPointer<T> = T extends Pointer<any> ? never : T;\n\n/**\n * The property should be handled like a pointer.\n */\nexport type PointerPropertyTypePointer = \"pointer\"\n\n/**\n * The property is a function that mutates the pointer.\n * Can also be used for get-set properties where also the getter\n * changes the pointer.\n */\nexport type PointerPropertyTypeMutate = \"mutate\"\n\n/**\n * The pointer is a function that computes values without changing the pointer.\n * This can be used as a performance optimization, because \"mutate\", the default \n * function behavior, has an overhead of creating new pointer values.\n * Can also be used for properties that just act as a getter.\n */\nexport type PointerPropertyTypeReadonly = \"readonly\"\n\n/**\n * The property has a readonly get and a mutating set function.\n */\nexport type PointerPropertyTypeGetSet = \"get-set\"\n\n/**\n * All possible pointer property types.\n */\nexport type PointerPropertyType\n = PointerPropertyTypePointer\n | PointerPropertyTypeMutate\n | PointerPropertyTypeReadonly\n | PointerPropertyTypeGetSet\n\nconst PointerProperties: unique symbol = Symbol(\"PointerProperties\");\n\n/**\n* Valid pointer signatures\n*/\ntype PointerFunc<T> = {\n (): T;\n <V extends T>(value: NoPointer<V>): void;\n}\n\ntype ComplexPointer<T extends object> =\n T extends Array<any> ? ArrayPointer<T> : ObjectPointer<T>;\n\ntype ArrayPointer<T> = T extends Array<infer I> ? {\n readonly [P in number]: Pointer<I>;\n} & Omit<T, number> : never\n\ntype ObjectPointer<T extends object> = {\n [P in keyof T]-?: T[P] extends Function ? ObjectPointerFunctionProperty<T, P> : ObjectPointerProperty<T, P>;\n}\n\ntype ObjectPointerProperty<T extends object, P extends keyof T> =\n T extends { [PointerProperties]: Partial<{ [PP in P]: Exclude<PointerPropertyType, PointerPropertyTypePointer> }> } ? T[P] : Pointer<T[P]>;\n\ntype ObjectPointerFunctionProperty<T extends object, P extends keyof T> =\n T extends { [PointerProperties]: Partial<{ [PP in P]: PointerPropertyTypePointer }> } ? Pointer<T[P]> : T[P];\n\n/**\n * We can't hide function properties, otherwise the pointer would not be callable.\n * But we can make them never, so that they are not \"usable\".\n */\ntype NeverFunctionProp<T> = {\n [P in Exclude<keyof Function, keyof NonNullable<T>>]: never;\n}\n\n/**\n * Convert undefined value to optional property.\n */\ntype UndefinedToOptional<T> =\n T extends object\n ? (T extends any[]\n ? UndefinedToOptionalArray<T>\n : (T extends Function\n ? T // unchanged function\n : UndefinedToOptionalObject<T>))\n : T // primary data type\n\ntype UndefinedToOptionalArray<T> =\n T extends Array<infer I>\n ? Array<UndefinedToOptional<I>>\n : T\n\ntype UndefinedToOptionalObject<T> =\n { [K in keyof T as undefined extends T[K] ? never : K]: UndefinedToOptional<T[K]> } &\n { [K in keyof T as undefined extends T[K] ? K : never]?: UndefinedToOptional<Exclude<T[K], undefined>> }\n\n/**\n * Whether the pointer update should bubble up\n */\nlet bubbleUp = true;\n\n/**\n * Whether the initialization has been done.\n */\nlet initialized = false;\n\n/**\n * Performs one-time initialization.\n */\nconst initialize = () => {\n initialized = true;\n\n // Arrays should work as expected, so we add a pointer schema to the array prototype.\n\n const arrayReadonly = [\n \"at\",\n \"concat\",\n \"entries\",\n \"every\",\n \"filter\",\n \"find\",\n \"findIndex\",\n \"findLast\",\n \"findLastIndex\",\n \"flat\",\n \"flatMap\",\n \"forEach\",\n \"includes\",\n \"indexOf\",\n \"join\",\n \"keys\",\n \"lastIndexOf\",\n \"map\",\n \"reduce\",\n \"reduceRight\",\n \"slice\",\n \"some\",\n \"toLocaleString\",\n \"toString\",\n \"valueOf\",\n \"values\",\n \"with\"\n ]\n\n Object.defineProperty(Array.prototype, PointerProperties, {\n configurable: false,\n enumerable: false,\n writable: false,\n value: Object.freeze({\n ...Object.fromEntries(Object.getOwnPropertyNames(Array.prototype).map(name => [\n name, arrayReadonly.includes(name) ? \"readonly\" : \"mutate\"\n ])),\n \"length\": \"get-set\",\n })\n })\n}\n\n/**\n * Creates a pointer for a value. The given value is the initial value of the pointer.\n * The setter is called when the pointer is set to a new value, so an external state, like\n * a variable or useState, can be updated. However, that external state should not update its value anymore.\n * Updates must be done through the pointer itself, otherwise the pointer won't see the changes.\n * To enforce this the value will be frozen.\n * \n * @param value The initial value of the pointer.\n * @param setter A function that will be called when the pointer is set.\n */\nexport const createPointer = <T>(value: PointerValue<T>, setter?: (newData: typeof value) => void): Pointer<typeof value> => {\n if (!initialized) {\n initialize();\n }\n return createInternalPointer(value, setter)\n}\n\nconst createInternalPointer = <T>(\n value: T,\n setter?: (newData: T) => void,\n thisPtr?: Pointer<any>,\n name?: string | symbol) => {\n\n // Prevent any changes, the pointer will handle changes itself.\n // We don't perform a deep freeze, because that would be too expensive.\n // If a prop will be accessed by pointer, it will be frozen later anyway.\n Object.freeze(value);\n\n // when we are an object, we store here our proxied properties\n const proxyProps: Record<PropertyKey, WeakRef<Pointer<any>>> = {}\n\n let propertyType = getPropertyType(thisPtr, name, value);\n\n const self = new Proxy(() => value, {\n\n apply(target, thisArg, argArray) {\n\n if (typeof value === \"function\" && propertyType !== \"pointer\") {\n // We allow \"regular\" function calls, if the object property is not threated as a pointer.\n // \"this\" is the pointer value of our thisPtr, so a call behaves like a normal method call.\n\n if (propertyType === \"readonly\") {\n // readonly function, no mutate needed. \"this\" won't change.\n return (value as Function).apply(thisPtr!(), argArray)\n }\n\n // Allow the function to mutate \"this\", which is the pointer value.\n let returnvalue\n const newThis = mutate(thisPtr!(), (newThis) => {\n returnvalue = (value as Function).apply(newThis, argArray)\n })\n\n bubbleUp = false\n thisPtr!(newThis)\n bubbleUp = true\n\n return returnvalue;\n }\n\n // called when the pointer value should be changed or read\n\n if (argArray.length === 0) {\n\n if (watchUsedPointers)\n usedPointers.add(self);\n\n return value;\n\n } else if (argArray.length === 1) {\n const newValue = argArray[0];\n\n if (newValue === value)\n return;\n\n value = Object.freeze(newValue);\n propertyType = getPropertyType(thisPtr, name, value);\n bubbleUp && setter?.(value)\n\n subscriberTrigger(self);\n\n // we have to disable bubble up, while updating children\n const prevBubbleUp = bubbleUp\n bubbleUp = false;\n\n for (const prop in proxyProps) {\n if (typeof value?.[prop as keyof typeof value] !== \"function\") {\n proxyProps[prop].deref()?.(value?.[prop as keyof typeof value] as NoPointer<any>);\n }\n }\n\n bubbleUp = prevBubbleUp;\n\n } else {\n throw new Error('Pointer can only be called with 0 or 1 arguments.');\n }\n },\n\n get(target, prop) {\n\n const type = getPropertyType(self, prop, undefined)\n\n if (type !== \"pointer\") {\n // Try to handle as normal property\n let propValue\n\n if (type === \"mutate\") {\n // A getter that mutates the pointer value.\n self(mutate(value!, (newValue: any) => {\n propValue = Reflect.get(newValue, prop, newValue);\n }) as NoPointer<T>)\n } else {\n propValue = value?.[prop as keyof typeof value];\n }\n\n // Should it be a function, we can't return the raw value, \n // we have to proxy it. It is probably a method that\n // acts upon the pointer value.\n if (typeof propValue !== \"function\") {\n return propValue\n }\n }\n\n let p = proxyProps[prop]?.deref()\n\n if (!p) {\n const propValue = value?.[prop as keyof typeof value]\n\n proxyProps[prop] = new WeakRef(p = createInternalPointer(propValue, (newValue) => {\n\n if (value === undefined) {\n // \"this\" is undefined. We will create it.\n // There is however an issue: We don't now the \"schema\".\n // We just can assume a plain object or array.\n if (typeof prop === \"string\" && parseInt(prop, 10).toString() === prop) {\n value = [] as T;\n } else {\n value = {} as T;\n }\n }\n\n value = mutate(value!, (value) => {\n if (newValue === undefined) {\n // By convention we delete the property for undefined values.\n // A optional property is far more common than a property that is set to undefined.\n Reflect.deleteProperty(value, prop);\n } else {\n Reflect.set(value, prop, newValue, value);\n }\n })\n\n propertyType = getPropertyType(thisPtr, name, value);\n Object.freeze(value);\n setter?.(value)\n\n subscriberTrigger(self);\n\n }, self, prop))\n }\n\n return p\n },\n\n set(target, prop, propValue): boolean {\n\n if (getPropertyType(self, prop, undefined) !== \"pointer\") {\n // property schema allows to set the property\n self(mutate(value!, (newValue) => {\n Reflect.set(newValue, prop, propValue, newValue);\n }) as NoPointer<T>)\n return true;\n }\n\n // we don't allow any change besides special cases\n return false;\n }\n\n }) as Pointer<T>\n\n return self;\n}\n\nconst getPropertyType = (\n thisPtr: Pointer<any> | undefined,\n propName: PropertyKey | undefined,\n propValue: any): PointerPropertyType => {\n\n if (thisPtr && propName) {\n const t = thisPtr()\n const pointerProps = t?.[PointerProperties]\n\n if (pointerProps && propName in pointerProps) {\n return pointerProps[propName];\n }\n }\n\n return typeof propValue === \"function\" ? \"mutate\" : \"pointer\";\n}\n\n/**\n * Adds a schema to a value that defines how a pointer for the given value should behave.\n * @param objectOrClass \n * @param map A map defining the properties. This map will be frozen, so it can't be changed later.\n * @returns \n */\nexport const pointerSchema = <\n T extends object,\n M extends Partial<Record<keyof T, PointerPropertyType>>,\n O extends T & { [PointerProperties]: M }>\n (objectOrClass: T, map: M): O => {\n\n const withMap = objectOrClass as unknown as O\n withMap[PointerProperties] = Object.freeze(map)\n return withMap\n}"],"mappings":"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","names":["index_exports","__export","createPointer","pointerSchema","ptrs","subscribe","useMemoPointer","usePointer","useStatePointer","__toCommonJS","import_react","mutate","value","action","mutatedObjects","mappedProps","inAction","shallowCloneObject","props","getters","proxyGetter","isArray","obj","descriptors","p","prop","changed","getter","v","cloned","finalizeMutation","finalizeMutationProp","usedPointers","watchUsedPointers","ptrs","component","props","usePointer","subscribers","subscribe","subscriber","pointer","wrappers","p","subWrapper","subscribersAdd","pointers","unSub","wrapper","subscribersRemove","subs","s","d","newSubs","subscriberTrigger","sub","old","PointerProperties","bubbleUp","initialized","initialize","arrayReadonly","name","createPointer","value","setter","createInternalPointer","thisPtr","proxyProps","propertyType","getPropertyType","self","target","thisArg","argArray","returnvalue","newThis","mutate","watchUsedPointers","usedPointers","newValue","subscriberTrigger","prevBubbleUp","prop","type","propValue","p","propName","pointerProps","pointerSchema","objectOrClass","map","withMap","useStatePointer","initialValue","usePointerHook","ptr","createPointer","watchUsedPointers","usedPointers","usePointer","useMemoPointer","value","pointers","p","subscriber","pointerMap","pm","newVersion","entry","subscribersAdd","version","subscribersRemove"]}