@preact/signals-react 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/signals.d.ts +5 -0
- package/dist/signals.js +1 -1
- package/dist/signals.js.map +1 -1
- package/dist/signals.min.js +1 -1
- package/dist/signals.min.js.map +1 -1
- package/dist/signals.mjs +1 -1
- package/dist/signals.mjs.map +1 -1
- package/dist/signals.module.js +1 -1
- package/dist/signals.module.js.map +1 -1
- package/package.json +5 -4
- package/src/index.ts +166 -85
- package/src/internal.d.ts +0 -4
- package/test/index.test.tsx +180 -54
- package/test/react-router.test.tsx +49 -0
- package/test/utils.ts +67 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @preact/signals-react
|
|
2
2
|
|
|
3
|
+
## 1.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#344](https://github.com/preactjs/signals/pull/344) [`acdead6`](https://github.com/preactjs/signals/commit/acdead6a8631d7198d8a55d6cbde7713b5776d6b) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Allow React ^16.14.0 as a peer dependency
|
|
8
|
+
|
|
9
|
+
## 1.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#335](https://github.com/preactjs/signals/pull/335) [`5fd438d`](https://github.com/preactjs/signals/commit/5fd438db9793d73343403e8926b9b69b03fb26f9) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Revert react integration to tracking current dispatcher
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#271](https://github.com/preactjs/signals/pull/271) [`0135d60`](https://github.com/preactjs/signals/commit/0135d60b6de1325ee2b027a25cd60cc379f9c198) Thanks [@billybimbob](https://github.com/billybimbob)! - type Signal as a React Element
|
|
18
|
+
|
|
19
|
+
* [#334](https://github.com/preactjs/signals/pull/334) [`0a58566`](https://github.com/preactjs/signals/commit/0a585660e141f3d92fb8789c234e69d5a1da8a86) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Run test suite agains React's production build
|
|
20
|
+
|
|
21
|
+
- [#246](https://github.com/preactjs/signals/pull/246) [`ad5a485`](https://github.com/preactjs/signals/commit/ad5a485e4fe3cfc1d1f60a57a30e50e88f7b1281) Thanks [@Shu-Ji](https://github.com/Shu-Ji)! - Support forwardRef in @preact/signals-react
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [[`862d9d6`](https://github.com/preactjs/signals/commit/862d9d6538b94e0a110213e98f2a0cabb14b8ad8), [`8b70764`](https://github.com/preactjs/signals/commit/8b7076436ce6d912f17d57da8ecd1bdfca852183), [`8e726ed`](https://github.com/preactjs/signals/commit/8e726ed1df6c90b85a93484f275baa7f013c799a)]:
|
|
24
|
+
- @preact/signals-core@1.3.0
|
|
25
|
+
|
|
3
26
|
## 1.2.2
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/dist/signals.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
1
2
|
import { signal, computed, batch, effect, Signal, type ReadonlySignal } from "@preact/signals-core";
|
|
2
3
|
export { signal, computed, batch, effect, Signal, type ReadonlySignal };
|
|
4
|
+
declare module "@preact/signals-core" {
|
|
5
|
+
interface Signal extends ReactElement {
|
|
6
|
+
}
|
|
7
|
+
}
|
|
3
8
|
export declare function useSignal<T>(value: T): Signal<T>;
|
|
4
9
|
export declare function useComputed<T>(compute: () => T): ReadonlySignal<T>;
|
|
5
10
|
export declare function useSignalEffect(cb: () => void | (() => void)): void;
|
package/dist/signals.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var r=require("react"),n=require("react/jsx-runtime"),
|
|
1
|
+
var r=require("react"),n=require("react/jsx-runtime"),e=require("react/jsx-dev-runtime"),t=require("@preact/signals-core"),u=require("use-sync-external-store/shim/index");function i(r){return r&&"object"==typeof r&&"default"in r?r.default:r}var o,f=/*#__PURE__*/i(r),c=/*#__PURE__*/i(n),a=/*#__PURE__*/i(e),s=[],l=Symbol.for("react.element");function v(r){if(o)o();o=r&&r.S()}var p=!1,x=null;Object.defineProperty(r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher,"current",{get:function(){return x},set:function(r){if(!p){var n=y(x),e=y(r),i=n===b&&e===d;x=r;if(n===d&&e===b){p=!0;var o=function(r){var n=r.useRef();if(null==n.current)n.current=function(){var r,n,e=0,u=t.effect(function(){r=this});r.c=function(){e=e+1|0;if(n)n()};return{updater:r,subscribe:function(r){n=r;return function(){e=e+1|0;n=void 0;u()}},getSnapshot:function(){return e}}}();var e=n.current;u.useSyncExternalStore(e.subscribe,e.getSnapshot,e.getSnapshot);return e}(r);p=!1;v(o.updater)}else if(i)v()}else x=r}});var b=0,d=1,g=new Map;function y(r){if(!r)return d;var n,e=g.get(r);if(void 0!==e)return e;if(r.useCallback.length<2)n=d;else if(/Invalid/.test(r.useCallback))n=2;else n=b;g.set(r,n);return n}function h(r){if("function"!=typeof r)return r;else return function(n,e){if("string"==typeof n&&e)for(var u in e){var i=e[u];if("children"!==u&&i instanceof t.Signal)e[u]=i.value}return r.call.apply(r,[r,n,e].concat([].slice.call(arguments,2)))}}var j=c,m=a;f.createElement=h(f.createElement);m.jsx&&(m.jsx=h(m.jsx));j.jsx&&(j.jsx=h(j.jsx));m.jsxs&&(m.jsxs=h(m.jsxs));j.jsxs&&(j.jsxs=h(j.jsxs));m.jsxDEV&&(m.jsxDEV=h(m.jsxDEV));j.jsxDEV&&(j.jsxDEV=h(j.jsxDEV));Object.defineProperties(t.Signal.prototype,{$$typeof:{configurable:!0,value:l},type:{configurable:!0,value:function(r){return r.data.value}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});exports.Signal=t.Signal;exports.batch=t.batch;exports.computed=t.computed;exports.effect=t.effect;exports.signal=t.signal;exports.useComputed=function(n){var e=r.useRef(n);e.current=n;return r.useMemo(function(){return t.computed(function(){return e.current()})},s)};exports.useSignal=function(n){return r.useMemo(function(){return t.signal(n)},s)};exports.useSignalEffect=function(n){var e=r.useRef(n);e.current=n;r.useEffect(function(){return t.effect(function(){return e.current()})},s)};//# sourceMappingURL=signals.js.map
|
package/dist/signals.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new WeakMap<\n\tFunctionComponent<any>,\n\tFunctionComponent<any>\n>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["Empty","Symbol","ReactMemoType","ProxyInstance","WeakMap","SupportsProxy","Proxy","apply","Component","thisArg","argumentsList","useMemo","createEffectStore","useSyncExternalStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","ProxyComponent","ProxyHandlers","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","unsubscribe","effect","this","_callback","version","onStoreChange","WrapJsx","jsx","type","props","rest","slice","call","concat","$$typeof","v","i","Signal","value","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","_ref","data","ref","exports","signalsCore","batch","computed","signal","useComputed","compute","useRef","$compute","current","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"signals.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as ReactInternals,\n\ttype ReactElement,\n\ttype useCallback,\n\ttype useReducer,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n\ninterface ReactDispatcher {\n\tuseRef: typeof useRef;\n\tuseCallback: typeof useCallback;\n\tuseReducer: typeof useReducer;\n\tuseSyncExternalStore: typeof useSyncExternalStore;\n}\n\nlet finishUpdate: (() => void) | undefined;\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\ninterface EffectStore {\n\tupdater: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore(): EffectStore {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change\n */\nfunction usePreactSignalStore(nextDispatcher: ReactDispatcher): EffectStore {\n\tconst storeRef = nextDispatcher.useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tstoreRef.current = createEffectStore();\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\treturn store;\n}\n\n// To track when we are entering and exiting a component render (i.e. before and\n// after React renders a component), we track how the dispatcher changes.\n// Outside of a component rendering, the dispatcher is set to an instance that\n// errors or warns when any hooks are called. This behavior is prevents hooks\n// from being used outside of components. Right before React renders a\n// component, the dispatcher is set to a valid one. Right after React finishes\n// rendering a component, the dispatcher is set to an erroring one again. This\n// erroring dispatcher is called the `ContextOnlyDispatcher` in React's source.\n//\n// So, we watch the getter and setter on `ReactCurrentDispatcher.current` to\n// monitor the changes to the current ReactDispatcher. When the dispatcher\n// changes from the ContextOnlyDispatcher to a valid dispatcher, we assume we\n// are entering a component render. At this point, we setup our\n// auto-subscriptions for any signals used in the component. We do this by\n// creating an effect and manually starting the effect. We use\n// `useSyncExternalStore` to trigger rerenders on the component when any signals\n// it uses changes.\n//\n// When the dispatcher changes from a valid dispatcher back to the\n// ContextOnlyDispatcher, we assume we are exiting a component render. At this\n// point we stop the effect.\n//\n// Some edge cases to be aware of:\n// - In development, useReducer, useState, and useMemo changes the dispatcher to\n// a different erroring dispatcher before invoking the reducer and resets it\n// right after.\n//\n// The useSyncExternalStore shim will use some of these hooks when we invoke\n// it while entering a component render. We need to prevent this dispatcher\n// change caused by these hooks from re-triggering our entering logic (it\n// would cause an infinite loop if we did not). We do this by using a lock to\n// prevent the setter from running while we are in the setter.\n//\n// When a Component's function body invokes useReducer, useState, or useMemo,\n// this change in dispatcher should not signal that we are exiting a component\n// render. We ignore this change by detecting these dispatchers as different\n// from ContextOnlyDispatcher and other valid dispatchers.\n//\n// - The `use` hook will change the dispatcher to from a valid update dispatcher\n// to a valid mount dispatcher in some cases. Similarly to useReducer\n// mentioned above, we should not signal that we are exiting a component\n// during this change. Because these other valid dispatchers do not pass the\n// ContextOnlyDispatcher check, they do not affect our logic.\nlet lock = false;\nlet currentDispatcher: ReactDispatcher | null = null;\nObject.defineProperty(ReactInternals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(nextDispatcher: ReactDispatcher) {\n\t\tif (lock) {\n\t\t\tcurrentDispatcher = nextDispatcher;\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentDispatcherType = getDispatcherType(currentDispatcher);\n\t\tconst nextDispatcherType = getDispatcherType(nextDispatcher);\n\n\t\t// We are entering a component render if the current dispatcher is the\n\t\t// ContextOnlyDispatcher and the next dispatcher is a valid dispatcher.\n\t\tconst isEnteringComponentRender =\n\t\t\tcurrentDispatcherType === ContextOnlyDispatcherType &&\n\t\t\tnextDispatcherType === ValidDispatcherType;\n\n\t\t// We are exiting a component render if the current dispatcher is a valid\n\t\t// dispatcher and the next dispatcher is the ContextOnlyDispatcher.\n\t\tconst isExitingComponentRender =\n\t\t\tcurrentDispatcherType === ValidDispatcherType &&\n\t\t\tnextDispatcherType === ContextOnlyDispatcherType;\n\n\t\t// Update the current dispatcher now so the hooks inside of the\n\t\t// useSyncExternalStore shim get the right dispatcher.\n\t\tcurrentDispatcher = nextDispatcher;\n\t\tif (isEnteringComponentRender) {\n\t\t\tlock = true;\n\t\t\tconst store = usePreactSignalStore(nextDispatcher);\n\t\t\tlock = false;\n\n\t\t\tsetCurrentUpdater(store.updater);\n\t\t} else if (isExitingComponentRender) {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\nconst ValidDispatcherType = 0;\nconst ContextOnlyDispatcherType = 1;\nconst ErroringDispatcherType = 2;\n\n// We inject a useSyncExternalStore into every function component via\n// CurrentDispatcher. This prevents injecting into anything other than a\n// function component render.\nconst dispatcherTypeCache = new Map<ReactDispatcher, number>();\nfunction getDispatcherType(dispatcher: ReactDispatcher | null): number {\n\t// Treat null the same as the ContextOnlyDispatcher.\n\tif (!dispatcher) return ContextOnlyDispatcherType;\n\n\tconst cached = dispatcherTypeCache.get(dispatcher);\n\tif (cached !== undefined) return cached;\n\n\t// The ContextOnlyDispatcher sets all the hook implementations to a function\n\t// that takes no arguments and throws and error. Check the number of arguments\n\t// for this dispatcher's useCallback implementation to determine if it is a\n\t// ContextOnlyDispatcher. All other dispatchers, erroring or not, define\n\t// functions with arguments and so fail this check.\n\tlet type: number;\n\tif (dispatcher.useCallback.length < 2) {\n\t\ttype = ContextOnlyDispatcherType;\n\t} else if (/Invalid/.test(dispatcher.useCallback as any)) {\n\t\ttype = ErroringDispatcherType;\n\t} else {\n\t\ttype = ValidDispatcherType;\n\t}\n\n\tdispatcherTypeCache.set(dispatcher, type);\n\treturn type;\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\ndeclare module \"@preact/signals-core\" {\n\t// @ts-ignore internal Signal is viewed as function\n\t// eslint-disable-next-line @typescript-eslint/no-empty-interface\n\tinterface Signal extends ReactElement {}\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: Text },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["finishUpdate","Empty","ReactElemType","Symbol","setCurrentUpdater","updater","_start","lock","Object","defineProperty","ReactInternals","ReactCurrentDispatcher","get","set","nextDispatcher","currentDispatcherType","getDispatcherType","currentDispatcher","nextDispatcherType","ValidDispatcherType","ContextOnlyDispatcherType","store","storeRef","useRef","current","onChangeNotifyReact","version","unsubscribe","effect","this","_callback","subscribe","onStoreChange","undefined","getSnapshot","createEffectStore","useSyncExternalStore","usePreactSignalStore","isExitingComponentRender","dispatcher","cached","dispatcherTypeCache","useCallback","length","type","test","WrapJsx","jsx","props","v","i","Signal","value","call","apply","concat","slice","arguments","JsxPro","jsxRuntime","jsxRuntimeDev","React","createElement","JsxDev","jsxs","jsxDEV","defineProperties","prototype","$$typeof","configurable","_ref","data","ref","exports","signalsCore","batch","computed","signal","useComputed","compute","$compute","useMemo","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
|
package/dist/signals.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(n
|
|
1
|
+
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("react"),require("react/jsx-runtime"),require("react/jsx-dev-runtime"),require("@preact/signals-core"),require("use-sync-external-store/shim/index")):"function"==typeof define&&define.amd?define(["exports","react","react/jsx-runtime","react/jsx-dev-runtime","@preact/signals-core","use-sync-external-store/shim/index"],n):n((e||self).reactSignals={},e.react,e.jsxRuntime,e.jsxRuntimeDev,e.signalsCore,e.index)}(this,function(e,n,r,t,i,u){function f(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var o,c=/*#__PURE__*/f(n),a=/*#__PURE__*/f(r),s=/*#__PURE__*/f(t),l=[],v=Symbol.for("react.element");function d(e){if(o)o();o=e&&e.S()}var p=!1,b=null;Object.defineProperty(n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher,"current",{get:function(){return b},set:function(e){if(!p){var n=h(b),r=h(e),t=n===g&&r===y;b=e;if(n===y&&r===g){p=!0;var f=function(e){var n=e.useRef();if(null==n.current)n.current=function(){var e,n,r=0,t=i.effect(function(){e=this});e.c=function(){r=r+1|0;if(n)n()};return{updater:e,subscribe:function(e){n=e;return function(){r=r+1|0;n=void 0;t()}},getSnapshot:function(){return r}}}();var r=n.current;u.useSyncExternalStore(r.subscribe,r.getSnapshot,r.getSnapshot);return r}(e);p=!1;d(f.updater)}else if(t)d()}else b=e}});var g=0,y=1,x=new Map;function h(e){if(!e)return y;var n,r=x.get(e);if(void 0!==r)return r;if(e.useCallback.length<2)n=y;else if(/Invalid/.test(e.useCallback))n=2;else n=g;x.set(e,n);return n}function m(e){if("function"!=typeof e)return e;else return function(n,r){if("string"==typeof n&&r)for(var t in r){var u=r[t];if("children"!==t&&u instanceof i.Signal)r[t]=u.value}return e.call.apply(e,[e,n,r].concat([].slice.call(arguments,2)))}}var j=a,q=s;c.createElement=m(c.createElement);q.jsx&&(q.jsx=m(q.jsx));j.jsx&&(j.jsx=m(j.jsx));q.jsxs&&(q.jsxs=m(q.jsxs));j.jsxs&&(j.jsxs=m(j.jsxs));q.jsxDEV&&(q.jsxDEV=m(q.jsxDEV));j.jsxDEV&&(j.jsxDEV=m(j.jsxDEV));Object.defineProperties(i.Signal.prototype,{$$typeof:{configurable:!0,value:v},type:{configurable:!0,value:function(e){return e.data.value}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});e.Signal=i.Signal;e.batch=i.batch;e.computed=i.computed;e.effect=i.effect;e.signal=i.signal;e.useComputed=function(e){var r=n.useRef(e);r.current=e;return n.useMemo(function(){return i.computed(function(){return r.current()})},l)};e.useSignal=function(e){return n.useMemo(function(){return i.signal(e)},l)};e.useSignalEffect=function(e){var r=n.useRef(e);r.current=e;n.useEffect(function(){return i.effect(function(){return r.current()})},l)}});//# sourceMappingURL=signals.min.js.map
|
package/dist/signals.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.min.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new WeakMap<\n\tFunctionComponent<any>,\n\tFunctionComponent<any>\n>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["Empty","Symbol","ReactMemoType","ProxyInstance","WeakMap","SupportsProxy","Proxy","apply","Component","thisArg","argumentsList","useMemo","createEffectStore","useSyncExternalStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","ProxyComponent","ProxyHandlers","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","unsubscribe","effect","this","_callback","version","onStoreChange","WrapJsx","jsx","type","props","rest","slice","call","concat","$$typeof","v","i","Signal","value","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","_ref","data","ref","exports","signalsCore","batch","computed","signal","useComputed","compute","useRef","$compute","current","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"signals.min.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as ReactInternals,\n\ttype ReactElement,\n\ttype useCallback,\n\ttype useReducer,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n\ninterface ReactDispatcher {\n\tuseRef: typeof useRef;\n\tuseCallback: typeof useCallback;\n\tuseReducer: typeof useReducer;\n\tuseSyncExternalStore: typeof useSyncExternalStore;\n}\n\nlet finishUpdate: (() => void) | undefined;\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\ninterface EffectStore {\n\tupdater: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore(): EffectStore {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change\n */\nfunction usePreactSignalStore(nextDispatcher: ReactDispatcher): EffectStore {\n\tconst storeRef = nextDispatcher.useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tstoreRef.current = createEffectStore();\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\treturn store;\n}\n\n// To track when we are entering and exiting a component render (i.e. before and\n// after React renders a component), we track how the dispatcher changes.\n// Outside of a component rendering, the dispatcher is set to an instance that\n// errors or warns when any hooks are called. This behavior is prevents hooks\n// from being used outside of components. Right before React renders a\n// component, the dispatcher is set to a valid one. Right after React finishes\n// rendering a component, the dispatcher is set to an erroring one again. This\n// erroring dispatcher is called the `ContextOnlyDispatcher` in React's source.\n//\n// So, we watch the getter and setter on `ReactCurrentDispatcher.current` to\n// monitor the changes to the current ReactDispatcher. When the dispatcher\n// changes from the ContextOnlyDispatcher to a valid dispatcher, we assume we\n// are entering a component render. At this point, we setup our\n// auto-subscriptions for any signals used in the component. We do this by\n// creating an effect and manually starting the effect. We use\n// `useSyncExternalStore` to trigger rerenders on the component when any signals\n// it uses changes.\n//\n// When the dispatcher changes from a valid dispatcher back to the\n// ContextOnlyDispatcher, we assume we are exiting a component render. At this\n// point we stop the effect.\n//\n// Some edge cases to be aware of:\n// - In development, useReducer, useState, and useMemo changes the dispatcher to\n// a different erroring dispatcher before invoking the reducer and resets it\n// right after.\n//\n// The useSyncExternalStore shim will use some of these hooks when we invoke\n// it while entering a component render. We need to prevent this dispatcher\n// change caused by these hooks from re-triggering our entering logic (it\n// would cause an infinite loop if we did not). We do this by using a lock to\n// prevent the setter from running while we are in the setter.\n//\n// When a Component's function body invokes useReducer, useState, or useMemo,\n// this change in dispatcher should not signal that we are exiting a component\n// render. We ignore this change by detecting these dispatchers as different\n// from ContextOnlyDispatcher and other valid dispatchers.\n//\n// - The `use` hook will change the dispatcher to from a valid update dispatcher\n// to a valid mount dispatcher in some cases. Similarly to useReducer\n// mentioned above, we should not signal that we are exiting a component\n// during this change. Because these other valid dispatchers do not pass the\n// ContextOnlyDispatcher check, they do not affect our logic.\nlet lock = false;\nlet currentDispatcher: ReactDispatcher | null = null;\nObject.defineProperty(ReactInternals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(nextDispatcher: ReactDispatcher) {\n\t\tif (lock) {\n\t\t\tcurrentDispatcher = nextDispatcher;\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentDispatcherType = getDispatcherType(currentDispatcher);\n\t\tconst nextDispatcherType = getDispatcherType(nextDispatcher);\n\n\t\t// We are entering a component render if the current dispatcher is the\n\t\t// ContextOnlyDispatcher and the next dispatcher is a valid dispatcher.\n\t\tconst isEnteringComponentRender =\n\t\t\tcurrentDispatcherType === ContextOnlyDispatcherType &&\n\t\t\tnextDispatcherType === ValidDispatcherType;\n\n\t\t// We are exiting a component render if the current dispatcher is a valid\n\t\t// dispatcher and the next dispatcher is the ContextOnlyDispatcher.\n\t\tconst isExitingComponentRender =\n\t\t\tcurrentDispatcherType === ValidDispatcherType &&\n\t\t\tnextDispatcherType === ContextOnlyDispatcherType;\n\n\t\t// Update the current dispatcher now so the hooks inside of the\n\t\t// useSyncExternalStore shim get the right dispatcher.\n\t\tcurrentDispatcher = nextDispatcher;\n\t\tif (isEnteringComponentRender) {\n\t\t\tlock = true;\n\t\t\tconst store = usePreactSignalStore(nextDispatcher);\n\t\t\tlock = false;\n\n\t\t\tsetCurrentUpdater(store.updater);\n\t\t} else if (isExitingComponentRender) {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\nconst ValidDispatcherType = 0;\nconst ContextOnlyDispatcherType = 1;\nconst ErroringDispatcherType = 2;\n\n// We inject a useSyncExternalStore into every function component via\n// CurrentDispatcher. This prevents injecting into anything other than a\n// function component render.\nconst dispatcherTypeCache = new Map<ReactDispatcher, number>();\nfunction getDispatcherType(dispatcher: ReactDispatcher | null): number {\n\t// Treat null the same as the ContextOnlyDispatcher.\n\tif (!dispatcher) return ContextOnlyDispatcherType;\n\n\tconst cached = dispatcherTypeCache.get(dispatcher);\n\tif (cached !== undefined) return cached;\n\n\t// The ContextOnlyDispatcher sets all the hook implementations to a function\n\t// that takes no arguments and throws and error. Check the number of arguments\n\t// for this dispatcher's useCallback implementation to determine if it is a\n\t// ContextOnlyDispatcher. All other dispatchers, erroring or not, define\n\t// functions with arguments and so fail this check.\n\tlet type: number;\n\tif (dispatcher.useCallback.length < 2) {\n\t\ttype = ContextOnlyDispatcherType;\n\t} else if (/Invalid/.test(dispatcher.useCallback as any)) {\n\t\ttype = ErroringDispatcherType;\n\t} else {\n\t\ttype = ValidDispatcherType;\n\t}\n\n\tdispatcherTypeCache.set(dispatcher, type);\n\treturn type;\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\ndeclare module \"@preact/signals-core\" {\n\t// @ts-ignore internal Signal is viewed as function\n\t// eslint-disable-next-line @typescript-eslint/no-empty-interface\n\tinterface Signal extends ReactElement {}\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: Text },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["finishUpdate","Empty","ReactElemType","Symbol","setCurrentUpdater","updater","_start","lock","Object","defineProperty","ReactInternals","ReactCurrentDispatcher","get","set","nextDispatcher","currentDispatcherType","getDispatcherType","currentDispatcher","nextDispatcherType","ValidDispatcherType","ContextOnlyDispatcherType","store","storeRef","useRef","current","onChangeNotifyReact","version","unsubscribe","effect","this","_callback","subscribe","onStoreChange","undefined","getSnapshot","createEffectStore","useSyncExternalStore","usePreactSignalStore","isExitingComponentRender","dispatcher","cached","dispatcherTypeCache","useCallback","length","type","test","WrapJsx","jsx","props","v","i","Signal","value","call","apply","concat","slice","arguments","JsxPro","jsxRuntime","jsxRuntimeDev","React","createElement","JsxDev","jsxs","jsxDEV","defineProperties","prototype","$$typeof","configurable","_ref","data","ref","exports","signalsCore","batch","computed","signal","useComputed","compute","$compute","useMemo","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
|
package/dist/signals.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import t,{
|
|
1
|
+
import t,{__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as n,useMemo as e,useRef as r,useEffect as o}from"react";import i from"react/jsx-runtime";import c from"react/jsx-dev-runtime";import{Signal as f,signal as u,computed as s,effect as l}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";import{useSyncExternalStore as a}from"use-sync-external-store/shim/index";const p=[],m=Symbol.for("react.element");let g;function b(t){if(g)g();g=t&&t.S()}let d=!1,v=null;Object.defineProperty(n.ReactCurrentDispatcher,"current",{get:()=>v,set(t){if(d){v=t;return}const n=j(v),e=j(t),r=n===h&&e===x;v=t;if(n===x&&e===h){d=!0;const n=function(t){const n=t.useRef();if(null==n.current)n.current=function(){let t,n,e=0,r=l(function(){t=this});t.c=function(){e=e+1|0;if(n)n()};return{updater:t,subscribe(t){n=t;return function(){e=e+1|0;n=void 0;r()}},getSnapshot:()=>e}}();const e=n.current;a(e.subscribe,e.getSnapshot,e.getSnapshot);return e}(t);d=!1;b(n.updater)}else if(r)b()}});const h=0,x=1,y=new Map;function j(t){if(!t)return x;const n=y.get(t);if(void 0!==n)return n;let e;if(t.useCallback.length<2)e=x;else if(/Invalid/.test(t.useCallback))e=2;else e=h;y.set(t,e);return e}function S(t){if("function"!=typeof t)return t;else return function(n,e,...r){if("string"==typeof n&&e)for(let t in e){let n=e[t];if("children"!==t&&n instanceof f)e[t]=n.value}return t.call(t,n,e,...r)}}const O=i,$=c;t.createElement=S(t.createElement);$.jsx&&($.jsx=S($.jsx));O.jsx&&(O.jsx=S(O.jsx));$.jsxs&&($.jsxs=S($.jsxs));O.jsxs&&(O.jsxs=S(O.jsxs));$.jsxDEV&&($.jsxDEV=S($.jsxDEV));O.jsxDEV&&(O.jsxDEV=S(O.jsxDEV));Object.defineProperties(f.prototype,{$$typeof:{configurable:!0,value:m},type:{configurable:!0,value:function({data:t}){return t.value}},props:{configurable:!0,get(){return{data:this}}},ref:{configurable:!0,value:null}});function useSignal(t){return e(()=>u(t),p)}function useComputed(t){const n=r(t);n.current=t;return e(()=>s(()=>n.current()),p)}function useSignalEffect(t){const n=r(t);n.current=t;o(()=>l(()=>n.current()),p)}export{useComputed,useSignal,useSignalEffect};//# sourceMappingURL=signals.mjs.map
|
package/dist/signals.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new WeakMap<\n\tFunctionComponent<any>,\n\tFunctionComponent<any>\n>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["React","Component","useMemo","useRef","useEffect","jsxRuntime","jsxRuntimeDev","useSyncExternalStore","Signal","signal","computed","effect","batch","Empty","Symbol","for","ReactMemoType","ProxyInstance","WeakMap","SupportsProxy","Proxy","ProxyHandlers","apply","thisArg","argumentsList","createEffectStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","set","ProxyComponent","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","version","unsubscribe","this","_callback","onStoreChange","WrapJsx","jsx","type","props","rest","call","$$typeof","i","v","value","JsxPro","JsxDev","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","data","ref","useSignal","useComputed","compute","$compute","current","useSignalEffect","cb","callback"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"signals.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as ReactInternals,\n\ttype ReactElement,\n\ttype useCallback,\n\ttype useReducer,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n\ninterface ReactDispatcher {\n\tuseRef: typeof useRef;\n\tuseCallback: typeof useCallback;\n\tuseReducer: typeof useReducer;\n\tuseSyncExternalStore: typeof useSyncExternalStore;\n}\n\nlet finishUpdate: (() => void) | undefined;\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\ninterface EffectStore {\n\tupdater: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore(): EffectStore {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change\n */\nfunction usePreactSignalStore(nextDispatcher: ReactDispatcher): EffectStore {\n\tconst storeRef = nextDispatcher.useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tstoreRef.current = createEffectStore();\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\treturn store;\n}\n\n// To track when we are entering and exiting a component render (i.e. before and\n// after React renders a component), we track how the dispatcher changes.\n// Outside of a component rendering, the dispatcher is set to an instance that\n// errors or warns when any hooks are called. This behavior is prevents hooks\n// from being used outside of components. Right before React renders a\n// component, the dispatcher is set to a valid one. Right after React finishes\n// rendering a component, the dispatcher is set to an erroring one again. This\n// erroring dispatcher is called the `ContextOnlyDispatcher` in React's source.\n//\n// So, we watch the getter and setter on `ReactCurrentDispatcher.current` to\n// monitor the changes to the current ReactDispatcher. When the dispatcher\n// changes from the ContextOnlyDispatcher to a valid dispatcher, we assume we\n// are entering a component render. At this point, we setup our\n// auto-subscriptions for any signals used in the component. We do this by\n// creating an effect and manually starting the effect. We use\n// `useSyncExternalStore` to trigger rerenders on the component when any signals\n// it uses changes.\n//\n// When the dispatcher changes from a valid dispatcher back to the\n// ContextOnlyDispatcher, we assume we are exiting a component render. At this\n// point we stop the effect.\n//\n// Some edge cases to be aware of:\n// - In development, useReducer, useState, and useMemo changes the dispatcher to\n// a different erroring dispatcher before invoking the reducer and resets it\n// right after.\n//\n// The useSyncExternalStore shim will use some of these hooks when we invoke\n// it while entering a component render. We need to prevent this dispatcher\n// change caused by these hooks from re-triggering our entering logic (it\n// would cause an infinite loop if we did not). We do this by using a lock to\n// prevent the setter from running while we are in the setter.\n//\n// When a Component's function body invokes useReducer, useState, or useMemo,\n// this change in dispatcher should not signal that we are exiting a component\n// render. We ignore this change by detecting these dispatchers as different\n// from ContextOnlyDispatcher and other valid dispatchers.\n//\n// - The `use` hook will change the dispatcher to from a valid update dispatcher\n// to a valid mount dispatcher in some cases. Similarly to useReducer\n// mentioned above, we should not signal that we are exiting a component\n// during this change. Because these other valid dispatchers do not pass the\n// ContextOnlyDispatcher check, they do not affect our logic.\nlet lock = false;\nlet currentDispatcher: ReactDispatcher | null = null;\nObject.defineProperty(ReactInternals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(nextDispatcher: ReactDispatcher) {\n\t\tif (lock) {\n\t\t\tcurrentDispatcher = nextDispatcher;\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentDispatcherType = getDispatcherType(currentDispatcher);\n\t\tconst nextDispatcherType = getDispatcherType(nextDispatcher);\n\n\t\t// We are entering a component render if the current dispatcher is the\n\t\t// ContextOnlyDispatcher and the next dispatcher is a valid dispatcher.\n\t\tconst isEnteringComponentRender =\n\t\t\tcurrentDispatcherType === ContextOnlyDispatcherType &&\n\t\t\tnextDispatcherType === ValidDispatcherType;\n\n\t\t// We are exiting a component render if the current dispatcher is a valid\n\t\t// dispatcher and the next dispatcher is the ContextOnlyDispatcher.\n\t\tconst isExitingComponentRender =\n\t\t\tcurrentDispatcherType === ValidDispatcherType &&\n\t\t\tnextDispatcherType === ContextOnlyDispatcherType;\n\n\t\t// Update the current dispatcher now so the hooks inside of the\n\t\t// useSyncExternalStore shim get the right dispatcher.\n\t\tcurrentDispatcher = nextDispatcher;\n\t\tif (isEnteringComponentRender) {\n\t\t\tlock = true;\n\t\t\tconst store = usePreactSignalStore(nextDispatcher);\n\t\t\tlock = false;\n\n\t\t\tsetCurrentUpdater(store.updater);\n\t\t} else if (isExitingComponentRender) {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\nconst ValidDispatcherType = 0;\nconst ContextOnlyDispatcherType = 1;\nconst ErroringDispatcherType = 2;\n\n// We inject a useSyncExternalStore into every function component via\n// CurrentDispatcher. This prevents injecting into anything other than a\n// function component render.\nconst dispatcherTypeCache = new Map<ReactDispatcher, number>();\nfunction getDispatcherType(dispatcher: ReactDispatcher | null): number {\n\t// Treat null the same as the ContextOnlyDispatcher.\n\tif (!dispatcher) return ContextOnlyDispatcherType;\n\n\tconst cached = dispatcherTypeCache.get(dispatcher);\n\tif (cached !== undefined) return cached;\n\n\t// The ContextOnlyDispatcher sets all the hook implementations to a function\n\t// that takes no arguments and throws and error. Check the number of arguments\n\t// for this dispatcher's useCallback implementation to determine if it is a\n\t// ContextOnlyDispatcher. All other dispatchers, erroring or not, define\n\t// functions with arguments and so fail this check.\n\tlet type: number;\n\tif (dispatcher.useCallback.length < 2) {\n\t\ttype = ContextOnlyDispatcherType;\n\t} else if (/Invalid/.test(dispatcher.useCallback as any)) {\n\t\ttype = ErroringDispatcherType;\n\t} else {\n\t\ttype = ValidDispatcherType;\n\t}\n\n\tdispatcherTypeCache.set(dispatcher, type);\n\treturn type;\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\ndeclare module \"@preact/signals-core\" {\n\t// @ts-ignore internal Signal is viewed as function\n\t// eslint-disable-next-line @typescript-eslint/no-empty-interface\n\tinterface Signal extends ReactElement {}\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: Text },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["Empty","ReactElemType","Symbol","for","finishUpdate","setCurrentUpdater","updater","_start","lock","currentDispatcher","Object","defineProperty","ReactInternals","ReactCurrentDispatcher","get","set","nextDispatcher","currentDispatcherType","getDispatcherType","isExitingComponentRender","ValidDispatcherType","nextDispatcherType","ContextOnlyDispatcherType","store","storeRef","useRef","current","onChangeNotifyReact","unsubscribe","effect","this","_callback","version","subscribe","onStoreChange","undefined","getSnapshot","createEffectStore","useSyncExternalStore","usePreactSignalStore","dispatcherTypeCache","Map","dispatcher","cached","type","useCallback","length","test","WrapJsx","jsx","props","rest","i","v","Signal","value","call","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","defineProperties","prototype","$$typeof","configurable","data","ref","useSignal","useMemo","signal","useComputed","compute","$compute","computed","cb","callback","useEffect","useSignalEffect"],"mappings":"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"}
|
package/dist/signals.module.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import n,{
|
|
1
|
+
import n,{__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as r,useMemo as t,useRef as e,useEffect as i}from"react";import u from"react/jsx-runtime";import f from"react/jsx-dev-runtime";import{Signal as o,signal as c,computed as a,effect as l}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";import{useSyncExternalStore as s}from"use-sync-external-store/shim/index";var v,p=[],m=Symbol.for("react.element");function g(n){if(v)v();v=n&&n.S()}var b=!1,d=null;Object.defineProperty(r.ReactCurrentDispatcher,"current",{get:function(){return d},set:function(n){if(!b){var r=j(d),t=j(n),e=r===h&&t===x;d=n;if(r===x&&t===h){b=!0;var i=function(n){var r=n.useRef();if(null==r.current)r.current=function(){var n,r,t=0,e=l(function(){n=this});n.c=function(){t=t+1|0;if(r)r()};return{updater:n,subscribe:function(n){r=n;return function(){t=t+1|0;r=void 0;e()}},getSnapshot:function(){return t}}}();var t=r.current;s(t.subscribe,t.getSnapshot,t.getSnapshot);return t}(n);b=!1;g(i.updater)}else if(e)g()}else d=n}});var h=0,x=1,y=new Map;function j(n){if(!n)return x;var r,t=y.get(n);if(void 0!==t)return t;if(n.useCallback.length<2)r=x;else if(/Invalid/.test(n.useCallback))r=2;else r=h;y.set(n,r);return r}function S(n){if("function"!=typeof n)return n;else return function(r,t){if("string"==typeof r&&t)for(var e in t){var i=t[e];if("children"!==e&&i instanceof o)t[e]=i.value}return n.call.apply(n,[n,r,t].concat([].slice.call(arguments,2)))}}var O=u,$=f;n.createElement=S(n.createElement);$.jsx&&($.jsx=S($.jsx));O.jsx&&(O.jsx=S(O.jsx));$.jsxs&&($.jsxs=S($.jsxs));O.jsxs&&(O.jsxs=S(O.jsxs));$.jsxDEV&&($.jsxDEV=S($.jsxDEV));O.jsxDEV&&(O.jsxDEV=S(O.jsxDEV));Object.defineProperties(o.prototype,{$$typeof:{configurable:!0,value:m},type:{configurable:!0,value:function(n){return n.data.value}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});function useSignal(n){return t(function(){return c(n)},p)}function useComputed(n){var r=e(n);r.current=n;return t(function(){return a(function(){return r.current()})},p)}function useSignalEffect(n){var r=e(n);r.current=n;i(function(){return l(function(){return r.current()})},p)}export{useComputed,useSignal,useSignalEffect};//# sourceMappingURL=signals.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.module.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new WeakMap<\n\tFunctionComponent<any>,\n\tFunctionComponent<any>\n>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["Empty","Symbol","ReactMemoType","ProxyInstance","WeakMap","SupportsProxy","Proxy","apply","Component","thisArg","argumentsList","useMemo","createEffectStore","useSyncExternalStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","ProxyComponent","ProxyHandlers","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","unsubscribe","effect","this","_callback","version","onStoreChange","WrapJsx","jsx","type","props","rest","slice","call","concat","$$typeof","v","i","Signal","value","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","_ref","data","ref","useSignal","signal","compute","useRef","$compute","current","computed","useSignalEffect","cb","callback","useEffect","useComputed"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"signals.module.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as ReactInternals,\n\ttype ReactElement,\n\ttype useCallback,\n\ttype useReducer,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n\ninterface ReactDispatcher {\n\tuseRef: typeof useRef;\n\tuseCallback: typeof useCallback;\n\tuseReducer: typeof useReducer;\n\tuseSyncExternalStore: typeof useSyncExternalStore;\n}\n\nlet finishUpdate: (() => void) | undefined;\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\ninterface EffectStore {\n\tupdater: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore(): EffectStore {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t};\n}\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change\n */\nfunction usePreactSignalStore(nextDispatcher: ReactDispatcher): EffectStore {\n\tconst storeRef = nextDispatcher.useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tstoreRef.current = createEffectStore();\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\treturn store;\n}\n\n// To track when we are entering and exiting a component render (i.e. before and\n// after React renders a component), we track how the dispatcher changes.\n// Outside of a component rendering, the dispatcher is set to an instance that\n// errors or warns when any hooks are called. This behavior is prevents hooks\n// from being used outside of components. Right before React renders a\n// component, the dispatcher is set to a valid one. Right after React finishes\n// rendering a component, the dispatcher is set to an erroring one again. This\n// erroring dispatcher is called the `ContextOnlyDispatcher` in React's source.\n//\n// So, we watch the getter and setter on `ReactCurrentDispatcher.current` to\n// monitor the changes to the current ReactDispatcher. When the dispatcher\n// changes from the ContextOnlyDispatcher to a valid dispatcher, we assume we\n// are entering a component render. At this point, we setup our\n// auto-subscriptions for any signals used in the component. We do this by\n// creating an effect and manually starting the effect. We use\n// `useSyncExternalStore` to trigger rerenders on the component when any signals\n// it uses changes.\n//\n// When the dispatcher changes from a valid dispatcher back to the\n// ContextOnlyDispatcher, we assume we are exiting a component render. At this\n// point we stop the effect.\n//\n// Some edge cases to be aware of:\n// - In development, useReducer, useState, and useMemo changes the dispatcher to\n// a different erroring dispatcher before invoking the reducer and resets it\n// right after.\n//\n// The useSyncExternalStore shim will use some of these hooks when we invoke\n// it while entering a component render. We need to prevent this dispatcher\n// change caused by these hooks from re-triggering our entering logic (it\n// would cause an infinite loop if we did not). We do this by using a lock to\n// prevent the setter from running while we are in the setter.\n//\n// When a Component's function body invokes useReducer, useState, or useMemo,\n// this change in dispatcher should not signal that we are exiting a component\n// render. We ignore this change by detecting these dispatchers as different\n// from ContextOnlyDispatcher and other valid dispatchers.\n//\n// - The `use` hook will change the dispatcher to from a valid update dispatcher\n// to a valid mount dispatcher in some cases. Similarly to useReducer\n// mentioned above, we should not signal that we are exiting a component\n// during this change. Because these other valid dispatchers do not pass the\n// ContextOnlyDispatcher check, they do not affect our logic.\nlet lock = false;\nlet currentDispatcher: ReactDispatcher | null = null;\nObject.defineProperty(ReactInternals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(nextDispatcher: ReactDispatcher) {\n\t\tif (lock) {\n\t\t\tcurrentDispatcher = nextDispatcher;\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentDispatcherType = getDispatcherType(currentDispatcher);\n\t\tconst nextDispatcherType = getDispatcherType(nextDispatcher);\n\n\t\t// We are entering a component render if the current dispatcher is the\n\t\t// ContextOnlyDispatcher and the next dispatcher is a valid dispatcher.\n\t\tconst isEnteringComponentRender =\n\t\t\tcurrentDispatcherType === ContextOnlyDispatcherType &&\n\t\t\tnextDispatcherType === ValidDispatcherType;\n\n\t\t// We are exiting a component render if the current dispatcher is a valid\n\t\t// dispatcher and the next dispatcher is the ContextOnlyDispatcher.\n\t\tconst isExitingComponentRender =\n\t\t\tcurrentDispatcherType === ValidDispatcherType &&\n\t\t\tnextDispatcherType === ContextOnlyDispatcherType;\n\n\t\t// Update the current dispatcher now so the hooks inside of the\n\t\t// useSyncExternalStore shim get the right dispatcher.\n\t\tcurrentDispatcher = nextDispatcher;\n\t\tif (isEnteringComponentRender) {\n\t\t\tlock = true;\n\t\t\tconst store = usePreactSignalStore(nextDispatcher);\n\t\t\tlock = false;\n\n\t\t\tsetCurrentUpdater(store.updater);\n\t\t} else if (isExitingComponentRender) {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\nconst ValidDispatcherType = 0;\nconst ContextOnlyDispatcherType = 1;\nconst ErroringDispatcherType = 2;\n\n// We inject a useSyncExternalStore into every function component via\n// CurrentDispatcher. This prevents injecting into anything other than a\n// function component render.\nconst dispatcherTypeCache = new Map<ReactDispatcher, number>();\nfunction getDispatcherType(dispatcher: ReactDispatcher | null): number {\n\t// Treat null the same as the ContextOnlyDispatcher.\n\tif (!dispatcher) return ContextOnlyDispatcherType;\n\n\tconst cached = dispatcherTypeCache.get(dispatcher);\n\tif (cached !== undefined) return cached;\n\n\t// The ContextOnlyDispatcher sets all the hook implementations to a function\n\t// that takes no arguments and throws and error. Check the number of arguments\n\t// for this dispatcher's useCallback implementation to determine if it is a\n\t// ContextOnlyDispatcher. All other dispatchers, erroring or not, define\n\t// functions with arguments and so fail this check.\n\tlet type: number;\n\tif (dispatcher.useCallback.length < 2) {\n\t\ttype = ContextOnlyDispatcherType;\n\t} else if (/Invalid/.test(dispatcher.useCallback as any)) {\n\t\ttype = ErroringDispatcherType;\n\t} else {\n\t\ttype = ValidDispatcherType;\n\t}\n\n\tdispatcherTypeCache.set(dispatcher, type);\n\treturn type;\n}\n\nfunction WrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\ndeclare module \"@preact/signals-core\" {\n\t// @ts-ignore internal Signal is viewed as function\n\t// eslint-disable-next-line @typescript-eslint/no-empty-interface\n\tinterface Signal extends ReactElement {}\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: Text },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => callback.current());\n\t}, Empty);\n}\n"],"names":["finishUpdate","Empty","ReactElemType","Symbol","setCurrentUpdater","updater","_start","lock","Object","defineProperty","ReactInternals","ReactCurrentDispatcher","get","set","nextDispatcher","currentDispatcherType","getDispatcherType","currentDispatcher","nextDispatcherType","ValidDispatcherType","ContextOnlyDispatcherType","store","storeRef","useRef","current","onChangeNotifyReact","version","unsubscribe","effect","this","_callback","subscribe","onStoreChange","undefined","getSnapshot","createEffectStore","useSyncExternalStore","usePreactSignalStore","isExitingComponentRender","dispatcher","cached","dispatcherTypeCache","useCallback","length","type","test","WrapJsx","jsx","props","v","i","Signal","value","call","apply","concat","slice","arguments","JsxPro","jsxRuntime","jsxRuntimeDev","React","createElement","JsxDev","jsxs","jsxDEV","defineProperties","prototype","$$typeof","configurable","_ref","data","ref","useSignal","useMemo","signal","useComputed","compute","$compute","computed","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@preact/signals-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Manage state with style in React",
|
|
6
6
|
"keywords": [],
|
|
@@ -35,18 +35,19 @@
|
|
|
35
35
|
},
|
|
36
36
|
"mangle": "../../mangle.json",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@preact/signals-core": "^1.
|
|
38
|
+
"@preact/signals-core": "^1.3.0",
|
|
39
39
|
"use-sync-external-store": "^1.2.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"react": "17.x || 18.x"
|
|
42
|
+
"react": "^16.14.0 || 17.x || 18.x"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/react": "^18.0.18",
|
|
46
46
|
"@types/react-dom": "^18.0.6",
|
|
47
47
|
"@types/use-sync-external-store": "^0.0.3",
|
|
48
48
|
"react": "^18.2.0",
|
|
49
|
-
"react-dom": "^18.2.0"
|
|
49
|
+
"react-dom": "^18.2.0",
|
|
50
|
+
"react-router-dom": "^6.9.0"
|
|
50
51
|
},
|
|
51
52
|
"scripts": {}
|
|
52
53
|
}
|