Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(compiler): avoid having to duplicate core environment #58444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/compiler-cli/test/ngtsc/hmr_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ runInEachFileSystem(() => {
/import\(\s*\/\* @vite-ignore \*\/\s+"\/@ng\/component\?c=test\.ts%40Cmp&t=" \+ encodeURIComponent\(d.timestamp\)/,
);
expect(jsContents).toMatch(
/\).then\(m => i0\.ɵɵreplaceMetadata\(Cmp, m\.default, \[Dep, transformValue, TOKEN, Component, Inject, ViewChild, Input\]\)\);/,
/\).then\(m => i0\.ɵɵreplaceMetadata\(Cmp, m\.default, i0, \[Dep, transformValue, TOKEN, Component, Inject, ViewChild, Input\]\)\);/,
);

expect(hmrContents).toContain(
Expand Down
4 changes: 1 addition & 3 deletions packages/compiler/src/output/output_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,8 +886,7 @@ export class ExternalExpr extends Expression {
return (
e instanceof ExternalExpr &&
this.value.name === e.value.name &&
this.value.moduleName === e.value.moduleName &&
this.value.runtime === e.value.runtime
this.value.moduleName === e.value.moduleName
);
}

Expand All @@ -908,7 +907,6 @@ export class ExternalReference {
constructor(
public moduleName: string | null,
public name: string | null,
public runtime?: any | null,
) {}
// Note: no isEquivalent method here as we use this as an interface too.
}
Expand Down
9 changes: 7 additions & 2 deletions packages/compiler/src/render3/r3_hmr_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ export function compileHmrInitializer(meta: R3HmrMetadata): o.Expression {
const dataName = 'd';
const locals = meta.locals.map((localName) => o.variable(localName));

// ɵɵreplaceMetadata(Comp, m.default, [...]);
// ɵɵreplaceMetadata(Comp, m.default, core, [...]);
const replaceMetadata = o
.importExpr(R3.replaceMetadata)
.callFn([meta.type, o.variable(moduleName).prop('default'), o.literalArr(locals)]);
.callFn([
meta.type,
o.variable(moduleName).prop('default'),
new o.ExternalExpr(R3.core),
o.literalArr(locals),
]);

// (m) => ɵɵreplaceMetadata(...)
const replaceCallback = o.arrowFn([new o.FnParam(moduleName)], replaceMetadata);
Expand Down
6 changes: 2 additions & 4 deletions packages/compiler/test/output/output_jit_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ describe('Output JIT', () => {
describe('regression', () => {
it('should generate unique argument names', () => {
const externalIds = newArray(10, 1).map(
(_, index) =>
new o.ExternalReference('@angular/core', `id_${index}_`, {name: `id_${index}_`}),
(_, index) => new o.ExternalReference('@angular/core', `id_${index}_`),
);
const externalIds1 = newArray(10, 1).map(
(_, index) =>
new o.ExternalReference('@angular/core', `id_${index}_1`, {name: `id_${index}_1`}),
(_, index) => new o.ExternalReference('@angular/core', `id_${index}_1`),
);
const ctx = EmitterVisitorContext.createRoot();
const reflectorContext: {[key: string]: string} = {};
Expand Down
260 changes: 3 additions & 257 deletions packages/core/src/render3/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import {Type} from '../interface/type';
import {assertDefined} from '../util/assert';
import {assertLView} from './assert';
import {ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineNgModule, ɵɵdefinePipe} from './definition';
import {getComponentDef} from './def_getters';
import {assertComponentDef} from './errors';
import {refreshView} from './instructions/change_detection';
Expand Down Expand Up @@ -42,74 +41,29 @@ import {
import {assertTNodeType} from './node_assert';
import {destroyLView, removeViewFromDOM} from './node_manipulation';

import * as iframe_attrs_validation from '../sanitization/iframe_attrs_validation';
import * as sanitization from '../sanitization/sanitization';
import * as r3 from './instructions/all';
import {
ɵɵdefineInjectable,
ɵɵdefineInjector,
ɵɵinject,
ɵɵinvalidFactoryDep,
forwardRef,
resolveForwardRef,
} from '../di';
import {registerNgModuleType} from '../linker/ng_module_registration';
import {ɵɵgetInheritedFactory} from './di';
import {ɵɵgetComponentDepsFactory} from './local_compilation';
import {ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵpipe} from './pipe';
import {
ɵɵpureFunction0,
ɵɵpureFunction1,
ɵɵpureFunction2,
ɵɵpureFunction3,
ɵɵpureFunction4,
ɵɵpureFunction5,
ɵɵpureFunction6,
ɵɵpureFunction7,
ɵɵpureFunction8,
ɵɵpureFunctionV,
} from './pure_function';
import {ɵɵsetComponentScope, ɵɵsetNgModuleScope} from './scope';
import {ɵɵresetView, ɵɵenableBindings, ɵɵdisableBindings, ɵɵrestoreView} from './state';
import {ɵɵtemplateRefExtractor} from './view_engine_compatibility_prebound';
import {ɵɵHostDirectivesFeature} from './features/host_directives_feature';
import {ɵɵNgOnChangesFeature} from './features/ng_onchanges_feature';
import {ɵɵProvidersFeature} from './features/providers_feature';
import {ɵɵCopyDefinitionFeature} from './features/copy_definition_feature';
import {ɵɵInheritDefinitionFeature} from './features/inherit_definition_feature';
import {ɵɵInputTransformsFeature} from './features/input_transforms_feature';
import {ɵɵExternalStylesFeature} from './features/external_styles_feature';
import {ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow} from './util/misc_utils';
import {ɵsetClassDebugInfo} from './debug/set_debug_info';

/** Cached environment for all HMR calls. */
let hmrEnvironment: Record<string, unknown> | null = null;

/**
* Replaces the metadata of a component type and re-renders all live instances of the component.
* @param type Class whose metadata will be replaced.
* @param applyMetadata Callback that will apply a new set of metadata on the `type` when invoked.
* @param environment Core runtime environment to use when applying the HMR update.
* @param locals Local symbols from the source location that have to be exposed to the callback.
* @codeGenApi
*/
export function ɵɵreplaceMetadata(
type: Type<unknown>,
applyMetadata: (...args: [Type<unknown>, Record<string, unknown>, ...unknown[]]) => void,
environment: Record<string, unknown>,
locals: unknown[],
) {
ngDevMode && assertComponentDef(type);
const oldDef = getComponentDef(type)!;

if (hmrEnvironment === null) {
hmrEnvironment = getHmrEnv();
}

// The reason `applyMetadata` is a callback that is invoked (almost) immediately is because
// the compiler usually produces more code than just the component definition, e.g. there
// can be functions for embedded views, the variables for the constant pool and `setClassMetadata`
// calls. The callback allows us to keep them isolate from the rest of the app and to invoke
// them at the right time.
applyMetadata.apply(null, [type, hmrEnvironment, ...locals]);
applyMetadata.apply(null, [type, environment, ...locals]);

// If a `tView` hasn't been created yet, it means that this component hasn't been instantianted
// before. In this case there's nothing left for us to do aside from patching it in.
Expand Down Expand Up @@ -278,211 +232,3 @@ function resetProjectionState(tNode: TElementNode): void {
tNode.projection = null;
}
}

/**
* The HMR replacement function needs access to all of `core`. This is similar to the
* `angularCoreEnv`, but without `replaceMetadata` to avoid circular dependencies. Furthermore,
* we can't something like a `nonHmrEnv` that is then combined with `replaceMetadata` to form the
* full environment, because it seems to break tree shaking internally.
*
* TODO(crisbeto): this is a temporary solution, we should be able to pass this in directly.
*/
function getHmrEnv(): Record<string, unknown> {
return {
'ɵɵattribute': r3.ɵɵattribute,
'ɵɵattributeInterpolate1': r3.ɵɵattributeInterpolate1,
'ɵɵattributeInterpolate2': r3.ɵɵattributeInterpolate2,
'ɵɵattributeInterpolate3': r3.ɵɵattributeInterpolate3,
'ɵɵattributeInterpolate4': r3.ɵɵattributeInterpolate4,
'ɵɵattributeInterpolate5': r3.ɵɵattributeInterpolate5,
'ɵɵattributeInterpolate6': r3.ɵɵattributeInterpolate6,
'ɵɵattributeInterpolate7': r3.ɵɵattributeInterpolate7,
'ɵɵattributeInterpolate8': r3.ɵɵattributeInterpolate8,
'ɵɵattributeInterpolateV': r3.ɵɵattributeInterpolateV,
'ɵɵdefineComponent': ɵɵdefineComponent,
'ɵɵdefineDirective': ɵɵdefineDirective,
'ɵɵdefineInjectable': ɵɵdefineInjectable,
'ɵɵdefineInjector': ɵɵdefineInjector,
'ɵɵdefineNgModule': ɵɵdefineNgModule,
'ɵɵdefinePipe': ɵɵdefinePipe,
'ɵɵdirectiveInject': r3.ɵɵdirectiveInject,
'ɵɵgetInheritedFactory': ɵɵgetInheritedFactory,
'ɵɵinject': ɵɵinject,
'ɵɵinjectAttribute': r3.ɵɵinjectAttribute,
'ɵɵinvalidFactory': r3.ɵɵinvalidFactory,
'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
'ɵɵtemplateRefExtractor': ɵɵtemplateRefExtractor,
'ɵɵresetView': ɵɵresetView,
'ɵɵHostDirectivesFeature': ɵɵHostDirectivesFeature,
'ɵɵNgOnChangesFeature': ɵɵNgOnChangesFeature,
'ɵɵProvidersFeature': ɵɵProvidersFeature,
'ɵɵCopyDefinitionFeature': ɵɵCopyDefinitionFeature,
'ɵɵInheritDefinitionFeature': ɵɵInheritDefinitionFeature,
'ɵɵInputTransformsFeature': ɵɵInputTransformsFeature,
'ɵɵExternalStylesFeature': ɵɵExternalStylesFeature,
'ɵɵnextContext': r3.ɵɵnextContext,
'ɵɵnamespaceHTML': r3.ɵɵnamespaceHTML,
'ɵɵnamespaceMathML': r3.ɵɵnamespaceMathML,
'ɵɵnamespaceSVG': r3.ɵɵnamespaceSVG,
'ɵɵenableBindings': ɵɵenableBindings,
'ɵɵdisableBindings': ɵɵdisableBindings,
'ɵɵelementStart': r3.ɵɵelementStart,
'ɵɵelementEnd': r3.ɵɵelementEnd,
'ɵɵelement': r3.ɵɵelement,
'ɵɵelementContainerStart': r3.ɵɵelementContainerStart,
'ɵɵelementContainerEnd': r3.ɵɵelementContainerEnd,
'ɵɵelementContainer': r3.ɵɵelementContainer,
'ɵɵpureFunction0': ɵɵpureFunction0,
'ɵɵpureFunction1': ɵɵpureFunction1,
'ɵɵpureFunction2': ɵɵpureFunction2,
'ɵɵpureFunction3': ɵɵpureFunction3,
'ɵɵpureFunction4': ɵɵpureFunction4,
'ɵɵpureFunction5': ɵɵpureFunction5,
'ɵɵpureFunction6': ɵɵpureFunction6,
'ɵɵpureFunction7': ɵɵpureFunction7,
'ɵɵpureFunction8': ɵɵpureFunction8,
'ɵɵpureFunctionV': ɵɵpureFunctionV,
'ɵɵgetCurrentView': r3.ɵɵgetCurrentView,
'ɵɵrestoreView': ɵɵrestoreView,
'ɵɵlistener': r3.ɵɵlistener,
'ɵɵprojection': r3.ɵɵprojection,
'ɵɵsyntheticHostProperty': r3.ɵɵsyntheticHostProperty,
'ɵɵsyntheticHostListener': r3.ɵɵsyntheticHostListener,
'ɵɵpipeBind1': ɵɵpipeBind1,
'ɵɵpipeBind2': ɵɵpipeBind2,
'ɵɵpipeBind3': ɵɵpipeBind3,
'ɵɵpipeBind4': ɵɵpipeBind4,
'ɵɵpipeBindV': ɵɵpipeBindV,
'ɵɵprojectionDef': r3.ɵɵprojectionDef,
'ɵɵhostProperty': r3.ɵɵhostProperty,
'ɵɵproperty': r3.ɵɵproperty,
'ɵɵpropertyInterpolate': r3.ɵɵpropertyInterpolate,
'ɵɵpropertyInterpolate1': r3.ɵɵpropertyInterpolate1,
'ɵɵpropertyInterpolate2': r3.ɵɵpropertyInterpolate2,
'ɵɵpropertyInterpolate3': r3.ɵɵpropertyInterpolate3,
'ɵɵpropertyInterpolate4': r3.ɵɵpropertyInterpolate4,
'ɵɵpropertyInterpolate5': r3.ɵɵpropertyInterpolate5,
'ɵɵpropertyInterpolate6': r3.ɵɵpropertyInterpolate6,
'ɵɵpropertyInterpolate7': r3.ɵɵpropertyInterpolate7,
'ɵɵpropertyInterpolate8': r3.ɵɵpropertyInterpolate8,
'ɵɵpropertyInterpolateV': r3.ɵɵpropertyInterpolateV,
'ɵɵpipe': ɵɵpipe,
'ɵɵqueryRefresh': r3.ɵɵqueryRefresh,
'ɵɵqueryAdvance': r3.ɵɵqueryAdvance,
'ɵɵviewQuery': r3.ɵɵviewQuery,
'ɵɵviewQuerySignal': r3.ɵɵviewQuerySignal,
'ɵɵloadQuery': r3.ɵɵloadQuery,
'ɵɵcontentQuery': r3.ɵɵcontentQuery,
'ɵɵcontentQuerySignal': r3.ɵɵcontentQuerySignal,
'ɵɵreference': r3.ɵɵreference,
'ɵɵclassMap': r3.ɵɵclassMap,
'ɵɵclassMapInterpolate1': r3.ɵɵclassMapInterpolate1,
'ɵɵclassMapInterpolate2': r3.ɵɵclassMapInterpolate2,
'ɵɵclassMapInterpolate3': r3.ɵɵclassMapInterpolate3,
'ɵɵclassMapInterpolate4': r3.ɵɵclassMapInterpolate4,
'ɵɵclassMapInterpolate5': r3.ɵɵclassMapInterpolate5,
'ɵɵclassMapInterpolate6': r3.ɵɵclassMapInterpolate6,
'ɵɵclassMapInterpolate7': r3.ɵɵclassMapInterpolate7,
'ɵɵclassMapInterpolate8': r3.ɵɵclassMapInterpolate8,
'ɵɵclassMapInterpolateV': r3.ɵɵclassMapInterpolateV,
'ɵɵstyleMap': r3.ɵɵstyleMap,
'ɵɵstyleMapInterpolate1': r3.ɵɵstyleMapInterpolate1,
'ɵɵstyleMapInterpolate2': r3.ɵɵstyleMapInterpolate2,
'ɵɵstyleMapInterpolate3': r3.ɵɵstyleMapInterpolate3,
'ɵɵstyleMapInterpolate4': r3.ɵɵstyleMapInterpolate4,
'ɵɵstyleMapInterpolate5': r3.ɵɵstyleMapInterpolate5,
'ɵɵstyleMapInterpolate6': r3.ɵɵstyleMapInterpolate6,
'ɵɵstyleMapInterpolate7': r3.ɵɵstyleMapInterpolate7,
'ɵɵstyleMapInterpolate8': r3.ɵɵstyleMapInterpolate8,
'ɵɵstyleMapInterpolateV': r3.ɵɵstyleMapInterpolateV,
'ɵɵstyleProp': r3.ɵɵstyleProp,
'ɵɵstylePropInterpolate1': r3.ɵɵstylePropInterpolate1,
'ɵɵstylePropInterpolate2': r3.ɵɵstylePropInterpolate2,
'ɵɵstylePropInterpolate3': r3.ɵɵstylePropInterpolate3,
'ɵɵstylePropInterpolate4': r3.ɵɵstylePropInterpolate4,
'ɵɵstylePropInterpolate5': r3.ɵɵstylePropInterpolate5,
'ɵɵstylePropInterpolate6': r3.ɵɵstylePropInterpolate6,
'ɵɵstylePropInterpolate7': r3.ɵɵstylePropInterpolate7,
'ɵɵstylePropInterpolate8': r3.ɵɵstylePropInterpolate8,
'ɵɵstylePropInterpolateV': r3.ɵɵstylePropInterpolateV,
'ɵɵclassProp': r3.ɵɵclassProp,
'ɵɵadvance': r3.ɵɵadvance,
'ɵɵtemplate': r3.ɵɵtemplate,
'ɵɵconditional': r3.ɵɵconditional,
'ɵɵdefer': r3.ɵɵdefer,
'ɵɵdeferWhen': r3.ɵɵdeferWhen,
'ɵɵdeferOnIdle': r3.ɵɵdeferOnIdle,
'ɵɵdeferOnImmediate': r3.ɵɵdeferOnImmediate,
'ɵɵdeferOnTimer': r3.ɵɵdeferOnTimer,
'ɵɵdeferOnHover': r3.ɵɵdeferOnHover,
'ɵɵdeferOnInteraction': r3.ɵɵdeferOnInteraction,
'ɵɵdeferOnViewport': r3.ɵɵdeferOnViewport,
'ɵɵdeferPrefetchWhen': r3.ɵɵdeferPrefetchWhen,
'ɵɵdeferPrefetchOnIdle': r3.ɵɵdeferPrefetchOnIdle,
'ɵɵdeferPrefetchOnImmediate': r3.ɵɵdeferPrefetchOnImmediate,
'ɵɵdeferPrefetchOnTimer': r3.ɵɵdeferPrefetchOnTimer,
'ɵɵdeferPrefetchOnHover': r3.ɵɵdeferPrefetchOnHover,
'ɵɵdeferPrefetchOnInteraction': r3.ɵɵdeferPrefetchOnInteraction,
'ɵɵdeferPrefetchOnViewport': r3.ɵɵdeferPrefetchOnViewport,
'ɵɵdeferHydrateWhen': r3.ɵɵdeferHydrateWhen,
'ɵɵdeferHydrateNever': r3.ɵɵdeferHydrateNever,
'ɵɵdeferHydrateOnIdle': r3.ɵɵdeferHydrateOnIdle,
'ɵɵdeferHydrateOnImmediate': r3.ɵɵdeferHydrateOnImmediate,
'ɵɵdeferHydrateOnTimer': r3.ɵɵdeferHydrateOnTimer,
'ɵɵdeferHydrateOnHover': r3.ɵɵdeferHydrateOnHover,
'ɵɵdeferHydrateOnInteraction': r3.ɵɵdeferHydrateOnInteraction,
'ɵɵdeferHydrateOnViewport': r3.ɵɵdeferHydrateOnViewport,
'ɵɵdeferEnableTimerScheduling': r3.ɵɵdeferEnableTimerScheduling,
'ɵɵrepeater': r3.ɵɵrepeater,
'ɵɵrepeaterCreate': r3.ɵɵrepeaterCreate,
'ɵɵrepeaterTrackByIndex': r3.ɵɵrepeaterTrackByIndex,
'ɵɵrepeaterTrackByIdentity': r3.ɵɵrepeaterTrackByIdentity,
'ɵɵcomponentInstance': r3.ɵɵcomponentInstance,
'ɵɵtext': r3.ɵɵtext,
'ɵɵtextInterpolate': r3.ɵɵtextInterpolate,
'ɵɵtextInterpolate1': r3.ɵɵtextInterpolate1,
'ɵɵtextInterpolate2': r3.ɵɵtextInterpolate2,
'ɵɵtextInterpolate3': r3.ɵɵtextInterpolate3,
'ɵɵtextInterpolate4': r3.ɵɵtextInterpolate4,
'ɵɵtextInterpolate5': r3.ɵɵtextInterpolate5,
'ɵɵtextInterpolate6': r3.ɵɵtextInterpolate6,
'ɵɵtextInterpolate7': r3.ɵɵtextInterpolate7,
'ɵɵtextInterpolate8': r3.ɵɵtextInterpolate8,
'ɵɵtextInterpolateV': r3.ɵɵtextInterpolateV,
'ɵɵi18n': r3.ɵɵi18n,
'ɵɵi18nAttributes': r3.ɵɵi18nAttributes,
'ɵɵi18nExp': r3.ɵɵi18nExp,
'ɵɵi18nStart': r3.ɵɵi18nStart,
'ɵɵi18nEnd': r3.ɵɵi18nEnd,
'ɵɵi18nApply': r3.ɵɵi18nApply,
'ɵɵi18nPostprocess': r3.ɵɵi18nPostprocess,
'ɵɵresolveWindow': ɵɵresolveWindow,
'ɵɵresolveDocument': ɵɵresolveDocument,
'ɵɵresolveBody': ɵɵresolveBody,
'ɵɵsetComponentScope': ɵɵsetComponentScope,
'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope,
'ɵɵregisterNgModuleType': registerNgModuleType,
'ɵɵgetComponentDepsFactory': ɵɵgetComponentDepsFactory,
'ɵsetClassDebugInfo': ɵsetClassDebugInfo,
'ɵɵdeclareLet': r3.ɵɵdeclareLet,
'ɵɵstoreLet': r3.ɵɵstoreLet,
'ɵɵreadContextLet': r3.ɵɵreadContextLet,

'ɵɵsanitizeHtml': sanitization.ɵɵsanitizeHtml,
'ɵɵsanitizeStyle': sanitization.ɵɵsanitizeStyle,
'ɵɵsanitizeResourceUrl': sanitization.ɵɵsanitizeResourceUrl,
'ɵɵsanitizeScript': sanitization.ɵɵsanitizeScript,
'ɵɵsanitizeUrl': sanitization.ɵɵsanitizeUrl,
'ɵɵsanitizeUrlOrResourceUrl': sanitization.ɵɵsanitizeUrlOrResourceUrl,
'ɵɵtrustConstantHtml': sanitization.ɵɵtrustConstantHtml,
'ɵɵtrustConstantResourceUrl': sanitization.ɵɵtrustConstantResourceUrl,
'ɵɵvalidateIframeAttribute': iframe_attrs_validation.ɵɵvalidateIframeAttribute,

'forwardRef': forwardRef,
'resolveForwardRef': resolveForwardRef,

'ɵɵtwoWayProperty': r3.ɵɵtwoWayProperty,
'ɵɵtwoWayBindingSet': r3.ɵɵtwoWayBindingSet,
'ɵɵtwoWayListener': r3.ɵɵtwoWayListener,
};
}
24 changes: 15 additions & 9 deletions packages/core/test/acceptance/hmr_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {compileComponent} from '@angular/core/src/render3/jit/directive';
import {angularCoreEnv} from '@angular/core/src/render3/jit/environment';
import {clearTranslations, loadTranslations} from '@angular/localize';
import {computeMsgId} from '@angular/compiler';

Expand Down Expand Up @@ -1955,15 +1956,20 @@ describe('hot module replacement', () => {
const CREATED_INITIALLY_MARKER = '__ngCreatedInitially__';

function replaceMetadata(type: Type<unknown>, metadata: Component) {
ɵɵreplaceMetadata(type, () => {
// TODO: the content of this callback is a hacky workaround to invoke the compiler in a test.
// in reality the callback will be generated by the compiler to be something along the lines
// of `MyComp[ɵcmp] = /* metadata */`.
// TODO: in reality this callback should also include `setClassMetadata` and
// `setClassDebugInfo`.
(type as any)[ɵNG_COMP_DEF] = null;
compileComponent(type, metadata);
}, []);
ɵɵreplaceMetadata(
type,
() => {
// TODO: the content of this callback is a hacky workaround to invoke the compiler in a test.
// in reality the callback will be generated by the compiler to be something along the lines
// of `MyComp[ɵcmp] = /* metadata */`.
// TODO: in reality this callback should also include `setClassMetadata` and
// `setClassDebugInfo`.
(type as any)[ɵNG_COMP_DEF] = null;
compileComponent(type, metadata);
},
angularCoreEnv,
[],
);
}

function expectHTML(element: HTMLElement, expectation: string) {
Expand Down