@ -8,12 +8,11 @@ import {
PROPS _IS _UPDATED
} from '../../../constants.js' ;
import { get _descriptor , is _function } from '../../shared/utils.js' ;
import { mutable_source , set, source , update } from './sources.js' ;
import { set, source , update } from './sources.js' ;
import { derived , derived _safe _equal } from './deriveds.js' ;
import { get , captured _signals , untrack } from '../runtime.js' ;
import { safe _equals } from './equality.js' ;
import { get , untrack } from '../runtime.js' ;
import * as e from '../errors.js' ;
import { LEGACY _ DERIVED_PROP , LEGACY _ PROPS, STATE _SYMBOL } from '#client/constants' ;
import { LEGACY _ PROPS, STATE _SYMBOL } from '#client/constants' ;
import { proxy } from '../proxy.js' ;
import { capture _store _binding } from './store.js' ;
import { legacy _mode _flag } from '../../flags/index.js' ;
@ -260,89 +259,92 @@ function has_destroyed_component_ctx(current_value) {
* @ returns { ( ( ) => V | ( ( arg : V ) => V ) | ( ( arg : V , mutation : boolean ) => V ) ) }
* /
export function prop ( props , key , flags , fallback ) {
var immutable = ( flags & PROPS _IS _IMMUTABLE ) !== 0 ;
var runes = ! legacy _mode _flag || ( flags & PROPS _IS _RUNES ) !== 0 ;
var bindable = ( flags & PROPS _IS _BINDABLE ) !== 0 ;
var lazy = ( flags & PROPS _IS _LAZY _INITIAL ) !== 0 ;
var is _store _sub = false ;
var prop _value ;
if ( bindable ) {
[ prop _value , is _store _sub ] = capture _store _binding ( ( ) => /** @type {V} */ ( props [ key ] ) ) ;
} else {
prop _value = /** @type {V} */ ( props [ key ] ) ;
}
// Can be the case when someone does `mount(Component, props)` with `let props = $state({...})`
// or `createClassComponent(Component, props)`
var is _entry _props = STATE _SYMBOL in props || LEGACY _PROPS in props ;
var setter =
( bindable &&
( get _descriptor ( props , key ) ? . set ? ?
( is _entry _props && key in props && ( ( v ) => ( props [ key ] = v ) ) ) ) ) ||
undefined ;
var fallback _value = /** @type {V} */ ( fallback ) ;
var fallback _dirty = true ;
var fallback _used = false ;
var get _fallback = ( ) => {
fallback _used = true ;
if ( fallback _dirty ) {
fallback _dirty = false ;
if ( lazy ) {
fallback _value = untrack ( /** @type {() => V} */ ( fallback ) ) ;
} else {
fallback _value = /** @type {V} */ ( fallback ) ;
}
fallback _value = lazy
? untrack ( /** @type {() => V} */ ( fallback ) )
: /** @type {V} */ ( fallback ) ;
}
return fallback _value ;
} ;
if ( prop _value === undefined && fallback !== undefined ) {
if ( setter && runes ) {
e . props _invalid _value ( key ) ;
}
/** @type {((v: V) => void) | undefined} */
var setter ;
prop _value = get _fallback ( ) ;
if ( setter ) setter ( prop _value ) ;
if ( bindable ) {
// Can be the case when someone does `mount(Component, props)` with `let props = $state({...})`
// or `createClassComponent(Component, props)`
var is _entry _props = STATE _SYMBOL in props || LEGACY _PROPS in props ;
setter =
get _descriptor ( props , key ) ? . set ? ?
( is _entry _props && key in props ? ( v ) => ( props [ key ] = v ) : undefined ) ;
}
var initial _value ;
var is _store _sub = false ;
if ( bindable ) {
[ initial _value , is _store _sub ] = capture _store _binding ( ( ) => /** @type {V} */ ( props [ key ] ) ) ;
} else {
initial _value = /** @type {V} */ ( props [ key ] ) ;
}
if ( initial _value === undefined && fallback !== undefined ) {
initial _value = get _fallback ( ) ;
if ( setter ) {
if ( runes ) e . props _invalid _value ( key ) ;
setter ( initial _value ) ;
}
}
/** @type {() => V} */
var getter ;
if ( runes ) {
getter = ( ) => {
var value = /** @type {V} */ ( props [ key ] ) ;
if ( value === undefined ) return get _fallback ( ) ;
fallback _dirty = true ;
fallback _used = false ;
return value ;
} ;
} else {
// Svelte 4 did not trigger updates when a primitive value was updated to the same value.
// Replicate that behavior through using a derived
var derived _getter = ( immutable ? derived : derived _safe _equal ) (
( ) => /** @type {V} */ ( props [ key ] )
) ;
derived _getter . f |= LEGACY _DERIVED _PROP ;
getter = ( ) => {
var value = get ( derived _getter ) ;
if ( value !== undefined ) fallback _value = /** @type {V} */ ( undefined ) ;
var value = /** @type {V} */ ( props [ key ] ) ;
if ( value !== undefined ) {
// in legacy mode, we don't revert to the fallback value
// if the prop goes from defined to undefined. The easiest
// way to model this is to make the fallback undefined
// as soon as the prop has a value
fallback _value = /** @type {V} */ ( undefined ) ;
}
return value === undefined ? fallback _value : value ;
} ;
}
// easy mode — prop is never written to
if ( ( flags & PROPS _IS _UPDATED ) === 0 && runes ) {
// prop is never written to — we only need a getter
if ( ( flags & PROPS _IS _UPDATED ) === 0 ) {
return getter ;
}
// intermediate mode — prop is written to, but the parent component had
// `bind:foo` which means we can just call `$$props.foo = value` directly
// prop is written to, but the parent component had `bind:foo` which
// means we can just call `$$props.foo = value` directly
if ( setter ) {
var legacy _parent = props . $$legacy ;
return function ( /** @type {any} */ value , /** @type {boolean} */ mutation ) {
if ( arguments . length > 0 ) {
// We don't want to notify if the value was mutated and the parent is in runes mode.
@ -352,82 +354,39 @@ export function prop(props, key, flags, fallback) {
if ( ! runes || ! mutation || legacy _parent || is _store _sub ) {
/** @type {Function} */ ( setter ) ( mutation ? getter ( ) : value ) ;
}
return value ;
} else {
return getter ( ) ;
}
return getter ( ) ;
} ;
}
// hard mode. this is where it gets ugly — the value in the child should
// synchronize with the parent, but it should also be possible to temporarily
// set the value to something else locally.
var from _child = false ;
var was _from _child = false ;
// The derived returns the current value. The underlying mutable
// source is written to from various places to persist this value.
var inner _current _value = mutable _source ( prop _value ) ;
var current _value = derived ( ( ) => {
var parent _value = getter ( ) ;
var child _value = get ( inner _current _value ) ;
if ( from _child ) {
from _child = false ;
was _from _child = true ;
return child _value ;
}
was _from _child = false ;
return ( inner _current _value . v = parent _value ) ;
} ) ;
// Ensure we eagerly capture the initial value if it's bindable
if ( bindable ) {
get ( current _value ) ;
}
// prop is written to, but there's no binding, which means we
// create a derived that we can write to locally
var d = ( ( flags & PROPS _IS _IMMUTABLE ) !== 0 ? derived : derived _safe _equal ) ( getter ) ;
if ( ! immutable ) current _value . equals = safe _equals ;
// Capture the initial value if it's bindable
if ( bindable ) get ( d ) ;
return function ( /** @type {any} */ value , /** @type {boolean} */ mutation ) {
// legacy nonsense — need to ensure the source is invalidated when necessary
// also needed for when handling inspect logic so we can inspect the correct source signal
if ( captured _signals !== null ) {
// set this so that we don't reset to the parent value if `d`
// is invalidated because of `invalidate_inner_signals` (rather
// than because the parent or child value changed)
from _child = was _from _child ;
// invoke getters so that signals are picked up by `invalidate_inner_signals`
getter ( ) ;
get ( inner _current _value ) ;
}
if ( arguments . length > 0 ) {
const new _value = mutation ? get ( current _value ) : runes && bindable ? proxy ( value ) : value ;
if ( ! current _value . equals ( new _value ) ) {
from _child = true ;
set ( inner _current _value , new _value ) ;
// To ensure the fallback value is consistent when used with proxies, we
// update the local fallback_value, but only if the fallback is actively used
if ( fallback _used && fallback _value !== undefined ) {
fallback _value = new _value ;
}
const new _value = mutation ? get ( d ) : runes && bindable ? proxy ( value ) : value ;
if ( has _destroyed _component _ctx ( current _value ) ) {
return value ;
}
set ( d , new _value ) ;
untrack ( ( ) => get ( current _value ) ) ; // force a synchronisation immediately
if ( fallback _value !== undefined ) {
fallback _value = new _value ;
}
return value ;
}
if ( has _destroyed _component _ctx ( current _value ) ) {
return current _value . v ;
// TODO is this still necessary post-#16263?
if ( has _destroyed _component _ctx ( d ) ) {
return d . v ;
}
return get ( current_value ) ;
return get ( d ) ;
} ;
}