feat(core): support TypeScript 4.7 (#45749)

Adds support for TypeScript 4.7. Changes include:
* Bumping the TS version as well as some Bazel dependencies to include https://github.com/bazelbuild/rules_nodejs/pull/3420.
* Adding a backwards-compatibility layer for calls to `updateTypeParameterDeclaration`.
* Making `LView` generic in order to make it easier to type the context based on the usage. Currently the context can be 4 different types which coupled with stricter type checking would required a lot of extra casting all over `core`.
* Fixing a bunch of miscellaneous type errors.
* Removing assertions of `ReferenceEntry.isDefinition` in a few of the language service tests. The field isn't returned by TS anymore and we weren't using it for anything.
* Resolving in error in the language service that was caused by TS attempting to parse HTML files when we try to open them. Previous TS was silently setting them as `ScriptKind.Unknown` and ignoring the errors, but now it throws. I've worked around it by setting them as `ScriptKind.JSX`.

PR Close #45749
This commit is contained in:
Kristiyan Kostadinov
2022-04-29 14:38:15 +02:00
committed by Dylan Hunn
parent fcc548a95f
commit 29039fcdbc
48 changed files with 419 additions and 176 deletions
+4 -3
View File
@@ -78,16 +78,17 @@ class ChainedInjector implements Injector {
constructor(private injector: Injector, private parentInjector: Injector) {}
get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags): T {
const value = this.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as T, flags);
const value = this.injector.get<T|typeof NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR>(
token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags);
if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
notFoundValue === (NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as unknown as T)) {
// Return the value from the root element injector when
// - it provides it
// (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
// - the module injector should not be checked
// (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
return value;
return value as T;
}
return this.parentInjector.get(token, notFoundValue, flags);
@@ -196,10 +196,10 @@ export function readPatchedData(target: any): LView|LContext|null {
return (typeof data === 'number') ? getLViewById(data) : data || null;
}
export function readPatchedLView(target: any): LView|null {
export function readPatchedLView<T>(target: any): LView<T>|null {
const value = readPatchedData(target);
if (value) {
return isLView(value) ? value : value.lView;
return (isLView(value) ? value : value.lView) as LView<T>;
}
return null;
}
+3 -2
View File
@@ -489,7 +489,7 @@ function lookupTokenUsingNodeInjector<T>(
// At this point, we have an injector which *may* contain the token, so we step through
// the providers and directives associated with the injector's corresponding node to get
// the instance.
const instance: T|null = searchTokensOnInjector<T>(
const instance: T|{}|null = searchTokensOnInjector<T>(
injectorIndex, lView, token, previousTView, flags, hostTElementNode);
if (instance !== NOT_FOUND) {
return instance;
@@ -803,7 +803,8 @@ function lookupTokenUsingEmbeddedInjector<T>(
// Before we go to the next LView, check if the token exists on the current embedded injector.
const embeddedViewInjector = currentLView[EMBEDDED_VIEW_INJECTOR];
if (embeddedViewInjector) {
const embeddedViewInjectorValue = embeddedViewInjector.get(token, NOT_FOUND as T, flags);
const embeddedViewInjectorValue =
embeddedViewInjector.get(token, NOT_FOUND as T | {}, flags);
if (embeddedViewInjectorValue !== NOT_FOUND) {
return embeddedViewInjectorValue;
}
@@ -10,6 +10,7 @@ import {assertDefined} from '../../util/assert';
import {getComponentViewByInstance} from '../context_discovery';
import {CONTEXT, RootContext, RootContextFlags, TVIEW} from '../interfaces/view';
import {getRootView} from '../util/view_traversal_utils';
import {detectChangesInternal, markViewDirty, scheduleTick, tickRootContext} from './shared';
/**
@@ -53,7 +54,7 @@ export function markDirty(component: {}): void {
* single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
* be changed when calling `renderComponent` and providing the `scheduler` option.
*/
export function tick<T>(component: T): void {
export function tick(component: {}): void {
const rootView = getRootView(component);
const rootContext = rootView[CONTEXT] as RootContext;
tickRootContext(rootContext);
@@ -40,7 +40,7 @@ import {getOrCreateLViewCleanup, getOrCreateTViewCleanup, handleError, loadCompo
export function ɵɵlistener(
eventName: string, listenerFn: (e?: any) => any, useCapture?: boolean,
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener {
const lView = getLView();
const lView = getLView<{}|null>();
const tView = getTView();
const tNode = getCurrentTNode()!;
listenerInternal(
@@ -73,7 +73,7 @@ export function ɵɵlistener(
export function ɵɵsyntheticHostListener(
eventName: string, listenerFn: (e?: any) => any): typeof ɵɵsyntheticHostListener {
const tNode = getCurrentTNode()!;
const lView = getLView();
const lView = getLView<{}|null>();
const tView = getTView();
const currentDef = getCurrentDirectiveDef(tView.data);
const renderer = loadComponentRenderer(currentDef, tNode, lView);
@@ -114,7 +114,7 @@ function findExistingListener(
}
function listenerInternal(
tView: TView, lView: LView, renderer: Renderer3, tNode: TNode, eventName: string,
tView: TView, lView: LView<{}|null>, renderer: Renderer3, tNode: TNode, eventName: string,
listenerFn: (e?: any) => any, useCapture: boolean,
eventTargetResolver?: GlobalTargetResolver): void {
const isTNodeDirectiveHost = isDirectiveHost(tNode);
@@ -250,7 +250,7 @@ function executeListenerWithErrorHandling(
* (the procedural renderer does this already, so in those cases, we should skip)
*/
function wrapListener(
tNode: TNode, lView: LView, context: {}|null, listenerFn: (e?: any) => any,
tNode: TNode, lView: LView<{}|null>, context: {}|null, listenerFn: (e?: any) => any,
wrapWithPreventDefault: boolean): EventListener {
// Note: we are performing most of the work in the listener function itself
// to optimize listener registration.
@@ -73,7 +73,7 @@ interface TViewDebug extends ITView {
*
* Simple slice will keep the same type, and we need it to be LView
*/
export function cloneToLViewFromTViewBlueprint(tView: TView): LView {
export function cloneToLViewFromTViewBlueprint<T>(tView: TView): LView<T> {
const debugTView = tView as TViewDebug;
const lView = getLViewToClone(debugTView.type, tView.template && tView.template.name);
return lView.concat(tView.blueprint) as any;
@@ -387,9 +387,9 @@ export function attachLContainerDebug(lContainer: LContainer) {
attachDebugObject(lContainer, new LContainerDebug(lContainer));
}
export function toDebug(obj: LView): ILViewDebug;
export function toDebug(obj: LView|null): ILViewDebug|null;
export function toDebug(obj: LView|LContainer|null): ILViewDebug|ILContainerDebug|null;
export function toDebug<T>(obj: LView<T>): ILViewDebug<T>;
export function toDebug<T>(obj: LView<T>|null): ILViewDebug<T>|null;
export function toDebug<T>(obj: LView<T>|LContainer|null): ILViewDebug<T>|ILContainerDebug|null;
export function toDebug(obj: any): any {
if (obj) {
const debug = (obj as any).debug;
@@ -432,8 +432,8 @@ function toHtml(value: any, includeChildren: boolean = false): string|null {
return null;
}
export class LViewDebug implements ILViewDebug {
constructor(private readonly _raw_lView: LView) {}
export class LViewDebug<T = unknown> implements ILViewDebug<T> {
constructor(private readonly _raw_lView: LView<T>) {}
/**
* Flags associated with the `LView` unpacked into a more readable state.
@@ -453,8 +453,8 @@ export class LViewDebug implements ILViewDebug {
indexWithinInitPhase: flags >> LViewFlags.IndexWithinInitPhaseShift,
};
}
get parent(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[PARENT]);
get parent(): ILViewDebug<T>|ILContainerDebug|null {
return toDebug<T>(this._raw_lView[PARENT] as LView<T>| LContainer | null);
}
get hostHTML(): string|null {
return toHtml(this._raw_lView[HOST], true);
@@ -462,7 +462,7 @@ export class LViewDebug implements ILViewDebug {
get html(): string {
return (this.nodes || []).map(mapToHTML).join('');
}
get context(): {}|null {
get context(): T {
return this._raw_lView[CONTEXT];
}
/**
@@ -498,8 +498,8 @@ export class LViewDebug implements ILViewDebug {
get childHead(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[CHILD_HEAD]);
}
get next(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[NEXT]);
get next(): ILViewDebug<T>|ILContainerDebug|null {
return toDebug<T>(this._raw_lView[NEXT] as LView<T>| LContainer | null);
}
get childTail(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[CHILD_TAIL]);
@@ -534,11 +534,11 @@ export class LViewDebug implements ILViewDebug {
/**
* Normalized view of child views (and containers) attached at this location.
*/
get childViews(): Array<ILViewDebug|ILContainerDebug> {
const childViews: Array<ILViewDebug|ILContainerDebug> = [];
get childViews(): Array<ILViewDebug<T>|ILContainerDebug> {
const childViews: Array<ILViewDebug<T>|ILContainerDebug> = [];
let child = this.childHead;
while (child) {
childViews.push(child);
childViews.push(child as ILViewDebug<T>| ILContainerDebug);
child = child.next;
}
return childViews;
@@ -292,20 +292,20 @@ export function allocExpando(
* - updating static queries (if any);
* - creating child components defined in a given view.
*/
export function renderView<T>(tView: TView, lView: LView, context: T): void {
export function renderView<T>(tView: TView, lView: LView<T>, context: T): void {
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
enterView(lView);
try {
const viewQuery = tView.viewQuery;
if (viewQuery !== null) {
executeViewQueryFn(RenderFlags.Create, viewQuery, context);
executeViewQueryFn<T>(RenderFlags.Create, viewQuery, context);
}
// Execute a template associated with this view, if it exists. A template function might not be
// defined for the root component views.
const templateFn = tView.template;
if (templateFn !== null) {
executeTemplate(tView, lView, templateFn, RenderFlags.Create, context);
executeTemplate<T>(tView, lView, templateFn, RenderFlags.Create, context);
}
// This needs to be set before children are processed to support recursive components.
@@ -328,7 +328,7 @@ export function renderView<T>(tView: TView, lView: LView, context: T): void {
// in case a child component has projected a container. The LContainer needs
// to exist so the embedded views are properly attached by the container.
if (tView.staticViewQueries) {
executeViewQueryFn(RenderFlags.Update, tView.viewQuery!, context);
executeViewQueryFn<T>(RenderFlags.Update, tView.viewQuery!, context);
}
// Render child component views.
@@ -439,7 +439,7 @@ export function refreshView<T>(
// refresh, the template might not yet be inserted.
const viewQuery = tView.viewQuery;
if (viewQuery !== null) {
executeViewQueryFn(RenderFlags.Update, viewQuery, context);
executeViewQueryFn<T>(RenderFlags.Update, viewQuery, context);
}
// execute view hooks (AfterViewInit, AfterViewChecked)
@@ -507,7 +507,7 @@ export function renderComponentOrTemplate<T>(
}
function executeTemplate<T>(
tView: TView, lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
tView: TView, lView: LView<T>, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
const prevSelectedIndex = getSelectedIndex();
const isUpdatePhase = rf & RenderFlags.Update;
try {
@@ -520,14 +520,14 @@ function executeTemplate<T>(
const preHookType =
isUpdatePhase ? ProfilerEvent.TemplateUpdateStart : ProfilerEvent.TemplateCreateStart;
profiler(preHookType, context);
profiler(preHookType, context as unknown as {});
templateFn(rf, context);
} finally {
setSelectedIndex(prevSelectedIndex);
const postHookType =
isUpdatePhase ? ProfilerEvent.TemplateUpdateEnd : ProfilerEvent.TemplateCreateEnd;
profiler(postHookType, context);
profiler(postHookType, context as unknown as {});
}
}
@@ -1995,7 +1995,7 @@ export function checkNoChangesInRootView(lView: LView): void {
}
function executeViewQueryFn<T>(
flags: RenderFlags, viewQueryFn: ViewQueriesFunction<{}>, component: T): void {
flags: RenderFlags, viewQueryFn: ViewQueriesFunction<T>, component: T): void {
ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
setCurrentQueryIndex(0);
viewQueryFn(flags, component);
+6 -6
View File
@@ -78,7 +78,7 @@ export interface OpaqueViewState {
* Keeping separate state for each view facilities view insertion / deletion, so we
* don't have to edit the data array based on which views are present.
*/
export interface LView extends Array<any> {
export interface LView<T = unknown> extends Array<any> {
/**
* Human readable representation of the `LView`.
*
@@ -180,7 +180,7 @@ export interface LView extends Array<any> {
* - For non-root components, the context is the component instance,
* - For inline views, the context is null.
*/
[CONTEXT]: {}|RootContext|null;
[CONTEXT]: T;
/** An optional Module Injector to be used as fall back after Element Injectors are consulted. */
readonly[INJECTOR]: Injector|null;
@@ -818,7 +818,7 @@ export const enum RootContextFlags {
* RootContext contains information which is shared for all components which
* were bootstrapped with {@link renderComponent}.
*/
export interface RootContext {
export interface RootContext<T = unknown> {
/**
* A function used for scheduling change detection in the future. Usually
* this is `requestAnimationFrame`.
@@ -836,7 +836,7 @@ export interface RootContext {
* RootComponents - The components that were instantiated by the call to
* {@link renderComponent}.
*/
components: {}[];
components: T[];
/**
* The player flushing handler to kick off all animations
@@ -935,7 +935,7 @@ export const unusedValueExportToPlacateAjd = 1;
* `LViewDebug` for easier debugging and test writing. It is the intent of `LViewDebug` to be used
* in tests.
*/
export interface LViewDebug {
export interface LViewDebug<T = unknown> {
/**
* Flags associated with the `LView` unpacked into a more readable state.
*
@@ -973,7 +973,7 @@ export interface LViewDebug {
*
* (Usually the component)
*/
readonly context: {}|null;
readonly context: T;
/**
* Hierarchical tree of nodes.
+2 -1
View File
@@ -9,6 +9,7 @@
import {PipeTransform} from '../change_detection/pipe_transform';
import {setInjectImplementation} from '../di/inject_switch';
import {RuntimeError, RuntimeErrorCode} from '../errors';
import {Type} from '../interface/type';
import {getFactoryDef} from './definition_factory';
import {setIncludeViewProviders} from './di';
@@ -83,7 +84,7 @@ function getPipeDef(name: string, registry: PipeDefList|null): PipeDef<any>|unde
}
if (ngDevMode) {
const lView = getLView();
const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
const declarationLView = lView[DECLARATION_COMPONENT_VIEW] as LView<Type<unknown>>;
const context = declarationLView[CONTEXT];
const component = context ? ` in the '${context.constructor.name}' component` : '';
throw new RuntimeError(
+4 -4
View File
@@ -266,8 +266,8 @@ export function ɵɵdisableBindings(): void {
/**
* Return the current `LView`.
*/
export function getLView(): LView {
return instructionState.lFrame.lView;
export function getLView<T>(): LView<T> {
return instructionState.lFrame.lView as LView<T>;
}
/**
@@ -294,7 +294,7 @@ export function getTView(): TView {
*/
export function ɵɵrestoreView<T = any>(viewToRestore: OpaqueViewState): T {
instructionState.lFrame.contextLView = viewToRestore as any as LView;
return (viewToRestore as any as LView)[CONTEXT] as T;
return (viewToRestore as any as LView)[CONTEXT] as unknown as T;
}
@@ -658,7 +658,7 @@ export function leaveView() {
export function nextContextImpl<T = any>(level: number): T {
const contextLView = instructionState.lFrame.contextLView =
walkUpViews(level, instructionState.lFrame.contextLView!);
return contextLView[CONTEXT] as T;
return contextLView[CONTEXT] as unknown as T;
}
function walkUpViews(nestingLevel: number, currentView: LView): LView {
@@ -19,7 +19,7 @@ import {LContext} from '../interfaces/context';
import {DirectiveDef} from '../interfaces/definition';
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
import {isLView} from '../interfaces/type_checks';
import {CLEANUP, CONTEXT, DebugNode, FLAGS, LView, LViewFlags, T_HOST, TVIEW, TViewType} from '../interfaces/view';
import {CLEANUP, CONTEXT, DebugNode, FLAGS, LView, LViewFlags, RootContext, T_HOST, TVIEW, TViewType} from '../interfaces/view';
import {stringifyForError} from './stringify_utils';
import {getLViewParent, getRootContext} from './view_traversal_utils';
@@ -67,7 +67,7 @@ export function getComponent<T>(element: Element): T|null {
context.component = getComponentAtNodeIndex(context.nodeIndex, lView);
}
return context.component as T;
return context.component as unknown as T;
}
@@ -83,7 +83,7 @@ export function getComponent<T>(element: Element): T|null {
* @publicApi
* @globalApi ng
*/
export function getContext<T>(element: Element): T|null {
export function getContext<T extends({} | RootContext)>(element: Element): T|null {
assertDomElement(element);
const context = getLContext(element)!;
const lView = context ? context.lView : null;
@@ -114,7 +114,7 @@ export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
while (lView[TVIEW].type === TViewType.Embedded && (parent = getLViewParent(lView)!)) {
lView = parent;
}
return lView[FLAGS] & LViewFlags.IsRoot ? null : lView[CONTEXT] as T;
return lView[FLAGS] & LViewFlags.IsRoot ? null : lView[CONTEXT] as unknown as T;
}
/**
@@ -129,8 +129,8 @@ export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
* @globalApi ng
*/
export function getRootComponents(elementOrDir: Element|{}): {}[] {
const lView = readPatchedLView(elementOrDir);
return lView !== null ? [...getRootContext(lView).components] : [];
const lView = readPatchedLView<{}>(elementOrDir);
return lView !== null ? [...getRootContext(lView).components as unknown as {}[]] : [];
}
/**
@@ -31,14 +31,14 @@ export function getLViewParent(lView: LView): LView|null {
*
* @param componentOrLView any component or `LView`
*/
export function getRootView(componentOrLView: LView|{}): LView {
export function getRootView<T>(componentOrLView: LView|{}): LView<T> {
ngDevMode && assertDefined(componentOrLView, 'component');
let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView)!;
while (lView && !(lView[FLAGS] & LViewFlags.IsRoot)) {
lView = getLViewParent(lView)!;
}
ngDevMode && assertLView(lView);
return lView;
return lView as LView<T>;
}
/**
@@ -48,7 +48,7 @@ export function getRootView(componentOrLView: LView|{}): LView {
*
* @param viewOrComponent the `LView` or component to get the root context for.
*/
export function getRootContext(viewOrComponent: LView|{}): RootContext {
export function getRootContext<T>(viewOrComponent: LView<T>|{}): RootContext {
const rootView = getRootView(viewOrComponent);
ngDevMode &&
assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
+4 -4
View File
@@ -60,11 +60,11 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
private _cdRefInjectingView?: LView) {}
get context(): T {
return this._lView[CONTEXT] as T;
return this._lView[CONTEXT] as unknown as T;
}
set context(value: T) {
this._lView[CONTEXT] = value;
this._lView[CONTEXT] = value as unknown as {};
}
get destroyed(): boolean {
@@ -271,7 +271,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
* See {@link ChangeDetectorRef#detach detach} for more information.
*/
detectChanges(): void {
detectChangesInternal(this._lView[TVIEW], this._lView, this.context);
detectChangesInternal(this._lView[TVIEW], this._lView, this.context as unknown as {});
}
/**
@@ -281,7 +281,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
* introduce other changes.
*/
checkNoChanges(): void {
checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context as unknown as {});
}
attachToViewContainerRef() {
+1 -1
View File
@@ -11,7 +11,7 @@ export function getNativeRequestAnimationFrame() {
let nativeRequestAnimationFrame: (callback: FrameRequestCallback) => number =
global['requestAnimationFrame'];
let nativeCancelAnimationFrame: (handle: number) => void = global['cancelAnimationFrame'];
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame! && nativeCancelAnimationFrame!) {
// use unpatched version of requestAnimationFrame(native delegate) if possible
// to avoid another Change detection
const unpatchedRequestAnimationFrame =