@preact/signals 1.0.3 → 1.0.4

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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # @preact/signals
2
2
 
3
+ ## 1.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#147](https://github.com/preactjs/signals/pull/147) [`3556499`](https://github.com/preactjs/signals/commit/355649903b766630b62cdd0f90a35d3eafa99fa9) Thanks [@developit](https://github.com/developit)! - Improve performance when rendering Signals as Text in Preact.
8
+
9
+ * [#148](https://github.com/preactjs/signals/pull/148) [`b948745`](https://github.com/preactjs/signals/commit/b948745de7b5b60a20ce3bdc5ee72d47d47f38ec) Thanks [@marvinhagemeister](https://github.com/marvinhagemeister)! - Move `types` field in `package.json` to the top of the entry list to ensure that TypeScript always finds it.
10
+
11
+ - [#153](https://github.com/preactjs/signals/pull/153) [`0da9ce3`](https://github.com/preactjs/signals/commit/0da9ce3c6f57cef67c3e84f0d829421aee8defff) Thanks [@developit](https://github.com/developit)! - Optimize the performance of prop bindings in Preact
12
+
13
+ - Updated dependencies [[`f2ba3d6`](https://github.com/preactjs/signals/commit/f2ba3d657bf8169c6ba1d47c0827aa18cfe1c947), [`160ea77`](https://github.com/preactjs/signals/commit/160ea7791f3adb55c562f5990e0b4848d8491a38), [`4385ea8`](https://github.com/preactjs/signals/commit/4385ea8c8358a154d8b789685bb061658ce1153f), [`b948745`](https://github.com/preactjs/signals/commit/b948745de7b5b60a20ce3bdc5ee72d47d47f38ec), [`00a59c6`](https://github.com/preactjs/signals/commit/00a59c6475bd4542fb934474d82d1e242b2ac870)]:
14
+ - @preact/signals-core@1.1.1
15
+
3
16
  ## 1.0.3
4
17
 
5
18
  ### Patch Changes
package/dist/signals.js CHANGED
@@ -1,2 +1 @@
1
- var n,r,t,e=require("preact"),i=require("preact/hooks"),u=require("@preact/signals-core"),o=new WeakSet,f=new WeakSet,c=new WeakSet;function a(n,r){e.options[n]=r.bind(null,e.options[n]||function(){})}var v=new WeakMap;function s(n){t&&t(!0,!0),r=n,t=n&&n._()}function l(n){var r=u.signal(void 0);return r._c=!0,r._u=n,r}function b(n){var r=v.get(n);if(r)r.__.length=0;else{var t=[];(r=l(function(){for(var r=n.__e,e=0;e<t.length;e++){var i=t[e],u=i.t,o=i.i._v;if(!r)return;u in r?r[u]=o:o?r.setAttribute(u,o):r.removeAttribute(u)}})).__=t,v.set(n,r)}return r}function p(n,r,t){"object"!=typeof n||null==n||(Array.isArray(n)?n.forEach(p):n instanceof u.Signal&&(t[r]=e.createElement(_,{data:n})))}function _(n){var t=this,e=n.data,o=h(e);o.value=e;var f=i.useMemo(function(){for(var n=t.__v;n=n.__;)if(n.__c){c.add(n.__c);break}return r._u=function(){t.base.data=f._v},u.computed(function(){var n=o.value.value;return 0===n?0:!0===n?"":n||""})},[]);return f.value}function h(n){return i.useMemo(function(){return u.signal(n)},[])}_.displayName="_st",a("__b",function(n,r){if("string"==typeof r.type){var t,e=r.props;for(var i in e){var o=e[i];"children"===i?p(o,"children",e):o instanceof u.Signal&&function(){t||(t=b(r)),t.__.push({t:i,i:o});var n=t._u;if(o._u){var u=o._u;o._u=function(){n(),u()}}else o._u=n;e[i]=o.peek()}()}s(t)}n(r)}),a("__r",function(r,t){var e,i=t.__c;i&&(o.delete(i),void 0===(e=v.get(i))&&(e=l(function(){o.add(i),i.setState({})}),v.set(i,e))),n=i,s(e),r(t)}),a("__e",function(r,t,e,i){s(),n=void 0,r(t,e,i)}),a("diffed",function(r,t){s(),n=void 0,r(t)}),a("unmount",function(n,r){var t=r.__c||r,e=v.get(t);if(e){v.delete(t);var i=e._d;i&&(i.forEach(function(n){return n._s.delete(e)}),i.clear())}n(r)}),a("__h",function(n,r,t,e){e<3&&f.add(r),n(r,t,e)}),e.Component.prototype.shouldComponentUpdate=function(n,r){var t,e=v.get(this);if(!(e&&0!==(null==(t=e._d)?void 0:t.size)||c.has(this)))return!0;if(o.has(this))return!0;if(f.has(this))return!0;for(var i in r)return!0;for(var u in n)if("__source"!==u&&n[u]!==this.props[u])return!0;for(var a in this.props)if(!(a in n))return!0;return!1},Object.defineProperty(exports,"Signal",{enumerable:!0,get:function(){return u.Signal}}),Object.defineProperty(exports,"batch",{enumerable:!0,get:function(){return u.batch}}),Object.defineProperty(exports,"computed",{enumerable:!0,get:function(){return u.computed}}),Object.defineProperty(exports,"effect",{enumerable:!0,get:function(){return u.effect}}),Object.defineProperty(exports,"signal",{enumerable:!0,get:function(){return u.signal}}),exports.useComputed=function(r){var t=i.useRef(r);return t.current=r,c.add(n),i.useMemo(function(){return u.computed(function(){return t.current()})},[])},exports.useSignal=h;
2
- //# sourceMappingURL=signals.js.map
1
+ var r,n,t,i=require("preact"),e=require("preact/hooks"),o=require("@preact/signals-core"),u=new WeakSet,f=new WeakSet,a=new WeakSet;function c(r,n){i.options[r]=n.bind(null,i.options[r]||function(){})}var v=new WeakMap;function s(r){t&&t(!0,!0),n=r,t=r&&r._()}function p(r){var n=o.signal(void 0);return n._u=r,n}function l(r){var t=this,i=r.data,u=h(i);u.value=i;var f=e.useMemo(function(){for(var r=t.__v;r=r.__;)if(r.__c){a.add(r.__c);break}return n._u=function(){t.base.data=f._v},o.computed(function(){var r=u.value.value;return 0===r?0:!0===r?"":r||""})},[]);return f.value}function _(r){var n={__proto__:null},t=p(function(i){var e=t.__;for(var u in e)if("children"!==u){var f=e[u];if(f instanceof o.Signal){var a=f.value,c=n[u];n[u]=a,!0===i||c===a||(u in r?r[u]=a:a?r.setAttribute(u,a):r.removeAttribute(u))}}});return t}function h(r){return e.useMemo(function(){return o.signal(r)},[])}l.displayName="_st",Object.defineProperties(o.Signal.prototype,{constructor:{configurable:!0},type:{configurable:!0,value:l},props:{configurable:!0,get:function(){return{data:this}}},__b:{configurable:!0,value:1}}),c("__b",function(r,n){if("string"==typeof n.type){var t,i=n.props;for(var e in i)if("children"!==e){var u=i[e];u instanceof o.Signal&&(t||(n.__np=t={}),t[e]=u,i[e]=u.peek())}}r(n)}),c("__r",function(n,t){var i,e=t.__c;e&&(u.delete(e),void 0===(i=v.get(e))&&(i=p(function(){u.add(e),e.setState({})}),v.set(e,i))),r=e,s(i),n(t)}),c("__e",function(n,t,i,e){s(),r=void 0,n(t,i,e)}),c("diffed",function(n,t){var i,e;if(s(),r=void 0,"string"==typeof t.type&&(i=t.__e)){var o=t.__np;o&&((e=i._u)||(e=_(i),i._u=e),e.__=o,s(e),e._u(!0))}n(t)}),c("unmount",function(r,n){var t=n.__c,i=t&&v.get(t);if(i&&(v.delete(t),i._()(!0,!0)),"string"==typeof n.type){var e=n.__e,o=e._u;o&&(o._()(!0,!0),e._u=null)}r(n)}),c("__h",function(r,n,t,i){i<3&&f.add(n),r(n,t,i)}),i.Component.prototype.shouldComponentUpdate=function(r,n){var t,i=v.get(this);if(!(i&&0!==(null==(t=i._d)?void 0:t.size)||a.has(this)))return!0;if(u.has(this))return!0;if(f.has(this))return!0;for(var e in n)return!0;for(var o in r)if("__source"!==o&&r[o]!==this.props[o])return!0;for(var c in this.props)if(!(c in r))return!0;return!1},exports.Signal=o.Signal,exports.batch=o.batch,exports.computed=o.computed,exports.effect=o.effect,exports.signal=o.signal,exports.useComputed=function(n){var t=e.useRef(n);return t.current=n,a.add(r),e.useMemo(function(){return o.computed(function(){return t.current()})},[])},exports.useSignal=h;//# sourceMappingURL=signals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.js","sources":["../src/index.ts"],"sourcesContent":["import { options, Component, createElement } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._canActivate = true;\n\ts._updater = updater;\n\treturn s;\n}\n\n// Get a (cached) Signal property updater for an element VNode\nfunction getElementUpdater(vnode: VNode) {\n\tlet updater = updaterForComponent.get(vnode) as ElementUpdater;\n\tif (!updater) {\n\t\tlet signalProps: Array<{ _key: string; _signal: Signal }> = [];\n\t\tupdater = createUpdater(() => {\n\t\t\tlet dom = vnode.__e as Element;\n\n\t\t\tfor (let i = 0; i < signalProps.length; i++) {\n\t\t\t\tlet { _key: prop, _signal: signal } = signalProps[i];\n\t\t\t\tlet value = signal._value;\n\t\t\t\tif (!dom) return;\n\t\t\t\tif (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}) as ElementUpdater;\n\t\tupdater._props = signalProps;\n\t\tupdaterForComponent.set(vnode, updater);\n\t} else {\n\t\tupdater._props.length = 0;\n\t}\n\treturn updater;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/** Convert Signals within (nested) props.children into Text components */\nfunction childToSignal<T>(child: any, i: keyof T, arr: T) {\n\tif (typeof child !== \"object\" || child == null) {\n\t\t// can't be a signal\n\t} else if (Array.isArray(child)) {\n\t\tchild.forEach(childToSignal);\n\t} else if (child instanceof Signal) {\n\t\t// @ts-ignore-next-line yes, arr can accept VNodes:\n\t\tarr[i] = createElement(Text, { data: child });\n\t}\n}\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\t// let orig = vnode.__o || vnode;\n\t\tlet props = vnode.props;\n\t\tlet updater;\n\n\t\tfor (let i in props) {\n\t\t\tlet value = props[i];\n\t\t\tif (i === \"children\") {\n\t\t\t\tchildToSignal(value, \"children\", props);\n\t\t\t} else if (value instanceof Signal) {\n\t\t\t\t// first Signal prop triggers creation/cleanup of the updater:\n\t\t\t\tif (!updater) updater = getElementUpdater(vnode);\n\t\t\t\t// track which props are Signals for precise updates:\n\t\t\t\tupdater._props.push({ _key: i, _signal: value });\n\t\t\t\tlet newUpdater = updater._updater;\n\t\t\t\tif (value._updater) {\n\t\t\t\t\tlet oldUpdater = value._updater;\n\t\t\t\t\tvalue._updater = () => {\n\t\t\t\t\t\tnewUpdater();\n\t\t\t\t\t\toldUpdater();\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tvalue._updater = newUpdater;\n\t\t\t\t}\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\n\t\tsetCurrentUpdater(updater);\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(vnode);\n});\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet thing = vnode.__c || vnode;\n\tconst updater = updaterForComponent.get(thing);\n\tif (updater) {\n\t\tupdaterForComponent.delete(thing);\n\t\tconst signals = updater._deps;\n\t\tif (signals) {\n\t\t\tsignals.forEach(signal => signal._subs.delete(updater));\n\t\t\tsignals.clear();\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["currentComponent","finishUpdate","hasPendingUpdate","WeakSet","hasComputeds","hook","hookName","hookFn","options","bind","updaterForComponent","setCurrentUpdater","updater","currentUpdater","_setCurrent","createUpdater","s","signal","undefined","_canActivate","_updater","getElementUpdater","vnode","get","_props","length","signalProps","dom","__e","i","prop","_key","_signal","_value","value","setAttribute","removeAttribute","set","childToSignal","child","arr","Array","isArray","forEach","Signal","createElement","Text","data","_ref","_this","this","currentSignal","useSignal","useMemo","v","__v","__","__c","add","base","computed","displayName","old","type","props","push","newUpdater","oldUpdater","peek","component","setState","error","oldVNode","thing","signals","_deps","_subs","clear","index","hasHookState","Component","prototype","shouldComponentUpdate","state","_updater$_deps","size","has","_i","_i2","useComputed","compute","$compute","useRef","current"],"mappings":"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"}
1
+ {"version":3,"file":"signals.js","sources":["../src/index.ts"],"sourcesContent":["import { options, Component } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._updater = updater;\n\treturn s;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\nObject.defineProperties(Signal.prototype, {\n\tconstructor: { configurable: true },\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\t// Setting a VNode's _depth to 1 forces Preact to clone it before modifying:\n\t// https://github.com/preactjs/preact/blob/d7a433ee8463a7dc23a05111bb47de9ec729ad4d/src/diff/children.js#L77\n\t// @todo remove this for Preact 11\n\t__b: { configurable: true, value: 1 },\n});\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\tlet signalProps: Record<string, any> | undefined;\n\n\t\tlet props = vnode.props;\n\t\tfor (let i in props) {\n\t\t\tif (i === \"children\") continue;\n\n\t\t\tlet value = props[i];\n\t\t\tif (value instanceof Signal) {\n\t\t\t\tif (!signalProps) vnode.__np = signalProps = {};\n\t\t\t\tsignalProps[i] = value;\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\n\tlet dom: Element;\n\tlet updater: ElementUpdater;\n\n\t// vnode._dom is undefined during string rendering,\n\t// so we use this to skip prop subscriptions during SSR.\n\tif (typeof vnode.type === \"string\" && (dom = vnode.__e as Element)) {\n\t\tlet props = vnode.__np;\n\t\tif (props) {\n\t\t\t// @ts-ignore-next\n\t\t\tupdater = dom._updater;\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createElementUpdater(dom);\n\t\t\t\t// @ts-ignore-next\n\t\t\t\tdom._updater = updater;\n\t\t\t}\n\t\t\tupdater!._props = props;\n\t\t\tsetCurrentUpdater(updater);\n\t\t\t// @ts-ignore-next we're adding an argument here\n\t\t\tupdater._updater(true);\n\t\t}\n\t}\n\told(vnode);\n});\n\n// per-element updater for 1+ signal bindings\nfunction createElementUpdater(dom: Element) {\n\tconst cache: Record<string, any> = { __proto__: null };\n\tconst updater = createUpdater((skip?: boolean) => {\n\t\tconst props = updater._props;\n\t\tfor (let prop in props) {\n\t\t\tif (prop === \"children\") continue;\n\t\t\tlet signal = props[prop];\n\t\t\tif (signal instanceof Signal) {\n\t\t\t\tlet value = signal.value;\n\t\t\t\tlet cached = cache[prop];\n\t\t\t\tcache[prop] = value;\n\t\t\t\tif (skip === true || cached === value) {\n\t\t\t\t\t// this is just a subscribe run, not an update\n\t\t\t\t} else if (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}) as ElementUpdater;\n\treturn updater;\n}\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet component = vnode.__c;\n\tconst updater = component && updaterForComponent.get(component);\n\tif (updater) {\n\t\tupdaterForComponent.delete(component);\n\t\tupdater._setCurrent()(true, true);\n\t}\n\n\tif (typeof vnode.type === \"string\") {\n\t\tconst dom = vnode.__e as Element;\n\n\t\t// @ts-ignore-next\n\t\tconst updater = dom._updater;\n\t\tif (updater) {\n\t\t\tupdater._setCurrent()(true, true);\n\t\t\t// @ts-ignore-next\n\t\t\tdom._updater = null;\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\t// @ts-ignore\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["currentComponent","currentUpdater","preact","require","hooks","signalsCore","hasPendingUpdate","WeakSet","hasHookState","hasComputeds","hookName","hookFn","options","bind","updaterForComponent","WeakMap","updater","finishUpdate","_setCurrent","createUpdater","signal","undefined","s","_updater","_ref","_this","this","data","currentSignal","useSignal","value","useMemo","v","__v","__","__c","add","base","_value","computed","createElementUpdater","dom","cache","__proto__","skip","props","_props","prop","_signal","cached","setAttribute","removeAttribute","Text","displayName","Object","defineProperties","Signal","prototype","constructor","configurable","type","get","__b","hook","old","vnode","signalProps","i","__np","peek","component","setState","set","setCurrentUpdater","error","oldVNode","__e","index","Component","shouldComponentUpdate","state","_updater$_deps","_deps","size","has","exports","batch","effect","useComputed","compute","$compute","useRef","current"],"mappings":"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"}
@@ -1,2 +1 @@
1
- !function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("preact"),require("preact/hooks"),require("@preact/signals-core")):"function"==typeof define&&define.amd?define(["exports","preact","preact/hooks","@preact/signals-core"],e):e((n||self).preactSignals={},n.preact,n.hooks,n.signalsCore)}(this,function(n,e,r,t){var i,u,o,f=new WeakSet,c=new WeakSet,a=new WeakSet;function s(n,r){e.options[n]=r.bind(null,e.options[n]||function(){})}var v=new WeakMap;function l(n){o&&o(!0,!0),u=n,o=n&&n._()}function d(n){var e=t.signal(void 0);return e._c=!0,e._u=n,e}function b(n){var e=v.get(n);if(e)e.__.length=0;else{var r=[];(e=d(function(){for(var e=n.__e,t=0;t<r.length;t++){var i=r[t],u=i.t,o=i.i._v;if(!e)return;u in e?e[u]=o:o?e.setAttribute(u,o):e.removeAttribute(u)}})).__=r,v.set(n,e)}return e}function p(n,r,i){"object"!=typeof n||null==n||(Array.isArray(n)?n.forEach(p):n instanceof t.Signal&&(i[r]=e.createElement(h,{data:n})))}function h(n){var e=this,i=n.data,o=g(i);o.value=i;var f=r.useMemo(function(){for(var n=e.__v;n=n.__;)if(n.__c){a.add(n.__c);break}return u._u=function(){e.base.data=f._v},t.computed(function(){var n=o.value.value;return 0===n?0:!0===n?"":n||""})},[]);return f.value}function g(n){return r.useMemo(function(){return t.signal(n)},[])}h.displayName="_st",s("__b",function(n,e){if("string"==typeof e.type){var r,i=e.props;for(var u in i){var o=i[u];"children"===u?p(o,"children",i):o instanceof t.Signal&&function(){r||(r=b(e)),r.__.push({t:u,i:o});var n=r._u;if(o._u){var t=o._u;o._u=function(){n(),t()}}else o._u=n;i[u]=o.peek()}()}l(r)}n(e)}),s("__r",function(n,e){var r,t=e.__c;t&&(f.delete(t),void 0===(r=v.get(t))&&(r=d(function(){f.add(t),t.setState({})}),v.set(t,r))),i=t,l(r),n(e)}),s("__e",function(n,e,r,t){l(),i=void 0,n(e,r,t)}),s("diffed",function(n,e){l(),i=void 0,n(e)}),s("unmount",function(n,e){var r=e.__c||e,t=v.get(r);if(t){v.delete(r);var i=t._d;i&&(i.forEach(function(n){return n._s.delete(t)}),i.clear())}n(e)}),s("__h",function(n,e,r,t){t<3&&c.add(e),n(e,r,t)}),e.Component.prototype.shouldComponentUpdate=function(n,e){var r,t=v.get(this);if(!(t&&0!==(null==(r=t._d)?void 0:r.size)||a.has(this)))return!0;if(f.has(this))return!0;if(c.has(this))return!0;for(var i in e)return!0;for(var u in n)if("__source"!==u&&n[u]!==this.props[u])return!0;for(var o in this.props)if(!(o in n))return!0;return!1},Object.defineProperty(n,"Signal",{enumerable:!0,get:function(){return t.Signal}}),Object.defineProperty(n,"batch",{enumerable:!0,get:function(){return t.batch}}),Object.defineProperty(n,"computed",{enumerable:!0,get:function(){return t.computed}}),Object.defineProperty(n,"effect",{enumerable:!0,get:function(){return t.effect}}),Object.defineProperty(n,"signal",{enumerable:!0,get:function(){return t.signal}}),n.useComputed=function(n){var e=r.useRef(n);return e.current=n,a.add(i),r.useMemo(function(){return t.computed(function(){return e.current()})},[])},n.useSignal=g});
2
- //# sourceMappingURL=signals.min.js.map
1
+ !function(n,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("preact"),require("preact/hooks"),require("@preact/signals-core")):"function"==typeof define&&define.amd?define(["exports","preact","preact/hooks","@preact/signals-core"],r):r((n||self).preactSignals={},n.preact,n.hooks,n.signalsCore)}(this,function(n,r,t,i){var e,o,f,u=new WeakSet,a=new WeakSet,c=new WeakSet;function v(n,t){r.options[n]=t.bind(null,r.options[n]||function(){})}var s=new WeakMap;function l(n){f&&f(!0,!0),o=n,f=n&&n._()}function p(n){var r=i.signal(void 0);return r._u=n,r}function d(n){var r=this,e=n.data,f=h(e);f.value=e;var u=t.useMemo(function(){for(var n=r.__v;n=n.__;)if(n.__c){c.add(n.__c);break}return o._u=function(){r.base.data=u._v},i.computed(function(){var n=f.value.value;return 0===n?0:!0===n?"":n||""})},[]);return u.value}function _(n){var r={__proto__:null},t=p(function(e){var o=t.__;for(var f in o)if("children"!==f){var u=o[f];if(u instanceof i.Signal){var a=u.value,c=r[f];r[f]=a,!0===e||c===a||(f in n?n[f]=a:a?n.setAttribute(f,a):n.removeAttribute(f))}}});return t}function h(n){return t.useMemo(function(){return i.signal(n)},[])}d.displayName="_st",Object.defineProperties(i.Signal.prototype,{constructor:{configurable:!0},type:{configurable:!0,value:d},props:{configurable:!0,get:function(){return{data:this}}},__b:{configurable:!0,value:1}}),v("__b",function(n,r){if("string"==typeof r.type){var t,e=r.props;for(var o in e)if("children"!==o){var f=e[o];f instanceof i.Signal&&(t||(r.__np=t={}),t[o]=f,e[o]=f.peek())}}n(r)}),v("__r",function(n,r){var t,i=r.__c;i&&(u.delete(i),void 0===(t=s.get(i))&&(t=p(function(){u.add(i),i.setState({})}),s.set(i,t))),e=i,l(t),n(r)}),v("__e",function(n,r,t,i){l(),e=void 0,n(r,t,i)}),v("diffed",function(n,r){var t,i;if(l(),e=void 0,"string"==typeof r.type&&(t=r.__e)){var o=r.__np;o&&((i=t._u)||(i=_(t),t._u=i),i.__=o,l(i),i._u(!0))}n(r)}),v("unmount",function(n,r){var t=r.__c,i=t&&s.get(t);if(i&&(s.delete(t),i._()(!0,!0)),"string"==typeof r.type){var e=r.__e,o=e._u;o&&(o._()(!0,!0),e._u=null)}n(r)}),v("__h",function(n,r,t,i){i<3&&a.add(r),n(r,t,i)}),r.Component.prototype.shouldComponentUpdate=function(n,r){var t,i=s.get(this);if(!(i&&0!==(null==(t=i._d)?void 0:t.size)||c.has(this)))return!0;if(u.has(this))return!0;if(a.has(this))return!0;for(var e in r)return!0;for(var o in n)if("__source"!==o&&n[o]!==this.props[o])return!0;for(var f in this.props)if(!(f in n))return!0;return!1},n.Signal=i.Signal,n.batch=i.batch,n.computed=i.computed,n.effect=i.effect,n.signal=i.signal,n.useComputed=function(n){var r=t.useRef(n);return r.current=n,c.add(e),t.useMemo(function(){return i.computed(function(){return r.current()})},[])},n.useSignal=h});//# sourceMappingURL=signals.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.min.js","sources":["../src/index.ts"],"sourcesContent":["import { options, Component, createElement } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._canActivate = true;\n\ts._updater = updater;\n\treturn s;\n}\n\n// Get a (cached) Signal property updater for an element VNode\nfunction getElementUpdater(vnode: VNode) {\n\tlet updater = updaterForComponent.get(vnode) as ElementUpdater;\n\tif (!updater) {\n\t\tlet signalProps: Array<{ _key: string; _signal: Signal }> = [];\n\t\tupdater = createUpdater(() => {\n\t\t\tlet dom = vnode.__e as Element;\n\n\t\t\tfor (let i = 0; i < signalProps.length; i++) {\n\t\t\t\tlet { _key: prop, _signal: signal } = signalProps[i];\n\t\t\t\tlet value = signal._value;\n\t\t\t\tif (!dom) return;\n\t\t\t\tif (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}) as ElementUpdater;\n\t\tupdater._props = signalProps;\n\t\tupdaterForComponent.set(vnode, updater);\n\t} else {\n\t\tupdater._props.length = 0;\n\t}\n\treturn updater;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/** Convert Signals within (nested) props.children into Text components */\nfunction childToSignal<T>(child: any, i: keyof T, arr: T) {\n\tif (typeof child !== \"object\" || child == null) {\n\t\t// can't be a signal\n\t} else if (Array.isArray(child)) {\n\t\tchild.forEach(childToSignal);\n\t} else if (child instanceof Signal) {\n\t\t// @ts-ignore-next-line yes, arr can accept VNodes:\n\t\tarr[i] = createElement(Text, { data: child });\n\t}\n}\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\t// let orig = vnode.__o || vnode;\n\t\tlet props = vnode.props;\n\t\tlet updater;\n\n\t\tfor (let i in props) {\n\t\t\tlet value = props[i];\n\t\t\tif (i === \"children\") {\n\t\t\t\tchildToSignal(value, \"children\", props);\n\t\t\t} else if (value instanceof Signal) {\n\t\t\t\t// first Signal prop triggers creation/cleanup of the updater:\n\t\t\t\tif (!updater) updater = getElementUpdater(vnode);\n\t\t\t\t// track which props are Signals for precise updates:\n\t\t\t\tupdater._props.push({ _key: i, _signal: value });\n\t\t\t\tlet newUpdater = updater._updater;\n\t\t\t\tif (value._updater) {\n\t\t\t\t\tlet oldUpdater = value._updater;\n\t\t\t\t\tvalue._updater = () => {\n\t\t\t\t\t\tnewUpdater();\n\t\t\t\t\t\toldUpdater();\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tvalue._updater = newUpdater;\n\t\t\t\t}\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\n\t\tsetCurrentUpdater(updater);\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(vnode);\n});\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet thing = vnode.__c || vnode;\n\tconst updater = updaterForComponent.get(thing);\n\tif (updater) {\n\t\tupdaterForComponent.delete(thing);\n\t\tconst signals = updater._deps;\n\t\tif (signals) {\n\t\t\tsignals.forEach(signal => signal._subs.delete(updater));\n\t\t\tsignals.clear();\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["currentComponent","finishUpdate","hasPendingUpdate","WeakSet","hasComputeds","hook","hookName","hookFn","options","bind","updaterForComponent","setCurrentUpdater","updater","currentUpdater","_setCurrent","createUpdater","s","signal","undefined","_canActivate","_updater","getElementUpdater","vnode","get","_props","length","signalProps","dom","__e","i","prop","_key","_signal","_value","value","setAttribute","removeAttribute","set","childToSignal","child","arr","Array","isArray","forEach","Signal","createElement","Text","data","_ref","_this","this","currentSignal","useSignal","useMemo","v","__v","__","__c","add","base","computed","displayName","old","type","props","push","newUpdater","oldUpdater","peek","component","setState","error","oldVNode","thing","signals","_deps","_subs","clear","index","hasHookState","Component","prototype","shouldComponentUpdate","state","_updater$_deps","size","has","_i","_i2","useComputed","compute","$compute","useRef","current"],"mappings":"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"}
1
+ {"version":3,"file":"signals.min.js","sources":["../src/index.ts"],"sourcesContent":["import { options, Component } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._updater = updater;\n\treturn s;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\nObject.defineProperties(Signal.prototype, {\n\tconstructor: { configurable: true },\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\t// Setting a VNode's _depth to 1 forces Preact to clone it before modifying:\n\t// https://github.com/preactjs/preact/blob/d7a433ee8463a7dc23a05111bb47de9ec729ad4d/src/diff/children.js#L77\n\t// @todo remove this for Preact 11\n\t__b: { configurable: true, value: 1 },\n});\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\tlet signalProps: Record<string, any> | undefined;\n\n\t\tlet props = vnode.props;\n\t\tfor (let i in props) {\n\t\t\tif (i === \"children\") continue;\n\n\t\t\tlet value = props[i];\n\t\t\tif (value instanceof Signal) {\n\t\t\t\tif (!signalProps) vnode.__np = signalProps = {};\n\t\t\t\tsignalProps[i] = value;\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\n\tlet dom: Element;\n\tlet updater: ElementUpdater;\n\n\t// vnode._dom is undefined during string rendering,\n\t// so we use this to skip prop subscriptions during SSR.\n\tif (typeof vnode.type === \"string\" && (dom = vnode.__e as Element)) {\n\t\tlet props = vnode.__np;\n\t\tif (props) {\n\t\t\t// @ts-ignore-next\n\t\t\tupdater = dom._updater;\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createElementUpdater(dom);\n\t\t\t\t// @ts-ignore-next\n\t\t\t\tdom._updater = updater;\n\t\t\t}\n\t\t\tupdater!._props = props;\n\t\t\tsetCurrentUpdater(updater);\n\t\t\t// @ts-ignore-next we're adding an argument here\n\t\t\tupdater._updater(true);\n\t\t}\n\t}\n\told(vnode);\n});\n\n// per-element updater for 1+ signal bindings\nfunction createElementUpdater(dom: Element) {\n\tconst cache: Record<string, any> = { __proto__: null };\n\tconst updater = createUpdater((skip?: boolean) => {\n\t\tconst props = updater._props;\n\t\tfor (let prop in props) {\n\t\t\tif (prop === \"children\") continue;\n\t\t\tlet signal = props[prop];\n\t\t\tif (signal instanceof Signal) {\n\t\t\t\tlet value = signal.value;\n\t\t\t\tlet cached = cache[prop];\n\t\t\t\tcache[prop] = value;\n\t\t\t\tif (skip === true || cached === value) {\n\t\t\t\t\t// this is just a subscribe run, not an update\n\t\t\t\t} else if (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}) as ElementUpdater;\n\treturn updater;\n}\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet component = vnode.__c;\n\tconst updater = component && updaterForComponent.get(component);\n\tif (updater) {\n\t\tupdaterForComponent.delete(component);\n\t\tupdater._setCurrent()(true, true);\n\t}\n\n\tif (typeof vnode.type === \"string\") {\n\t\tconst dom = vnode.__e as Element;\n\n\t\t// @ts-ignore-next\n\t\tconst updater = dom._updater;\n\t\tif (updater) {\n\t\t\tupdater._setCurrent()(true, true);\n\t\t\t// @ts-ignore-next\n\t\t\tdom._updater = null;\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\t// @ts-ignore\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["g","f","exports","module","require","define","amd","globalThis","self","preactSignals","preact","hooks","signalsCore","this","currentComponent","currentUpdater","hasPendingUpdate","WeakSet","hasHookState","hasComputeds","hookName","hookFn","options","bind","updaterForComponent","WeakMap","updater","finishUpdate","_setCurrent","createUpdater","signal","undefined","s","_updater","_ref","_this","data","currentSignal","useSignal","value","useMemo","v","__v","__","__c","add","base","_value","computed","createElementUpdater","dom","cache","__proto__","skip","props","_props","prop","_signal","cached","setAttribute","removeAttribute","Text","displayName","Object","defineProperties","Signal","prototype","constructor","configurable","type","get","__b","hook","old","vnode","signalProps","i","__np","peek","component","setState","set","setCurrentUpdater","error","oldVNode","__e","index","Component","shouldComponentUpdate","state","_updater$_deps","_deps","size","has","batch","effect","useComputed","compute","$compute","useRef","current"],"mappings":"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"}
package/dist/signals.mjs CHANGED
@@ -1,2 +1 @@
1
- import{Component as t,options as e,createElement as n}from"preact";import{useMemo as r,useRef as i}from"preact/hooks";import{Signal as o,signal as f,computed as l}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";const c=new WeakSet,s=new WeakSet,u=new WeakSet;function a(t,n){e[t]=n.bind(null,e[t]||(()=>{}))}let _,h,p;const d=new WeakMap;function m(t){p&&p(!0,!0),h=t,p=t&&t._()}function k(t){const e=f(void 0);return e._c=!0,e._u=t,e}function g(t){let e=d.get(t);if(e)e.__.length=0;else{let n=[];e=k(()=>{let e=t.__e;for(let t=0;t<n.length;t++){let{t:r,i}=n[t],o=i._v;if(!e)return;r in e?e[r]=o:o?e.setAttribute(r,o):e.removeAttribute(r)}}),e.__=n,d.set(t,e)}return e}function v(t,e,r){"object"!=typeof t||null==t||(Array.isArray(t)?t.forEach(v):t instanceof o&&(r[e]=n(y,{data:t})))}function y({data:t}){const e=b(t);e.value=t;const n=r(()=>{let t=this.__v;for(;t=t.__;)if(t.__c){u.add(t.__c);break}return h._u=()=>{this.base.data=n._v},l(()=>{let t=e.value.value;return 0===t?0:!0===t?"":t||""})},[]);return n.value}function b(t){return r(()=>f(t),[])}function w(t){const e=i(t);return e.current=t,u.add(_),r(()=>l(()=>e.current()),[])}y.displayName="_st",a("__b",(t,e)=>{if("string"==typeof e.type){let t,n=e.props;for(let r in n){let i=n[r];if("children"===r)v(i,"children",n);else if(i instanceof o){t||(t=g(e)),t.__.push({t:r,i});let o=t._u;if(i._u){let t=i._u;i._u=()=>{o(),t()}}else i._u=o;n[r]=i.peek()}}m(t)}t(e)}),a("__r",(t,e)=>{let n,r=e.__c;r&&(c.delete(r),n=d.get(r),void 0===n&&(n=k(()=>{c.add(r),r.setState({})}),d.set(r,n))),_=r,m(n),t(e)}),a("__e",(t,e,n,r)=>{m(),_=void 0,t(e,n,r)}),a("diffed",(t,e)=>{m(),_=void 0,t(e)}),a("unmount",(t,e)=>{let n=e.__c||e;const r=d.get(n);if(r){d.delete(n);const t=r._d;t&&(t.forEach(t=>t._s.delete(r)),t.clear())}t(e)}),a("__h",(t,e,n,r)=>{r<3&&s.add(e),t(e,n,r)}),t.prototype.shouldComponentUpdate=function(t,e){var n;const r=d.get(this);if(!(r&&0!==(null==(n=r._d)?void 0:n.size)||u.has(this)))return!0;if(c.has(this))return!0;if(s.has(this))return!0;for(let t in e)return!0;for(let e in t)if("__source"!==e&&t[e]!==this.props[e])return!0;for(let e in this.props)if(!(e in t))return!0;return!1};export{w as useComputed,b as useSignal};
2
- //# sourceMappingURL=signals.mjs.map
1
+ import{Component as t,options as n}from"preact";import{useMemo as e,useRef as r}from"preact/hooks";import{Signal as i,computed as o,signal as f}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";const c=new WeakSet,u=new WeakSet,l=new WeakSet;function s(t,e){n[t]=e.bind(null,n[t]||(()=>{}))}let a,p,_;const h=new WeakMap;function d(t){_&&_(!0,!0),p=t,_=t&&t._()}function g(t){const n=f(void 0);return n._u=t,n}function b({data:t}){const n=v(t);n.value=t;const r=e(()=>{let t=this.__v;for(;t=t.__;)if(t.__c){l.add(t.__c);break}return p._u=()=>{this.base.data=r._v},o(()=>{let t=n.value.value;return 0===t?0:!0===t?"":t||""})},[]);return r.value}function m(t){const n={__proto__:null},e=g(r=>{const o=e.__;for(let e in o){if("children"===e)continue;let f=o[e];if(f instanceof i){let i=f.value,o=n[e];n[e]=i,!0===r||o===i||(e in t?t[e]=i:i?t.setAttribute(e,i):t.removeAttribute(e))}}});return e}function v(t){return e(()=>f(t),[])}function k(t){const n=r(t);return n.current=t,l.add(a),e(()=>o(()=>n.current()),[])}b.displayName="_st",Object.defineProperties(i.prototype,{constructor:{configurable:!0},type:{configurable:!0,value:b},props:{configurable:!0,get(){return{data:this}}},__b:{configurable:!0,value:1}}),s("__b",(t,n)=>{if("string"==typeof n.type){let t,e=n.props;for(let r in e){if("children"===r)continue;let o=e[r];o instanceof i&&(t||(n.__np=t={}),t[r]=o,e[r]=o.peek())}}t(n)}),s("__r",(t,n)=>{let e,r=n.__c;r&&(c.delete(r),e=h.get(r),void 0===e&&(e=g(()=>{c.add(r),r.setState({})}),h.set(r,e))),a=r,d(e),t(n)}),s("__e",(t,n,e,r)=>{d(),a=void 0,t(n,e,r)}),s("diffed",(t,n)=>{let e,r;if(d(),a=void 0,"string"==typeof n.type&&(e=n.__e)){let t=n.__np;t&&(r=e._u,r||(r=m(e),e._u=r),r.__=t,d(r),r._u(!0))}t(n)}),s("unmount",(t,n)=>{let e=n.__c;const r=e&&h.get(e);if(r&&(h.delete(e),r._()(!0,!0)),"string"==typeof n.type){const t=n.__e,e=t._u;e&&(e._()(!0,!0),t._u=null)}t(n)}),s("__h",(t,n,e,r)=>{r<3&&u.add(n),t(n,e,r)}),t.prototype.shouldComponentUpdate=function(t,n){var e;const r=h.get(this);if(!(r&&0!==(null==(e=r._d)?void 0:e.size)||l.has(this)))return!0;if(c.has(this))return!0;if(u.has(this))return!0;for(let t in n)return!0;for(let n in t)if("__source"!==n&&t[n]!==this.props[n])return!0;for(let n in this.props)if(!(n in t))return!0;return!1};export{k as useComputed,v as useSignal};//# sourceMappingURL=signals.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.mjs","sources":["../src/index.ts"],"sourcesContent":["import { options, Component, createElement } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._canActivate = true;\n\ts._updater = updater;\n\treturn s;\n}\n\n// Get a (cached) Signal property updater for an element VNode\nfunction getElementUpdater(vnode: VNode) {\n\tlet updater = updaterForComponent.get(vnode) as ElementUpdater;\n\tif (!updater) {\n\t\tlet signalProps: Array<{ _key: string; _signal: Signal }> = [];\n\t\tupdater = createUpdater(() => {\n\t\t\tlet dom = vnode.__e as Element;\n\n\t\t\tfor (let i = 0; i < signalProps.length; i++) {\n\t\t\t\tlet { _key: prop, _signal: signal } = signalProps[i];\n\t\t\t\tlet value = signal._value;\n\t\t\t\tif (!dom) return;\n\t\t\t\tif (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}) as ElementUpdater;\n\t\tupdater._props = signalProps;\n\t\tupdaterForComponent.set(vnode, updater);\n\t} else {\n\t\tupdater._props.length = 0;\n\t}\n\treturn updater;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/** Convert Signals within (nested) props.children into Text components */\nfunction childToSignal<T>(child: any, i: keyof T, arr: T) {\n\tif (typeof child !== \"object\" || child == null) {\n\t\t// can't be a signal\n\t} else if (Array.isArray(child)) {\n\t\tchild.forEach(childToSignal);\n\t} else if (child instanceof Signal) {\n\t\t// @ts-ignore-next-line yes, arr can accept VNodes:\n\t\tarr[i] = createElement(Text, { data: child });\n\t}\n}\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\t// let orig = vnode.__o || vnode;\n\t\tlet props = vnode.props;\n\t\tlet updater;\n\n\t\tfor (let i in props) {\n\t\t\tlet value = props[i];\n\t\t\tif (i === \"children\") {\n\t\t\t\tchildToSignal(value, \"children\", props);\n\t\t\t} else if (value instanceof Signal) {\n\t\t\t\t// first Signal prop triggers creation/cleanup of the updater:\n\t\t\t\tif (!updater) updater = getElementUpdater(vnode);\n\t\t\t\t// track which props are Signals for precise updates:\n\t\t\t\tupdater._props.push({ _key: i, _signal: value });\n\t\t\t\tlet newUpdater = updater._updater;\n\t\t\t\tif (value._updater) {\n\t\t\t\t\tlet oldUpdater = value._updater;\n\t\t\t\t\tvalue._updater = () => {\n\t\t\t\t\t\tnewUpdater();\n\t\t\t\t\t\toldUpdater();\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tvalue._updater = newUpdater;\n\t\t\t\t}\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\n\t\tsetCurrentUpdater(updater);\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(vnode);\n});\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet thing = vnode.__c || vnode;\n\tconst updater = updaterForComponent.get(thing);\n\tif (updater) {\n\t\tupdaterForComponent.delete(thing);\n\t\tconst signals = updater._deps;\n\t\tif (signals) {\n\t\t\tsignals.forEach(signal => signal._subs.delete(updater));\n\t\t\tsignals.clear();\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["hasPendingUpdate","WeakSet","hasComputeds","hook","hookName","hookFn","options","bind","currentComponent","currentUpdater","finishUpdate","updaterForComponent","WeakMap","setCurrentUpdater","updater","_setCurrent","createUpdater","s","signal","undefined","_canActivate","_updater","getElementUpdater","vnode","get","_props","length","signalProps","__e","i","_key","prop","_signal","value","_value","dom","setAttribute","removeAttribute","set","childToSignal","child","arr","Array","isArray","forEach","Signal","createElement","Text","data","currentSignal","useSignal","useMemo","v","this","__v","__","__c","add","base","computed","useComputed","compute","$compute","useRef","current","displayName","old","type","props","push","newUpdater","oldUpdater","peek","component","delete","setState","error","oldVNode","thing","signals","_deps","_subs","clear","index","hasHookState","Component","prototype","shouldComponentUpdate","state","_updater$_deps","size","has"],"mappings":"oQAsBA,MAAsBA,EAAG,IAAIC,UAGR,IAArBA,QAGMC,EAAe,YAGrB,SAAAC,EAAsCC,EAAaC,GAElDC,EAAQF,GAAYC,EAAOE,KAAK,KAAMD,EAAQF,IAAc,MAAtB,GACtC,CAED,IAAAI,EACIC,EACJC,EACA,MAAMC,EAAsB,IAAIC,QAEhC,SAAAC,EAA2BC,GAEtBJ,GAAcA,GAAa,GAAM,GAErCD,EAAiBK,EACjBJ,EAAeI,GAAWA,EAAQC,GAClC,CAED,SAASC,EAAcF,GACtB,MAAOG,EAAGC,OAAOC,GAGjB,OAFAF,EAAEG,IAAe,EACjBH,EAAEI,GAAWP,EACNG,CACP,CAGD,SAAAK,EAA2BC,GAC1B,MAAcZ,EAAoBa,IAAID,GACtC,GAAKT,EAsBJA,EAAQW,GAAOC,OAAS,MAtBX,CACb,IAAeC,EAA6C,GAC5Db,EAAUE,EAAc,KACvB,MAAUO,EAAMK,IAEhB,IAAK,IAAIC,EAAI,EAAGA,EAAIF,EAAYD,OAAQG,IAAK,CAC5C,IAAMC,EAAMC,EAAMC,GAAoBL,EAAYE,GACzCI,EAAGf,EAAOgB,GACnB,IAAKC,EAAK,OACNJ,KAAQI,EAEXA,EAAIJ,GAAQE,EACFA,EACVE,EAAIC,aAAaL,EAAME,GAEvBE,EAAIE,gBAAgBN,EAErB,IAEFjB,EAAQW,GAASE,EACjBhB,EAAoB2B,IAAIf,EAAOT,EAC/B,CAGD,OAAOA,CACP,CAYD,SAAAyB,EAA0BC,EAAYX,EAAYY,GAC5B,iBAAVD,GAA+B,MAATA,IAEtBE,MAAMC,QAAQH,GACxBA,EAAMI,QAAQL,GACJC,aAAiBK,IAE3BJ,EAAIZ,GAAKiB,EAAcC,EAAM,CAAEC,KAAMR,KAEtC,CAMD,SAAAO,GAAmCC,KAAEA,IAKpC,MAAMC,EAAgBC,EAAUF,GAChCC,EAAchB,MAAQe,EAEtB,MAAO/B,EAAGkC,EAAQ,KAEjB,IAAKC,EAAGC,KAAKC,IACb,KAAQF,EAAIA,EAAEG,IACb,GAAIH,EAAEI,IAAK,CACVtD,EAAauD,IAAIL,EAAEI,KACnB,KACA,CAQF,OAJA/C,EAAgBY,GAAW,KACzBgC,KAAKK,KAAcV,KAAO/B,EAAEiB,EAAAA,EAGfyB,EAAC,KACf,MAAWV,EAAchB,MACZA,MACb,OAAa,IAALhB,EAAS,GAAU,IAANA,EAAa,GAAKA,GAAK,IAH9B,EAKb,IAEH,OAAOA,EAAEgB,KACT,CAqJK,SAAAiB,EAAuBjB,GAC5B,OAAOkB,EAAQ,IAAMjC,EAAUe,GAAQ,GACvC,CAEe2B,SAAAA,EAAeC,GAC9B,MAAcC,EAAGC,EAAOF,GAGxB,OAFAC,EAASE,QAAUH,EACnB3D,EAAauD,IAAIjD,GACV2C,EAAQ,IAAMQ,EAAY,IAAMG,EAASE,WAAY,GAC5D,CA7JDjB,EAAKkB,YAAc,MAGnB9D,QAAwB,CAAC+D,EAAK3C,KAC7B,GAA0B,iBAAfA,EAAM4C,KAAmB,CAEnC,IACIrD,EADKsD,EAAG7C,EAAM6C,MAGlB,IAAK,IAALvC,KAAAuC,EAAqB,CACpB,IAASnC,EAAGmC,EAAMvC,GAClB,GAAU,aAANA,EACHU,EAAcN,EAAO,WAAYmC,QAC3B,GAAInC,aAAJY,EAA6B,CAE9B/B,IAASA,EAAUQ,EAAkBC,IAE1CT,EAAQW,GAAO4C,KAAK,CAAEvC,EAAMD,EAAGG,IAC/B,IAAIsC,EAAaxD,EAAQO,GACzB,GAAIY,EAAMZ,GAAU,CACnB,IAAIkD,EAAatC,EAAMZ,GACvBY,EAAMZ,GAAW,KAChBiD,IACAC,GACA,CACD,MACAtC,EAAMZ,GAAWiD,EAElBF,EAAMvC,GAAKI,EAAMuC,MACjB,CACD,CAED3D,EAAkBC,EAClB,CAEDoD,EAAI3C,EACJ,GAGDpB,QAA0B,CAAC+D,EAAK3C,KAC/B,IAAAT,EAEa2D,EAAGlD,EAAMiC,IAClBiB,IACHzE,EAAiB0E,OAAOD,GAExB3D,EAAUH,EAAoBa,IAAIiD,QAClBtD,IAAZL,IACHA,EAAUE,EAAc,KACvBhB,EAAiByD,IAAIgB,GACrBA,EAAUE,SAAS,CAAnB,EAAA,GAEDhE,EAAoB2B,IAAImC,EAAW3D,KAIrCN,EAAmBiE,EACnB5D,EAAkBC,GAClBoD,EAAI3C,EACJ,GAGDpB,EAAI,MAA2B,CAAC+D,EAAKU,EAAOrD,EAAOsD,KAClDhE,IACAL,OAAmBW,EACnB+C,EAAIU,EAAOrD,EAAOsD,EAClB,GAGD1E,WAA0B,CAAC+D,EAAK3C,KAC/BV,IACAL,OAAmBW,EACnB+C,EAAI3C,EACJ,GAGDpB,YAA2B,CAAC+D,EAAK3C,KAChC,IAASuD,EAAGvD,EAAMiC,KAAOjC,EACzB,MAAaT,EAAGH,EAAoBa,IAAIsD,GACxC,GAAIhE,EAAS,CACZH,EAAoB+D,OAAOI,GAC3B,MAAMC,EAAUjE,EAAQkE,GACpBD,IACHA,EAAQnC,QAAQ1B,GAAUA,EAAO+D,GAAMP,OAAO5D,IAC9CiE,EAAQG,QAET,CACDhB,EAAI3C,EAAD,GAIJpB,EAAI,MAAoB,CAAC+D,EAAKO,EAAWU,EAAOhB,KAC3CA,EAAO,GAAGiB,EAAa3B,IAAIgB,GAC/BP,EAAIO,EAAWU,EAAOhB,KAOvBkB,EAAUC,UAAUC,sBAAwB,SAAUnB,EAAOoB,GAAK,IAAAC,EAEjE,MAAM3E,EAAUH,EAAoBa,IAAI6B,MA2BxC,KAzBmBvC,GAAmC,YAAxBA,EAAAA,EAAQkE,aAAOU,OAyBzBxF,EAAayF,IAAItC,OAAO,SAG5C,GAAIrD,EAAiB2F,IAAItC,MAAO,OAAA,EAGhC,GAAI+B,EAAaO,IAAItC,MAAO,OAAA,EAC5B,IAAK,IAALxB,KAAA2D,EAAqB,OAAO,EAG5B,IAAK,IAAL3D,KAAAuC,EACC,GAAU,aAANvC,GAAoBuC,EAAMvC,KAAOwB,KAAKe,MAAMvC,GAAI,OAAO,EAE5D,IAAK,IAALA,KAAmBuC,KAAAA,MAAO,KAAMvC,KAAFuC,GAAe,OAAA,EAG7C,OAAO,CACP"}
1
+ {"version":3,"file":"signals.mjs","sources":["../src/index.ts"],"sourcesContent":["import { options, Component } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._updater = updater;\n\treturn s;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\nObject.defineProperties(Signal.prototype, {\n\tconstructor: { configurable: true },\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\t// Setting a VNode's _depth to 1 forces Preact to clone it before modifying:\n\t// https://github.com/preactjs/preact/blob/d7a433ee8463a7dc23a05111bb47de9ec729ad4d/src/diff/children.js#L77\n\t// @todo remove this for Preact 11\n\t__b: { configurable: true, value: 1 },\n});\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\tlet signalProps: Record<string, any> | undefined;\n\n\t\tlet props = vnode.props;\n\t\tfor (let i in props) {\n\t\t\tif (i === \"children\") continue;\n\n\t\t\tlet value = props[i];\n\t\t\tif (value instanceof Signal) {\n\t\t\t\tif (!signalProps) vnode.__np = signalProps = {};\n\t\t\t\tsignalProps[i] = value;\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\n\tlet dom: Element;\n\tlet updater: ElementUpdater;\n\n\t// vnode._dom is undefined during string rendering,\n\t// so we use this to skip prop subscriptions during SSR.\n\tif (typeof vnode.type === \"string\" && (dom = vnode.__e as Element)) {\n\t\tlet props = vnode.__np;\n\t\tif (props) {\n\t\t\t// @ts-ignore-next\n\t\t\tupdater = dom._updater;\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createElementUpdater(dom);\n\t\t\t\t// @ts-ignore-next\n\t\t\t\tdom._updater = updater;\n\t\t\t}\n\t\t\tupdater!._props = props;\n\t\t\tsetCurrentUpdater(updater);\n\t\t\t// @ts-ignore-next we're adding an argument here\n\t\t\tupdater._updater(true);\n\t\t}\n\t}\n\told(vnode);\n});\n\n// per-element updater for 1+ signal bindings\nfunction createElementUpdater(dom: Element) {\n\tconst cache: Record<string, any> = { __proto__: null };\n\tconst updater = createUpdater((skip?: boolean) => {\n\t\tconst props = updater._props;\n\t\tfor (let prop in props) {\n\t\t\tif (prop === \"children\") continue;\n\t\t\tlet signal = props[prop];\n\t\t\tif (signal instanceof Signal) {\n\t\t\t\tlet value = signal.value;\n\t\t\t\tlet cached = cache[prop];\n\t\t\t\tcache[prop] = value;\n\t\t\t\tif (skip === true || cached === value) {\n\t\t\t\t\t// this is just a subscribe run, not an update\n\t\t\t\t} else if (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}) as ElementUpdater;\n\treturn updater;\n}\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet component = vnode.__c;\n\tconst updater = component && updaterForComponent.get(component);\n\tif (updater) {\n\t\tupdaterForComponent.delete(component);\n\t\tupdater._setCurrent()(true, true);\n\t}\n\n\tif (typeof vnode.type === \"string\") {\n\t\tconst dom = vnode.__e as Element;\n\n\t\t// @ts-ignore-next\n\t\tconst updater = dom._updater;\n\t\tif (updater) {\n\t\t\tupdater._setCurrent()(true, true);\n\t\t\t// @ts-ignore-next\n\t\t\tdom._updater = null;\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\t// @ts-ignore\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["Component","options","useMemo","useRef","Signal","computed","signal","batch","effect","hasPendingUpdate","WeakSet","hasHookState","hasComputeds","hook","hookName","hookFn","bind","currentComponent","currentUpdater","finishUpdate","updaterForComponent","WeakMap","setCurrentUpdater","updater","_setCurrent","createUpdater","s","undefined","_updater","Text","data","currentSignal","useSignal","value","v","this","__v","__","__c","add","base","_value","dom","cache","__proto__","skip","props","_props","prop","cached","setAttribute","removeAttribute","useComputed","compute","$compute","current","displayName","Object","defineProperties","prototype","constructor","configurable","type","get","__b","old","vnode","signalProps","i","__np","peek","component","delete","setState","set","error","oldVNode","__e","createElementUpdater","index","shouldComponentUpdate","state","_updater$_deps","size","_deps","has"],"mappings":"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"}
@@ -1,2 +1 @@
1
- import{Component as n,options as r,createElement as t}from"preact";import{useMemo as i,useRef as o}from"preact/hooks";import{Signal as e,signal as f,computed as u}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";var a,c,v,s=new WeakSet,l=new WeakSet,p=new WeakSet;function _(n,t){r[n]=t.bind(null,r[n]||function(){})}var h=new WeakMap;function d(n){v&&v(!0,!0),c=n,v=n&&n._()}function m(n){var r=f(void 0);return r._c=!0,r._u=n,r}function k(n){var r=h.get(n);if(r)r.__.length=0;else{var t=[];(r=m(function(){for(var r=n.__e,i=0;i<t.length;i++){var o=t[i],e=o.t,f=o.i._v;if(!r)return;e in r?r[e]=f:f?r.setAttribute(e,f):r.removeAttribute(e)}})).__=t,h.set(n,r)}return r}function g(n,r,i){"object"!=typeof n||null==n||(Array.isArray(n)?n.forEach(g):n instanceof e&&(i[r]=t(b,{data:n})))}function b(n){var r=this,t=n.data,o=w(t);o.value=t;var e=i(function(){for(var n=r.__v;n=n.__;)if(n.__c){p.add(n.__c);break}return c._u=function(){r.base.data=e._v},u(function(){var n=o.value.value;return 0===n?0:!0===n?"":n||""})},[]);return e.value}function w(n){return i(function(){return f(n)},[])}function y(n){var r=o(n);return r.current=n,p.add(a),i(function(){return u(function(){return r.current()})},[])}b.displayName="_st",_("__b",function(n,r){if("string"==typeof r.type){var t,i=r.props;for(var o in i){var f=i[o];"children"===o?g(f,"children",i):f instanceof e&&function(){t||(t=k(r)),t.__.push({t:o,i:f});var n=t._u;if(f._u){var e=f._u;f._u=function(){n(),e()}}else f._u=n;i[o]=f.peek()}()}d(t)}n(r)}),_("__r",function(n,r){var t,i=r.__c;i&&(s.delete(i),void 0===(t=h.get(i))&&(t=m(function(){s.add(i),i.setState({})}),h.set(i,t))),a=i,d(t),n(r)}),_("__e",function(n,r,t,i){d(),a=void 0,n(r,t,i)}),_("diffed",function(n,r){d(),a=void 0,n(r)}),_("unmount",function(n,r){var t=r.__c||r,i=h.get(t);if(i){h.delete(t);var o=i._d;o&&(o.forEach(function(n){return n._s.delete(i)}),o.clear())}n(r)}),_("__h",function(n,r,t,i){i<3&&l.add(r),n(r,t,i)}),n.prototype.shouldComponentUpdate=function(n,r){var t,i=h.get(this);if(!(i&&0!==(null==(t=i._d)?void 0:t.size)||p.has(this)))return!0;if(s.has(this))return!0;if(l.has(this))return!0;for(var o in r)return!0;for(var e in n)if("__source"!==e&&n[e]!==this.props[e])return!0;for(var f in this.props)if(!(f in n))return!0;return!1};export{y as useComputed,w as useSignal};
2
- //# sourceMappingURL=signals.module.js.map
1
+ import{Component as n,options as r}from"preact";import{useMemo as t,useRef as i}from"preact/hooks";import{Signal as o,computed as e,signal as f}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";var u,a,c,v=new WeakSet,s=new WeakSet,l=new WeakSet;function p(n,t){r[n]=t.bind(null,r[n]||function(){})}var _=new WeakMap;function h(n){c&&c(!0,!0),a=n,c=n&&n._()}function g(n){var r=f(void 0);return r._u=n,r}function d(n){var r=this,i=n.data,o=m(i);o.value=i;var f=t(function(){for(var n=r.__v;n=n.__;)if(n.__c){l.add(n.__c);break}return a._u=function(){r.base.data=f._v},e(function(){var n=o.value.value;return 0===n?0:!0===n?"":n||""})},[]);return f.value}function b(n){var r={__proto__:null},t=g(function(i){var e=t.__;for(var f in e)if("children"!==f){var u=e[f];if(u instanceof o){var a=u.value,c=r[f];r[f]=a,!0===i||c===a||(f in n?n[f]=a:a?n.setAttribute(f,a):n.removeAttribute(f))}}});return t}function m(n){return t(function(){return f(n)},[])}function k(n){var r=i(n);return r.current=n,l.add(u),t(function(){return e(function(){return r.current()})},[])}d.displayName="_st",Object.defineProperties(o.prototype,{constructor:{configurable:!0},type:{configurable:!0,value:d},props:{configurable:!0,get:function(){return{data:this}}},__b:{configurable:!0,value:1}}),p("__b",function(n,r){if("string"==typeof r.type){var t,i=r.props;for(var e in i)if("children"!==e){var f=i[e];f instanceof o&&(t||(r.__np=t={}),t[e]=f,i[e]=f.peek())}}n(r)}),p("__r",function(n,r){var t,i=r.__c;i&&(v.delete(i),void 0===(t=_.get(i))&&(t=g(function(){v.add(i),i.setState({})}),_.set(i,t))),u=i,h(t),n(r)}),p("__e",function(n,r,t,i){h(),u=void 0,n(r,t,i)}),p("diffed",function(n,r){var t,i;if(h(),u=void 0,"string"==typeof r.type&&(t=r.__e)){var o=r.__np;o&&((i=t._u)||(i=b(t),t._u=i),i.__=o,h(i),i._u(!0))}n(r)}),p("unmount",function(n,r){var t=r.__c,i=t&&_.get(t);if(i&&(_.delete(t),i._()(!0,!0)),"string"==typeof r.type){var o=r.__e,e=o._u;e&&(e._()(!0,!0),o._u=null)}n(r)}),p("__h",function(n,r,t,i){i<3&&s.add(r),n(r,t,i)}),n.prototype.shouldComponentUpdate=function(n,r){var t,i=_.get(this);if(!(i&&0!==(null==(t=i._d)?void 0:t.size)||l.has(this)))return!0;if(v.has(this))return!0;if(s.has(this))return!0;for(var o in r)return!0;for(var e in n)if("__source"!==e&&n[e]!==this.props[e])return!0;for(var f in this.props)if(!(f in n))return!0;return!1};export{k as useComputed,m as useSignal};//# sourceMappingURL=signals.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.module.js","sources":["../src/index.ts"],"sourcesContent":["import { options, Component, createElement } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._canActivate = true;\n\ts._updater = updater;\n\treturn s;\n}\n\n// Get a (cached) Signal property updater for an element VNode\nfunction getElementUpdater(vnode: VNode) {\n\tlet updater = updaterForComponent.get(vnode) as ElementUpdater;\n\tif (!updater) {\n\t\tlet signalProps: Array<{ _key: string; _signal: Signal }> = [];\n\t\tupdater = createUpdater(() => {\n\t\t\tlet dom = vnode.__e as Element;\n\n\t\t\tfor (let i = 0; i < signalProps.length; i++) {\n\t\t\t\tlet { _key: prop, _signal: signal } = signalProps[i];\n\t\t\t\tlet value = signal._value;\n\t\t\t\tif (!dom) return;\n\t\t\t\tif (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}) as ElementUpdater;\n\t\tupdater._props = signalProps;\n\t\tupdaterForComponent.set(vnode, updater);\n\t} else {\n\t\tupdater._props.length = 0;\n\t}\n\treturn updater;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/** Convert Signals within (nested) props.children into Text components */\nfunction childToSignal<T>(child: any, i: keyof T, arr: T) {\n\tif (typeof child !== \"object\" || child == null) {\n\t\t// can't be a signal\n\t} else if (Array.isArray(child)) {\n\t\tchild.forEach(childToSignal);\n\t} else if (child instanceof Signal) {\n\t\t// @ts-ignore-next-line yes, arr can accept VNodes:\n\t\tarr[i] = createElement(Text, { data: child });\n\t}\n}\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\t// let orig = vnode.__o || vnode;\n\t\tlet props = vnode.props;\n\t\tlet updater;\n\n\t\tfor (let i in props) {\n\t\t\tlet value = props[i];\n\t\t\tif (i === \"children\") {\n\t\t\t\tchildToSignal(value, \"children\", props);\n\t\t\t} else if (value instanceof Signal) {\n\t\t\t\t// first Signal prop triggers creation/cleanup of the updater:\n\t\t\t\tif (!updater) updater = getElementUpdater(vnode);\n\t\t\t\t// track which props are Signals for precise updates:\n\t\t\t\tupdater._props.push({ _key: i, _signal: value });\n\t\t\t\tlet newUpdater = updater._updater;\n\t\t\t\tif (value._updater) {\n\t\t\t\t\tlet oldUpdater = value._updater;\n\t\t\t\t\tvalue._updater = () => {\n\t\t\t\t\t\tnewUpdater();\n\t\t\t\t\t\toldUpdater();\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tvalue._updater = newUpdater;\n\t\t\t\t}\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\n\t\tsetCurrentUpdater(updater);\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(vnode);\n});\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet thing = vnode.__c || vnode;\n\tconst updater = updaterForComponent.get(thing);\n\tif (updater) {\n\t\tupdaterForComponent.delete(thing);\n\t\tconst signals = updater._deps;\n\t\tif (signals) {\n\t\t\tsignals.forEach(signal => signal._subs.delete(updater));\n\t\t\tsignals.clear();\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["currentComponent","finishUpdate","hasPendingUpdate","WeakSet","hasComputeds","hook","hookName","hookFn","options","bind","updaterForComponent","setCurrentUpdater","updater","currentUpdater","_setCurrent","createUpdater","s","signal","undefined","_canActivate","_updater","getElementUpdater","vnode","get","_props","length","signalProps","dom","__e","i","prop","_key","_signal","_value","value","setAttribute","removeAttribute","set","childToSignal","child","arr","Array","isArray","forEach","Signal","createElement","Text","data","_ref","_this","this","currentSignal","useSignal","useMemo","v","__v","__","__c","add","base","computed","useComputed","compute","$compute","useRef","current","displayName","old","type","props","push","newUpdater","oldUpdater","peek","component","setState","error","oldVNode","thing","signals","_deps","_subs","clear","index","hasHookState","Component","prototype","shouldComponentUpdate","state","_updater$_deps","size","has","_i","_i2"],"mappings":"oQAsBA,IAcIA,IAEJC,EAhBsBC,EAAG,IAAIC,UAGR,IAArBA,QAGMC,EAAe,YAGrB,SAAAC,EAAsCC,EAAaC,GAElDC,EAAQF,GAAYC,EAAOE,KAAK,KAAMD,EAAQF,IAAc,WAAO,EACnE,CAKD,IAAMI,EAAsB,YAE5B,SAAAC,EAA2BC,GAEtBX,GAAcA,GAAa,GAAM,GAErCY,EAAiBD,EACjBX,EAAeW,GAAWA,EAAQE,GAClC,CAED,SAASC,EAAcH,GACtB,IAAOI,EAAGC,OAAOC,GAGjB,OAFAF,EAAEG,IAAe,EACjBH,EAAEI,GAAWR,EACNI,CACP,CAGD,SAAAK,EAA2BC,GAC1B,IAAWV,EAAGF,EAAoBa,IAAID,GACtC,GAAKV,EAsBJA,EAAQY,GAAOC,OAAS,MAtBX,CACb,IAAeC,EAA6C,IAC5Dd,EAAUG,EAAc,WAGvB,IAFA,IAAOY,EAAGL,EAAMM,IAEPC,EAAI,EAAGA,EAAIH,EAAYD,OAAQI,IAAK,CAC5C,IAAsCH,EAAAA,EAAYG,GAAtCC,EAANC,EAAAA,IAAYC,EAAAA,EACCC,GACnB,IAAKN,EAAK,OACNG,KAAJH,EAECA,EAAIG,GAAQI,EACFA,EACVP,EAAIQ,aAAaL,EAAMI,GAEvBP,EAAIS,gBAAgBN,EAErB,CACD,IACON,GAASE,EACjBhB,EAAoB2B,IAAIf,EAAOV,EAC/B,CAGD,OAAOA,CACP,CAYD,SAAS0B,EAAiBC,EAAYV,EAAYW,GAC5B,iBAAjBD,GAAsC,MAATA,IAEtBE,MAAMC,QAAQH,GACxBA,EAAMI,QAAQL,GACJC,aAAJK,IAENJ,EAAIX,GAAKgB,EAAcC,EAAM,CAAEC,KAAMR,KAEtC,CAMD,SAASO,EAAoDE,GAAA,IAAAC,EAAAC,KAAAH,EAAAC,EAAxBD,KAKjBI,EAAGC,EAAUL,GAChCI,EAAcjB,MAAQa,EAEtB,MAAUM,EAAQ,WAGjB,IADA,IAAKC,EAAGL,EAAKM,IACLD,EAAIA,EAAEE,IACb,GAAIF,EAAEG,IAAK,CACVrD,EAAasD,IAAIJ,EAAEG,KACnB,KACA,CAQF,OAJA5C,EAAgBO,GAAW,WACzB6B,EAAKU,KAAcZ,KAAO/B,EAAEiB,EAC7B,EAEM2B,EAAS,WACf,IACI5C,EADOmC,EAAcjB,MACZA,MACb,OAAa,IAANlB,EAAU,GAAU,IAANA,EAAa,GAAKA,GAAK,EAC5C,EACD,EAAE,IAEH,OAAQA,EAACkB,KACT,CAqJekB,SAAAA,EAAalB,GAC5B,OAAOmB,EAAQ,WAAMpC,OAAAA,EAAUiB,EAAhB,EAAwB,GACvC,CAEe2B,SAAAA,EAAeC,GAC9B,IAAcC,EAAGC,EAAOF,GAGxB,OAFAC,EAASE,QAAUH,EACnB1D,EAAasD,IAAI1D,GACVqD,EAAQ,WAAA,OAAcO,EAAI,kBAAcG,EAACE,SAAf,EAAlB,EAA6C,GAC5D,CA7JDnB,EAAKoB,YAAc,MAGnB7D,QAAwB,SAAC8D,EAAK7C,GAC7B,GAA0B,iBAAVA,EAAC8C,KAAmB,CAEnC,IACAxD,EADIyD,EAAQ/C,EAAM+C,MAGlB,IAAK,SAASA,EAAO,CACpB,IAAInC,EAAQmC,EAAMxC,GACR,aAANA,EACHS,EAAcJ,EAAO,WAAYmC,GACvBnC,aAAiBU,GAAQ,WAE9BhC,IAASA,EAAUS,EAAkBC,IAE1CV,EAAQY,GAAO8C,KAAK,CAAEvC,EAAMF,EAAGG,EAASE,IACxC,IAAcqC,EAAG3D,EAAQQ,GACzB,GAAIc,EAAMd,GAAU,CACnB,IAAcoD,EAAGtC,EAAMd,GACvBc,EAAMd,GAAW,WAChBmD,IACAC,GACA,CACD,MACAtC,EAAMd,GAAWmD,EAElBF,EAAMxC,GAAKK,EAAMuC,MACjB,CAhBmC,EAiBpC,CAED9D,EAAkBC,EAClB,CAEDuD,EAAI7C,EACJ,GAGDjB,QAA0B,SAAC8D,EAAK7C,GAC/B,IAAAV,EAEa8D,EAAGpD,EAAMmC,IAClBiB,IACHxE,EAAA,OAAwBwE,QAGRxD,KADhBN,EAAUF,EAAoBa,IAAImD,MAEjC9D,EAAUG,EAAc,WACvBb,EAAiBwD,IAAIgB,GACrBA,EAAUC,SAAS,CAAA,EACnB,GACDjE,EAAoB2B,IAAIqC,EAAW9D,KAIrCZ,EAAmB0E,EACnB/D,EAAkBC,GAClBuD,EAAI7C,EACJ,GAGDjB,EAAI,MAA2B,SAAC8D,EAAKS,EAAOtD,EAAOuD,GAClDlE,IACAX,OAAmBkB,EACnBiD,EAAIS,EAAOtD,EAAOuD,EAClB,GAGDxE,WAA0B,SAAC8D,EAAK7C,GAC/BX,IACAX,OAAmBkB,EACnBiD,EAAI7C,EACJ,GAGDjB,YAA2B,SAAC8D,EAAK7C,GAChC,IAAIwD,EAAQxD,EAAMmC,KAAOnC,EACnBV,EAAUF,EAAoBa,IAAIuD,GACxC,GAAIlE,EAAS,CACZF,EAAA,OAA2BoE,GAC3B,IAAMC,EAAUnE,EAAQoE,GACpBD,IACHA,EAAQpC,QAAQ,SAAA1B,GAAUA,OAAAA,EAAOgE,UAAarE,EAAxB,GACtBmE,EAAQG,QAET,CACDf,EAAI7C,EACJ,GAGDjB,EAAI,MAAoB,SAAC8D,EAAKO,EAAWS,EAAOf,GAC3CA,EAAO,GAAGgB,EAAa1B,IAAIgB,GAC/BP,EAAIO,EAAWS,EAAOf,EACtB,GAMDiB,EAAUC,UAAUC,sBAAwB,SAAUlB,EAAOmB,GAAK,IAAAC,EAE3D7E,EAAUF,EAAoBa,IAAI2B,MA2BxC,KAzBmBtC,GAAmC,KAAT8E,OAAf9E,EAAAA,EAAQoE,SAAOU,EAAAA,EAAAA,OAyBzBtF,EAAauF,IAAIzC,OAAO,OAAA,EAG5C,GAAIhD,EAAiByF,IAAIzC,MAAO,OAAA,EAGhC,GAAIkC,EAAaO,IAAIzC,MAAO,OAAA,EAC5B,IAAK,IAALrB,OAAqB,OAArB,EAGA,IAAK,IAAL+D,OACC,GAAU,aAAN/D,GAAoBwC,EAAMxC,KAAOqB,KAAKmB,MAAMxC,GAAI,OACpD,EACD,IAAK,IAALgE,UAAmBxB,MAAO,KAAMxC,KAAFwC,GAAe,OAAO,EAGpD,OACA,CAAA"}
1
+ {"version":3,"file":"signals.module.js","sources":["../src/index.ts"],"sourcesContent":["import { options, Component } from \"preact\";\nimport { useRef, useMemo } from \"preact/hooks\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tVNode,\n\tComponentType,\n\tOptionsTypes,\n\tHookFn,\n\tUpdater,\n\tElementUpdater,\n} from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n// Components that have a pending Signal update: (used to bypass default sCU:false)\nconst hasPendingUpdate = new WeakSet<Component>();\n\n// Components that have useState()/useReducer() hooks:\nconst hasHookState = new WeakSet<Component>();\n\n// Components that have useComputed():\nconst hasComputeds = new WeakSet<Component>();\n\n// Install a Preact options hook\nfunction hook<T extends OptionsTypes>(hookName: T, hookFn: HookFn<T>) {\n\t// @ts-ignore-next-line private options hooks usage\n\toptions[hookName] = hookFn.bind(null, options[hookName] || (() => {}));\n}\n\nlet currentComponent: Component | undefined;\nlet currentUpdater: Updater | undefined;\nlet finishUpdate: ReturnType<Updater[\"_setCurrent\"]> | undefined;\nconst updaterForComponent = new WeakMap<Component | VNode, Updater>();\n\nfunction setCurrentUpdater(updater?: Updater) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate(true, true);\n\t// start tracking the new update:\n\tcurrentUpdater = updater;\n\tfinishUpdate = updater && updater._setCurrent();\n}\n\nfunction createUpdater(updater: () => void) {\n\tconst s = signal(undefined) as Updater;\n\ts._updater = updater;\n\treturn s;\n}\n\n/** @todo This may be needed for complex prop value detection. */\n// function isSignalValue(value: any): value is Signal {\n// \tif (typeof value !== \"object\" || value == null) return false;\n// \tif (value instanceof Signal) return true;\n// \t// @TODO: uncomment this when we land Reactive (ideally behind a brand check)\n// \t// for (let i in value) if (value[i] instanceof Signal) return true;\n// \treturn false;\n// }\n\n/**\n * A wrapper component that renders a Signal directly as a Text node.\n * @todo: in Preact 11, just decorate Signal with `type:null`\n */\nfunction Text(this: ComponentType, { data }: { data: Signal }) {\n\t// hasComputeds.add(this);\n\n\t// Store the props.data signal in another signal so that\n\t// passing a new signal reference re-runs the text computed:\n\tconst currentSignal = useSignal(data);\n\tcurrentSignal.value = data;\n\n\tconst s = useMemo(() => {\n\t\t// mark the parent component as having computeds so it gets optimized\n\t\tlet v = this.__v;\n\t\twhile ((v = v.__!)) {\n\t\t\tif (v.__c) {\n\t\t\t\thasComputeds.add(v.__c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Replace this component's vdom updater with a direct text one:\n\t\tcurrentUpdater!._updater = () => {\n\t\t\t(this.base as Text).data = s._value;\n\t\t};\n\n\t\treturn computed(() => {\n\t\t\tlet data = currentSignal.value;\n\t\t\tlet s = data.value;\n\t\t\treturn s === 0 ? 0 : s === true ? \"\" : s || \"\";\n\t\t});\n\t}, []);\n\n\treturn s.value;\n}\nText.displayName = \"_st\";\n\nObject.defineProperties(Signal.prototype, {\n\tconstructor: { configurable: true },\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\t// Setting a VNode's _depth to 1 forces Preact to clone it before modifying:\n\t// https://github.com/preactjs/preact/blob/d7a433ee8463a7dc23a05111bb47de9ec729ad4d/src/diff/children.js#L77\n\t// @todo remove this for Preact 11\n\t__b: { configurable: true, value: 1 },\n});\n\n/** Inject low-level property/attribute bindings for Signals into Preact's diff */\nhook(OptionsTypes.DIFF, (old, vnode) => {\n\tif (typeof vnode.type === \"string\") {\n\t\tlet signalProps: Record<string, any> | undefined;\n\n\t\tlet props = vnode.props;\n\t\tfor (let i in props) {\n\t\t\tif (i === \"children\") continue;\n\n\t\t\tlet value = props[i];\n\t\t\tif (value instanceof Signal) {\n\t\t\t\tif (!signalProps) vnode.__np = signalProps = {};\n\t\t\t\tsignalProps[i] = value;\n\t\t\t\tprops[i] = value.peek();\n\t\t\t}\n\t\t}\n\t}\n\n\told(vnode);\n});\n\n/** Set up Updater before rendering a component */\nhook(OptionsTypes.RENDER, (old, vnode) => {\n\tlet updater;\n\n\tlet component = vnode.__c;\n\tif (component) {\n\t\thasPendingUpdate.delete(component);\n\n\t\tupdater = updaterForComponent.get(component);\n\t\tif (updater === undefined) {\n\t\t\tupdater = createUpdater(() => {\n\t\t\t\thasPendingUpdate.add(component);\n\t\t\t\tcomponent.setState({});\n\t\t\t});\n\t\t\tupdaterForComponent.set(component, updater);\n\t\t}\n\t}\n\n\tcurrentComponent = component;\n\tsetCurrentUpdater(updater);\n\told(vnode);\n});\n\n/** Finish current updater if a component errors */\nhook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\told(error, vnode, oldVNode);\n});\n\n/** Finish current updater after rendering any VNode */\nhook(OptionsTypes.DIFFED, (old, vnode) => {\n\tsetCurrentUpdater();\n\tcurrentComponent = undefined;\n\n\tlet dom: Element;\n\tlet updater: ElementUpdater;\n\n\t// vnode._dom is undefined during string rendering,\n\t// so we use this to skip prop subscriptions during SSR.\n\tif (typeof vnode.type === \"string\" && (dom = vnode.__e as Element)) {\n\t\tlet props = vnode.__np;\n\t\tif (props) {\n\t\t\t// @ts-ignore-next\n\t\t\tupdater = dom._updater;\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createElementUpdater(dom);\n\t\t\t\t// @ts-ignore-next\n\t\t\t\tdom._updater = updater;\n\t\t\t}\n\t\t\tupdater!._props = props;\n\t\t\tsetCurrentUpdater(updater);\n\t\t\t// @ts-ignore-next we're adding an argument here\n\t\t\tupdater._updater(true);\n\t\t}\n\t}\n\told(vnode);\n});\n\n// per-element updater for 1+ signal bindings\nfunction createElementUpdater(dom: Element) {\n\tconst cache: Record<string, any> = { __proto__: null };\n\tconst updater = createUpdater((skip?: boolean) => {\n\t\tconst props = updater._props;\n\t\tfor (let prop in props) {\n\t\t\tif (prop === \"children\") continue;\n\t\t\tlet signal = props[prop];\n\t\t\tif (signal instanceof Signal) {\n\t\t\t\tlet value = signal.value;\n\t\t\t\tlet cached = cache[prop];\n\t\t\t\tcache[prop] = value;\n\t\t\t\tif (skip === true || cached === value) {\n\t\t\t\t\t// this is just a subscribe run, not an update\n\t\t\t\t} else if (prop in dom) {\n\t\t\t\t\t// @ts-ignore-next-line silly\n\t\t\t\t\tdom[prop] = value;\n\t\t\t\t} else if (value) {\n\t\t\t\t\tdom.setAttribute(prop, value);\n\t\t\t\t} else {\n\t\t\t\t\tdom.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}) as ElementUpdater;\n\treturn updater;\n}\n\n/** Unsubscribe from Signals when unmounting components/vnodes */\nhook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {\n\tlet component = vnode.__c;\n\tconst updater = component && updaterForComponent.get(component);\n\tif (updater) {\n\t\tupdaterForComponent.delete(component);\n\t\tupdater._setCurrent()(true, true);\n\t}\n\n\tif (typeof vnode.type === \"string\") {\n\t\tconst dom = vnode.__e as Element;\n\n\t\t// @ts-ignore-next\n\t\tconst updater = dom._updater;\n\t\tif (updater) {\n\t\t\tupdater._setCurrent()(true, true);\n\t\t\t// @ts-ignore-next\n\t\t\tdom._updater = null;\n\t\t}\n\t}\n\told(vnode);\n});\n\n/** Mark components that use hook state so we can skip sCU optimization. */\nhook(OptionsTypes.HOOK, (old, component, index, type) => {\n\tif (type < 3) hasHookState.add(component);\n\told(component, index, type);\n});\n\n/**\n * Auto-memoize components that use Signals/Computeds.\n * Note: Does _not_ optimize components that use hook/class state.\n */\nComponent.prototype.shouldComponentUpdate = function (props, state) {\n\t// @todo: Once preactjs/preact#3671 lands, this could just use `currentUpdater`:\n\tconst updater = updaterForComponent.get(this);\n\n\tconst hasSignals = updater && updater._deps?.size !== 0;\n\n\t// let reason;\n\t// if (!hasSignals && !hasComputeds.has(this)) {\n\t// \treason = \"no signals or computeds\";\n\t// } else if (hasPendingUpdate.has(this)) {\n\t// \treason = \"has pending update\";\n\t// } else if (hasHookState.has(this)) {\n\t// \treason = \"has hook state\";\n\t// }\n\t// if (reason) {\n\t// \tif (!this) reason += \" (`this` bug)\";\n\t// \tconsole.log(\"not optimizing\", this?.constructor?.name, \": \", reason, {\n\t// \t\tdetails: {\n\t// \t\t\thasSignals,\n\t// \t\t\thasComputeds: hasComputeds.has(this),\n\t// \t\t\thasPendingUpdate: hasPendingUpdate.has(this),\n\t// \t\t\thasHookState: hasHookState.has(this),\n\t// \t\t\tdeps: Array.from(updater._deps),\n\t// \t\t\tupdater,\n\t// \t\t},\n\t// \t});\n\t// }\n\n\t// if this component used no signals or computeds, update:\n\tif (!hasSignals && !hasComputeds.has(this)) return true;\n\n\t// if there is a pending re-render triggered from Signals, update:\n\tif (hasPendingUpdate.has(this)) return true;\n\n\t// if there is hook or class state, update:\n\tif (hasHookState.has(this)) return true;\n\t// @ts-ignore\n\tfor (let i in state) return true;\n\n\t// if any non-Signal props changed, update:\n\tfor (let i in props) {\n\t\tif (i !== \"__source\" && props[i] !== this.props[i]) return true;\n\t}\n\tfor (let i in this.props) if (!(i in props)) return true;\n\n\t// this is a purely Signal-driven component, don't update:\n\treturn false;\n};\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\thasComputeds.add(currentComponent!);\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\n/**\n * @todo Determine which Reactive implementation we'll be using.\n * @internal\n */\n// export function useReactive<T extends object>(value: T): Reactive<T> {\n// \treturn useMemo(() => reactive<T>(value), []);\n// }\n\n/**\n * @internal\n * Update a Reactive's using the properties of an object or other Reactive.\n * Also works for Signals.\n * @example\n * // Update a Reactive with Object.assign()-like syntax:\n * const r = reactive({ name: \"Alice\" });\n * update(r, { name: \"Bob\" });\n * update(r, { age: 42 }); // property 'age' does not exist in type '{ name?: string }'\n * update(r, 2); // '2' has no properties in common with '{ name?: string }'\n * console.log(r.name.value); // \"Bob\"\n *\n * @example\n * // Update a Reactive with the properties of another Reactive:\n * const A = reactive({ name: \"Alice\" });\n * const B = reactive({ name: \"Bob\", age: 42 });\n * update(A, B);\n * console.log(`${A.name} is ${A.age}`); // \"Bob is 42\"\n *\n * @example\n * // Update a signal with assign()-like syntax:\n * const s = signal(42);\n * update(s, \"hi\"); // Argument type 'string' not assignable to type 'number'\n * update(s, {}); // Argument type '{}' not assignable to type 'number'\n * update(s, 43);\n * console.log(s.value); // 43\n *\n * @param obj The Reactive or Signal to be updated\n * @param update The value, Signal, object or Reactive to update `obj` to match\n * @param overwrite If `true`, any properties `obj` missing from `update` are set to `undefined`\n */\n/*\nexport function update<T extends SignalOrReactive>(\n\tobj: T,\n\tupdate: Partial<Unwrap<T>>,\n\toverwrite = false\n) {\n\tif (obj instanceof Signal) {\n\t\tobj.value = peekValue(update);\n\t} else {\n\t\tfor (let i in update) {\n\t\t\tif (i in obj) {\n\t\t\t\tobj[i].value = peekValue(update[i]);\n\t\t\t} else {\n\t\t\t\tlet sig = signal(peekValue(update[i]));\n\t\t\t\tsig[KEY] = i;\n\t\t\t\tobj[i] = sig;\n\t\t\t}\n\t\t}\n\t\tif (overwrite) {\n\t\t\tfor (let i in obj) {\n\t\t\t\tif (!(i in update)) {\n\t\t\t\t\tobj[i].value = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n*/\n"],"names":["Component","options","useMemo","useRef","Signal","computed","signal","batch","effect","currentComponent","currentUpdater","hasPendingUpdate","WeakSet","hasHookState","hasComputeds","hookName","hookFn","bind","updaterForComponent","WeakMap","updater","finishUpdate","_setCurrent","createUpdater","undefined","s","_updater","_ref","_this","this","data","currentSignal","useSignal","value","v","__v","__","__c","add","base","_value","createElementUpdater","dom","cache","__proto__","skip","props","_props","prop","_signal","cached","setAttribute","removeAttribute","useComputed","compute","$compute","current","Text","displayName","Object","defineProperties","prototype","constructor","configurable","type","get","__b","hook","old","vnode","signalProps","i","__np","peek","component","setState","set","setCurrentUpdater","error","oldVNode","__e","index","shouldComponentUpdate","state","_updater$_deps","_deps","size","has"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preact/signals",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "license": "MIT",
5
5
  "description": "",
6
6
  "keywords": [],
@@ -9,7 +9,8 @@
9
9
  ],
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "https://github.com/preactjs/signals"
12
+ "url": "https://github.com/preactjs/signals",
13
+ "directory": "packages/preact"
13
14
  },
14
15
  "bugs": "https://github.com/preactjs/signals/issues",
15
16
  "homepage": "https://preactjs.com",
@@ -25,16 +26,16 @@
25
26
  "source": "src/index.ts",
26
27
  "exports": {
27
28
  ".": {
29
+ "types": "./dist/signals.d.ts",
28
30
  "browser": "./dist/signals.module.js",
29
31
  "umd": "./dist/signals.umd.js",
30
32
  "import": "./dist/signals.mjs",
31
- "require": "./dist/signals.js",
32
- "types": "./dist/signals.d.ts"
33
+ "require": "./dist/signals.js"
33
34
  }
34
35
  },
35
36
  "mangle": "../../mangle.json",
36
37
  "dependencies": {
37
- "@preact/signals-core": "^1.0.1"
38
+ "@preact/signals-core": "^1.1.1"
38
39
  },
39
40
  "peerDependencies": {
40
41
  "preact": "10.x"
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { options, Component, createElement } from "preact";
1
+ import { options, Component } from "preact";
2
2
  import { useRef, useMemo } from "preact/hooks";
3
3
  import {
4
4
  signal,
@@ -49,41 +49,10 @@ function setCurrentUpdater(updater?: Updater) {
49
49
 
50
50
  function createUpdater(updater: () => void) {
51
51
  const s = signal(undefined) as Updater;
52
- s._canActivate = true;
53
52
  s._updater = updater;
54
53
  return s;
55
54
  }
56
55
 
57
- // Get a (cached) Signal property updater for an element VNode
58
- function getElementUpdater(vnode: VNode) {
59
- let updater = updaterForComponent.get(vnode) as ElementUpdater;
60
- if (!updater) {
61
- let signalProps: Array<{ _key: string; _signal: Signal }> = [];
62
- updater = createUpdater(() => {
63
- let dom = vnode.__e as Element;
64
-
65
- for (let i = 0; i < signalProps.length; i++) {
66
- let { _key: prop, _signal: signal } = signalProps[i];
67
- let value = signal._value;
68
- if (!dom) return;
69
- if (prop in dom) {
70
- // @ts-ignore-next-line silly
71
- dom[prop] = value;
72
- } else if (value) {
73
- dom.setAttribute(prop, value);
74
- } else {
75
- dom.removeAttribute(prop);
76
- }
77
- }
78
- }) as ElementUpdater;
79
- updater._props = signalProps;
80
- updaterForComponent.set(vnode, updater);
81
- } else {
82
- updater._props.length = 0;
83
- }
84
- return updater;
85
- }
86
-
87
56
  /** @todo This may be needed for complex prop value detection. */
88
57
  // function isSignalValue(value: any): value is Signal {
89
58
  // if (typeof value !== "object" || value == null) return false;
@@ -93,18 +62,6 @@ function getElementUpdater(vnode: VNode) {
93
62
  // return false;
94
63
  // }
95
64
 
96
- /** Convert Signals within (nested) props.children into Text components */
97
- function childToSignal<T>(child: any, i: keyof T, arr: T) {
98
- if (typeof child !== "object" || child == null) {
99
- // can't be a signal
100
- } else if (Array.isArray(child)) {
101
- child.forEach(childToSignal);
102
- } else if (child instanceof Signal) {
103
- // @ts-ignore-next-line yes, arr can accept VNodes:
104
- arr[i] = createElement(Text, { data: child });
105
- }
106
- }
107
-
108
65
  /**
109
66
  * A wrapper component that renders a Signal directly as a Text node.
110
67
  * @todo: in Preact 11, just decorate Signal with `type:null`
@@ -143,37 +100,37 @@ function Text(this: ComponentType, { data }: { data: Signal }) {
143
100
  }
144
101
  Text.displayName = "_st";
145
102
 
103
+ Object.defineProperties(Signal.prototype, {
104
+ constructor: { configurable: true },
105
+ type: { configurable: true, value: Text },
106
+ props: {
107
+ configurable: true,
108
+ get() {
109
+ return { data: this };
110
+ },
111
+ },
112
+ // Setting a VNode's _depth to 1 forces Preact to clone it before modifying:
113
+ // https://github.com/preactjs/preact/blob/d7a433ee8463a7dc23a05111bb47de9ec729ad4d/src/diff/children.js#L77
114
+ // @todo remove this for Preact 11
115
+ __b: { configurable: true, value: 1 },
116
+ });
117
+
146
118
  /** Inject low-level property/attribute bindings for Signals into Preact's diff */
147
119
  hook(OptionsTypes.DIFF, (old, vnode) => {
148
120
  if (typeof vnode.type === "string") {
149
- // let orig = vnode.__o || vnode;
150
- let props = vnode.props;
151
- let updater;
121
+ let signalProps: Record<string, any> | undefined;
152
122
 
123
+ let props = vnode.props;
153
124
  for (let i in props) {
125
+ if (i === "children") continue;
126
+
154
127
  let value = props[i];
155
- if (i === "children") {
156
- childToSignal(value, "children", props);
157
- } else if (value instanceof Signal) {
158
- // first Signal prop triggers creation/cleanup of the updater:
159
- if (!updater) updater = getElementUpdater(vnode);
160
- // track which props are Signals for precise updates:
161
- updater._props.push({ _key: i, _signal: value });
162
- let newUpdater = updater._updater;
163
- if (value._updater) {
164
- let oldUpdater = value._updater;
165
- value._updater = () => {
166
- newUpdater();
167
- oldUpdater();
168
- };
169
- } else {
170
- value._updater = newUpdater;
171
- }
128
+ if (value instanceof Signal) {
129
+ if (!signalProps) vnode.__np = signalProps = {};
130
+ signalProps[i] = value;
172
131
  props[i] = value.peek();
173
132
  }
174
133
  }
175
-
176
- setCurrentUpdater(updater);
177
134
  }
178
135
 
179
136
  old(vnode);
@@ -213,19 +170,77 @@ hook(OptionsTypes.CATCH_ERROR, (old, error, vnode, oldVNode) => {
213
170
  hook(OptionsTypes.DIFFED, (old, vnode) => {
214
171
  setCurrentUpdater();
215
172
  currentComponent = undefined;
173
+
174
+ let dom: Element;
175
+ let updater: ElementUpdater;
176
+
177
+ // vnode._dom is undefined during string rendering,
178
+ // so we use this to skip prop subscriptions during SSR.
179
+ if (typeof vnode.type === "string" && (dom = vnode.__e as Element)) {
180
+ let props = vnode.__np;
181
+ if (props) {
182
+ // @ts-ignore-next
183
+ updater = dom._updater;
184
+ if (!updater) {
185
+ updater = createElementUpdater(dom);
186
+ // @ts-ignore-next
187
+ dom._updater = updater;
188
+ }
189
+ updater!._props = props;
190
+ setCurrentUpdater(updater);
191
+ // @ts-ignore-next we're adding an argument here
192
+ updater._updater(true);
193
+ }
194
+ }
216
195
  old(vnode);
217
196
  });
218
197
 
198
+ // per-element updater for 1+ signal bindings
199
+ function createElementUpdater(dom: Element) {
200
+ const cache: Record<string, any> = { __proto__: null };
201
+ const updater = createUpdater((skip?: boolean) => {
202
+ const props = updater._props;
203
+ for (let prop in props) {
204
+ if (prop === "children") continue;
205
+ let signal = props[prop];
206
+ if (signal instanceof Signal) {
207
+ let value = signal.value;
208
+ let cached = cache[prop];
209
+ cache[prop] = value;
210
+ if (skip === true || cached === value) {
211
+ // this is just a subscribe run, not an update
212
+ } else if (prop in dom) {
213
+ // @ts-ignore-next-line silly
214
+ dom[prop] = value;
215
+ } else if (value) {
216
+ dom.setAttribute(prop, value);
217
+ } else {
218
+ dom.removeAttribute(prop);
219
+ }
220
+ }
221
+ }
222
+ }) as ElementUpdater;
223
+ return updater;
224
+ }
225
+
219
226
  /** Unsubscribe from Signals when unmounting components/vnodes */
220
227
  hook(OptionsTypes.UNMOUNT, (old, vnode: VNode) => {
221
- let thing = vnode.__c || vnode;
222
- const updater = updaterForComponent.get(thing);
228
+ let component = vnode.__c;
229
+ const updater = component && updaterForComponent.get(component);
223
230
  if (updater) {
224
- updaterForComponent.delete(thing);
225
- const signals = updater._deps;
226
- if (signals) {
227
- signals.forEach(signal => signal._subs.delete(updater));
228
- signals.clear();
231
+ updaterForComponent.delete(component);
232
+ updater._setCurrent()(true, true);
233
+ }
234
+
235
+ if (typeof vnode.type === "string") {
236
+ const dom = vnode.__e as Element;
237
+
238
+ // @ts-ignore-next
239
+ const updater = dom._updater;
240
+ if (updater) {
241
+ updater._setCurrent()(true, true);
242
+ // @ts-ignore-next
243
+ dom._updater = null;
229
244
  }
230
245
  }
231
246
  old(vnode);
@@ -277,6 +292,7 @@ Component.prototype.shouldComponentUpdate = function (props, state) {
277
292
 
278
293
  // if there is hook or class state, update:
279
294
  if (hasHookState.has(this)) return true;
295
+ // @ts-ignore
280
296
  for (let i in state) return true;
281
297
 
282
298
  // if any non-Signal props changed, update:
package/src/internal.d.ts CHANGED
@@ -8,6 +8,8 @@ export interface VNode<P = any> extends preact.VNode<P> {
8
8
  __?: VNode;
9
9
  /** The DOM node for this VNode */
10
10
  __e?: Element | Text;
11
+ /** Props that had Signal values before diffing (used after diffing to subscribe) */
12
+ __np?: Record<string, any> | null;
11
13
  }
12
14
 
13
15
  export interface ComponentType extends Component {
@@ -18,7 +20,7 @@ export interface ComponentType extends Component {
18
20
  export type Updater = Signal<unknown>;
19
21
 
20
22
  export interface ElementUpdater extends Updater {
21
- _props: Array<{ _key: string, _signal: Signal }>;
23
+ _props: Record<string, any>;
22
24
  }
23
25
 
24
26
  export const enum OptionsTypes {
File without changes
@@ -1,6 +1,5 @@
1
1
  import { signal, useComputed } from "@preact/signals";
2
- import { h, render } from "preact";
3
- import { useMemo } from "preact/hooks";
2
+ import { createElement, render } from "preact";
4
3
  import { setupRerender } from "preact/test-utils";
5
4
 
6
5
  const sleep = (ms?: number) => new Promise(r => setTimeout(r, ms));
@@ -20,7 +19,7 @@ describe("@preact/signals", () => {
20
19
 
21
20
  describe("Text bindings", () => {
22
21
  it("should render text without signals", () => {
23
- render(h("span", null, "test"), scratch);
22
+ render(<span>test</span>, scratch);
24
23
  const span = scratch.firstChild;
25
24
  const text = span?.firstChild;
26
25
  expect(text).to.have.property("data", "test");
@@ -28,7 +27,7 @@ describe("@preact/signals", () => {
28
27
 
29
28
  it("should render Signals as Text", () => {
30
29
  const sig = signal("test");
31
- render(h("span", null, sig), scratch);
30
+ render(<span>{sig}</span>, scratch);
32
31
  const span = scratch.firstChild;
33
32
  expect(span).to.have.property("firstChild").that.is.an.instanceOf(Text);
34
33
  const text = span?.firstChild;
@@ -37,7 +36,7 @@ describe("@preact/signals", () => {
37
36
 
38
37
  it("should update Signal-based Text (no parent component)", () => {
39
38
  const sig = signal("test");
40
- render(h("span", null, sig), scratch);
39
+ render(<span>{sig}</span>, scratch);
41
40
 
42
41
  const text = scratch.firstChild!.firstChild!;
43
42
  expect(text).to.have.property("data", "test");
@@ -55,9 +54,9 @@ describe("@preact/signals", () => {
55
54
  const spy = sinon.spy();
56
55
  function App({ x }: { x: typeof sig }) {
57
56
  spy();
58
- return h("span", null, x);
57
+ return <span>{x}</span>;
59
58
  }
60
- render(h(App, { x: sig }), scratch);
59
+ render(<App x={sig} />, scratch);
61
60
  spy.resetHistory();
62
61
 
63
62
  const text = scratch.firstChild!.firstChild!;
@@ -79,16 +78,16 @@ describe("@preact/signals", () => {
79
78
  const spy = sinon.spy();
80
79
  function App({ x }: { x: typeof sig }) {
81
80
  spy();
82
- return h("span", null, x);
81
+ return <span>{x}</span>;
83
82
  }
84
- render(h(App, { x: sig }), scratch);
83
+ render(<App x={sig} />, scratch);
85
84
  spy.resetHistory();
86
85
 
87
86
  const text = scratch.firstChild!.firstChild!;
88
87
  expect(text).to.have.property("data", "test");
89
88
 
90
89
  const sig2 = signal("different");
91
- render(h(App, { x: sig2 }), scratch);
90
+ render(<App x={sig2} />, scratch);
92
91
  expect(spy).to.have.been.called;
93
92
  spy.resetHistory();
94
93
 
@@ -123,10 +122,10 @@ describe("@preact/signals", () => {
123
122
 
124
123
  function App() {
125
124
  const value = sig.value;
126
- return h("p", null, value);
125
+ return <p>{value}</p>;
127
126
  }
128
127
 
129
- render(h(App, {}), scratch);
128
+ render(<App />, scratch);
130
129
  expect(scratch.textContent).to.equal("foo");
131
130
 
132
131
  sig.value = "bar";
@@ -146,10 +145,10 @@ describe("@preact/signals", () => {
146
145
  });
147
146
 
148
147
  const str = arr.value.join(", ");
149
- return h("p", null, str);
148
+ return <p>{str}</p>;
150
149
  }
151
150
 
152
- const fn = () => render(h(App, {}), scratch);
151
+ const fn = () => render(<App />, scratch);
153
152
  expect(fn).not.to.throw;
154
153
  });
155
154
 
@@ -158,16 +157,16 @@ describe("@preact/signals", () => {
158
157
 
159
158
  function Child() {
160
159
  const value = sig.value;
161
- return h("p", null, value);
160
+ return <p>{value}</p>;
162
161
  }
163
162
 
164
163
  const spy = sinon.spy();
165
164
  function App() {
166
165
  spy();
167
- return h(Child, null);
166
+ return <Child />;
168
167
  }
169
168
 
170
- render(h(App, {}), scratch);
169
+ render(<App />, scratch);
171
170
  expect(scratch.textContent).to.equal("foo");
172
171
 
173
172
  sig.value = "bar";
@@ -180,7 +179,7 @@ describe("@preact/signals", () => {
180
179
  it("should set the initial value of the checked property", () => {
181
180
  const s = signal(true);
182
181
  // @ts-ignore
183
- render(h("input", { checked: s }), scratch);
182
+ render(<input checked={s} />, scratch);
184
183
 
185
184
  expect(scratch.firstChild).to.have.property("checked", true);
186
185
  expect(s.value).to.equal(true);
@@ -189,7 +188,7 @@ describe("@preact/signals", () => {
189
188
  it("should update the checked property on change", () => {
190
189
  const s = signal(true);
191
190
  // @ts-ignore
192
- render(h("input", { checked: s }), scratch);
191
+ render(<input checked={s} />, scratch);
193
192
 
194
193
  expect(scratch.firstChild).to.have.property("checked", true);
195
194
 
@@ -204,9 +203,9 @@ describe("@preact/signals", () => {
204
203
  function Wrap() {
205
204
  spy();
206
205
  // @ts-ignore
207
- return h("input", { value: s });
206
+ return <input value={s} />;
208
207
  }
209
- render(h(Wrap, {}), scratch);
208
+ render(<Wrap />, scratch);
210
209
  spy.resetHistory();
211
210
 
212
211
  expect(scratch.firstChild).to.have.property("value", "initial");
@@ -234,9 +233,9 @@ describe("@preact/signals", () => {
234
233
  function Wrap() {
235
234
  spy();
236
235
  // @ts-ignore
237
- return h("div", { style });
236
+ return <div style={style} />;
238
237
  }
239
- render(h(Wrap, {}), scratch);
238
+ render(<Wrap />, scratch);
240
239
  spy.resetHistory();
241
240
 
242
241
  const div = scratch.firstChild as HTMLDivElement;