diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts index 7cc48ec7b81d..1811bc762fcb 100644 --- a/src/generators/dom/preprocess.ts +++ b/src/generators/dom/preprocess.ts @@ -317,7 +317,9 @@ const preprocessors = { generator.components.has(node.name) || node.name === ':Self'; if (isComponent) { - node._state = getChildState(state); + node._state = getChildState(state, { + isYield: true + }); } else { const name = block.getUniqueName( node.name.replace(/[^a-zA-Z0-9_$]/g, '_') diff --git a/src/generators/dom/visitors/Element/Binding.ts b/src/generators/dom/visitors/Element/Binding.ts index 945145cb64a2..6ddc73f4da61 100644 --- a/src/generators/dom/visitors/Element/Binding.ts +++ b/src/generators/dom/visitors/Element/Binding.ts @@ -87,16 +87,8 @@ export default function visitBinding( const { name } = getObject(attribute.value); const tailSnippet = getTailSnippet(attribute.value); - if (state.inEachBlock === true) { - updateElement = deindent` - var ${value} = ${snippet}; - `; - } else { - updateElement = deindent` - var ${value} = #component.get( '${name}' )${tailSnippet}; - `; - } - updateElement += ` + updateElement = deindent` + var ${value} = ${snippet}; for ( var #i = 0; #i < ${state.parentNode}.options.length; #i += 1 ) { var ${option} = ${state.parentNode}.options[#i]; @@ -168,8 +160,10 @@ export default function visitBinding( `@addListener( ${state.parentNode}, '${eventName}', ${handler} );` ); - if (node.name !== 'audio' && node.name !== 'video') + if (node.name !== 'audio' && node.name !== 'video') { node.initialUpdate = updateElement; + node.initialUpdateNeedsStateObject = !block.contexts.has(name); + } if (updateCondition !== null) { // audio/video duration is read-only, it never updates diff --git a/src/generators/dom/visitors/Element/Element.ts b/src/generators/dom/visitors/Element/Element.ts index 9a8e6005833c..08ab6b2c6837 100644 --- a/src/generators/dom/visitors/Element/Element.ts +++ b/src/generators/dom/visitors/Element/Element.ts @@ -195,6 +195,17 @@ export default function visitElement( } if (node.initialUpdate) { + // special case — if we're in a yield block, then we may call mount + // long after the fragment is created. We may therefore need to get + // the latest `state` object + // TODO what about contexts in yield blocks? do we need to do + // `var ${contextName} = [something complicated]`? + const needsStateObject = node.initialUpdateNeedsStateObject && state.isYield; + + if ( needsStateObject ) { + block.builders.mount.addLine(`var state = #component.get()`); + } + block.builders.mount.addBlock(node.initialUpdate); }