UNPKG

@angular/compiler-cli

Version:
1,330 lines (1,317 loc) • 562 kB
import {createRequire as __cjsCompatRequire} from 'module'; const require = __cjsCompatRequire(import.meta.url); import { AmbientImport, ClassMemberAccessLevel, ClassMemberKind, CompletionKind, DOC_PAGE_BASE_URL, DynamicValue, EnumValue, Environment, ErrorCode, ExpressionIdentifier, FatalDiagnosticError, ImportFlags, ImportManager, ImportedSymbolsTracker, MetaKind, OptimizeFor, PotentialImportKind, PotentialImportMode, Reference, ReferenceEmitEnvironment, ReferenceEmitKind, RegistryDomSchemaChecker, SymbolBuilder, SymbolKind, SyntheticValue, TcbInliningRequirement, TypeParameterEmitter, TypeScriptReflectionHost, assertSuccessfulReferenceEmit, attachDefaultImportDeclaration, classMemberAccessLevelToString, describeResolvedType, ensureTypeCheckFilePreparationImports, entityNameToValue, extractDirectiveTypeCheckMeta, filterToMembersWithDecorator, findAllMatchingNodes, findFirstMatchingNode, findTypeCheckBlock, flattenInheritedDirectiveMetadata, generateInlineTypeCtor, generateTcbTypeParameters, getDefaultImportDeclaration, getProjectRelativePath, getSourceFile, getSourceFileOrNull, getSourceMapping, getTokenAtPosition, getTypeCheckId, hasInjectableFields, identifierOfNode, isAliasImportDeclaration, isDirectiveDeclaration, isDtsPath, isFromDtsFile, isHostDirectiveMetaForGlobalMode, isNamedClassDeclaration, isNonDeclarationTsPath, isSymbolAliasOf, isSymbolWithValueDeclaration, loadIsReferencedAliasDeclarationPatch, makeDiagnostic, makeDiagnosticChain, makeRelatedInformation, makeTemplateDiagnostic, ngErrorCode, nodeNameForError, presetImportManagerForceNamespaceImports, reflectClassMember, reflectObjectLiteral, requiresInlineTypeCheckBlock, requiresInlineTypeCtor, tempPrint, toUnredirectedSourceFile, traceDynamicValue, translateExpression, translateStatement, translateType, typeNodeToValueExpr } from "./chunk-QY6RCOQ6.js"; import { absoluteFrom, absoluteFromSourceFile, getSourceFileOrError, relative } from "./chunk-UTWH365F.js"; // packages/compiler-cli/src/ngtsc/transform/jit/src/downlevel_decorators_transform.js import ts from "typescript"; function isAngularDecorator(decorator, isCore) { return isCore || decorator.import !== null && decorator.import.from === "@angular/core"; } var DECORATOR_INVOCATION_JSDOC_TYPE = "!Array<{type: !Function, args: (undefined|!Array<?>)}>"; function extractMetadataFromSingleDecorator(decorator, diagnostics) { const metadataProperties = []; const expr = decorator.expression; switch (expr.kind) { case ts.SyntaxKind.Identifier: metadataProperties.push(ts.factory.createPropertyAssignment("type", expr)); break; case ts.SyntaxKind.CallExpression: const call = expr; metadataProperties.push(ts.factory.createPropertyAssignment("type", call.expression)); if (call.arguments.length) { const args = []; for (const arg of call.arguments) { args.push(arg); } const argsArrayLiteral = ts.factory.createArrayLiteralExpression(ts.factory.createNodeArray(args, true)); metadataProperties.push(ts.factory.createPropertyAssignment("args", argsArrayLiteral)); } break; default: diagnostics.push({ file: decorator.getSourceFile(), start: decorator.getStart(), length: decorator.getEnd() - decorator.getStart(), messageText: `${ts.SyntaxKind[decorator.kind]} not implemented in gathering decorator metadata.`, category: ts.DiagnosticCategory.Error, code: 0 }); break; } return ts.factory.createObjectLiteralExpression(metadataProperties); } function createCtorParametersClassProperty(diagnostics, entityNameToExpression, ctorParameters, isClosureCompilerEnabled) { const params = []; for (const ctorParam of ctorParameters) { if (!ctorParam.type && ctorParam.decorators.length === 0) { params.push(ts.factory.createNull()); continue; } const paramType = ctorParam.type ? typeReferenceToExpression(entityNameToExpression, ctorParam.type) : void 0; const members = [ ts.factory.createPropertyAssignment("type", paramType || ts.factory.createIdentifier("undefined")) ]; const decorators = []; for (const deco of ctorParam.decorators) { decorators.push(extractMetadataFromSingleDecorator(deco, diagnostics)); } if (decorators.length) { members.push(ts.factory.createPropertyAssignment("decorators", ts.factory.createArrayLiteralExpression(decorators))); } params.push(ts.factory.createObjectLiteralExpression(members)); } const initializer = ts.factory.createArrowFunction(void 0, void 0, [], void 0, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createArrayLiteralExpression(params, true)); const ctorProp = ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.StaticKeyword)], "ctorParameters", void 0, void 0, initializer); if (isClosureCompilerEnabled) { ts.setSyntheticLeadingComments(ctorProp, [ { kind: ts.SyntaxKind.MultiLineCommentTrivia, text: [ `*`, ` * @type {function(): !Array<(null|{`, ` * type: ?,`, ` * decorators: (undefined|${DECORATOR_INVOCATION_JSDOC_TYPE}),`, ` * })>}`, ` * @nocollapse`, ` ` ].join("\n"), pos: -1, end: -1, hasTrailingNewLine: true } ]); } return ctorProp; } function typeReferenceToExpression(entityNameToExpression, node) { let kind = node.kind; if (ts.isLiteralTypeNode(node)) { kind = node.literal.kind; } switch (kind) { case ts.SyntaxKind.FunctionType: case ts.SyntaxKind.ConstructorType: return ts.factory.createIdentifier("Function"); case ts.SyntaxKind.ArrayType: case ts.SyntaxKind.TupleType: return ts.factory.createIdentifier("Array"); case ts.SyntaxKind.TypePredicate: case ts.SyntaxKind.TrueKeyword: case ts.SyntaxKind.FalseKeyword: case ts.SyntaxKind.BooleanKeyword: return ts.factory.createIdentifier("Boolean"); case ts.SyntaxKind.StringLiteral: case ts.SyntaxKind.StringKeyword: return ts.factory.createIdentifier("String"); case ts.SyntaxKind.ObjectKeyword: return ts.factory.createIdentifier("Object"); case ts.SyntaxKind.NumberKeyword: case ts.SyntaxKind.NumericLiteral: return ts.factory.createIdentifier("Number"); case ts.SyntaxKind.TypeReference: const typeRef = node; return entityNameToExpression(typeRef.typeName); case ts.SyntaxKind.UnionType: const childTypeNodes = node.types.filter((t) => !(ts.isLiteralTypeNode(t) && t.literal.kind === ts.SyntaxKind.NullKeyword)); return childTypeNodes.length === 1 ? typeReferenceToExpression(entityNameToExpression, childTypeNodes[0]) : void 0; default: return void 0; } } function symbolIsRuntimeValue(typeChecker, symbol) { if (symbol.flags & ts.SymbolFlags.Alias) { symbol = typeChecker.getAliasedSymbol(symbol); } return (symbol.flags & ts.SymbolFlags.Value & ts.SymbolFlags.ConstEnumExcludes) !== 0; } function getDownlevelDecoratorsTransform(typeChecker, host, diagnostics, isCore, isClosureCompilerEnabled, shouldTransformClass) { function addJSDocTypeAnnotation(node, jsdocType) { if (!isClosureCompilerEnabled) { return; } ts.setSyntheticLeadingComments(node, [ { kind: ts.SyntaxKind.MultiLineCommentTrivia, text: `* @type {${jsdocType}} `, pos: -1, end: -1, hasTrailingNewLine: true } ]); } function createPropDecoratorsClassProperty(diagnostics2, properties) { const entries = []; for (const [name, decorators] of properties.entries()) { entries.push(ts.factory.createPropertyAssignment(name, ts.factory.createArrayLiteralExpression(decorators.map((deco) => extractMetadataFromSingleDecorator(deco, diagnostics2))))); } const initializer = ts.factory.createObjectLiteralExpression(entries, true); const prop = ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.StaticKeyword)], "propDecorators", void 0, void 0, initializer); addJSDocTypeAnnotation(prop, `!Object<string, ${DECORATOR_INVOCATION_JSDOC_TYPE}>`); return prop; } return (context) => { const referencedParameterTypes = loadIsReferencedAliasDeclarationPatch(context); function entityNameToExpression(name) { const symbol = typeChecker.getSymbolAtLocation(name); if (!symbol || !symbolIsRuntimeValue(typeChecker, symbol) || !symbol.declarations || symbol.declarations.length === 0) { return void 0; } if (ts.isQualifiedName(name)) { const containerExpr = entityNameToExpression(name.left); if (containerExpr === void 0) { return void 0; } return ts.factory.createPropertyAccessExpression(containerExpr, name.right); } const decl = symbol.declarations[0]; if (isAliasImportDeclaration(decl)) { referencedParameterTypes?.add(decl); if (decl.name !== void 0) { return ts.setOriginalNode(ts.factory.createIdentifier(decl.name.text), decl.name); } } return ts.setOriginalNode(ts.factory.createIdentifier(name.text), name); } function transformClassElement(element) { element = ts.visitEachChild(element, decoratorDownlevelVisitor, context); const decoratorsToKeep = []; const toLower = []; const decorators = host.getDecoratorsOfDeclaration(element) || []; for (const decorator of decorators) { const decoratorNode = decorator.node; if (!isAngularDecorator(decorator, isCore)) { decoratorsToKeep.push(decoratorNode); continue; } toLower.push(decoratorNode); } if (!toLower.length) return [void 0, element, []]; if (!element.name || !ts.isIdentifier(element.name)) { diagnostics.push({ file: element.getSourceFile(), start: element.getStart(), length: element.getEnd() - element.getStart(), messageText: `Cannot process decorators for class element with non-analyzable name.`, category: ts.DiagnosticCategory.Error, code: 0 }); return [void 0, element, []]; } const elementModifiers = ts.canHaveModifiers(element) ? ts.getModifiers(element) : void 0; let modifiers; if (decoratorsToKeep.length || elementModifiers?.length) { modifiers = ts.setTextRange(ts.factory.createNodeArray([...decoratorsToKeep, ...elementModifiers || []]), element.modifiers); } return [element.name.text, cloneClassElementWithModifiers(element, modifiers), toLower]; } function transformConstructor(ctor) { ctor = ts.visitEachChild(ctor, decoratorDownlevelVisitor, context); const newParameters = []; const oldParameters = ctor.parameters; const parametersInfo = []; for (const param of oldParameters) { const decoratorsToKeep = []; const paramInfo = { decorators: [], type: null }; const decorators = host.getDecoratorsOfDeclaration(param) || []; for (const decorator of decorators) { const decoratorNode = decorator.node; if (!isAngularDecorator(decorator, isCore)) { decoratorsToKeep.push(decoratorNode); continue; } paramInfo.decorators.push(decoratorNode); } if (param.type) { paramInfo.type = param.type; } parametersInfo.push(paramInfo); let modifiers; const paramModifiers = ts.getModifiers(param); if (decoratorsToKeep.length || paramModifiers?.length) { modifiers = [...decoratorsToKeep, ...paramModifiers || []]; } const newParam = ts.factory.updateParameterDeclaration(param, modifiers, param.dotDotDotToken, param.name, param.questionToken, param.type, param.initializer); newParameters.push(newParam); } const updated = ts.factory.updateConstructorDeclaration(ctor, ts.getModifiers(ctor), newParameters, ctor.body); return [updated, parametersInfo]; } function transformClassDeclaration(classDecl) { const newMembers = []; const decoratedProperties = /* @__PURE__ */ new Map(); let classParameters = null; for (const member of classDecl.members) { switch (member.kind) { case ts.SyntaxKind.PropertyDeclaration: case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: case ts.SyntaxKind.MethodDeclaration: { const [name, newMember, decorators] = transformClassElement(member); newMembers.push(newMember); if (name) decoratedProperties.set(name, decorators); continue; } case ts.SyntaxKind.Constructor: { const ctor = member; if (!ctor.body) break; const [newMember, parametersInfo] = transformConstructor(member); classParameters = parametersInfo; newMembers.push(newMember); continue; } default: break; } newMembers.push(ts.visitEachChild(member, decoratorDownlevelVisitor, context)); } const possibleAngularDecorators = host.getDecoratorsOfDeclaration(classDecl) || []; const hasAngularDecorator = possibleAngularDecorators.some((d) => isAngularDecorator(d, isCore)); if (classParameters) { if (hasAngularDecorator || classParameters.some((p) => !!p.decorators.length)) { newMembers.push(createCtorParametersClassProperty(diagnostics, entityNameToExpression, classParameters, isClosureCompilerEnabled)); } } if (decoratedProperties.size) { newMembers.push(createPropDecoratorsClassProperty(diagnostics, decoratedProperties)); } const members = ts.setTextRange(ts.factory.createNodeArray(newMembers, classDecl.members.hasTrailingComma), classDecl.members); return ts.factory.updateClassDeclaration(classDecl, classDecl.modifiers, classDecl.name, classDecl.typeParameters, classDecl.heritageClauses, members); } function decoratorDownlevelVisitor(node) { if (ts.isClassDeclaration(node) && (shouldTransformClass === void 0 || shouldTransformClass(node))) { return transformClassDeclaration(node); } return ts.visitEachChild(node, decoratorDownlevelVisitor, context); } return (sf) => { return ts.visitEachChild(sf, decoratorDownlevelVisitor, context); }; }; } function cloneClassElementWithModifiers(node, modifiers) { let clone; if (ts.isMethodDeclaration(node)) { clone = ts.factory.createMethodDeclaration(modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body); } else if (ts.isPropertyDeclaration(node)) { clone = ts.factory.createPropertyDeclaration(modifiers, node.name, node.questionToken, node.type, node.initializer); } else if (ts.isGetAccessor(node)) { clone = ts.factory.createGetAccessorDeclaration(modifiers, node.name, node.parameters, node.type, node.body); } else if (ts.isSetAccessor(node)) { clone = ts.factory.createSetAccessorDeclaration(modifiers, node.name, node.parameters, node.body); } else { throw new Error(`Unsupported decorated member with kind ${ts.SyntaxKind[node.kind]}`); } return ts.setOriginalNode(clone, node); } // packages/compiler-cli/src/ngtsc/annotations/common/src/util.js import { ExternalExpr, ParseLocation, ParseSourceFile, ParseSourceSpan, ReadPropExpr, WrappedNodeExpr } from "@angular/compiler"; import ts2 from "typescript"; var CORE_MODULE = "@angular/core"; function valueReferenceToExpression(valueRef) { if (valueRef.kind === 2) { return null; } else if (valueRef.kind === 0) { const expr = new WrappedNodeExpr(valueRef.expression); if (valueRef.defaultImportStatement !== null) { attachDefaultImportDeclaration(expr, valueRef.defaultImportStatement); } return expr; } else { let importExpr = new ExternalExpr({ moduleName: valueRef.moduleName, name: valueRef.importedName }); if (valueRef.nestedPath !== null) { for (const property of valueRef.nestedPath) { importExpr = new ReadPropExpr(importExpr, property); } } return importExpr; } } function toR3Reference(origin, ref, context, refEmitter) { const emittedValueRef = refEmitter.emit(ref, context); assertSuccessfulReferenceEmit(emittedValueRef, origin, "class"); const emittedTypeRef = refEmitter.emit(ref, context, ImportFlags.ForceNewImport | ImportFlags.AllowTypeImports); assertSuccessfulReferenceEmit(emittedTypeRef, origin, "class"); return { value: emittedValueRef.expression, type: emittedTypeRef.expression }; } function isAngularCore(decorator) { return decorator.import !== null && decorator.import.from === CORE_MODULE; } function isAngularCoreReferenceWithPotentialAliasing(reference, symbolName, isCore) { return (reference.ownedByModuleGuess === CORE_MODULE || isCore) && reference.debugName?.replace(/\$\d+$/, "") === symbolName; } function findAngularDecorator(decorators, name, isCore) { return decorators.find((decorator) => isAngularDecorator2(decorator, name, isCore)); } function isAngularDecorator2(decorator, name, isCore) { if (isCore) { return decorator.name === name; } else if (isAngularCore(decorator)) { return decorator.import.name === name; } return false; } function getAngularDecorators(decorators, names, isCore) { return decorators.filter((decorator) => { const name = isCore ? decorator.name : decorator.import?.name; if (name === void 0 || !names.includes(name)) { return false; } return isCore || isAngularCore(decorator); }); } function unwrapExpression(node) { while (ts2.isAsExpression(node) || ts2.isParenthesizedExpression(node)) { node = node.expression; } return node; } function expandForwardRef(arg) { arg = unwrapExpression(arg); if (!ts2.isArrowFunction(arg) && !ts2.isFunctionExpression(arg)) { return null; } const body = arg.body; if (ts2.isBlock(body)) { if (body.statements.length !== 1) { return null; } const stmt = body.statements[0]; if (!ts2.isReturnStatement(stmt) || stmt.expression === void 0) { return null; } return stmt.expression; } else { return body; } } function tryUnwrapForwardRef(node, reflector) { node = unwrapExpression(node); if (!ts2.isCallExpression(node) || node.arguments.length !== 1) { return null; } const fn = ts2.isPropertyAccessExpression(node.expression) ? node.expression.name : node.expression; if (!ts2.isIdentifier(fn)) { return null; } const expr = expandForwardRef(node.arguments[0]); if (expr === null) { return null; } const imp = reflector.getImportOfIdentifier(fn); if (imp === null || imp.from !== "@angular/core" || imp.name !== "forwardRef") { return null; } return expr; } function createForwardRefResolver(isCore) { return (fn, callExpr, resolve, unresolvable) => { if (!isAngularCoreReferenceWithPotentialAliasing(fn, "forwardRef", isCore) || callExpr.arguments.length !== 1) { return unresolvable; } const expanded = expandForwardRef(callExpr.arguments[0]); if (expanded !== null) { return resolve(expanded); } else { return unresolvable; } }; } function combineResolvers(resolvers) { return (fn, callExpr, resolve, unresolvable) => { for (const resolver of resolvers) { const resolved = resolver(fn, callExpr, resolve, unresolvable); if (resolved !== unresolvable) { return resolved; } } return unresolvable; }; } function isExpressionForwardReference(expr, context, contextSource) { if (isWrappedTsNodeExpr(expr)) { const node = ts2.getOriginalNode(expr.node); return node.getSourceFile() === contextSource && context.pos < node.pos; } else { return false; } } function isWrappedTsNodeExpr(expr) { return expr instanceof WrappedNodeExpr; } function readBaseClass(node, reflector, evaluator) { const baseExpression = reflector.getBaseClassExpression(node); if (baseExpression !== null) { const baseClass = evaluator.evaluate(baseExpression); if (baseClass instanceof Reference && reflector.isClass(baseClass.node)) { return baseClass; } else { return "dynamic"; } } return null; } var parensWrapperTransformerFactory = (context) => { const visitor = (node) => { const visited = ts2.visitEachChild(node, visitor, context); if (ts2.isArrowFunction(visited) || ts2.isFunctionExpression(visited)) { return ts2.factory.createParenthesizedExpression(visited); } return visited; }; return (node) => ts2.visitEachChild(node, visitor, context); }; function wrapFunctionExpressionsInParens(expression) { return ts2.transform(expression, [parensWrapperTransformerFactory]).transformed[0]; } function resolveProvidersRequiringFactory(rawProviders, reflector, evaluator) { const providers = /* @__PURE__ */ new Set(); const resolvedProviders = evaluator.evaluate(rawProviders); if (!Array.isArray(resolvedProviders)) { return providers; } resolvedProviders.forEach(function processProviders(provider) { let tokenClass = null; if (Array.isArray(provider)) { provider.forEach(processProviders); } else if (provider instanceof Reference) { tokenClass = provider; } else if (provider instanceof Map && provider.has("useClass") && !provider.has("deps")) { const useExisting = provider.get("useClass"); if (useExisting instanceof Reference) { tokenClass = useExisting; } } if (tokenClass !== null && !tokenClass.node.getSourceFile().isDeclarationFile && reflector.isClass(tokenClass.node)) { const constructorParameters = reflector.getConstructorParameters(tokenClass.node); if (constructorParameters !== null && constructorParameters.length > 0) { providers.add(tokenClass); } } }); return providers; } function wrapTypeReference(clazz) { const value = new WrappedNodeExpr(clazz.name); const type = value; return { value, type }; } function createSourceSpan(node) { const sf = node.getSourceFile(); const [startOffset, endOffset] = [node.getStart(), node.getEnd()]; const { line: startLine, character: startCol } = sf.getLineAndCharacterOfPosition(startOffset); const { line: endLine, character: endCol } = sf.getLineAndCharacterOfPosition(endOffset); const parseSf = new ParseSourceFile(sf.getFullText(), sf.fileName); return new ParseSourceSpan(new ParseLocation(parseSf, startOffset, startLine + 1, startCol + 1), new ParseLocation(parseSf, endOffset, endLine + 1, endCol + 1)); } function compileResults(fac, def, metadataStmt, propName, additionalFields, deferrableImports, debugInfo = null, hmrInitializer = null) { const statements = def.statements; if (metadataStmt !== null) { statements.push(metadataStmt); } if (debugInfo !== null) { statements.push(debugInfo); } if (hmrInitializer !== null) { statements.push(hmrInitializer); } const results = [ fac, { name: propName, initializer: def.expression, statements: def.statements, type: def.type, deferrableImports } ]; if (additionalFields !== null) { results.push(...additionalFields); } return results; } function toFactoryMetadata(meta, target) { return { name: meta.name, type: meta.type, typeArgumentCount: meta.typeArgumentCount, deps: meta.deps, target }; } function resolveImportedFile(moduleResolver, importedFile, expr, origin) { if (importedFile !== "unknown") { return importedFile; } if (!(expr instanceof ExternalExpr)) { return null; } return moduleResolver.resolveModule(expr.value.moduleName, origin.fileName); } function getOriginNodeForDiagnostics(expr, container) { const nodeSf = expr.getSourceFile(); const exprSf = container.getSourceFile(); if (nodeSf === exprSf && expr.pos >= container.pos && expr.end <= container.end) { return expr; } else { return container; } } function isAbstractClassDeclaration(clazz) { return ts2.canHaveModifiers(clazz) && clazz.modifiers !== void 0 ? clazz.modifiers.some((mod) => mod.kind === ts2.SyntaxKind.AbstractKeyword) : false; } // packages/compiler-cli/src/ngtsc/transform/src/api.js var CompilationMode; (function(CompilationMode2) { CompilationMode2[CompilationMode2["FULL"] = 0] = "FULL"; CompilationMode2[CompilationMode2["PARTIAL"] = 1] = "PARTIAL"; CompilationMode2[CompilationMode2["LOCAL"] = 2] = "LOCAL"; })(CompilationMode || (CompilationMode = {})); var HandlerPrecedence; (function(HandlerPrecedence2) { HandlerPrecedence2[HandlerPrecedence2["PRIMARY"] = 0] = "PRIMARY"; HandlerPrecedence2[HandlerPrecedence2["SHARED"] = 1] = "SHARED"; HandlerPrecedence2[HandlerPrecedence2["WEAK"] = 2] = "WEAK"; })(HandlerPrecedence || (HandlerPrecedence = {})); // packages/compiler-cli/src/ngtsc/perf/src/api.js var PerfPhase; (function(PerfPhase2) { PerfPhase2[PerfPhase2["Unaccounted"] = 0] = "Unaccounted"; PerfPhase2[PerfPhase2["Setup"] = 1] = "Setup"; PerfPhase2[PerfPhase2["TypeScriptProgramCreate"] = 2] = "TypeScriptProgramCreate"; PerfPhase2[PerfPhase2["Reconciliation"] = 3] = "Reconciliation"; PerfPhase2[PerfPhase2["ResourceUpdate"] = 4] = "ResourceUpdate"; PerfPhase2[PerfPhase2["TypeScriptDiagnostics"] = 5] = "TypeScriptDiagnostics"; PerfPhase2[PerfPhase2["Analysis"] = 6] = "Analysis"; PerfPhase2[PerfPhase2["Resolve"] = 7] = "Resolve"; PerfPhase2[PerfPhase2["CycleDetection"] = 8] = "CycleDetection"; PerfPhase2[PerfPhase2["TcbGeneration"] = 9] = "TcbGeneration"; PerfPhase2[PerfPhase2["TcbUpdateProgram"] = 10] = "TcbUpdateProgram"; PerfPhase2[PerfPhase2["TypeScriptEmit"] = 11] = "TypeScriptEmit"; PerfPhase2[PerfPhase2["Compile"] = 12] = "Compile"; PerfPhase2[PerfPhase2["TtcAutocompletion"] = 13] = "TtcAutocompletion"; PerfPhase2[PerfPhase2["TtcDiagnostics"] = 14] = "TtcDiagnostics"; PerfPhase2[PerfPhase2["TtcSuggestionDiagnostics"] = 15] = "TtcSuggestionDiagnostics"; PerfPhase2[PerfPhase2["TtcSymbol"] = 16] = "TtcSymbol"; PerfPhase2[PerfPhase2["LsReferencesAndRenames"] = 17] = "LsReferencesAndRenames"; PerfPhase2[PerfPhase2["LsQuickInfo"] = 18] = "LsQuickInfo"; PerfPhase2[PerfPhase2["LsDefinition"] = 19] = "LsDefinition"; PerfPhase2[PerfPhase2["LsCompletions"] = 20] = "LsCompletions"; PerfPhase2[PerfPhase2["LsTcb"] = 21] = "LsTcb"; PerfPhase2[PerfPhase2["LsDiagnostics"] = 22] = "LsDiagnostics"; PerfPhase2[PerfPhase2["LsSuggestionDiagnostics"] = 23] = "LsSuggestionDiagnostics"; PerfPhase2[PerfPhase2["LsComponentLocations"] = 24] = "LsComponentLocations"; PerfPhase2[PerfPhase2["LsSignatureHelp"] = 25] = "LsSignatureHelp"; PerfPhase2[PerfPhase2["OutliningSpans"] = 26] = "OutliningSpans"; PerfPhase2[PerfPhase2["LsCodeFixes"] = 27] = "LsCodeFixes"; PerfPhase2[PerfPhase2["LsCodeFixesAll"] = 28] = "LsCodeFixesAll"; PerfPhase2[PerfPhase2["LSComputeApplicableRefactorings"] = 29] = "LSComputeApplicableRefactorings"; PerfPhase2[PerfPhase2["LSApplyRefactoring"] = 30] = "LSApplyRefactoring"; PerfPhase2[PerfPhase2["LSSemanticClassification"] = 31] = "LSSemanticClassification"; PerfPhase2[PerfPhase2["LAST"] = 32] = "LAST"; })(PerfPhase || (PerfPhase = {})); var PerfEvent; (function(PerfEvent2) { PerfEvent2[PerfEvent2["InputDtsFile"] = 0] = "InputDtsFile"; PerfEvent2[PerfEvent2["InputTsFile"] = 1] = "InputTsFile"; PerfEvent2[PerfEvent2["AnalyzeComponent"] = 2] = "AnalyzeComponent"; PerfEvent2[PerfEvent2["AnalyzeDirective"] = 3] = "AnalyzeDirective"; PerfEvent2[PerfEvent2["AnalyzeInjectable"] = 4] = "AnalyzeInjectable"; PerfEvent2[PerfEvent2["AnalyzeNgModule"] = 5] = "AnalyzeNgModule"; PerfEvent2[PerfEvent2["AnalyzePipe"] = 6] = "AnalyzePipe"; PerfEvent2[PerfEvent2["AnalyzeService"] = 7] = "AnalyzeService"; PerfEvent2[PerfEvent2["TraitAnalyze"] = 8] = "TraitAnalyze"; PerfEvent2[PerfEvent2["TraitReuseAnalysis"] = 9] = "TraitReuseAnalysis"; PerfEvent2[PerfEvent2["SourceFilePhysicalChange"] = 10] = "SourceFilePhysicalChange"; PerfEvent2[PerfEvent2["SourceFileLogicalChange"] = 11] = "SourceFileLogicalChange"; PerfEvent2[PerfEvent2["SourceFileReuseAnalysis"] = 12] = "SourceFileReuseAnalysis"; PerfEvent2[PerfEvent2["GenerateTcb"] = 13] = "GenerateTcb"; PerfEvent2[PerfEvent2["SkipGenerateTcbNoInline"] = 14] = "SkipGenerateTcbNoInline"; PerfEvent2[PerfEvent2["ReuseTypeCheckFile"] = 15] = "ReuseTypeCheckFile"; PerfEvent2[PerfEvent2["UpdateTypeCheckProgram"] = 16] = "UpdateTypeCheckProgram"; PerfEvent2[PerfEvent2["EmitSkipSourceFile"] = 17] = "EmitSkipSourceFile"; PerfEvent2[PerfEvent2["EmitSourceFile"] = 18] = "EmitSourceFile"; PerfEvent2[PerfEvent2["LAST"] = 19] = "LAST"; })(PerfEvent || (PerfEvent = {})); var PerfCheckpoint; (function(PerfCheckpoint2) { PerfCheckpoint2[PerfCheckpoint2["Initial"] = 0] = "Initial"; PerfCheckpoint2[PerfCheckpoint2["TypeScriptProgramCreate"] = 1] = "TypeScriptProgramCreate"; PerfCheckpoint2[PerfCheckpoint2["PreAnalysis"] = 2] = "PreAnalysis"; PerfCheckpoint2[PerfCheckpoint2["Analysis"] = 3] = "Analysis"; PerfCheckpoint2[PerfCheckpoint2["Resolve"] = 4] = "Resolve"; PerfCheckpoint2[PerfCheckpoint2["TtcGeneration"] = 5] = "TtcGeneration"; PerfCheckpoint2[PerfCheckpoint2["TtcUpdateProgram"] = 6] = "TtcUpdateProgram"; PerfCheckpoint2[PerfCheckpoint2["PreEmit"] = 7] = "PreEmit"; PerfCheckpoint2[PerfCheckpoint2["Emit"] = 8] = "Emit"; PerfCheckpoint2[PerfCheckpoint2["LAST"] = 9] = "LAST"; })(PerfCheckpoint || (PerfCheckpoint = {})); // packages/compiler-cli/src/ngtsc/perf/src/noop.js var NoopPerfRecorder = class { eventCount() { } memory() { } phase() { return PerfPhase.Unaccounted; } inPhase(phase, fn) { return fn(); } reset() { } }; var NOOP_PERF_RECORDER = new NoopPerfRecorder(); // packages/compiler-cli/src/ngtsc/perf/src/clock.js function mark() { return process.hrtime(); } function timeSinceInMicros(mark2) { const delta = process.hrtime(mark2); return delta[0] * 1e6 + Math.floor(delta[1] / 1e3); } // packages/compiler-cli/src/ngtsc/perf/src/recorder.js var ActivePerfRecorder = class _ActivePerfRecorder { zeroTime; counters; phaseTime; bytes; currentPhase = PerfPhase.Unaccounted; currentPhaseEntered; /** * Creates an `ActivePerfRecorder` with its zero point set to the current time. */ static zeroedToNow() { return new _ActivePerfRecorder(mark()); } constructor(zeroTime) { this.zeroTime = zeroTime; this.currentPhaseEntered = this.zeroTime; this.counters = Array(PerfEvent.LAST).fill(0); this.phaseTime = Array(PerfPhase.LAST).fill(0); this.bytes = Array(PerfCheckpoint.LAST).fill(0); this.memory(PerfCheckpoint.Initial); } reset() { this.counters = Array(PerfEvent.LAST).fill(0); this.phaseTime = Array(PerfPhase.LAST).fill(0); this.bytes = Array(PerfCheckpoint.LAST).fill(0); this.zeroTime = mark(); this.currentPhase = PerfPhase.Unaccounted; this.currentPhaseEntered = this.zeroTime; } memory(after) { this.bytes[after] = process.memoryUsage().heapUsed; } phase(phase) { const previous = this.currentPhase; this.phaseTime[this.currentPhase] += timeSinceInMicros(this.currentPhaseEntered); this.currentPhase = phase; this.currentPhaseEntered = mark(); return previous; } inPhase(phase, fn) { const previousPhase = this.phase(phase); try { return fn(); } finally { this.phase(previousPhase); } } eventCount(counter, incrementBy = 1) { this.counters[counter] += incrementBy; } /** * Return the current performance metrics as a serializable object. */ finalize() { this.phase(PerfPhase.Unaccounted); const results = { events: {}, phases: {}, memory: {} }; for (let i = 0; i < this.phaseTime.length; i++) { if (this.phaseTime[i] > 0) { results.phases[PerfPhase[i]] = this.phaseTime[i]; } } for (let i = 0; i < this.phaseTime.length; i++) { if (this.counters[i] > 0) { results.events[PerfEvent[i]] = this.counters[i]; } } for (let i = 0; i < this.bytes.length; i++) { if (this.bytes[i] > 0) { results.memory[PerfCheckpoint[i]] = this.bytes[i]; } } return results; } }; var DelegatingPerfRecorder = class { target; constructor(target) { this.target = target; } eventCount(counter, incrementBy) { this.target.eventCount(counter, incrementBy); } phase(phase) { return this.target.phase(phase); } inPhase(phase, fn) { const previousPhase = this.target.phase(phase); try { return fn(); } finally { this.target.phase(previousPhase); } } memory(after) { this.target.memory(after); } reset() { this.target.reset(); } }; // packages/compiler-cli/src/ngtsc/transform/src/alias.js import ts3 from "typescript"; function aliasTransformFactory(exportStatements) { return () => { return (file) => { if (ts3.isBundle(file) || !exportStatements.has(file.fileName)) { return file; } const statements = [...file.statements]; exportStatements.get(file.fileName).forEach(([moduleName, symbolName], aliasName) => { const stmt = ts3.factory.createExportDeclaration( /* modifiers */ void 0, /* isTypeOnly */ false, /* exportClause */ ts3.factory.createNamedExports([ ts3.factory.createExportSpecifier(false, symbolName, aliasName) ]), /* moduleSpecifier */ ts3.factory.createStringLiteral(moduleName) ); statements.push(stmt); }); return ts3.factory.updateSourceFile(file, statements); }; }; } // packages/compiler-cli/src/ngtsc/transform/src/compilation.js import ts4 from "typescript"; // packages/compiler-cli/src/ngtsc/transform/src/trait.js var TraitState; (function(TraitState2) { TraitState2[TraitState2["Pending"] = 0] = "Pending"; TraitState2[TraitState2["Analyzed"] = 1] = "Analyzed"; TraitState2[TraitState2["Resolved"] = 2] = "Resolved"; TraitState2[TraitState2["Skipped"] = 3] = "Skipped"; })(TraitState || (TraitState = {})); var Trait = { pending: (handler, detected) => TraitImpl.pending(handler, detected) }; var TraitImpl = class _TraitImpl { state = TraitState.Pending; handler; detected; analysis = null; symbol = null; resolution = null; analysisDiagnostics = null; resolveDiagnostics = null; typeCheckDiagnostics = null; constructor(handler, detected) { this.handler = handler; this.detected = detected; } toAnalyzed(analysis, diagnostics, symbol) { this.assertTransitionLegal(TraitState.Pending, TraitState.Analyzed); this.analysis = analysis; this.analysisDiagnostics = diagnostics; this.symbol = symbol; this.state = TraitState.Analyzed; return this; } toResolved(resolution, diagnostics) { this.assertTransitionLegal(TraitState.Analyzed, TraitState.Resolved); if (this.analysis === null) { throw new Error(`Cannot transition an Analyzed trait with a null analysis to Resolved`); } this.resolution = resolution; this.state = TraitState.Resolved; this.resolveDiagnostics = diagnostics; this.typeCheckDiagnostics = null; return this; } toSkipped() { this.assertTransitionLegal(TraitState.Pending, TraitState.Skipped); this.state = TraitState.Skipped; return this; } /** * Verifies that the trait is currently in one of the `allowedState`s. * * If correctly used, the `Trait` type and transition methods prevent illegal transitions from * occurring. However, if a reference to the `TraitImpl` instance typed with the previous * interface is retained after calling one of its transition methods, it will allow for illegal * transitions to take place. Hence, this assertion provides a little extra runtime protection. */ assertTransitionLegal(allowedState, transitionTo) { if (!(this.state === allowedState)) { throw new Error(`Assertion failure: cannot transition from ${TraitState[this.state]} to ${TraitState[transitionTo]}.`); } } /** * Construct a new `TraitImpl` in the pending state. */ static pending(handler, detected) { return new _TraitImpl(handler, detected); } }; // packages/compiler-cli/src/ngtsc/transform/src/compilation.js var TraitCompiler = class { handlers; reflector; perf; incrementalBuild; compileNonExportedClasses; compilationMode; dtsTransforms; semanticDepGraphUpdater; sourceFileTypeIdentifier; emitDeclarationOnly; emitIntermediateTs; /** * Maps class declarations to their `ClassRecord`, which tracks the Ivy traits being applied to * those classes. */ classes = /* @__PURE__ */ new Map(); /** * Maps source files to any class declaration(s) within them which have been discovered to contain * Ivy traits. */ fileToClasses = /* @__PURE__ */ new Map(); /** * Tracks which source files have been analyzed but did not contain any traits. This set allows * the compiler to skip analyzing these files in an incremental rebuild. */ filesWithoutTraits = /* @__PURE__ */ new Set(); reexportMap = /* @__PURE__ */ new Map(); handlersByName = /* @__PURE__ */ new Map(); constructor(handlers, reflector, perf, incrementalBuild, compileNonExportedClasses, compilationMode, dtsTransforms, semanticDepGraphUpdater, sourceFileTypeIdentifier, emitDeclarationOnly, emitIntermediateTs) { this.handlers = handlers; this.reflector = reflector; this.perf = perf; this.incrementalBuild = incrementalBuild; this.compileNonExportedClasses = compileNonExportedClasses; this.compilationMode = compilationMode; this.dtsTransforms = dtsTransforms; this.semanticDepGraphUpdater = semanticDepGraphUpdater; this.sourceFileTypeIdentifier = sourceFileTypeIdentifier; this.emitDeclarationOnly = emitDeclarationOnly; this.emitIntermediateTs = emitIntermediateTs; for (const handler of handlers) { this.handlersByName.set(handler.name, handler); } } analyzeSync(sf) { this.analyze(sf, false); } analyzeAsync(sf) { return this.analyze(sf, true); } analyze(sf, preanalyze) { if (sf.isDeclarationFile || this.sourceFileTypeIdentifier.isShim(sf) || this.sourceFileTypeIdentifier.isResource(sf)) { return void 0; } const promises = []; const priorWork = this.compilationMode !== CompilationMode.LOCAL ? this.incrementalBuild.priorAnalysisFor(sf) : null; if (priorWork !== null) { this.perf.eventCount(PerfEvent.SourceFileReuseAnalysis); if (priorWork.length > 0) { for (const priorRecord of priorWork) { this.adopt(priorRecord); } this.perf.eventCount(PerfEvent.TraitReuseAnalysis, priorWork.length); } else { this.filesWithoutTraits.add(sf); } return; } const visit2 = (node) => { if (this.reflector.isClass(node)) { this.analyzeClass(node, preanalyze ? promises : null); } ts4.forEachChild(node, visit2); }; visit2(sf); if (!this.fileToClasses.has(sf)) { this.filesWithoutTraits.add(sf); } if (preanalyze && promises.length > 0) { return Promise.all(promises).then(() => void 0); } else { return void 0; } } recordFor(clazz) { if (this.classes.has(clazz)) { return this.classes.get(clazz); } else { return null; } } getAnalyzedRecords() { const result = /* @__PURE__ */ new Map(); for (const [sf, classes] of this.fileToClasses) { const records = []; for (const clazz of classes) { records.push(this.classes.get(clazz)); } result.set(sf, records); } for (const sf of this.filesWithoutTraits) { result.set(sf, []); } return result; } /** * Import a `ClassRecord` from a previous compilation (only to be used in global compilation * modes) * * Traits from the `ClassRecord` have accurate metadata, but the `handler` is from the old program * and needs to be updated (matching is done by name). A new pending trait is created and then * transitioned to analyzed using the previous analysis. If the trait is in the errored state, * instead the errors are copied over. */ adopt(priorRecord) { const record = { hasPrimaryHandler: priorRecord.hasPrimaryHandler, hasWeakHandlers: priorRecord.hasWeakHandlers, metaDiagnostics: priorRecord.metaDiagnostics, node: priorRecord.node, traits: [] }; for (const priorTrait of priorRecord.traits) { const handler = this.handlersByName.get(priorTrait.handler.name); let trait = Trait.pending(handler, priorTrait.detected); if (priorTrait.state === TraitState.Analyzed || priorTrait.state === TraitState.Resolved) { const symbol = this.makeSymbolForTrait(handler, record.node, priorTrait.analysis); trait = trait.toAnalyzed(priorTrait.analysis, priorTrait.analysisDiagnostics, symbol); if (trait.analysis !== null && trait.handler.register !== void 0) { trait.handler.register(record.node, trait.analysis); } } else if (priorTrait.state === TraitState.Skipped) { trait = trait.toSkipped(); } record.traits.push(trait); } this.classes.set(record.node, record); const sf = record.node.getSourceFile(); if (!this.fileToClasses.has(sf)) { this.fileToClasses.set(sf, /* @__PURE__ */ new Set()); } this.fileToClasses.get(sf).add(record.node); } scanClassForTraits(clazz) { if (!this.compileNonExportedClasses && !this.reflector.isStaticallyExported(clazz)) { return null; } const decorators = this.reflector.getDecoratorsOfDeclaration(clazz); return this.detectTraits(clazz, decorators); } detectTraits(clazz, decorators) { let record = this.recordFor(clazz); let foundTraits = []; const nonNgDecoratorsInLocalMode = this.compilationMode === CompilationMode.LOCAL ? new Set(decorators) : null; for (const handler of this.handlers) { const result = handler.detect(clazz, decorators); if (result === void 0) { continue; } if (nonNgDecoratorsInLocalMode !== null && result.decorator !== null) { nonNgDecoratorsInLocalMode.delete(result.decorator); } const isPrimaryHandler = handler.precedence === HandlerPrecedence.PRIMARY; const isWeakHandler = handler.precedence === HandlerPrecedence.WEAK; const trait = Trait.pending(handler, result); foundTraits.push(trait); if (record === null) { record = { node: clazz, traits: [trait], metaDiagnostics: null, hasPrimaryHandler: isPrimaryHandler, hasWeakHandlers: isWeakHandler }; this.classes.set(clazz, record); const sf = clazz.getSourceFile(); if (!this.fileToClasses.has(sf)) { this.fileToClasses.set(sf, /* @__PURE__ */ new Set()); } this.fileToClasses.get(sf).add(clazz); } else { if (!isWeakHandler && record.hasWeakHandlers) { record.traits = record.traits.filter((field) => field.handler.precedence !== HandlerPrecedence.WEAK); record.hasWeakHandlers = false; } else if (isWeakHandler && !record.hasWeakHandlers) { continue; } if (isPrimaryHandler && record.hasPrimaryHandler) { record.metaDiagnostics = [ { category: ts4.DiagnosticCategory.Error, code: Number("-99" + ErrorCode.DECORATOR_COLLISION), file: getSourceFile(clazz), start: clazz.getStart(void 0, false), length: clazz.getWidth(), messageText: "Two incompatible decorators on class" } ]; record.traits = foundTraits = []; break; } record.traits.push(trait); record.hasPrimaryHandler = record.hasPrimaryHandler || isPrimaryHandler; } } if (nonNgDecoratorsInLocalMode !== null && nonNgDecoratorsInLocalMode.size > 0 && record !== null && record.metaDiagnostics === null) { const compilationModeName = this.emitDeclarationOnly ? "experimental declaration-only emission" : "local compilation"; record.metaDiagnostics = [...nonNgDecoratorsInLocalMode].map((decorator) => ({ category: ts4.DiagnosticCategory.Error, code: Number("-99" + ErrorCode.DECORATOR_UNEXPECTED), file: getSourceFile(clazz), start: decorator.node.getStart(), length: decorator.node.getWidth(), messageText: `In ${compilationModeName} mode, Angular does not support custom decorators. Ensure all class decorators are from Angular.` })); record.traits = foundTraits = []; } return foundTraits.length > 0 ? foundTraits : null; } makeSymbolForTrait(handler, decl, analysis) { if (analysis === null) { return null; } const symbol = handler.symbol(decl, analysis); if (symbol !== null && this.semanticDepGraphUpdater !== null) { const isPrimary = handler.precedence === HandlerPrecedence.PRIMARY; if (!isPrimary) { throw new Error(`AssertionError: ${handler.name} returned a symbol but is not a primary handler.`); } this.semanticDepGraphUpdater.registerSymbol(symbol); } return symbol; } analyzeClass(clazz, preanalyzeQueue) { const traits = this.scanClassForTraits(clazz); if (traits === null) { return; } for (const trait of traits) { const analyze = () => this.analyzeTrait(clazz, trait); let preanalysis = null; if (preanalyzeQueue !== null && trait.handler.preanalyze !== void 0) { try { preanalysis = trait.handler.preanalyze(clazz, trait.detected.metadata) || null; } catch (err) { if (err instanceof FatalDiagnosticError) { trait.toAnalyzed(null, [err.toDiagnostic()], null); return; } else { throw err; } } } if (preanalysis !== null) { preanalyzeQueue.push(preanalysis.then(analyze)); } else { analyze(); } } } analyzeTrait(clazz, trait) { if (trait.state !== TraitState.Pending) { throw new Error(`Attempt to analyze trait of ${clazz.name.text} in state ${TraitState[trait.state]} (expected DETECTED)`); } this.perf.eventCount(PerfEvent.TraitAnalyze); let result; try { result = trait.handler.analyze(clazz, trait.detected.metadata); } catch (err) { if (err instanceof FatalDiagnosticError) { trait.toAnalyzed(null, [err.toDiagnostic()], null); return; } else { throw err; } } const symbol = this.makeSymbolForTrait(trait.handler, clazz, result.analysis ?? null); if (result.analysis !== void 0 && trait.handler.register !== void 0) { trait.handler.register(clazz, result.analysis); } trait = trait.toAnalyzed(result.analysis ?? null, result.diagnostics ?? null, symbol); } resolve() { const classes = this.classes.keys(); for (const clazz of classes) { const record = this.classes.get(clazz); for (let trait of record.traits) { const handler = trait.handler; switch (trait.state) { case TraitState.Skipped: continue; case TraitState.Pending: throw new Error(`Resolving a trait that hasn't been analyzed: ${clazz.name.text} / ${trait.handler.name}`); case TraitState.Resolved: throw new Error(`Resolving an already resolved trait`); } if (trait.analysis === null) { continue; } if (handler.resolve === void 0) { trait = trait.toResolved(null, null); continue; } let result; try { result = handler.resolve(clazz, trait.analysis, trait.symbol); } catch (err) { if (err instanceof FatalDiagnosticError) { trait = trait.toResolved(null, [err.toDiagnostic()]); continue; } else { throw err; } } trait = trait.toResolved(result.data ?? null, result.diagnostics ?? null); if (result.reexports !== void 0) { const fileName = clazz.getSourceFile().fileName; if (!this.reexportMap.has(fileName)) { this.reexportMap.set(fileName, /* @__PURE__ */ new Map()); } const fileReexports = this.reexportMap.get(fileName); for (const reexport of result.reexports) { fileReexports.set(reexport.asAlias, [reexport.fromModule, reexport.symbolName]); } } } } } /** * Generate type-checking code into the `TypeCheckContext` for any components within the given * `ts.SourceFile`. */ typeCheck(sf, ctx) { if (!this.fileToClasses.has(sf) || this.compilationMode === CompilationMode.LOCAL) { return; } for (const clazz of this.fileToClasses.get(sf)) { const record = this.classes.get(clazz); for (const trait of record.traits) { if (trait.state !== TraitState.Resolved) { continue; } else if (trait.handler.typeCheck === void 0) { continue; } if (trait.resolution !== null) { trait.handler.type