@@ -10,10 +10,12 @@ import get_slot_data from '../../utils/get_slot_data';
10
10
import Expression from '../../nodes/shared/Expression' ;
11
11
import is_dynamic from './shared/is_dynamic' ;
12
12
import { Identifier , ObjectExpression } from 'estree' ;
13
+ import create_debugging_comment from './shared/create_debugging_comment' ;
13
14
14
15
export default class SlotWrapper extends Wrapper {
15
16
node : Slot ;
16
17
fragment : FragmentWrapper ;
18
+ fallback : Block | null = null ;
17
19
18
20
var : Identifier = { type : 'Identifier' , name : 'slot' } ;
19
21
dependencies : Set < string > = new Set ( [ '$$scope' ] ) ;
@@ -30,9 +32,17 @@ export default class SlotWrapper extends Wrapper {
30
32
this . cannot_use_innerhtml ( ) ;
31
33
this . not_static_content ( ) ;
32
34
35
+ if ( this . node . children . length ) {
36
+ this . fallback = block . child ( {
37
+ comment : create_debugging_comment ( this . node . children [ 0 ] , this . renderer . component ) ,
38
+ name : this . renderer . component . get_unique_name ( `fallback_block` ) ,
39
+ type : 'fallback'
40
+ } ) ;
41
+ }
42
+
33
43
this . fragment = new FragmentWrapper (
34
44
renderer ,
35
- block ,
45
+ this . fallback ,
36
46
node . children ,
37
47
parent ,
38
48
strip_whitespace ,
@@ -103,86 +113,90 @@ export default class SlotWrapper extends Wrapper {
103
113
get_slot_context_fn = 'null' ;
104
114
}
105
115
116
+ if ( this . fallback ) {
117
+ this . fragment . render ( this . fallback , null , x `#nodes` as Identifier ) ;
118
+ renderer . blocks . push ( this . fallback ) ;
119
+ }
120
+
106
121
const slot = block . get_unique_name ( `${ sanitize ( slot_name ) } _slot` ) ;
107
122
const slot_definition = block . get_unique_name ( `${ sanitize ( slot_name ) } _slot_template` ) ;
123
+ const slot_or_fallback = this . fallback ? block . get_unique_name ( `${ sanitize ( slot_name ) } _slot_or_fallback` ) : slot ;
108
124
109
125
block . chunks . init . push ( b `
110
126
const ${ slot_definition } = ${ renderer . reference ( '$$slots' ) } .${ slot_name } ;
111
127
const ${ slot } = @create_slot(${ slot_definition } , #ctx, ${ renderer . reference ( '$$scope' ) } , ${ get_slot_context_fn } );
128
+ ${ this . fallback ? b `const ${ slot_or_fallback } = ${ slot } || ${ this . fallback . name } (#ctx);` : null }
112
129
` ) ;
113
130
114
- // TODO this is a dreadful hack! Should probably make this nicer
115
- const { create, claim, hydrate, mount, update, destroy } = block . chunks ;
116
-
117
- block . chunks . create = [ ] ;
118
- block . chunks . claim = [ ] ;
119
- block . chunks . hydrate = [ ] ;
120
- block . chunks . mount = [ ] ;
121
- block . chunks . update = [ ] ;
122
- block . chunks . destroy = [ ] ;
123
-
124
- const listeners = block . event_listeners ;
125
- block . event_listeners = [ ] ;
126
- this . fragment . render ( block , parent_node , parent_nodes ) ;
127
- block . render_listeners ( `_${ slot . name } ` ) ;
128
- block . event_listeners = listeners ;
129
-
130
- if ( block . chunks . create . length ) create . push ( b `if (!${ slot } ) { ${ block . chunks . create } }` ) ;
131
- if ( block . chunks . claim . length ) claim . push ( b `if (!${ slot } ) { ${ block . chunks . claim } }` ) ;
132
- if ( block . chunks . hydrate . length ) hydrate . push ( b `if (!${ slot } ) { ${ block . chunks . hydrate } }` ) ;
133
- if ( block . chunks . mount . length ) mount . push ( b `if (!${ slot } ) { ${ block . chunks . mount } }` ) ;
134
- if ( block . chunks . update . length ) update . push ( b `if (!${ slot } ) { ${ block . chunks . update } }` ) ;
135
- if ( block . chunks . destroy . length ) destroy . push ( b `if (!${ slot } ) { ${ block . chunks . destroy } }` ) ;
136
-
137
- block . chunks . create = create ;
138
- block . chunks . claim = claim ;
139
- block . chunks . hydrate = hydrate ;
140
- block . chunks . mount = mount ;
141
- block . chunks . update = update ;
142
- block . chunks . destroy = destroy ;
143
-
144
131
block . chunks . create . push (
145
- b `if (${ slot } ) ${ slot } .c();`
132
+ b `if (${ slot_or_fallback } ) ${ slot_or_fallback } .c();`
146
133
) ;
147
134
148
135
if ( renderer . options . hydratable ) {
149
136
block . chunks . claim . push (
150
- b `if (${ slot } ) ${ slot } .l(${ parent_nodes } );`
137
+ b `if (${ slot_or_fallback } ) ${ slot_or_fallback } .l(${ parent_nodes } );`
151
138
) ;
152
139
}
153
140
154
141
block . chunks . mount . push ( b `
155
- if (${ slot } ) {
156
- ${ slot } .m(${ parent_node || '#target' } , ${ parent_node ? 'null' : 'anchor' } );
142
+ if (${ slot_or_fallback } ) {
143
+ ${ slot_or_fallback } .m(${ parent_node || '#target' } , ${ parent_node ? 'null' : 'anchor' } );
157
144
}
158
145
` ) ;
159
146
160
147
block . chunks . intro . push (
161
- b `@transition_in(${ slot } , #local);`
148
+ b `@transition_in(${ slot_or_fallback } , #local);`
162
149
) ;
163
150
164
151
block . chunks . outro . push (
165
- b `@transition_out(${ slot } , #local);`
152
+ b `@transition_out(${ slot_or_fallback } , #local);`
166
153
) ;
167
154
168
- const dynamic_dependencies = Array . from ( this . dependencies ) . filter ( name => {
155
+ const is_dependency_dynamic = name => {
169
156
if ( name === '$$scope' ) return true ;
170
157
if ( this . node . scope . is_let ( name ) ) return true ;
171
158
const variable = renderer . component . var_lookup . get ( name ) ;
172
159
return is_dynamic ( variable ) ;
173
- } ) ;
160
+ } ;
161
+
162
+ const dynamic_dependencies = Array . from ( this . dependencies ) . filter ( is_dependency_dynamic ) ;
163
+
164
+ const fallback_dynamic_dependencies = this . fallback
165
+ ? Array . from ( this . fallback . dependencies ) . filter ( is_dependency_dynamic )
166
+ : [ ] ;
174
167
175
- block . chunks . update . push ( b `
176
- if (${ slot } && ${ slot } .p && ${ renderer . dirty ( dynamic_dependencies ) } ) {
168
+ const slot_update = b `
169
+ if (${ slot } .p && ${ renderer . dirty ( dynamic_dependencies ) } ) {
177
170
${ slot } .p(
178
171
@get_slot_context(${ slot_definition } , #ctx, ${ renderer . reference ( '$$scope' ) } , ${ get_slot_context_fn } ),
179
172
@get_slot_changes(${ slot_definition } , ${ renderer . reference ( '$$scope' ) } , #dirty, ${ get_slot_changes_fn } )
180
173
);
181
174
}
182
- ` ) ;
175
+ ` ;
176
+ const fallback_update = this . fallback && fallback_dynamic_dependencies . length > 0 && b `
177
+ if (${ slot_or_fallback } && ${ slot_or_fallback } .p && ${ renderer . dirty ( fallback_dynamic_dependencies ) } ) {
178
+ ${ slot_or_fallback } .p(#ctx, #dirty);
179
+ }
180
+ ` ;
181
+
182
+ if ( fallback_update ) {
183
+ block . chunks . update . push ( b `
184
+ if (${ slot } ) {
185
+ ${ slot_update }
186
+ } else {
187
+ ${ fallback_update }
188
+ }
189
+ ` ) ;
190
+ } else {
191
+ block . chunks . update . push ( b `
192
+ if (${ slot } ) {
193
+ ${ slot_update }
194
+ }
195
+ ` ) ;
196
+ }
183
197
184
198
block . chunks . destroy . push (
185
- b `if (${ slot } ) ${ slot } .d(detaching);`
199
+ b `if (${ slot_or_fallback } ) ${ slot_or_fallback } .d(detaching);`
186
200
) ;
187
201
}
188
202
}
0 commit comments