1
- /** @import { BlockStatement, Statement, Pattern , Expression } from 'estree' */
1
+ /** @import { BlockStatement, Statement, Property , Expression } from 'estree' */
2
2
/** @import { AST } from '#compiler' */
3
3
/** @import { ComponentContext } from '../types' */
4
4
@@ -11,27 +11,45 @@ export function SvelteBoundary(node, context) {
11
11
const nodes = [ ] ;
12
12
/** @type {Statement[] } */
13
13
const snippet_statements = [ ] ;
14
- /** @type {Expression } */
15
- let failed_param = b . literal ( null ) ;
16
- /** @type {Expression | null } */
17
- let onerror = null ;
14
+ /** @type {Array<Property[] | Expression> } */
15
+ const props_and_spreads = [ ] ;
16
+
17
+ let has_spread = false ;
18
+
19
+ const push_prop = ( /** @type {Property } */ prop ) => {
20
+ let current = props_and_spreads . at ( - 1 ) ;
21
+ if ( Array . isArray ( current ) ) {
22
+ current . push ( prop ) ;
23
+ }
24
+ const arr = [ prop ] ;
25
+ props_and_spreads . push ( arr ) ;
26
+ } ;
18
27
19
28
for ( const attribute of node . attributes ) {
29
+ if ( attribute . type === 'SpreadAttribute' ) {
30
+ has_spread = true ;
31
+ props_and_spreads . push ( attribute . expression ) ;
32
+ continue ;
33
+ }
20
34
if (
21
35
attribute . type !== 'Attribute' ||
22
36
attribute . value === true ||
23
37
Array . isArray ( attribute . value )
24
38
) {
25
39
continue ;
26
40
}
27
- if ( attribute . name === 'onerror' ) {
28
- onerror = /** @type {Expression } */ (
29
- context . visit ( attribute . value . expression , context . state )
30
- ) ;
31
- } else if ( attribute . name === 'failed' ) {
32
- failed_param = /** @type {Expression } */ (
41
+ if ( attribute . name === 'onerror' || attribute . name === 'failed' ) {
42
+ const value = /** @type {Expression } */ (
33
43
context . visit ( attribute . value . expression , context . state )
34
44
) ;
45
+
46
+ if ( attribute . metadata . expression . has_state ) {
47
+ push_prop (
48
+ b . prop ( 'get' , b . id ( attribute . name ) , b . function ( null , [ ] , b . block ( [ b . return ( value ) ] ) ) )
49
+ ) ;
50
+ } else {
51
+ push_prop ( b . prop ( 'init' , b . id ( attribute . name ) , value ) ) ;
52
+ }
35
53
}
36
54
}
37
55
@@ -41,7 +59,8 @@ export function SvelteBoundary(node, context) {
41
59
const init = [ ] ;
42
60
const block_state = { ...context . state , init } ;
43
61
context . visit ( child , block_state ) ;
44
- failed_param = b . id ( 'failed' ) ;
62
+ const current = props_and_spreads . at ( - 1 ) ?? props_and_spreads . push ( [ ] ) ;
63
+ push_prop ( b . prop ( 'init' , b . id ( 'failed' ) , b . id ( 'failed' ) ) ) ;
45
64
snippet_statements . push ( ...init ) ;
46
65
} else {
47
66
nodes . push ( child ) ;
@@ -58,14 +77,16 @@ export function SvelteBoundary(node, context) {
58
77
)
59
78
) ;
60
79
80
+ const props_expression =
81
+ ! has_spread && Array . isArray ( props_and_spreads [ 0 ] )
82
+ ? b . object ( props_and_spreads [ 0 ] )
83
+ : b . call (
84
+ '$.spread_props' ,
85
+ ...props_and_spreads . map ( ( p ) => ( Array . isArray ( p ) ? b . object ( p ) : p ) )
86
+ ) ;
87
+
61
88
const boundary = b . stmt (
62
- b . call (
63
- '$.boundary' ,
64
- context . state . node ,
65
- b . arrow ( [ b . id ( '$$anchor' ) ] , block ) ,
66
- failed_param ,
67
- ! onerror ? b . literal ( null ) : onerror
68
- )
89
+ b . call ( '$.boundary' , context . state . node , b . arrow ( [ b . id ( '$$anchor' ) ] , block ) , props_expression )
69
90
) ;
70
91
71
92
context . state . template . push ( '<!>' ) ;
0 commit comments