mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(core): always create new renderer when applying HMR metadata update (#58527)
The DOM renderer classes perform initialization that captures state from the component definition during construction. To ensure that the state is kept synchronized with any newly applied metadata from an HMR `applyMetadata` call, each renderer is now recreated during the apply process. This also allows inline component styles to be updated in cases where external component stylesheets may not be viable. PR Close #58527
This commit is contained in:
parent
1035b47d0b
commit
d076c32059
1 changed files with 20 additions and 1 deletions
|
|
@ -40,6 +40,7 @@ import {
|
|||
} from './interfaces/view';
|
||||
import {assertTNodeType} from './node_assert';
|
||||
import {destroyLView, removeViewFromDOM} from './node_manipulation';
|
||||
import {RendererFactory} from './interfaces/renderer';
|
||||
|
||||
/**
|
||||
* Replaces the metadata of a component type and re-renders all live instances of the component.
|
||||
|
|
@ -114,6 +115,19 @@ function recreateMatchingLViews(def: ComponentDef<unknown>, rootLView: LView): v
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any cached renderers from the factory for the provided type.
|
||||
* This is currently used by the HMR logic to ensure Renderers are kept
|
||||
* synchronized with any definition metadata updates.
|
||||
* @param factory A RendererFactory2 instance.
|
||||
* @param def A ComponentDef instance.
|
||||
*/
|
||||
function clearRendererCache(factory: RendererFactory, def: ComponentDef<unknown>) {
|
||||
// Cast to `any` to read a private field.
|
||||
// NOTE: This must be kept synchronized with the renderer factory implementation in platform-browser.
|
||||
(factory as any).rendererByCompId?.remove(def.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreates an LView in-place from a new component definition.
|
||||
* @param def Definition from which to recreate the view.
|
||||
|
|
@ -132,6 +146,11 @@ function recreateLView(def: ComponentDef<unknown>, lView: LView<unknown>): void
|
|||
// Recreate the TView since the template might've changed.
|
||||
const newTView = getOrCreateComponentTView(def);
|
||||
|
||||
// Always force the creation of a new renderer to ensure state captured during construction
|
||||
// stays consistent with the new component definition by clearing any old cached factories.
|
||||
const rendererFactory = lView[ENVIRONMENT].rendererFactory;
|
||||
clearRendererCache(rendererFactory, def);
|
||||
|
||||
// Create a new LView from the new TView, but reusing the existing TNode and DOM node.
|
||||
const newLView = createLView(
|
||||
parentLView,
|
||||
|
|
@ -141,7 +160,7 @@ function recreateLView(def: ComponentDef<unknown>, lView: LView<unknown>): void
|
|||
host,
|
||||
tNode,
|
||||
null,
|
||||
lView[ENVIRONMENT].rendererFactory.createRenderer(host, def),
|
||||
rendererFactory.createRenderer(host, def),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
|
|
|
|||
Loading…
Reference in a new issue