@plastic-js/plastic 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/jsx-runtime.js +13 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plastic-js/plastic",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "main": "src/index.js",
5
5
  "access": "public",
6
6
  "sideEffects": false,
@@ -640,14 +640,17 @@ const disposeBindings = (bindings)=> {
640
640
  // free. The value is resolved through `resolveReactiveValue` so signals and
641
641
  // zero-arg accessor thunks (used widely by ark-plastic / zag adapters) are
642
642
  // unwrapped before being applied to the DOM.
643
- const bindReactiveProp = (element, props, key)=> {
643
+ const bindReactiveProp = (element, props, key, propsIsTracked)=> {
644
644
  const rawValue = props[key]
645
645
 
646
646
  // Static (non-reactive) fast path: write the prop directly with no binding
647
647
  // effect. Most JSX props in real apps are static (className='row', id=...,
648
648
  // type='button' etc.) — building an effect for each one was the biggest
649
649
  // per-component cost in mount benchmarks.
650
- if (!isReactive(rawValue)){
650
+ // Skip the fast path when `props` is itself a tracking proxy (tree /
651
+ // mergeProps): the value may be a plain string but reading `props[key]`
652
+ // subscribes through the proxy, so we need an effect to re-run on change.
653
+ if (!propsIsTracked && !isReactive(rawValue)){
651
654
  let prevStyleValue
652
655
  if (key === 'className' || key === 'class'){
653
656
  applyClassProp(element, rawValue)
@@ -747,6 +750,7 @@ const bindReactiveEvent = (element, props, key)=> {
747
750
  // keys later we tear down the previous bindings and rebuild them from the
748
751
  // current key set.
749
752
  const applyProps = (element, props = {})=> {
753
+ const propsIsTracked = isMergedProps(props) || isTree(props)
750
754
  const setup = ()=> {
751
755
  const bindings = []
752
756
  // Only register cleanup if there's an owner/computation to attach to.
@@ -778,16 +782,17 @@ const applyProps = (element, props = {})=> {
778
782
  bindings.push(bindReactiveEvent(element, props, key))
779
783
  continue
780
784
  }
781
- bindings.push(bindReactiveProp(element, props, key))
785
+ bindings.push(bindReactiveProp(element, props, key, propsIsTracked))
782
786
  }
783
787
  }
784
788
 
785
789
  // Only wrap in an outer binding effect when the proxy has dynamic keys (a
786
- // function-typed spread source like `{...api()}`). For static-key proxies
787
- // (the common babel reactive transform output with no spreads), and for
788
- // plain object props, keys never change skip the outer effect to avoid
789
- // one owner-effect allocation per element.
790
- if (isMergedProps(props) && !hasMergedPropsStaticKeys(props)){
790
+ // function-typed spread source like `{...api()}`, or any tree proxy whose
791
+ // key set may grow/shrink at runtime). For static-key proxies (the common
792
+ // babel reactive transform output with no spreads), and for plain object
793
+ // props, keys never change — skip the outer effect to avoid one
794
+ // owner-effect allocation per element.
795
+ if ((isMergedProps(props) && !hasMergedPropsStaticKeys(props)) || isTree(props)){
791
796
  createBindingEffect(setup)
792
797
  } else {
793
798
  setup()