@@ -974,9 +974,6 @@ function create_block(parent, name, nodes, context) {
974
974
/** @type {import('estree').Statement | undefined } */
975
975
let close = undefined ;
976
976
977
- /** @type {import('estree').Identifier | undefined } */
978
- let id = undefined ;
979
-
980
977
/** @type {import('../types').ComponentClientTransformState } */
981
978
const state = {
982
979
...context . state ,
@@ -999,7 +996,7 @@ function create_block(parent, name, nodes, context) {
999
996
if ( is_single_element ) {
1000
997
const element = /** @type {import('#compiler').RegularElement } */ ( trimmed [ 0 ] ) ;
1001
998
1002
- id = b . id ( context . state . scope . generate ( element . name ) ) ;
999
+ const id = b . id ( context . state . scope . generate ( element . name ) ) ;
1003
1000
1004
1001
context . visit ( element , {
1005
1002
...state ,
@@ -1014,7 +1011,7 @@ function create_block(parent, name, nodes, context) {
1014
1011
1015
1012
body . push (
1016
1013
b . var (
1017
- id . name ,
1014
+ id ,
1018
1015
b . call (
1019
1016
'$.open' ,
1020
1017
b . id ( '$$anchor' ) ,
@@ -1028,15 +1025,30 @@ function create_block(parent, name, nodes, context) {
1028
1025
} else if ( is_single_child_not_needing_template ) {
1029
1026
context . visit ( trimmed [ 0 ] , state ) ;
1030
1027
body . push ( ...state . init ) ;
1031
- } else {
1032
- id = b . id ( context . state . scope . generate ( 'fragment' ) ) ;
1028
+ } else if ( trimmed . length > 0 ) {
1029
+ const id = b . id ( context . state . scope . generate ( 'fragment' ) ) ;
1030
+ const node_id = b . id ( context . state . scope . generate ( 'node' ) ) ;
1033
1031
1034
- process_children ( trimmed , b . call ( '$.child_frag' , id ) , {
1032
+ process_children ( trimmed , node_id , {
1035
1033
...context ,
1036
1034
state
1037
1035
} ) ;
1038
1036
1039
- if ( state . template . length > 0 ) {
1037
+ const template = state . template [ 0 ] ;
1038
+
1039
+ if ( state . template . length === 1 && ( template === ' ' || template === '<!>' ) ) {
1040
+ if ( template === ' ' ) {
1041
+ body . push ( b . var ( node_id , b . call ( '$.space' , b . id ( '$$anchor' ) ) ) , ...state . init ) ;
1042
+ close = b . stmt ( b . call ( '$.close' , b . id ( '$$anchor' ) , node_id ) ) ;
1043
+ } else {
1044
+ body . push (
1045
+ b . var ( id , b . call ( '$.comment' , b . id ( '$$anchor' ) ) ) ,
1046
+ b . var ( node_id , b . call ( '$.child_frag' , id ) ) ,
1047
+ ...state . init
1048
+ ) ;
1049
+ close = b . stmt ( b . call ( '$.close_frag' , b . id ( '$$anchor' ) , id ) ) ;
1050
+ }
1051
+ } else {
1040
1052
const callee = namespace === 'svg' ? '$.svg_template' : '$.template' ;
1041
1053
1042
1054
state . hoisted . push (
@@ -1048,20 +1060,22 @@ function create_block(parent, name, nodes, context) {
1048
1060
1049
1061
body . push (
1050
1062
b . var (
1051
- id . name ,
1063
+ id ,
1052
1064
b . call (
1053
1065
'$.open_frag' ,
1054
1066
b . id ( '$$anchor' ) ,
1055
1067
b . literal ( ! state . metadata . template_needs_import_node ) ,
1056
1068
template_name
1057
1069
)
1058
1070
) ,
1071
+ b . var ( node_id , b . call ( '$.child_frag' , id ) ) ,
1059
1072
...state . init
1060
1073
) ;
1074
+
1061
1075
close = b . stmt ( b . call ( '$.close_frag' , b . id ( '$$anchor' ) , id ) ) ;
1062
- } else {
1063
- body . push ( ...state . init ) ;
1064
1076
}
1077
+ } else {
1078
+ body . push ( ...state . init ) ;
1065
1079
}
1066
1080
1067
1081
if ( state . update . length > 0 || state . update_effects . length > 0 ) {
@@ -1359,13 +1373,11 @@ function process_children(nodes, parent, { visit, state }) {
1359
1373
1360
1374
state . template . push ( ' ' ) ;
1361
1375
1362
- const name = state . scope . generate ( 'text' ) ;
1363
- state . init . push ( b . var ( name , expression ) ) ;
1364
-
1376
+ const text_id = get_node_id ( expression , state , 'text' ) ;
1365
1377
const singular = b . stmt (
1366
1378
b . call (
1367
1379
'$.text_effect' ,
1368
- b . id ( name ) ,
1380
+ text_id ,
1369
1381
b . thunk ( /** @type {import('estree').Expression } */ ( visit ( node . expression ) ) )
1370
1382
)
1371
1383
) ;
@@ -1378,7 +1390,7 @@ function process_children(nodes, parent, { visit, state }) {
1378
1390
grouped : b . stmt (
1379
1391
b . call (
1380
1392
'$.text' ,
1381
- b . id ( name ) ,
1393
+ text_id ,
1382
1394
/** @type {import('estree').Expression } */ ( visit ( node . expression ) )
1383
1395
)
1384
1396
)
@@ -1388,7 +1400,7 @@ function process_children(nodes, parent, { visit, state }) {
1388
1400
b . stmt (
1389
1401
b . assignment (
1390
1402
'=' ,
1391
- b . id ( ` ${ name } . nodeValue` ) ,
1403
+ b . member ( text_id , b . id ( ' nodeValue' ) ) ,
1392
1404
b . call (
1393
1405
'$.stringify' ,
1394
1406
/** @type {import('estree').Expression } */ ( visit ( node . expression ) )
@@ -1403,17 +1415,16 @@ function process_children(nodes, parent, { visit, state }) {
1403
1415
1404
1416
state . template . push ( ' ' ) ;
1405
1417
1406
- const name = state . scope . generate ( 'text' ) ;
1418
+ const text_id = get_node_id ( expression , state , 'text' ) ;
1407
1419
const contains_call_expression = sequence . some (
1408
1420
( n ) => n . type === 'ExpressionTag' && n . metadata . contains_call_expression
1409
1421
) ;
1410
- state . init . push ( b . var ( name , expression ) ) ;
1411
1422
const assignment = serialize_template_literal ( sequence , visit , state ) [ 1 ] ;
1412
- const init = b . stmt ( b . assignment ( '=' , b . id ( ` ${ name } . nodeValue` ) , assignment ) ) ;
1423
+ const init = b . stmt ( b . assignment ( '=' , b . member ( text_id , b . id ( ' nodeValue' ) ) , assignment ) ) ;
1413
1424
const singular = b . stmt (
1414
1425
b . call (
1415
1426
'$.text_effect' ,
1416
- b . id ( name ) ,
1427
+ text_id ,
1417
1428
b . thunk ( serialize_template_literal ( sequence , visit , state ) [ 1 ] )
1418
1429
)
1419
1430
) ;
@@ -1426,13 +1437,13 @@ function process_children(nodes, parent, { visit, state }) {
1426
1437
) {
1427
1438
state . update . push ( {
1428
1439
singular,
1429
- grouped : b . stmt ( b . call ( '$.text' , b . id ( name ) , assignment ) )
1440
+ grouped : b . stmt ( b . call ( '$.text' , text_id , assignment ) )
1430
1441
} ) ;
1431
1442
} else {
1432
1443
state . init . push ( init ) ;
1433
1444
}
1434
1445
1435
- expression = b . call ( '$.sibling' , b . id ( name ) ) ;
1446
+ expression = b . call ( '$.sibling' , text_id ) ;
1436
1447
}
1437
1448
1438
1449
for ( let i = 0 ; i < nodes . length ; i += 1 ) {
@@ -1456,9 +1467,6 @@ function process_children(nodes, parent, { visit, state }) {
1456
1467
// get hoisted inside clean_nodes?
1457
1468
visit ( node , state ) ;
1458
1469
} else {
1459
- const name = state . scope . generate ( node . type === 'RegularElement' ? node . name : 'node' ) ;
1460
- const id = b . id ( name ) ;
1461
-
1462
1470
// Optimization path for each blocks. If the parent isn't a fragment and it only has
1463
1471
// a single child, then we can classify the block as being "controlled".
1464
1472
if (
@@ -1471,7 +1479,12 @@ function process_children(nodes, parent, { visit, state }) {
1471
1479
node . metadata . is_controlled = true ;
1472
1480
visit ( node , state ) ;
1473
1481
} else {
1474
- state . init . push ( b . var ( name , expression ) ) ;
1482
+ const id = get_node_id (
1483
+ expression ,
1484
+ state ,
1485
+ node . type === 'RegularElement' ? node . name : 'node'
1486
+ ) ;
1487
+
1475
1488
expression = b . call ( '$.sibling' , id ) ;
1476
1489
1477
1490
visit ( node , {
@@ -1488,6 +1501,22 @@ function process_children(nodes, parent, { visit, state }) {
1488
1501
}
1489
1502
}
1490
1503
1504
+ /**
1505
+ * @param {import('estree').Expression } expression
1506
+ * @param {import('../types.js').ComponentClientTransformState } state
1507
+ * @param {string } name
1508
+ */
1509
+ function get_node_id ( expression , state , name ) {
1510
+ let id = expression ;
1511
+
1512
+ if ( id . type !== 'Identifier' ) {
1513
+ id = b . id ( state . scope . generate ( name ) ) ;
1514
+
1515
+ state . init . push ( b . var ( id , expression ) ) ;
1516
+ }
1517
+ return id ;
1518
+ }
1519
+
1491
1520
/**
1492
1521
* @param {true | Array<import('#compiler').Text | import('#compiler').ExpressionTag> } attribute_value
1493
1522
* @param {import('../types').ComponentContext } context
0 commit comments