@analogjs/vite-plugin-angular 3.0.0-alpha.36 → 3.0.0-alpha.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/package.json +3 -4
- package/src/lib/angular-jit-plugin.js +3 -0
- package/src/lib/angular-jit-plugin.js.map +1 -1
- package/src/lib/angular-vite-plugin.d.ts +12 -7
- package/src/lib/angular-vite-plugin.js +7 -5
- package/src/lib/angular-vite-plugin.js.map +1 -1
- package/src/lib/compiler/angular-version.d.ts +19 -0
- package/src/lib/compiler/angular-version.js +16 -0
- package/src/lib/compiler/angular-version.js.map +1 -0
- package/src/lib/compiler/class-field-lowering.d.ts +23 -0
- package/src/lib/compiler/class-field-lowering.js +131 -0
- package/src/lib/compiler/class-field-lowering.js.map +1 -0
- package/src/lib/compiler/compile.d.ts +44 -0
- package/src/lib/compiler/compile.js +731 -0
- package/src/lib/compiler/compile.js.map +1 -0
- package/src/lib/compiler/constants.d.ts +18 -0
- package/src/lib/compiler/constants.js +52 -0
- package/src/lib/compiler/constants.js.map +1 -0
- package/src/lib/compiler/debug.d.ts +22 -0
- package/src/lib/compiler/debug.js +20 -0
- package/src/lib/compiler/debug.js.map +1 -0
- package/src/lib/compiler/defer.d.ts +47 -0
- package/src/lib/compiler/defer.js +138 -0
- package/src/lib/compiler/defer.js.map +1 -0
- package/src/lib/compiler/dts-reader.d.ts +35 -0
- package/src/lib/compiler/dts-reader.js +365 -0
- package/src/lib/compiler/dts-reader.js.map +1 -0
- package/src/lib/compiler/hmr.d.ts +16 -0
- package/src/lib/compiler/hmr.js +69 -0
- package/src/lib/compiler/hmr.js.map +1 -0
- package/src/lib/compiler/index.d.ts +7 -0
- package/src/lib/compiler/index.js +7 -0
- package/src/lib/compiler/jit-metadata.d.ts +14 -0
- package/src/lib/compiler/jit-metadata.js +146 -0
- package/src/lib/compiler/jit-metadata.js.map +1 -0
- package/src/lib/compiler/jit-transform.d.ts +24 -0
- package/src/lib/compiler/jit-transform.js +200 -0
- package/src/lib/compiler/jit-transform.js.map +1 -0
- package/src/lib/compiler/js-emitter.d.ts +10 -0
- package/src/lib/compiler/js-emitter.js +420 -0
- package/src/lib/compiler/js-emitter.js.map +1 -0
- package/src/lib/compiler/metadata.d.ts +45 -0
- package/src/lib/compiler/metadata.js +633 -0
- package/src/lib/compiler/metadata.js.map +1 -0
- package/src/lib/compiler/registry.d.ts +49 -0
- package/src/lib/compiler/registry.js +164 -0
- package/src/lib/compiler/registry.js.map +1 -0
- package/src/lib/compiler/resource-inliner.d.ts +21 -0
- package/src/lib/compiler/resource-inliner.js +152 -0
- package/src/lib/compiler/resource-inliner.js.map +1 -0
- package/src/lib/compiler/style-ast.d.ts +8 -0
- package/src/lib/compiler/style-ast.js +54 -0
- package/src/lib/compiler/style-ast.js.map +1 -0
- package/src/lib/compiler/styles.d.ts +13 -0
- package/src/lib/compiler/test-helpers.d.ts +7 -0
- package/src/lib/compiler/type-elision.d.ts +26 -0
- package/src/lib/compiler/type-elision.js +211 -0
- package/src/lib/compiler/type-elision.js.map +1 -0
- package/src/lib/compiler/utils.d.ts +10 -0
- package/src/lib/compiler/utils.js +35 -0
- package/src/lib/compiler/utils.js.map +1 -0
- package/src/lib/{analog-compiler-plugin.d.ts → fast-compile-plugin.d.ts} +3 -3
- package/src/lib/{analog-compiler-plugin.js → fast-compile-plugin.js} +46 -33
- package/src/lib/fast-compile-plugin.js.map +1 -0
- package/src/lib/utils/virtual-resources.d.ts +16 -0
- package/src/lib/utils/virtual-resources.js +31 -2
- package/src/lib/utils/virtual-resources.js.map +1 -1
- package/src/lib/analog-compiler-plugin.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","names":[],"sources":["../../../../src/lib/compiler/compile.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as o from '@angular/compiler';\nimport MagicString from 'magic-string';\nimport { parseSync } from 'oxc-parser';\nimport {\n ConstantPool,\n compileComponentFromMetadata,\n compileDirectiveFromMetadata,\n compilePipeFromMetadata,\n compileNgModule,\n compileInjector,\n R3NgModuleMetadataKind,\n R3SelectorScopeMode,\n FactoryTarget,\n compileFactoryFunction,\n parseTemplate,\n makeBindingParser,\n parseHostBindings,\n ParseSourceFile,\n ParseLocation,\n ParseSourceSpan,\n compileClassMetadata,\n compileDeclareComponentFromMetadata,\n compileDeclareDirectiveFromMetadata,\n compileDeclarePipeFromMetadata,\n compileDeclareNgModuleFromMetadata,\n compileDeclareInjectorFromMetadata,\n compileDeclareInjectableFromMetadata,\n compileDeclareFactoryFunction,\n compileDeclareClassMetadata,\n} from '@angular/compiler';\nimport { ComponentRegistry } from './registry.js';\nimport { findAllClasses } from './utils.js';\nimport { ANGULAR_DECORATORS, FIELD_DECORATORS } from './constants.js';\nimport {\n detectTypeOnlyImportNames,\n elideTypeOnlyImportsMagicString,\n} from './type-elision.js';\n\nimport {\n emitAngularExpr,\n emitAngularStmt,\n setEmitterSourceFile,\n setEmitterSourceCode,\n} from './js-emitter.js';\nimport { lowerClassFields } from './class-field-lowering.js';\nimport {\n extractMetadata,\n collectStringConstants,\n detectSignals,\n detectFieldDecorators,\n extractConstructorDeps,\n} from './metadata.js';\nimport { buildDeferDependencyMap } from './defer.js';\nimport { debugCompile, debugEmit } from './debug.js';\nimport { ANGULAR_MAJOR } from './angular-version.js';\n\n/**\n * COMPLETE EXHAUSTIVE ANGULAR LITE COMPILER\n * Translates Angular Decorators + Signals to Ivy Static Definitions.\n *\n * @param registry - Optional external registry from the global analysis plugin.\n * When provided, used to resolve component/directive selectors for template compilation.\n */\nexport interface CompileResult {\n code: string;\n /** Source map for the transformation */\n map: ReturnType<MagicString['generateMap']>;\n /** Absolute paths of external resources (templateUrl, styleUrl) read during compilation */\n resourceDependencies: string[];\n}\n\nexport interface CompileOptions {\n registry?: ComponentRegistry;\n /** Pre-resolved style contents keyed by absolute file path (e.g. SCSS already compiled to CSS). */\n resolvedStyles?: Map<string, string>;\n /** Pre-processed inline styles (index in styles array → compiled CSS). */\n resolvedInlineStyles?: Map<number, string>;\n /**\n * When `false` (default), instance class field initializers are lowered to\n * constructor assignments (matching TypeScript's `useDefineForClassFields: false`\n * behavior). This is required for Angular's `inject()` and constructor DI to\n * work correctly with the standard Angular tsconfig.\n */\n useDefineForClassFields?: boolean;\n /** Enable legacy i18n message ID format (default: true). */\n enableI18nLegacyMessageIdFormat?: boolean;\n /** Normalize line endings in ICU expressions (default: true). */\n i18nNormalizeLineEndingsInICUs?: boolean;\n /** Use external IDs in `$localize` calls (for Closure Compiler compatibility). */\n i18nUseExternalIds?: boolean;\n /**\n * Compilation output mode.\n * - `'full'` (default): Emit final Ivy definitions (`ɵɵdefineComponent`) for application builds.\n * - `'partial'`: Emit partial declarations (`ɵɵngDeclareComponent`) for library publishing.\n * Partial output is version-stable and linked at application build time.\n */\n compilationMode?: 'full' | 'partial';\n}\n\ntype CompileMetadata = ReturnType<typeof extractMetadata>;\n\ntype CompileDeclaration = {\n type: o.Expression;\n selector: string | null;\n className?: string;\n kind: number;\n name?: string;\n inputs?: string[];\n outputs?: string[];\n exportAs?: string[];\n isComponent?: boolean;\n};\n\nfunction hasExportModifier(node: ts.Node): boolean {\n return (\n ts.canHaveModifiers(node) &&\n ts\n .getModifiers(node)\n ?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) === true\n );\n}\n\n/**\n * Collect identifier names referenced in eagerly-evaluated code only.\n * Skips function/arrow/class bodies so that lazy references\n * (e.g. `const TOKEN = () => LaterClass`) are not treated as dependencies.\n */\nfunction collectIdentifiers(node: ts.Node): Set<string> {\n const ids = new Set<string>();\n function walk(n: ts.Node) {\n if (ts.isIdentifier(n)) {\n ids.add(n.text);\n }\n // Stop recursing into lazily-evaluated scopes\n if (ts.isFunctionLike(n) || ts.isClassLike(n)) {\n return;\n }\n ts.forEachChild(n, walk);\n }\n ts.forEachChild(node, walk);\n return ids;\n}\n\n/** Extract the names defined by a top-level statement. */\nfunction getDefinedNames(stmt: ts.Statement): string[] {\n if (ts.isVariableStatement(stmt)) {\n const names: string[] = [];\n for (const decl of stmt.declarationList.declarations) {\n collectBindingNames(decl.name, names);\n }\n return names;\n }\n if (ts.isFunctionDeclaration(stmt) && stmt.name) {\n return [stmt.name.text];\n }\n if (ts.isClassDeclaration(stmt) && stmt.name) {\n return [stmt.name.text];\n }\n return [];\n}\n\n/** Recursively collect all bound identifiers from a binding name/pattern. */\nfunction collectBindingNames(name: ts.BindingName, out: string[]): void {\n if (ts.isIdentifier(name)) {\n out.push(name.text);\n } else if (\n ts.isObjectBindingPattern(name) ||\n ts.isArrayBindingPattern(name)\n ) {\n for (const el of name.elements) {\n if (!ts.isOmittedExpression(el)) {\n collectBindingNames(el.name, out);\n }\n }\n }\n}\n\nexport function compile(\n sourceCode: string,\n fileName: string,\n optionsOrRegistry?: CompileOptions | ComponentRegistry,\n): CompileResult {\n // Backward compat: accept ComponentRegistry directly\n const opts: CompileOptions =\n optionsOrRegistry instanceof Map\n ? { registry: optionsOrRegistry }\n : optionsOrRegistry || {};\n const registry = opts.registry;\n const resolvedStyles = opts.resolvedStyles;\n const resolvedInlineStyles = opts.resolvedInlineStyles;\n const useDefineForClassFields = opts.useDefineForClassFields ?? false;\n const isPartial = opts.compilationMode === 'partial';\n const startTimeMs = debugCompile.enabled ? performance.now() : 0;\n debugCompile(\n 'compile %s (mode=%s, registry=%d entries)',\n fileName,\n isPartial ? 'partial' : 'full',\n registry?.size ?? 0,\n );\n const origSourceFile = ts.createSourceFile(\n fileName,\n sourceCode,\n ts.ScriptTarget.Latest,\n true,\n );\n // OXC parse for metadata extraction (faster than TS for decorator/signal analysis)\n const { program: oxcProgram } = parseSync(fileName, sourceCode);\n const oxcClassMap = new Map<string, any>();\n for (const stmt of oxcProgram.body) {\n const decl =\n stmt.type === 'ExportNamedDeclaration' ||\n stmt.type === 'ExportDefaultDeclaration'\n ? (stmt as any).declaration\n : stmt;\n if (\n decl &&\n (decl.type === 'ClassDeclaration' || decl.type === 'ClassExpression') &&\n decl.id?.name\n ) {\n oxcClassMap.set(decl.id.name, decl);\n }\n }\n\n // Collect module-level string constants so decorator metadata can resolve\n // template-literal interpolations like `template: \\`<div class=\"${tw}\">x</div>\\``.\n const stringConsts = collectStringConstants(oxcProgram);\n\n const constantPool = new ConstantPool();\n const resourceDependencies: string[] = [];\n const parseFile = new ParseSourceFile(sourceCode, fileName);\n const parseLoc = new ParseLocation(parseFile, 0, 0, 0);\n const typeSourceSpan = new ParseSourceSpan(parseLoc, parseLoc);\n const typeOnlyImports = detectTypeOnlyImportNames(sourceCode);\n const importSpecifierByName = new Map<string, string>();\n const importedNames = new Set<string>();\n\n for (const stmt of origSourceFile.statements) {\n if (\n !ts.isImportDeclaration(stmt) ||\n !stmt.importClause?.namedBindings ||\n !ts.isNamedImports(stmt.importClause.namedBindings)\n ) {\n continue;\n }\n\n const moduleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n // Explicit `import type { X }` — declaration-level type-only import\n const isDeclarationTypeOnly = stmt.importClause.isTypeOnly;\n for (const element of stmt.importClause.namedBindings.elements) {\n const localName = element.name.text;\n importedNames.add(localName);\n importSpecifierByName.set(localName, moduleSpecifier);\n // Explicit `import { type X }` — specifier-level type-only import.\n // Both forms erase the symbol at runtime, so they cannot be used as\n // DI tokens. Add them to typeOnlyImports so extractConstructorDeps\n // surfaces ɵɵinvalidFactory() instead of emitting a broken\n // ɵɵdirectiveInject(X) referring to a non-existent value.\n if (isDeclarationTypeOnly || element.isTypeOnly) {\n typeOnlyImports.add(localName);\n }\n }\n }\n\n // Inject 'import * as i0 from \"@angular/core\"'\n const sourceFile = injectAngularImport(origSourceFile);\n\n // Build a file-local selector map as fallback when no external registry is provided.\n // Skip the expensive extractMetadata scan when a registry covers all classes.\n const localSelectors = new Map<string, string>();\n if (!registry) {\n for (const [clsName, oxcNode] of oxcClassMap) {\n const decs: any[] = oxcNode.decorators || [];\n if (decs.length > 0) {\n const meta = extractMetadata(decs[0], sourceCode, stringConsts);\n if (meta?.selector) {\n localSelectors.set(clsName, meta.selector.split(',')[0].trim());\n }\n }\n }\n }\n\n const bindingParser = isPartial ? undefined : makeBindingParser();\n setEmitterSourceFile(origSourceFile);\n setEmitterSourceCode(sourceCode);\n\n // --- Direct walk: compile each Angular-decorated class and collect string outputs ---\n // This replaces the previous ts.transform + printer.printNode approach.\n // By emitting strings directly from the Angular output AST, we skip both\n // ts.factory node creation and ts.Printer serialization (~4x faster).\n interface ClassCompileResult {\n ivyCode: string[]; // \"static ɵfac = ...\", \"static ɵcmp = ...\", etc.\n decorators: ts.Decorator[]; // Angular decorators to remove\n classEnd: number; // Position of closing } in original source\n }\n const classResults: ClassCompileResult[] = [];\n // Per-class hoisted helper statements returned via R3CompiledExpression.statements\n // (e.g. nested template helper functions for `@if`/`@for`/`@switch` blocks).\n // Older Angular majors (≤19) return these on `cmp.statements` rather than\n // pushing them into the shared ConstantPool, so we collect them here and\n // emit them alongside the constant-pool helpers in step 3. Without this,\n // any component with control-flow blocks references undefined symbols like\n // `MyComponent_Conditional_0_Template`.\n const hoistedHelpers: string[] = [];\n // Track synthetic imports needed for NgModule export expansion.\n // Maps exported class name → import specifier.\n const syntheticImports = new Map<string, string>();\n\n // ANGULAR_DECORATORS imported from utils\n\n for (const node of findAllClasses(origSourceFile)) {\n const decorators = ts.getDecorators(node);\n if (!decorators || decorators.length === 0) continue;\n\n const className = node.name?.text;\n if (!className) continue;\n\n const angularDecorators = decorators.filter((dec) => {\n if (!ts.isCallExpression(dec.expression)) return false;\n const name = dec.expression.expression.getText(origSourceFile);\n return ANGULAR_DECORATORS.has(name);\n });\n if (angularDecorators.length === 0) continue;\n\n const ivyCode: string[] = [];\n let targetType: FactoryTarget = FactoryTarget.Injectable;\n // Store resolved resources per decorator for metadata inlining\n const resolvedResources = new Map<\n ts.Decorator,\n { template?: string; styles?: string[] }\n >();\n\n const classRef: o.R3Reference = {\n value: new o.WrappedNodeExpr(className),\n type: new o.WrappedNodeExpr(className),\n };\n\n // Detect `class Foo extends Bar` so the directive/component def\n // gets `usesInheritance: true`. Angular's compiler turns that into\n // `features: [InheritDefinitionFeature]`, which is what causes the\n // runtime to merge inputs/outputs/queries/host bindings from the\n // base class. Without it, derived directives like\n // `BrnPopover extends BrnDialog` lose every input declared on the\n // base, and any host directive that references those inputs by\n // public name fails at runtime with NG0311.\n const extendsClause = node.heritageClauses?.find(\n (h) => h.token === ts.SyntaxKind.ExtendsKeyword,\n );\n const usesInheritance = !!extendsClause && extendsClause.types.length > 0;\n\n // Look up the corresponding OXC class node for metadata extraction\n const oxcNode = oxcClassMap.get(className);\n\n let classCompileError: Error | null = null;\n\n angularDecorators.forEach((dec) => {\n const decoratorName = (\n dec.expression as ts.CallExpression\n ).expression.getText(origSourceFile);\n // Find the matching OXC decorator by name\n const oxcDec = oxcNode?.decorators?.find((d: any) => {\n const expr = d.expression;\n return (\n expr?.type === 'CallExpression' && expr.callee?.name === decoratorName\n );\n });\n const meta = extractMetadata(oxcDec, sourceCode, stringConsts);\n const sigs = oxcNode\n ? detectSignals(oxcNode, sourceCode)\n : { inputs: {}, outputs: {}, viewQueries: [], contentQueries: [] };\n const fields = oxcNode\n ? detectFieldDecorators(oxcNode, sourceCode)\n : {\n inputs: {},\n outputs: {},\n viewQueries: [],\n contentQueries: [],\n hostProperties: {},\n hostListeners: {},\n };\n const hostBindings = parseHostBindings(meta.hostRaw || {});\n\n const hostMetadata: o.R3HostMetadata = {\n attributes: hostBindings.attributes,\n listeners: { ...hostBindings.listeners, ...fields.hostListeners },\n properties: { ...hostBindings.properties, ...fields.hostProperties },\n specialAttributes: hostBindings.specialAttributes,\n };\n\n switch (decoratorName) {\n case 'Component': {\n targetType = FactoryTarget.Component;\n if (!meta.selector) {\n meta.selector = `ng-component-${className.toLowerCase()}`;\n }\n\n const declarations: CompileDeclaration[] = [];\n // Dedupe by class name across direct imports, tuple-barrel\n // expansion, and NgModule export expansion so the final\n // `dependencies: () => [...]` list never contains the same\n // class twice. Otherwise Angular's runtime throws NG0300\n // (\"Multiple components match …\") when a file lists both\n // `NgIcon` and a barrel like `HlmIconImports = [HlmIcon, NgIcon]`\n // that re-exports it, or when two NgModules re-export the same\n // directive (e.g. FormsModule + ReactiveFormsModule →\n // DefaultValueAccessor).\n const seenDeclarationNames = new Set<string>();\n\n // Expand `imports` entries that are not directives themselves\n // (e.g. NgModules and tuple barrels like `HlmSelectImports =\n // [HlmSelect, HlmSelectContent, ...] as const`) into the\n // underlying directive class names. Returns the original entry\n // when it doesn't match either expansion case.\n const collectExpandedImports = (\n depClassName: string,\n visited: Set<string>,\n ): string[] => {\n if (visited.has(depClassName)) return [];\n visited.add(depClassName);\n const entry = registry?.get(depClassName);\n if (!entry) return [depClassName];\n if (entry.kind === 'ngmodule' && entry.exports) {\n const out: string[] = [];\n for (const name of entry.exports) {\n out.push(...collectExpandedImports(name, visited));\n }\n return out;\n }\n if (entry.kind === 'tuple' && entry.members) {\n const out: string[] = [];\n for (const name of entry.members) {\n out.push(...collectExpandedImports(name, visited));\n }\n return out;\n }\n return [depClassName];\n };\n\n for (const dep of Array.isArray(meta.imports) ? meta.imports : []) {\n const depNode = dep.node;\n const depClassName: string =\n typeof depNode === 'string'\n ? depNode\n : (depNode?.name ?? depNode?.type === 'Identifier')\n ? depNode.name\n : sourceCode.slice(depNode?.start ?? 0, depNode?.end ?? 0);\n const registryEntry = registry?.get(depClassName);\n\n // Tuple barrel: `imports: [HlmSelectImports]` where the\n // const is `[HlmSelect, HlmSelectContent, ...] as const`.\n // Expand into the underlying directive declarations and\n // track synthetic imports for any classes not already\n // referenced in this file.\n if (registryEntry?.kind === 'tuple' && registryEntry.members) {\n const expanded = collectExpandedImports(depClassName, new Set());\n const tupleSpecifier = importSpecifierByName.get(depClassName);\n for (const memberName of expanded) {\n const memberEntry = registry?.get(memberName);\n if (!memberEntry || memberEntry.kind === 'tuple') continue;\n const memberRef = new o.WrappedNodeExpr(memberName);\n if (memberEntry.sourcePackage || tupleSpecifier) {\n if (!importedNames.has(memberName)) {\n syntheticImports.set(\n memberName,\n memberEntry.sourcePackage || tupleSpecifier!,\n );\n }\n }\n const kind = memberEntry.kind === 'pipe' ? 1 : 0;\n const memberDecl: CompileDeclaration = {\n type: memberRef,\n selector: memberEntry.selector,\n kind,\n ...(kind === 1 ? { name: memberEntry.pipeName } : {}),\n };\n if (memberEntry.inputs) {\n memberDecl.inputs = Object.values(memberEntry.inputs).map(\n (i) => i.bindingPropertyName,\n );\n }\n if (memberEntry.outputs) {\n memberDecl.outputs = Object.values(\n memberEntry.outputs,\n ) as string[];\n }\n if (!seenDeclarationNames.has(memberName)) {\n seenDeclarationNames.add(memberName);\n declarations.push(memberDecl);\n }\n }\n continue;\n }\n\n if (registryEntry?.kind === 'ngmodule' && registryEntry.exports) {\n const moduleSpecifier = importSpecifierByName.get(depClassName);\n\n // Recursively collect all non-module exports (handles nested NgModules\n // like ReactiveFormsModule → ɵInternalFormsSharedModule → DefaultValueAccessor)\n const allExports: string[] = [];\n const expandModule = (\n moduleName: string,\n visited = new Set<string>(),\n ) => {\n if (visited.has(moduleName)) return;\n visited.add(moduleName);\n const mod = registry?.get(moduleName);\n if (!mod?.exports) return;\n for (const name of mod.exports) {\n const entry = registry?.get(name);\n if (!entry) continue;\n if (entry.kind === 'ngmodule') {\n expandModule(name, visited);\n } else {\n allExports.push(name);\n }\n }\n };\n expandModule(depClassName);\n\n for (const exportedName of allExports) {\n const exportedEntry = registry?.get(exportedName);\n if (exportedEntry) {\n const kind = exportedEntry.kind === 'pipe' ? 1 : 0;\n // Create a reference to the exported class. If it's not\n // already imported, track it for synthetic import injection.\n const exportedRef = new o.WrappedNodeExpr(exportedName);\n if (exportedEntry.sourcePackage || moduleSpecifier) {\n syntheticImports.set(\n exportedName,\n exportedEntry.sourcePackage || moduleSpecifier!,\n );\n }\n const decl: CompileDeclaration = {\n type: exportedRef,\n selector: exportedEntry.selector,\n kind,\n ...(kind === 1 ? { name: exportedEntry.pipeName } : {}),\n };\n if (exportedEntry.inputs) {\n decl.inputs = Object.values(exportedEntry.inputs).map(\n (i) => i.bindingPropertyName,\n );\n }\n if (exportedEntry.outputs) {\n decl.outputs = Object.values(\n exportedEntry.outputs,\n ) as string[];\n }\n if (!seenDeclarationNames.has(exportedName)) {\n seenDeclarationNames.add(exportedName);\n declarations.push(decl);\n }\n }\n }\n continue;\n }\n\n const selector =\n registryEntry?.selector ?? localSelectors.get(depClassName);\n const kind = registryEntry?.kind === 'pipe' ? 1 : 0;\n const decl: CompileDeclaration = {\n type: dep,\n selector: selector || `_unresolved-${depClassName}`,\n kind,\n ...(kind === 1 ? { name: registryEntry?.pipeName } : {}),\n };\n // Pass inputs/outputs from registry so template bindings resolve.\n // R3DirectiveDependencyMetadata expects inputs/outputs as string[]\n // of binding property names.\n if (registryEntry?.inputs) {\n decl.inputs = Object.values(registryEntry.inputs).map(\n (i) => i.bindingPropertyName,\n );\n }\n if (registryEntry?.outputs) {\n decl.outputs = Object.values(registryEntry.outputs) as string[];\n }\n if (!seenDeclarationNames.has(depClassName)) {\n seenDeclarationNames.add(depClassName);\n declarations.push(decl);\n }\n }\n\n // Add self-reference so recursive components (e.g. tree views)\n // can use their own selector in their template.\n // Skip in partial mode — the linker handles self-resolution.\n if (!isPartial && !seenDeclarationNames.has(className)) {\n const selfInputs = Object.entries(sigs.inputs).map(\n ([, v]: [string, any]) => v.bindingPropertyName,\n );\n const selfOutputs = Object.values({\n ...meta.outputs,\n ...fields.outputs,\n ...sigs.outputs,\n }) as string[];\n seenDeclarationNames.add(className);\n declarations.push({\n type: classRef.value,\n selector: meta.selector,\n kind: 0,\n ...(selfInputs.length > 0 ? { inputs: selfInputs } : {}),\n ...(selfOutputs.length > 0 ? { outputs: selfOutputs } : {}),\n });\n }\n\n let templateContent = meta.template || '';\n if (!templateContent && meta.templateUrl) {\n try {\n const templatePath = path.resolve(\n path.dirname(fileName),\n meta.templateUrl,\n );\n templateContent = fs.readFileSync(templatePath, 'utf-8');\n resourceDependencies.push(templatePath);\n } catch {\n console.warn(\n `[fast-compile] Could not read template file \"${meta.templateUrl}\" for ${className}`,\n );\n }\n }\n\n if (Array.isArray(meta.styleUrls)) {\n for (const url of meta.styleUrls) {\n try {\n const stylePath = path.resolve(path.dirname(fileName), url);\n const styleContent =\n resolvedStyles?.get(stylePath) ??\n fs.readFileSync(stylePath, 'utf-8');\n meta.styles.push(styleContent);\n resourceDependencies.push(stylePath);\n } catch {\n console.warn(\n `[fast-compile] Could not read style file \"${url}\" for ${className}`,\n );\n }\n }\n }\n\n if (resolvedInlineStyles) {\n for (const [idx, css] of resolvedInlineStyles) {\n if (idx < meta.styles.length) {\n meta.styles[idx] = css;\n }\n }\n }\n\n // Store resolved resources for metadata inlining\n resolvedResources.set(dec, {\n template: templateContent || undefined,\n styles: meta.styles?.length > 0 ? [...meta.styles] : undefined,\n });\n\n const parsedTemplate = parseTemplate(templateContent, fileName, {\n preserveWhitespaces: meta.preserveWhitespaces,\n enableI18nLegacyMessageIdFormat:\n opts.enableI18nLegacyMessageIdFormat ?? true,\n i18nNormalizeLineEndingsInICUs:\n opts.i18nNormalizeLineEndingsInICUs ?? true,\n });\n\n const ivyInputs: Record<string, unknown> = {};\n if (Array.isArray(meta.inputs)) {\n meta.inputs.forEach((i: string) => (ivyInputs[i] = i));\n } else if (meta.inputs) {\n Object.assign(ivyInputs, meta.inputs);\n }\n Object.assign(ivyInputs, fields.inputs);\n for (const [key, val] of Object.entries(sigs.inputs)) {\n const sigDesc = val as {\n bindingPropertyName?: string;\n required?: boolean;\n transform?: o.Expression | null;\n };\n ivyInputs[key] = {\n classPropertyName: key,\n // Honor the binding name (alias) extracted by detectSignals\n // so `input(null, { alias: 'aria-label' })` registers with\n // the public name `aria-label`, not the class property name.\n bindingPropertyName: sigDesc.bindingPropertyName ?? key,\n isSignal: true,\n required: sigDesc.required || false,\n transformFunction: sigDesc.transform || null,\n };\n }\n const templateErrors = parsedTemplate.errors ?? [];\n if (templateErrors.length > 0) {\n const firstError = templateErrors[0];\n classCompileError = new Error(\n `[fast-compile] Template parse error in ${fileName} (${className}): ${firstError.msg}`,\n );\n return;\n }\n\n const componentMeta: CompileMetadata & {\n name: string;\n type: o.R3Reference;\n typeSourceSpan: ParseSourceSpan;\n declarations: CompileDeclaration[];\n template: {\n nodes: o.Node[];\n ngContentSelectors: string[];\n preserveWhitespaces: boolean;\n };\n } = {\n ...meta,\n name: className,\n type: classRef,\n typeSourceSpan,\n declarations,\n template: {\n nodes: parsedTemplate.nodes,\n ngContentSelectors: parsedTemplate.ngContentSelectors,\n preserveWhitespaces: parsedTemplate.preserveWhitespaces,\n },\n styles: [...(meta.styles || []), ...(parsedTemplate.styles || [])],\n inputs: ivyInputs,\n outputs: { ...meta.outputs, ...fields.outputs, ...sigs.outputs },\n viewQueries: [...fields.viewQueries, ...sigs.viewQueries],\n queries: [...fields.contentQueries, ...sigs.contentQueries],\n host: hostMetadata,\n changeDetection: meta.changeDetection ?? (isPartial ? null : 1),\n encapsulation: meta.encapsulation ?? 0,\n exportAs: meta.exportAs,\n providers: meta.providers?.length\n ? new o.LiteralArrayExpr(meta.providers)\n : null,\n viewProviders: meta.viewProviders?.length\n ? new o.LiteralArrayExpr(meta.viewProviders)\n : null,\n animations: meta.animations?.length\n ? new o.LiteralArrayExpr(meta.animations)\n : null,\n isStandalone: meta.standalone,\n imports: meta.imports,\n lifecycle: { usesOnChanges: false },\n // Angular v19/v20's `createComponentDefinitionMap` reads\n // `meta.interpolation.start` and `meta.interpolation.end`\n // unconditionally (the `!== DEFAULT_INTERPOLATION_CONFIG` check\n // is reference-equality, so a missing field enters the block\n // and crashes with `Cannot read properties of undefined`). v21\n // dropped the field from `createComponentDefinitionMap`\n // entirely. Use the v19/v20 singleton when the Angular package\n // exports it (matches the reference-equality check, skipping\n // the partial-mode emission block) and fall back to a plain\n // shape on v21+ where the field is ignored anyway.\n interpolation: (\n o as {\n DEFAULT_INTERPOLATION_CONFIG?: { start: string; end: string };\n }\n ).DEFAULT_INTERPOLATION_CONFIG ?? { start: '{{', end: '}}' },\n usesInheritance,\n defer: {\n mode: 0,\n blocks: buildDeferDependencyMap(\n parsedTemplate,\n sourceFile,\n registry,\n localSelectors,\n ).blocks,\n },\n declarationListEmitMode: 1,\n i18nUseExternalIds: opts.i18nUseExternalIds ?? false,\n relativeContextFilePath: fileName,\n controlCreate: null,\n };\n\n if (ANGULAR_MAJOR < 18) {\n // Angular v17 reads `meta.deferBlocks`, `meta.deferrableTypes`,\n // and `meta.deferBlockDepsEmitMode` as flat top-level fields on\n // the component metadata; v18 nested them under `meta.defer`.\n // `compileComponentFromMetadata` on v17 reads `.size` on the two\n // Maps unconditionally (compiler.mjs ~30770), so the fields must\n // exist as Maps even for components that don't use @defer.\n // Empty Maps are sufficient for the no-@defer case — components\n // that actually use @defer on v17 are not supported (the v17\n // @defer ABI is significantly different from v18+ and is not\n // worth back-porting per the minimum-effort policy).\n componentMeta.deferBlocks = new Map();\n componentMeta.deferrableTypes = new Map();\n componentMeta.deferBlockDepsEmitMode = 0;\n }\n\n if (ANGULAR_MAJOR >= 20) {\n componentMeta.hasDirectiveDependencies =\n declarations.length > 0 ||\n (Array.isArray(meta.imports) && meta.imports.length > 0);\n }\n\n if (isPartial) {\n // Partial compilation accesses .inputs, .outputs, .exportAs on\n // each declaration — ensure they are arrays (not undefined).\n componentMeta.declarations = declarations.map((d) => ({\n ...d,\n inputs: d.inputs ?? null,\n outputs: d.outputs ?? null,\n exportAs: d.exportAs ?? null,\n isComponent: d.isComponent ?? false,\n }));\n const cmp = compileDeclareComponentFromMetadata(\n componentMeta,\n parsedTemplate,\n {\n content: templateContent,\n sourceUrl: fileName,\n isInline: !meta.templateUrl,\n inlineTemplateLiteralExpression: null,\n },\n );\n ivyCode.push(\n `static ɵcmp = /*@__PURE__*/ ${emitAngularExpr(cmp.expression)}`,\n );\n for (const stmt of cmp.statements ?? []) {\n hoistedHelpers.push(emitAngularStmt(stmt));\n }\n } else {\n const cmp = compileComponentFromMetadata(\n componentMeta,\n constantPool,\n bindingParser!,\n );\n ivyCode.push(\n `static ɵcmp = /*@__PURE__*/ ${emitAngularExpr(cmp.expression)}`,\n );\n // Hoist nested template helper functions returned via\n // R3CompiledExpression.statements. On Angular ≤19 these contain\n // `*_Conditional_*_Template`, `*_For_*_Template`, etc. functions\n // that the component definition references; on Angular ≥20 they\n // are typically pushed into the shared constantPool instead and\n // this loop is a no-op.\n for (const stmt of cmp.statements ?? []) {\n hoistedHelpers.push(emitAngularStmt(stmt));\n }\n }\n break;\n }\n\n case 'Directive': {\n targetType = FactoryTarget.Directive;\n // Build proper input descriptors (same as Component path)\n const dirInputs: Record<string, unknown> = {};\n if (Array.isArray(meta.inputs)) {\n meta.inputs.forEach((i: string) => (dirInputs[i] = i));\n } else if (meta.inputs) {\n Object.assign(dirInputs, meta.inputs);\n }\n Object.assign(dirInputs, fields.inputs);\n for (const [key, val] of Object.entries(sigs.inputs)) {\n const sigDesc = val as {\n bindingPropertyName?: string;\n required?: boolean;\n transform?: o.Expression | null;\n };\n dirInputs[key] = {\n classPropertyName: key,\n // Honor the binding name (alias) extracted by detectSignals.\n bindingPropertyName: sigDesc.bindingPropertyName ?? key,\n isSignal: true,\n required: sigDesc.required || false,\n transformFunction: sigDesc.transform || null,\n };\n }\n const directiveMeta = {\n ...meta,\n // Abstract base directives are declared as `@Directive()` with\n // no metadata. Angular's R3DirectiveMetadata accepts\n // `selector: string | null`, but the downstream selector parser\n // calls `.replace()` on the value and crashes on `undefined`.\n // Coerce missing selectors to `null` so abstract base classes\n // compile correctly.\n selector: meta.selector ?? null,\n name: className,\n type: classRef,\n typeSourceSpan,\n host: hostMetadata,\n inputs: dirInputs,\n outputs: { ...meta.outputs, ...fields.outputs, ...sigs.outputs },\n viewQueries: [...fields.viewQueries, ...sigs.viewQueries],\n queries: [...fields.contentQueries, ...sigs.contentQueries],\n // Angular's compiler treats `providers` as an Expression and\n // emits `ɵɵProvidersFeature(<expr>)` whenever it is truthy.\n // Passing the bare JS array of WrappedNodeExpr from\n // extractMetadata causes the emitter to lower it to `null`,\n // which then crashes Angular at runtime in `resolveProvider`\n // because it tries to read `.provide` on `null`. Wrap into a\n // LiteralArrayExpr (matching the Component branch) so it\n // emits a real array literal — and pass `null` when there are\n // no providers so Angular skips the feature entirely.\n providers: meta.providers?.length\n ? new o.LiteralArrayExpr(meta.providers)\n : null,\n exportAs: meta.exportAs,\n isStandalone: meta.standalone,\n lifecycle: { usesOnChanges: false },\n usesInheritance,\n controlCreate: null,\n };\n if (isPartial) {\n const dir = compileDeclareDirectiveFromMetadata(directiveMeta);\n ivyCode.push(\n `static ɵdir = /*@__PURE__*/ ${emitAngularExpr(dir.expression)}`,\n );\n } else {\n const dir = compileDirectiveFromMetadata(\n directiveMeta,\n constantPool,\n bindingParser!,\n );\n ivyCode.push(\n `static ɵdir = /*@__PURE__*/ ${emitAngularExpr(dir.expression)}`,\n );\n }\n break;\n }\n\n case 'Pipe': {\n targetType = FactoryTarget.Pipe;\n const pipeMeta = {\n ...meta,\n name: className,\n pipeName: meta.name,\n type: classRef,\n isStandalone: meta.standalone,\n pure: meta.pure ?? true,\n };\n if (isPartial) {\n const pipe = compileDeclarePipeFromMetadata(pipeMeta);\n ivyCode.push(\n `static ɵpipe = /*@__PURE__*/ ${emitAngularExpr(pipe.expression)}`,\n );\n } else {\n const pipe = compilePipeFromMetadata(pipeMeta);\n ivyCode.push(\n `static ɵpipe = /*@__PURE__*/ ${emitAngularExpr(pipe.expression)}`,\n );\n }\n break;\n }\n\n case 'Injectable': {\n targetType = FactoryTarget.Injectable;\n const injectableMeta: any = {\n name: className,\n type: classRef,\n typeArgumentCount: 0,\n providedIn: {\n expression: new o.LiteralExpr(meta.providedIn || 'root'),\n forwardRef: 0,\n },\n };\n // Forward provider configuration so `ɵprov` honors useFactory/\n // useClass/useExisting/useValue. Without this, an\n // `@Injectable({ useFactory: () => ... })` quietly falls back\n // to constructor instantiation.\n if (meta.useClass) injectableMeta.useClass = meta.useClass;\n if (meta.useFactory) injectableMeta.useFactory = meta.useFactory;\n if (meta.useExisting) injectableMeta.useExisting = meta.useExisting;\n if (meta.useValue) injectableMeta.useValue = meta.useValue;\n if (isPartial) {\n const inj = compileDeclareInjectableFromMetadata(injectableMeta);\n ivyCode.push(\n `static ɵprov = /*@__PURE__*/ ${emitAngularExpr(inj.expression)}`,\n );\n } else {\n const inj = o.compileInjectable(injectableMeta, true);\n ivyCode.push(\n `static ɵprov = /*@__PURE__*/ ${emitAngularExpr(inj.expression)}`,\n );\n }\n break;\n }\n\n case 'NgModule': {\n targetType = FactoryTarget.NgModule;\n const ngModuleImports = Array.isArray(meta.imports)\n ? meta.imports\n : [];\n const ngModuleDeclarations = Array.isArray(meta.declarations)\n ? meta.declarations\n : [];\n const ngModuleExports = Array.isArray(meta.exports)\n ? meta.exports\n : [];\n const ngModuleBootstrap = Array.isArray(meta.bootstrap)\n ? meta.bootstrap\n : [];\n\n const ngModuleMeta = {\n kind: R3NgModuleMetadataKind.Global as const,\n type: classRef,\n bootstrap: ngModuleBootstrap.map((e: o.WrappedNodeExpr<any>) => ({\n value: e,\n type: e,\n })),\n declarations: ngModuleDeclarations.map(\n (e: o.WrappedNodeExpr<any>) => ({ value: e, type: e }),\n ),\n publicDeclarationTypes: null,\n imports: ngModuleImports.map((e: o.WrappedNodeExpr<any>) => ({\n value: e,\n type: e,\n })),\n includeImportTypes: true,\n exports: ngModuleExports.map((e: o.WrappedNodeExpr<any>) => ({\n value: e,\n type: e,\n })),\n selectorScopeMode: R3SelectorScopeMode.Inline,\n containsForwardDecls: false,\n schemas: [],\n id: null,\n };\n const injectorMeta = {\n name: className,\n type: classRef,\n providers: meta.providers\n ? new o.LiteralArrayExpr(meta.providers)\n : null,\n imports: ngModuleImports.map((e: o.WrappedNodeExpr<any>) => e),\n };\n if (isPartial) {\n const ngMod = compileDeclareNgModuleFromMetadata(ngModuleMeta);\n ivyCode.push(\n `static ɵmod = /*@__PURE__*/ ${emitAngularExpr(ngMod.expression)}`,\n );\n const injector = compileDeclareInjectorFromMetadata(injectorMeta);\n ivyCode.push(\n `static ɵinj = /*@__PURE__*/ ${emitAngularExpr(injector.expression)}`,\n );\n } else {\n const ngMod = compileNgModule(ngModuleMeta);\n ivyCode.push(\n `static ɵmod = /*@__PURE__*/ ${emitAngularExpr(ngMod.expression)}`,\n );\n const injector = compileInjector(injectorMeta);\n ivyCode.push(\n `static ɵinj = /*@__PURE__*/ ${emitAngularExpr(injector.expression)}`,\n );\n }\n break;\n }\n }\n });\n\n if (classCompileError) {\n throw classCompileError;\n }\n\n // Generate factory\n const deps = oxcNode\n ? extractConstructorDeps(oxcNode, sourceCode, typeOnlyImports)\n : [];\n if (deps === null) {\n const baseVar = `ɵ${className}_BaseFactory`;\n ivyCode.unshift(\n `static ɵfac = /*@__PURE__*/ (() => { let ${baseVar}; return function ${className}_Factory(__ngFactoryType__) { return (${baseVar} || (${baseVar} = i0.ɵɵgetInheritedFactory(${className})))(__ngFactoryType__ || ${className}); }; })()`,\n );\n } else if (deps === 'invalid') {\n ivyCode.unshift(\n `static ɵfac = function ${className}_Factory(__ngFactoryType__) { i0.ɵɵinvalidFactory(); }`,\n );\n } else {\n const factoryMeta = {\n name: className,\n type: classRef,\n typeArgumentCount: 0,\n deps,\n target: targetType,\n };\n if (isPartial) {\n const fac = compileDeclareFactoryFunction(factoryMeta);\n ivyCode.unshift(\n `static ɵfac = /*@__PURE__*/ ${emitAngularExpr(fac.expression)}`,\n );\n } else {\n const fac = compileFactoryFunction(factoryMeta);\n ivyCode.unshift(\n `static ɵfac = /*@__PURE__*/ ${emitAngularExpr(fac.expression)}`,\n );\n }\n }\n\n // Emit setClassMetadata for runtime decorator reflection (devMode only)\n angularDecorators.forEach((dec) => {\n const call = dec.expression as ts.CallExpression;\n const decName = call.expression.getText(origSourceFile);\n const decArgsNode = call.arguments[0];\n\n // Build the decorator args for setClassMetadata, inlining resources if needed.\n const resources = resolvedResources.get(dec);\n let metadataArgsExpr: string | null = null;\n if (decArgsNode) {\n if (resources && ts.isObjectLiteralExpression(decArgsNode)) {\n // Inline external templateUrl/styleUrl(s) into the metadata so Angular's\n // runtime doesn't try to fetch relative URLs (which fails during SSR).\n const rewrittenProps: string[] = [];\n let needsTransform = false;\n for (const prop of (decArgsNode as ts.ObjectLiteralExpression)\n .properties) {\n if (!ts.isPropertyAssignment(prop)) {\n rewrittenProps.push(prop.getText(origSourceFile));\n continue;\n }\n const propName = prop.name?.getText(origSourceFile);\n\n if (propName === 'templateUrl' && resources.template) {\n rewrittenProps.push(\n `template: ${JSON.stringify(resources.template)}`,\n );\n needsTransform = true;\n } else if (\n (propName === 'styleUrl' || propName === 'styleUrls') &&\n resources.styles?.length\n ) {\n rewrittenProps.push(\n `styles: [${resources.styles.map((s) => JSON.stringify(s)).join(', ')}]`,\n );\n needsTransform = true;\n } else {\n rewrittenProps.push(prop.getText(origSourceFile));\n }\n }\n metadataArgsExpr = needsTransform\n ? `{${rewrittenProps.join(', ')}}`\n : decArgsNode.getText(origSourceFile);\n } else {\n metadataArgsExpr = decArgsNode.getText(origSourceFile);\n }\n }\n\n try {\n // `LiteralMapPropertyAssignment` was a class with a constructor in\n // Angular up through ~v19, removed-then-restored in later v20/v21\n // patches. The only stable shape across versions is the plain\n // `{ key, value, quoted }` object literal — Angular's own emitter\n // and Analog's `JSEmitter` both consume entries via duck typing\n // (`.key` / `.value` / `.quoted`), and `compileClassMetadata` does\n // not `instanceof`-check entries. The js-emitter has a matching\n // comment at the consumption site. Using `new o.LiteralMapProperty\n // Assignment(...)` would throw \"is not a constructor\" on Angular\n // versions where the class export is missing (e.g. 20.3.x), and\n // the surrounding try/catch would silently disable class metadata\n // emission for every class in the project.\n const classMetaInput = {\n type: new o.WrappedNodeExpr(ts.factory.createIdentifier(className)),\n decorators: new o.LiteralArrayExpr([\n new o.LiteralMapExpr([\n {\n key: 'type',\n value: new o.WrappedNodeExpr(decName),\n quoted: false,\n },\n ...(metadataArgsExpr\n ? [\n {\n key: 'args',\n value: new o.LiteralArrayExpr([\n new o.WrappedNodeExpr(metadataArgsExpr),\n ]),\n quoted: false,\n },\n ]\n : []),\n ] as unknown as o.LiteralMapPropertyAssignment[]),\n ]),\n ctorParameters: null,\n propDecorators: null,\n };\n const classMetadataExpr = isPartial\n ? compileDeclareClassMetadata(classMetaInput)\n : compileClassMetadata(classMetaInput);\n constantPool.statements.push(\n new o.ExpressionStatement(classMetadataExpr),\n );\n } catch (e) {\n // Skip if compileClassMetadata fails — surfaced via DEBUG=analog-fast-compile\n if (debugCompile.enabled) {\n debugCompile(\n 'compileClassMetadata failed for %s in %s: %s',\n className,\n fileName,\n (e as Error)?.message,\n );\n }\n }\n });\n\n // Collect member decorators (@HostListener, @HostBinding, @Input, @Output,\n // @ViewChild, @ContentChild, etc.) so they are removed from the source.\n // The metadata has already been extracted by detectFieldDecorators().\n const memberDecorators: ts.Decorator[] = [];\n for (const member of node.members) {\n const mDecorators = ts.getDecorators(member as any);\n if (!mDecorators) continue;\n for (const dec of mDecorators) {\n if (!ts.isCallExpression(dec.expression)) continue;\n const decName = dec.expression.expression.getText(origSourceFile);\n if (FIELD_DECORATORS.has(decName)) {\n memberDecorators.push(dec);\n }\n }\n }\n\n classResults.push({\n ivyCode,\n decorators: [...angularDecorators, ...memberDecorators],\n classEnd: node.getEnd(),\n });\n }\n\n // Apply edits via MagicString\n const ms = new MagicString(sourceCode, { filename: fileName });\n\n // 1. Prepend i0 import (skip if already present)\n if (!sourceCode.includes('import * as i0 from')) {\n ms.prepend('import * as i0 from \"@angular/core\";\\n');\n }\n\n // 1b. Inject synthetic imports for NgModule-exported classes\n for (const [name, specifier] of syntheticImports) {\n if (!importedNames.has(name)) {\n ms.prepend(`import { ${name} } from \"${specifier}\";\\n`);\n importedNames.add(name);\n }\n }\n\n // 2a. Hoist non-exported variable/function declarations that appear after\n // a class to just before the first class. This avoids TDZ errors when\n // static ɵcmp references file-level constants declared after the class.\n //\n // We must NOT hoist a statement whose initializer references a name\n // (class, exported const/let) that is defined between firstClassPos and\n // the statement itself — doing so would move the reference before the\n // definition and cause a TDZ error at runtime.\n if (classResults.length > 0) {\n // Find the position right before the first class (any class, not just Angular-decorated)\n let firstClassPos = Infinity;\n const nonHoistableNames = new Set<string>();\n for (const stmt of origSourceFile.statements) {\n if (ts.isClassDeclaration(stmt)) {\n firstClassPos = stmt.getStart(origSourceFile);\n // The first class itself is non-hoistable — statements hoisted\n // before it must not reference it.\n if (stmt.name) {\n nonHoistableNames.add(stmt.name.text);\n }\n break;\n }\n }\n\n // Pass 1: collect names defined by statements that will NOT be hoisted\n // (classes, exported vars/functions) and therefore remain after firstClassPos.\n for (const stmt of origSourceFile.statements) {\n const stmtStart = stmt.getStart(origSourceFile);\n if (stmtStart <= firstClassPos) continue;\n\n if (ts.isClassDeclaration(stmt) && stmt.name) {\n nonHoistableNames.add(stmt.name.text);\n }\n if (ts.isEnumDeclaration(stmt)) {\n nonHoistableNames.add(stmt.name.text);\n }\n if (ts.isVariableStatement(stmt) && hasExportModifier(stmt)) {\n for (const decl of stmt.declarationList.declarations) {\n const names: string[] = [];\n collectBindingNames(decl.name, names);\n for (const n of names) {\n nonHoistableNames.add(n);\n }\n }\n }\n if (\n ts.isFunctionDeclaration(stmt) &&\n hasExportModifier(stmt) &&\n stmt.name\n ) {\n nonHoistableNames.add(stmt.name.text);\n }\n }\n\n // Pass 2: for each hoist candidate, check if it references any\n // non-hoistable name. If it does, skip it and add its own names to the\n // non-hoistable set (transitivity).\n for (const stmt of origSourceFile.statements) {\n const stmtStart = stmt.getStart(origSourceFile);\n if (stmtStart <= firstClassPos) continue;\n\n const isCandidate =\n (ts.isVariableStatement(stmt) && !hasExportModifier(stmt)) ||\n (ts.isFunctionDeclaration(stmt) && !hasExportModifier(stmt));\n if (!isCandidate) continue;\n\n const referencedIds = collectIdentifiers(stmt);\n let referencesNonHoistable = false;\n for (const id of referencedIds) {\n if (nonHoistableNames.has(id)) {\n referencesNonHoistable = true;\n break;\n }\n }\n\n if (referencesNonHoistable) {\n // Don't hoist — mark this statement's names as non-hoistable too\n for (const name of getDefinedNames(stmt)) {\n nonHoistableNames.add(name);\n }\n } else {\n const text = stmt.getText(origSourceFile);\n ms.remove(stmtStart, stmt.getEnd());\n ms.appendLeft(firstClassPos, text + '\\n');\n }\n }\n }\n\n // 2. For each compiled class: remove decorators + insert Ivy definitions\n for (const cr of classResults) {\n // Remove Angular decorators from source\n for (const dec of cr.decorators) {\n const start = dec.getStart(origSourceFile);\n const end = dec.getEnd();\n let trimEnd = end;\n while (\n trimEnd < sourceCode.length &&\n (sourceCode[trimEnd] === ' ' ||\n sourceCode[trimEnd] === '\\n' ||\n sourceCode[trimEnd] === '\\r')\n ) {\n trimEnd++;\n }\n ms.remove(start, trimEnd);\n }\n\n // Insert static members before closing }\n if (cr.ivyCode.length > 0) {\n const memberCode = cr.ivyCode.map((c) => ' ' + c + ';').join('\\n');\n ms.appendLeft(cr.classEnd - 1, '\\n' + memberCode + '\\n');\n }\n }\n\n // 3. Emit constant pool statements.\n // Split into: helper declarations (const/function) that must appear before\n // the class (since static property initializers reference them), and\n // side-effect statements (setClassMetadata IIFEs) that go after.\n const helpers: string[] = [];\n const sideEffects: string[] = [];\n // Per-class hoisted helpers (nested template functions) come first so they\n // are available when subsequent constant-pool helpers reference them.\n helpers.push(...hoistedHelpers);\n for (const s of constantPool.statements) {\n const code = emitAngularStmt(s);\n if (\n s instanceof o.ExpressionStatement &&\n s.expr instanceof o.InvokeFunctionExpr\n ) {\n // setClassMetadata is wrapped in `(() => { ... })()` — annotate\n // the IIFE call so bundlers can drop it when ngDevMode is folded\n // to false at production build time.\n sideEffects.push(`/*@__PURE__*/ ${code}`);\n } else {\n helpers.push(code);\n }\n }\n\n if (helpers.length > 0) {\n // Insert helpers after the last import / top-level non-class statement,\n // well before any class that references them.\n // Detect which imported names are type-only so we skip imports that will\n // be fully removed by elideTypeOnlyImportsMagicString (step 4).\n // Inserting at a position inside a soon-to-be-removed range would cause\n // MagicString to discard the helpers along with the import.\n const willElide = detectTypeOnlyImportNames(ms.toString());\n\n let insertPos = 0;\n for (const stmt of origSourceFile.statements) {\n if (ts.isImportDeclaration(stmt)) {\n // Skip imports that will be entirely removed by type elision\n if (willElide.size > 0 && stmt.importClause) {\n const clause = stmt.importClause;\n const namedBindings =\n clause.namedBindings && ts.isNamedImports(clause.namedBindings)\n ? clause.namedBindings.elements\n : undefined;\n const defaultName = clause.name;\n const allElided =\n (!defaultName || willElide.has(defaultName.text)) &&\n (!namedBindings ||\n namedBindings.every(\n (el) => el.isTypeOnly || willElide.has(el.name.text),\n ));\n if (allElided) continue;\n }\n insertPos = stmt.getEnd();\n } else if (\n ts.isVariableStatement(stmt) &&\n !stmt.getText(origSourceFile).includes('class')\n ) {\n insertPos = stmt.getEnd();\n } else if (!ts.isExportAssignment(stmt)) {\n // Stop at the first class or non-import/non-variable statement\n break;\n }\n }\n // Helpers must survive downstream `ms.overwrite()` / `ms.remove()` of\n // imports performed by the type-only specifier elision pass (step 5).\n //\n // Case `insertPos > 0`: a surviving import ends at `insertPos`. Use\n // `appendRight(insertPos, …)` so helpers bind to the `\\n` after the\n // import's `;` — outside any overwrite range `[node.start, node.end)`\n // of a preceding import. `appendLeft(insertPos, …)` would bind to the\n // `;` itself, which IS inside the overwrite range and would be wiped.\n //\n // Case `insertPos === 0`: no import survives — every import is going\n // to be elided, and `elideTypeOnlyImportsMagicString` will\n // `ms.remove(0, declEnd)` the first one. `appendRight(0, …)` anchors\n // to the character at position 0 (the first import's first char),\n // which is inside `[0, declEnd)` and gets wiped. Use `appendLeft(0, …)`\n // instead — it anchors to the LEFT of position 0, outside any range\n // starting at 0, so the helpers survive. Ordering is still correct\n // because the i0 import prepended in step 1 lives in MagicString's\n // `intro` (from `ms.prepend`), which always emits before any\n // `appendLeft` content at position 0.\n if (insertPos === 0) {\n ms.appendLeft(0, helpers.join('\\n') + '\\n');\n } else {\n ms.appendRight(insertPos, '\\n' + helpers.join('\\n') + '\\n');\n }\n }\n if (sideEffects.length > 0) {\n ms.append('\\n\\n' + sideEffects.join('\\n'));\n }\n\n // 4. Lower class field initializers to constructor assignments when\n // useDefineForClassFields is false (standard Angular tsconfig).\n // Uses the original OXC AST positions which are still valid for MagicString\n // since MagicString tracks edits relative to the original source.\n // Ivy static definitions (ɵcmp, ɵfac) are not in the original AST so they\n // are unaffected, and shouldLowerField skips static fields regardless.\n if (!useDefineForClassFields) {\n lowerClassFields(ms, sourceCode, oxcProgram);\n }\n\n // 5. Elide imports that are only used in type positions (type annotations,\n // implements, generics, etc.). Without this pass, single-file transpilers\n // like OXC / esbuild cannot tell that `import { SomeType }` is type-only\n // and will leave the import in the output, causing runtime errors.\n elideTypeOnlyImportsMagicString(ms);\n\n const map = ms.generateMap({\n source: fileName,\n file: fileName + '.js',\n includeContent: true,\n hires: 'boundary',\n });\n\n if (debugCompile.enabled) {\n debugCompile(\n 'compile %s done (%dms, %d classes, %d resource deps)',\n fileName,\n Math.round(performance.now() - startTimeMs),\n classResults.length,\n resourceDependencies.length,\n );\n }\n return {\n code: ms.toString(),\n map,\n resourceDependencies,\n };\n}\n\nfunction injectAngularImport(sf: ts.SourceFile) {\n return ts.factory.updateSourceFile(sf, [\n ts.factory.createImportDeclaration(\n undefined,\n ts.factory.createImportClause(\n false,\n undefined,\n ts.factory.createNamespaceImport(ts.factory.createIdentifier('i0')),\n ),\n ts.factory.createStringLiteral('@angular/core'),\n ),\n ...sf.statements,\n ]);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Angular name constants for the fast-compile path.
|
|
3
|
+
*
|
|
4
|
+
* Centralised here to prevent drift when decorator sets are referenced
|
|
5
|
+
* across multiple source files (compile, registry, JIT, metadata).
|
|
6
|
+
*/
|
|
7
|
+
/** All five Angular class decorators. */
|
|
8
|
+
export declare const ANGULAR_DECORATORS: unknown;
|
|
9
|
+
/**
|
|
10
|
+
* Angular decorators that produce compilable declarations (selector, template,
|
|
11
|
+
* pipe name, or module exports). Excludes `@Injectable` which self-registers
|
|
12
|
+
* via ɵprov and doesn't need Ivy compilation.
|
|
13
|
+
*/
|
|
14
|
+
export declare const COMPILABLE_DECORATORS: unknown;
|
|
15
|
+
/** Decorator names used on class fields and host bindings. */
|
|
16
|
+
export declare const FIELD_DECORATORS: unknown;
|
|
17
|
+
/** Signal-based reactive APIs that need downleveling or metadata extraction. */
|
|
18
|
+
export declare const SIGNAL_APIS: unknown;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region packages/vite-plugin-angular/src/lib/compiler/constants.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared Angular name constants for the fast-compile path.
|
|
4
|
+
*
|
|
5
|
+
* Centralised here to prevent drift when decorator sets are referenced
|
|
6
|
+
* across multiple source files (compile, registry, JIT, metadata).
|
|
7
|
+
*/
|
|
8
|
+
/** All five Angular class decorators. */
|
|
9
|
+
var ANGULAR_DECORATORS = new Set([
|
|
10
|
+
"Component",
|
|
11
|
+
"Directive",
|
|
12
|
+
"Pipe",
|
|
13
|
+
"Injectable",
|
|
14
|
+
"NgModule"
|
|
15
|
+
]);
|
|
16
|
+
/**
|
|
17
|
+
* Angular decorators that produce compilable declarations (selector, template,
|
|
18
|
+
* pipe name, or module exports). Excludes `@Injectable` which self-registers
|
|
19
|
+
* via ɵprov and doesn't need Ivy compilation.
|
|
20
|
+
*/
|
|
21
|
+
var COMPILABLE_DECORATORS = new Set([
|
|
22
|
+
"Component",
|
|
23
|
+
"Directive",
|
|
24
|
+
"Pipe",
|
|
25
|
+
"NgModule"
|
|
26
|
+
]);
|
|
27
|
+
/** Decorator names used on class fields and host bindings. */
|
|
28
|
+
var FIELD_DECORATORS = new Set([
|
|
29
|
+
"Input",
|
|
30
|
+
"Output",
|
|
31
|
+
"ViewChild",
|
|
32
|
+
"ViewChildren",
|
|
33
|
+
"ContentChild",
|
|
34
|
+
"ContentChildren",
|
|
35
|
+
"HostBinding",
|
|
36
|
+
"HostListener"
|
|
37
|
+
]);
|
|
38
|
+
/** Signal-based reactive APIs that need downleveling or metadata extraction. */
|
|
39
|
+
var SIGNAL_APIS = new Set([
|
|
40
|
+
"input",
|
|
41
|
+
"model",
|
|
42
|
+
"output",
|
|
43
|
+
"outputFromObservable",
|
|
44
|
+
"viewChild",
|
|
45
|
+
"viewChildren",
|
|
46
|
+
"contentChild",
|
|
47
|
+
"contentChildren"
|
|
48
|
+
]);
|
|
49
|
+
//#endregion
|
|
50
|
+
export { ANGULAR_DECORATORS, COMPILABLE_DECORATORS, FIELD_DECORATORS, SIGNAL_APIS };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/lib/compiler/constants.ts"],"sourcesContent":["/**\n * Shared Angular name constants for the fast-compile path.\n *\n * Centralised here to prevent drift when decorator sets are referenced\n * across multiple source files (compile, registry, JIT, metadata).\n */\n\n/** All five Angular class decorators. */\nexport const ANGULAR_DECORATORS = new Set([\n 'Component',\n 'Directive',\n 'Pipe',\n 'Injectable',\n 'NgModule',\n]);\n\n/**\n * Angular decorators that produce compilable declarations (selector, template,\n * pipe name, or module exports). Excludes `@Injectable` which self-registers\n * via ɵprov and doesn't need Ivy compilation.\n */\nexport const COMPILABLE_DECORATORS = new Set([\n 'Component',\n 'Directive',\n 'Pipe',\n 'NgModule',\n]);\n\n/** Decorator names used on class fields and host bindings. */\nexport const FIELD_DECORATORS = new Set([\n 'Input',\n 'Output',\n 'ViewChild',\n 'ViewChildren',\n 'ContentChild',\n 'ContentChildren',\n 'HostBinding',\n 'HostListener',\n]);\n\n/** Signal-based reactive APIs that need downleveling or metadata extraction. */\nexport const SIGNAL_APIS = new Set([\n 'input',\n 'model',\n 'output',\n 'outputFromObservable',\n 'viewChild',\n 'viewChildren',\n 'contentChild',\n 'contentChildren',\n]);\n"],"mappings":";;;;;;;;AAQA,IAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,IAAa,wBAAwB,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACD,CAAC;;AAGF,IAAa,mBAAmB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,IAAa,cAAc,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level compile/transform events: per-file start, end, timing,
|
|
3
|
+
* fatal errors that get rethrown after logging.
|
|
4
|
+
*/
|
|
5
|
+
export declare const debugCompile: unknown;
|
|
6
|
+
/**
|
|
7
|
+
* Registry scanning of `.ts` and `.d.ts` files. Useful when a directive
|
|
8
|
+
* or pipe is not being recognized as a dependency — turning this on
|
|
9
|
+
* shows what the registry actually saw.
|
|
10
|
+
*/
|
|
11
|
+
export declare const debugRegistry: unknown;
|
|
12
|
+
/**
|
|
13
|
+
* Cross-file dependency resolution decisions: how an `imports: [...]`
|
|
14
|
+
* entry was resolved to underlying directives, NgModule export
|
|
15
|
+
* expansion, tuple barrel expansion.
|
|
16
|
+
*/
|
|
17
|
+
export declare const debugResolve: unknown;
|
|
18
|
+
/**
|
|
19
|
+
* Code emission and helper hoisting: which Ivy instructions were
|
|
20
|
+
* emitted, where helpers were inserted, type-only import elision.
|
|
21
|
+
*/
|
|
22
|
+
export declare const debugEmit: unknown;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createDebug } from "obug";
|
|
2
|
+
//#region packages/vite-plugin-angular/src/lib/compiler/debug.ts
|
|
3
|
+
var root = createDebug("analog-fast-compile");
|
|
4
|
+
/**
|
|
5
|
+
* Top-level compile/transform events: per-file start, end, timing,
|
|
6
|
+
* fatal errors that get rethrown after logging.
|
|
7
|
+
*/
|
|
8
|
+
var debugCompile = root;
|
|
9
|
+
/**
|
|
10
|
+
* Registry scanning of `.ts` and `.d.ts` files. Useful when a directive
|
|
11
|
+
* or pipe is not being recognized as a dependency — turning this on
|
|
12
|
+
* shows what the registry actually saw.
|
|
13
|
+
*/
|
|
14
|
+
var debugRegistry = root.extend("registry");
|
|
15
|
+
root.extend("resolve");
|
|
16
|
+
root.extend("emit");
|
|
17
|
+
//#endregion
|
|
18
|
+
export { debugCompile, debugRegistry };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","names":[],"sources":["../../../../src/lib/compiler/debug.ts"],"sourcesContent":["import { createDebug } from 'obug';\n\n// Structured debug output for the fast-compile path. Activated via the\n// `DEBUG` environment variable, e.g.:\n//\n// DEBUG=analog-fast-compile npm run build # top-level events\n// DEBUG=analog-fast-compile:* npm run build # everything\n// DEBUG=analog-fast-compile:registry npm run build # only registry\n//\n// Each namespace is a `Debugger` from obug — callable like console.log\n// (with %s/%d/%O formatters), with a `.enabled` boolean for cheap\n// gating before expensive payload construction.\n\nconst root = createDebug('analog-fast-compile');\n\n/**\n * Top-level compile/transform events: per-file start, end, timing,\n * fatal errors that get rethrown after logging.\n */\nexport const debugCompile = root;\n\n/**\n * Registry scanning of `.ts` and `.d.ts` files. Useful when a directive\n * or pipe is not being recognized as a dependency — turning this on\n * shows what the registry actually saw.\n */\nexport const debugRegistry = root.extend('registry');\n\n/**\n * Cross-file dependency resolution decisions: how an `imports: [...]`\n * entry was resolved to underlying directives, NgModule export\n * expansion, tuple barrel expansion.\n */\nexport const debugResolve = root.extend('resolve');\n\n/**\n * Code emission and helper hoisting: which Ivy instructions were\n * emitted, where helpers were inserted, type-only import elision.\n */\nexport const debugEmit = root.extend('emit');\n"],"mappings":";;AAaA,IAAM,OAAO,YAAY,sBAAsB;;;;;AAM/C,IAAa,eAAe;;;;;;AAO5B,IAAa,gBAAgB,KAAK,OAAO,WAAW;AAOxB,KAAK,OAAO,UAAU;AAMzB,KAAK,OAAO,OAAO"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
import { ComponentRegistry } from "./registry.js";
|
|
3
|
+
/** Recursively collect all DeferredBlock nodes from a template AST. */
|
|
4
|
+
export declare function collectDeferBlocks(nodes: any[]): any[];
|
|
5
|
+
/** Collect element tag names from template AST nodes recursively. */
|
|
6
|
+
export declare function collectElementNames(nodes: any[]): Set<string>;
|
|
7
|
+
/** Information about how a class is imported. */
|
|
8
|
+
export interface ImportInfo {
|
|
9
|
+
/** Module path from the import statement. */
|
|
10
|
+
path: string;
|
|
11
|
+
/** Whether the class was imported as a default import (`import X from`). */
|
|
12
|
+
isDefault: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Original exported name on the source module's namespace. For
|
|
15
|
+
* `import { HeavyWidget as Widget } from './heavy'`, the local
|
|
16
|
+
* binding is `Widget` but the namespace exposes `HeavyWidget` —
|
|
17
|
+
* `await import('./heavy')` returns `{ HeavyWidget }`, not
|
|
18
|
+
* `{ Widget }`. Defer dependency emit must use the exported name,
|
|
19
|
+
* not the local alias, or the lookup resolves to `undefined` at
|
|
20
|
+
* runtime.
|
|
21
|
+
*/
|
|
22
|
+
exportName: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build import info map: localName → { path, isDefault, exportName }
|
|
26
|
+
* from source file imports. Tracks default vs named imports plus the
|
|
27
|
+
* original exported name so the defer dependency generator can emit
|
|
28
|
+
* `import('./p').then(m => m.default)` for default imports and
|
|
29
|
+
* `import('./p').then(m => m.OriginalExportName)` for aliased named
|
|
30
|
+
* imports.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildImportMap(sf: ts.SourceFile): Map<string, ImportInfo>;
|
|
33
|
+
/**
|
|
34
|
+
* Build defer block dependency map with dynamic import() expressions.
|
|
35
|
+
*
|
|
36
|
+
* For each defer block, identifies which imported components are only used
|
|
37
|
+
* inside defer blocks (not in the eager template), and generates dynamic
|
|
38
|
+
* import expressions for lazy loading.
|
|
39
|
+
*
|
|
40
|
+
* Returns:
|
|
41
|
+
* - blocks: Map<DeferredBlock, Expression | null> for compileComponentFromMetadata
|
|
42
|
+
* - deferredImports: Set<string> of class names that should be removed from static imports
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildDeferDependencyMap(parsedTemplate: any, sourceFile: ts.SourceFile, registry: ComponentRegistry | undefined, localSelectors: Map<string, string>): {
|
|
45
|
+
blocks: Map<any, any>;
|
|
46
|
+
deferredImports: Set<string>;
|
|
47
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as o from "@angular/compiler";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
//#region packages/vite-plugin-angular/src/lib/compiler/defer.ts
|
|
4
|
+
/** Recursively collect all DeferredBlock nodes from a template AST. */
|
|
5
|
+
function collectDeferBlocks(nodes) {
|
|
6
|
+
const result = [];
|
|
7
|
+
function walk(node) {
|
|
8
|
+
if (!node) return;
|
|
9
|
+
if (node.constructor?.name === "DeferredBlock") result.push(node);
|
|
10
|
+
if (Array.isArray(node.children)) node.children.forEach(walk);
|
|
11
|
+
if (Array.isArray(node.branches)) node.branches.forEach(walk);
|
|
12
|
+
if (Array.isArray(node.cases)) node.cases.forEach(walk);
|
|
13
|
+
if (node.empty?.children) node.empty.children.forEach(walk);
|
|
14
|
+
if (node.placeholder?.children) node.placeholder.children.forEach(walk);
|
|
15
|
+
if (node.loading?.children) node.loading.children.forEach(walk);
|
|
16
|
+
if (node.error?.children) node.error.children.forEach(walk);
|
|
17
|
+
}
|
|
18
|
+
nodes.forEach(walk);
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
/** Collect element tag names from template AST nodes recursively. */
|
|
22
|
+
function collectElementNames(nodes) {
|
|
23
|
+
const result = /* @__PURE__ */ new Set();
|
|
24
|
+
function walk(node) {
|
|
25
|
+
if (!node) return;
|
|
26
|
+
if (node.constructor?.name === "Element") result.add(node.name);
|
|
27
|
+
if (Array.isArray(node.children)) node.children.forEach(walk);
|
|
28
|
+
if (Array.isArray(node.branches)) node.branches.forEach(walk);
|
|
29
|
+
if (Array.isArray(node.cases)) node.cases.forEach(walk);
|
|
30
|
+
if (node.empty?.children) node.empty.children.forEach(walk);
|
|
31
|
+
}
|
|
32
|
+
nodes.forEach(walk);
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build import info map: localName → { path, isDefault, exportName }
|
|
37
|
+
* from source file imports. Tracks default vs named imports plus the
|
|
38
|
+
* original exported name so the defer dependency generator can emit
|
|
39
|
+
* `import('./p').then(m => m.default)` for default imports and
|
|
40
|
+
* `import('./p').then(m => m.OriginalExportName)` for aliased named
|
|
41
|
+
* imports.
|
|
42
|
+
*/
|
|
43
|
+
function buildImportMap(sf) {
|
|
44
|
+
const result = /* @__PURE__ */ new Map();
|
|
45
|
+
for (const stmt of sf.statements) {
|
|
46
|
+
if (!ts.isImportDeclaration(stmt) || !stmt.importClause) continue;
|
|
47
|
+
const path = stmt.moduleSpecifier.text;
|
|
48
|
+
const clause = stmt.importClause;
|
|
49
|
+
if (clause.name) result.set(clause.name.text, {
|
|
50
|
+
path,
|
|
51
|
+
isDefault: true,
|
|
52
|
+
exportName: "default"
|
|
53
|
+
});
|
|
54
|
+
if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) for (const el of clause.namedBindings.elements) {
|
|
55
|
+
const exportName = el.propertyName?.text ?? el.name.text;
|
|
56
|
+
const info = {
|
|
57
|
+
path,
|
|
58
|
+
isDefault: false,
|
|
59
|
+
exportName
|
|
60
|
+
};
|
|
61
|
+
result.set(el.name.text, info);
|
|
62
|
+
if (exportName !== el.name.text) result.set(exportName, info);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build defer block dependency map with dynamic import() expressions.
|
|
69
|
+
*
|
|
70
|
+
* For each defer block, identifies which imported components are only used
|
|
71
|
+
* inside defer blocks (not in the eager template), and generates dynamic
|
|
72
|
+
* import expressions for lazy loading.
|
|
73
|
+
*
|
|
74
|
+
* Returns:
|
|
75
|
+
* - blocks: Map<DeferredBlock, Expression | null> for compileComponentFromMetadata
|
|
76
|
+
* - deferredImports: Set<string> of class names that should be removed from static imports
|
|
77
|
+
*/
|
|
78
|
+
function buildDeferDependencyMap(parsedTemplate, sourceFile, registry, localSelectors) {
|
|
79
|
+
const deferBlocks = collectDeferBlocks(parsedTemplate.nodes);
|
|
80
|
+
if (deferBlocks.length === 0) return {
|
|
81
|
+
blocks: /* @__PURE__ */ new Map(),
|
|
82
|
+
deferredImports: /* @__PURE__ */ new Set()
|
|
83
|
+
};
|
|
84
|
+
collectElementNames(parsedTemplate.nodes);
|
|
85
|
+
const deferElements = /* @__PURE__ */ new Set();
|
|
86
|
+
for (const block of deferBlocks) {
|
|
87
|
+
const elements = collectElementNames(block.children || []);
|
|
88
|
+
for (const el of elements) deferElements.add(el);
|
|
89
|
+
}
|
|
90
|
+
const eagerElements = /* @__PURE__ */ new Set();
|
|
91
|
+
for (const node of parsedTemplate.nodes) if (node.constructor?.name !== "DeferredBlock") {
|
|
92
|
+
const names = collectElementNames([node]);
|
|
93
|
+
for (const n of names) eagerElements.add(n);
|
|
94
|
+
}
|
|
95
|
+
const selectorToClass = /* @__PURE__ */ new Map();
|
|
96
|
+
if (registry) {
|
|
97
|
+
for (const [className, entry] of registry) if (entry.selector) selectorToClass.set(entry.selector, className);
|
|
98
|
+
}
|
|
99
|
+
for (const [className, selector] of localSelectors) selectorToClass.set(selector, className);
|
|
100
|
+
const importMap = buildImportMap(sourceFile);
|
|
101
|
+
const deferredImports = /* @__PURE__ */ new Set();
|
|
102
|
+
const deferOnlyElements = /* @__PURE__ */ new Set();
|
|
103
|
+
for (const el of deferElements) if (!eagerElements.has(el)) deferOnlyElements.add(el);
|
|
104
|
+
for (const el of deferOnlyElements) {
|
|
105
|
+
const className = selectorToClass.get(el);
|
|
106
|
+
if (className && importMap.has(className)) deferredImports.add(className);
|
|
107
|
+
}
|
|
108
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
109
|
+
for (const block of deferBlocks) {
|
|
110
|
+
const blockElements = collectElementNames(block.children || []);
|
|
111
|
+
const blockDeps = [];
|
|
112
|
+
const seenInBlock = /* @__PURE__ */ new Set();
|
|
113
|
+
for (const el of blockElements) {
|
|
114
|
+
const className = selectorToClass.get(el);
|
|
115
|
+
if (!className || !deferredImports.has(className)) continue;
|
|
116
|
+
const info = importMap.get(className);
|
|
117
|
+
const symbolName = info.exportName;
|
|
118
|
+
const key = `${info.path}#${symbolName}`;
|
|
119
|
+
if (seenInBlock.has(key)) continue;
|
|
120
|
+
seenInBlock.add(key);
|
|
121
|
+
const ast = o.outputAst;
|
|
122
|
+
const mVar = ast.variable("m");
|
|
123
|
+
const innerFn = ast.arrowFn([new ast.FnParam("m", ast.DYNAMIC_TYPE)], new o.ReadPropExpr(mVar, symbolName));
|
|
124
|
+
const importExpr = new o.InvokeFunctionExpr(new o.ReadPropExpr(new o.DynamicImportExpr(new o.LiteralExpr(info.path)), "then"), [innerFn]);
|
|
125
|
+
blockDeps.push(new o.ArrowFunctionExpr([], importExpr));
|
|
126
|
+
}
|
|
127
|
+
if (blockDeps.length > 0) blocks.set(block, new o.ArrowFunctionExpr([], new o.LiteralArrayExpr(blockDeps)));
|
|
128
|
+
else blocks.set(block, null);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
blocks,
|
|
132
|
+
deferredImports
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { buildDeferDependencyMap };
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=defer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defer.js","names":[],"sources":["../../../../src/lib/compiler/defer.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as o from '@angular/compiler';\nimport { ComponentRegistry } from './registry.js';\n\n/** Recursively collect all DeferredBlock nodes from a template AST. */\nexport function collectDeferBlocks(nodes: any[]): any[] {\n const result: any[] = [];\n function walk(node: any) {\n if (!node) return;\n if (node.constructor?.name === 'DeferredBlock') {\n result.push(node);\n }\n // Walk all possible child structures across block types:\n // Element/Template: children\n // IfBlock: branches (each has children)\n // ForLoopBlock: children, empty (has children)\n // SwitchBlock: cases (each has children)\n // DeferredBlock: children, placeholder/loading/error (each has children)\n if (Array.isArray(node.children)) node.children.forEach(walk);\n if (Array.isArray(node.branches)) node.branches.forEach(walk);\n if (Array.isArray(node.cases)) node.cases.forEach(walk);\n if (node.empty?.children) node.empty.children.forEach(walk);\n if (node.placeholder?.children) node.placeholder.children.forEach(walk);\n if (node.loading?.children) node.loading.children.forEach(walk);\n if (node.error?.children) node.error.children.forEach(walk);\n }\n nodes.forEach(walk);\n return result;\n}\n\n/** Collect element tag names from template AST nodes recursively. */\nexport function collectElementNames(nodes: any[]): Set<string> {\n const result = new Set<string>();\n function walk(node: any) {\n if (!node) return;\n if (node.constructor?.name === 'Element') result.add(node.name);\n if (Array.isArray(node.children)) node.children.forEach(walk);\n if (Array.isArray(node.branches)) node.branches.forEach(walk);\n if (Array.isArray(node.cases)) node.cases.forEach(walk);\n if (node.empty?.children) node.empty.children.forEach(walk);\n }\n nodes.forEach(walk);\n return result;\n}\n\n/** Information about how a class is imported. */\nexport interface ImportInfo {\n /** Module path from the import statement. */\n path: string;\n /** Whether the class was imported as a default import (`import X from`). */\n isDefault: boolean;\n /**\n * Original exported name on the source module's namespace. For\n * `import { HeavyWidget as Widget } from './heavy'`, the local\n * binding is `Widget` but the namespace exposes `HeavyWidget` —\n * `await import('./heavy')` returns `{ HeavyWidget }`, not\n * `{ Widget }`. Defer dependency emit must use the exported name,\n * not the local alias, or the lookup resolves to `undefined` at\n * runtime.\n */\n exportName: string;\n}\n\n/**\n * Build import info map: localName → { path, isDefault, exportName }\n * from source file imports. Tracks default vs named imports plus the\n * original exported name so the defer dependency generator can emit\n * `import('./p').then(m => m.default)` for default imports and\n * `import('./p').then(m => m.OriginalExportName)` for aliased named\n * imports.\n */\nexport function buildImportMap(sf: ts.SourceFile): Map<string, ImportInfo> {\n const result = new Map<string, ImportInfo>();\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause) continue;\n const path = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const clause = stmt.importClause;\n if (clause.name) {\n result.set(clause.name.text, {\n path,\n isDefault: true,\n exportName: 'default',\n });\n }\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements) {\n // `import { Foo as Bar }` → propertyName is `Foo`, name is `Bar`.\n // `import { Foo }` → propertyName is undefined.\n const exportName = el.propertyName?.text ?? el.name.text;\n const info: ImportInfo = { path, isDefault: false, exportName };\n // Key the map by BOTH the local binding and the original export\n // name. The defer-dep lookup uses the className from the\n // registry — which is always the original class name from the\n // source file (`HeavyWidget`), not the consumer's local alias\n // (`Widget`). Without the export-name key, aliased imports\n // would silently produce no defer dependency at all.\n result.set(el.name.text, info);\n if (exportName !== el.name.text) {\n result.set(exportName, info);\n }\n }\n }\n }\n return result;\n}\n\n/**\n * Build defer block dependency map with dynamic import() expressions.\n *\n * For each defer block, identifies which imported components are only used\n * inside defer blocks (not in the eager template), and generates dynamic\n * import expressions for lazy loading.\n *\n * Returns:\n * - blocks: Map<DeferredBlock, Expression | null> for compileComponentFromMetadata\n * - deferredImports: Set<string> of class names that should be removed from static imports\n */\nexport function buildDeferDependencyMap(\n parsedTemplate: any,\n sourceFile: ts.SourceFile,\n registry: ComponentRegistry | undefined,\n localSelectors: Map<string, string>,\n): { blocks: Map<any, any>; deferredImports: Set<string> } {\n const deferBlocks = collectDeferBlocks(parsedTemplate.nodes);\n if (deferBlocks.length === 0) {\n return { blocks: new Map(), deferredImports: new Set() };\n }\n\n // Collect all element names in eager (non-defer) template parts\n const allElements = collectElementNames(parsedTemplate.nodes);\n const deferElements = new Set<string>();\n for (const block of deferBlocks) {\n const elements = collectElementNames(block.children || []);\n for (const el of elements) deferElements.add(el);\n }\n // Eager elements = all elements minus those only in defer blocks\n // (An element is eager if it appears anywhere outside defer blocks too)\n // Simple approach: collect elements from non-defer top-level nodes\n const eagerElements = new Set<string>();\n for (const node of parsedTemplate.nodes) {\n if (node.constructor?.name !== 'DeferredBlock') {\n const names = collectElementNames([node]);\n for (const n of names) eagerElements.add(n);\n }\n }\n\n // Build selector → className map from registry + local selectors\n const selectorToClass = new Map<string, string>();\n if (registry) {\n for (const [className, entry] of registry) {\n if (entry.selector) selectorToClass.set(entry.selector, className);\n }\n }\n for (const [className, selector] of localSelectors) {\n selectorToClass.set(selector, className);\n }\n\n // Build className → importPath map\n const importMap = buildImportMap(sourceFile);\n\n // Find defer-only component class names\n const deferredImports = new Set<string>();\n const deferOnlyElements = new Set<string>();\n for (const el of deferElements) {\n if (!eagerElements.has(el)) deferOnlyElements.add(el);\n }\n\n for (const el of deferOnlyElements) {\n const className = selectorToClass.get(el);\n if (className && importMap.has(className)) {\n deferredImports.add(className);\n }\n }\n\n // Build the blocks map with dependency functions\n const blocks = new Map<any, any>();\n for (const block of deferBlocks) {\n const blockElements = collectElementNames(block.children || []);\n const blockDeps: any[] = [];\n // Within a single block, dedupe by `${path}#${symbolName}` so two\n // refs to the same component don't generate two import expressions.\n const seenInBlock = new Set<string>();\n\n for (const el of blockElements) {\n const className = selectorToClass.get(el);\n if (!className || !deferredImports.has(className)) continue;\n const info = importMap.get(className)!;\n // Use the original exported name (tracked by buildImportMap) so\n // aliased imports like `import { HeavyWidget as Widget }` resolve\n // to `m.HeavyWidget` instead of `m.Widget` (which would be\n // `undefined` on the module namespace).\n const symbolName = info.exportName;\n const key = `${info.path}#${symbolName}`;\n if (seenInBlock.has(key)) continue;\n seenInBlock.add(key);\n // import('./path').then(m => m.ClassName) — or `m.default` for\n // default imports. Without the `.then(...)` resolver Angular's\n // runtime gets a module namespace and can't find the class.\n // `FnParam` and the `variable()` helper aren't on the top-level\n // namespace; they live in the `outputAst` sub-namespace.\n const ast: any = (o as any).outputAst;\n const mVar = ast.variable('m');\n const innerFn = ast.arrowFn(\n [new ast.FnParam('m', ast.DYNAMIC_TYPE)],\n new o.ReadPropExpr(mVar, symbolName),\n );\n const importExpr = new o.InvokeFunctionExpr(\n new o.ReadPropExpr(\n new o.DynamicImportExpr(new o.LiteralExpr(info.path)),\n 'then',\n ),\n [innerFn],\n );\n blockDeps.push(new o.ArrowFunctionExpr([], importExpr));\n }\n\n if (blockDeps.length > 0) {\n // () => [import('./a').then(m => m.A), import('./b').then(m => m.default)]\n blocks.set(\n block,\n new o.ArrowFunctionExpr([], new o.LiteralArrayExpr(blockDeps)),\n );\n } else {\n blocks.set(block, null);\n }\n }\n\n return { blocks, deferredImports };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RegistryEntry } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Scan a single .d.ts file and extract Angular directive/component/pipe
|
|
4
|
+
* metadata from the static ɵdir / ɵcmp / ɵpipe type declarations.
|
|
5
|
+
*
|
|
6
|
+
* This mirrors what ngtsc's DtsMetadataReader does: it reads the type
|
|
7
|
+
* parameters of ɵɵDirectiveDeclaration / ɵɵComponentDeclaration /
|
|
8
|
+
* ɵɵPipeDeclaration to discover selectors, inputs, and outputs for
|
|
9
|
+
* pre-compiled Angular packages.
|
|
10
|
+
*/
|
|
11
|
+
export declare function scanDtsFile(code: string, fileName: string): RegistryEntry[];
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a package's directory in node_modules, scan all its .d.ts files,
|
|
14
|
+
* and return RegistryEntry[] for every Angular declaration found.
|
|
15
|
+
*
|
|
16
|
+
* @param packageName e.g. "@angular/router"
|
|
17
|
+
* @param basePath project root (where node_modules lives)
|
|
18
|
+
*/
|
|
19
|
+
export declare function scanPackageDts(packageName: string, basePath: string): RegistryEntry[];
|
|
20
|
+
/**
|
|
21
|
+
* Parse a source file with OXC and return the set of bare-specifier package
|
|
22
|
+
* names it imports (e.g. "@angular/router", "rxjs"). Relative imports are
|
|
23
|
+
* skipped.
|
|
24
|
+
*/
|
|
25
|
+
export declare function collectImportedPackages(code: string, fileName: string): Set<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Parse a source file with OXC and return the relative-path specifiers it
|
|
28
|
+
* re-exports via `export * from './x'`, `export * as Ns from './x'`, or
|
|
29
|
+
* `export { … } from './x'`. Bare-specifier re-exports are skipped.
|
|
30
|
+
*
|
|
31
|
+
* Used by the analog Vite plugin to walk library entry barrels at startup
|
|
32
|
+
* (e.g. `helm/select/src/index.ts` → `./lib/hlm-select`) so the underlying
|
|
33
|
+
* directive classes land in the registry before any consumer is compiled.
|
|
34
|
+
*/
|
|
35
|
+
export declare function collectRelativeReExports(code: string, fileName: string): string[];
|