@@ -286,12 +286,15 @@ function htmlToElement(html) {
286
286
const template = document . createElement ( 'template' ) ;
287
287
html = html . trim ( ) ;
288
288
template . innerHTML = html ;
289
- const child = template . content . firstChild ;
289
+ if ( template . content . childElementCount > 1 ) {
290
+ throw new Error ( `Component HTML contains ${ template . content . childElementCount } elements, but only 1 root element is allowed.` ) ;
291
+ }
292
+ const child = template . content . firstElementChild ;
290
293
if ( ! child ) {
291
294
throw new Error ( 'Child not found' ) ;
292
295
}
293
296
if ( ! ( child instanceof HTMLElement ) ) {
294
- throw new Error ( `Created element is not an Element from HTML : ${ html . trim ( ) } ` ) ;
297
+ throw new Error ( `Created element is not an HTMLElement : ${ html . trim ( ) } ` ) ;
295
298
}
296
299
return child ;
297
300
}
@@ -1194,7 +1197,7 @@ function executeMorphdom(rootFromElement, rootToElement, modifiedFieldElements,
1194
1197
const childComponentToElement = findChildComponent ( childComponent . id , rootToElement ) ;
1195
1198
if ( childComponentToElement && childComponentToElement . tagName !== childComponent . element . tagName ) {
1196
1199
const newTag = cloneElementWithNewTagName ( childComponentToElement , childComponent . element . tagName ) ;
1197
- rootToElement . replaceChild ( newTag , childComponentToElement ) ;
1200
+ childComponentToElement . replaceWith ( newTag ) ;
1198
1201
}
1199
1202
} ) ;
1200
1203
morphdom ( rootFromElement , rootToElement , {
@@ -1219,7 +1222,7 @@ function executeMorphdom(rootFromElement, rootToElement, modifiedFieldElements,
1219
1222
if ( modifiedFieldElements . includes ( fromEl ) ) {
1220
1223
setValueOnElement ( toEl , getElementValue ( fromEl ) ) ;
1221
1224
}
1222
- if ( fromEl . isEqualNode ( toEl ) ) {
1225
+ if ( fromEl instanceof HTMLElement && toEl instanceof HTMLElement && fromEl . isEqualNode ( toEl ) ) {
1223
1226
const normalizedFromEl = cloneHTMLElement ( fromEl ) ;
1224
1227
normalizeAttributesForComparison ( normalizedFromEl ) ;
1225
1228
const normalizedToEl = cloneHTMLElement ( toEl ) ;
@@ -1424,7 +1427,7 @@ class Component {
1424
1427
}
1425
1428
return this . valueStore . get ( modelName ) ;
1426
1429
}
1427
- action ( name , args , debounce = false ) {
1430
+ action ( name , args = { } , debounce = false ) {
1428
1431
const promise = this . nextRequestPromise ;
1429
1432
this . pendingActions . push ( {
1430
1433
name,
@@ -1516,15 +1519,20 @@ class Component {
1516
1519
this . isRequestPending = false ;
1517
1520
this . backendRequest . promise . then ( async ( response ) => {
1518
1521
const backendResponse = new BackendResponse ( response ) ;
1519
- thisPromiseResolve ( backendResponse ) ;
1520
1522
const html = await backendResponse . getBody ( ) ;
1521
1523
const headers = backendResponse . response . headers ;
1522
1524
if ( headers . get ( 'Content-Type' ) !== 'application/vnd.live-component+html' && ! headers . get ( 'X-Live-Redirect' ) ) {
1523
- this . renderError ( html ) ;
1525
+ const controls = { displayError : true } ;
1526
+ this . hooks . triggerHook ( 'response:error' , backendResponse , controls ) ;
1527
+ if ( controls . displayError ) {
1528
+ this . renderError ( html ) ;
1529
+ }
1530
+ thisPromiseResolve ( backendResponse ) ;
1524
1531
return response ;
1525
1532
}
1526
1533
this . processRerender ( html , backendResponse ) ;
1527
1534
this . backendRequest = null ;
1535
+ thisPromiseResolve ( backendResponse ) ;
1528
1536
if ( this . isRequestPending ) {
1529
1537
this . isRequestPending = false ;
1530
1538
this . performRequest ( ) ;
@@ -1552,7 +1560,14 @@ class Component {
1552
1560
this . valueStore . updatedModels . forEach ( ( modelName ) => {
1553
1561
modifiedModelValues [ modelName ] = this . valueStore . get ( modelName ) ;
1554
1562
} ) ;
1555
- const newElement = htmlToElement ( html ) ;
1563
+ let newElement ;
1564
+ try {
1565
+ newElement = htmlToElement ( html ) ;
1566
+ }
1567
+ catch ( error ) {
1568
+ console . error ( 'There was a problem with the component HTML returned:' ) ;
1569
+ throw error ;
1570
+ }
1556
1571
this . hooks . triggerHook ( 'loading.state:finished' , newElement ) ;
1557
1572
this . valueStore . reinitializeData ( this . elementDriver . getComponentData ( newElement ) ) ;
1558
1573
executeMorphdom ( this . element , newElement , this . unsyncedInputsTracker . getUnsyncedInputs ( ) , ( element ) => getValueFromElement ( element , this . valueStore ) , Array . from ( this . getChildren ( ) . values ( ) ) , this . elementDriver . findChildComponentElement , this . elementDriver . getKeyFromElement ) ;
0 commit comments