@analogjs/vite-plugin-angular 3.0.0-alpha.91 → 3.0.0-alpha.93

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.
Files changed (34) hide show
  1. package/README.md +16 -1
  2. package/package.json +1 -1
  3. package/src/lib/angular-vite-plugin.d.ts +1 -1
  4. package/src/lib/angular-vite-plugin.js +35 -18
  5. package/src/lib/angular-vite-plugin.js.map +1 -1
  6. package/src/lib/compilation-api/compilation-api-plugin.js +52 -34
  7. package/src/lib/compilation-api/compilation-api-plugin.js.map +1 -1
  8. package/src/lib/compiler/angular-version.d.ts +2 -0
  9. package/src/lib/compiler/angular-version.js +2 -1
  10. package/src/lib/compiler/angular-version.js.map +1 -1
  11. package/src/lib/compiler/defer.js +2 -0
  12. package/src/lib/compiler/defer.js.map +1 -1
  13. package/src/lib/compiler/js-emitter.js +15 -1
  14. package/src/lib/compiler/js-emitter.js.map +1 -1
  15. package/src/lib/compiler-plugin.js +18 -12
  16. package/src/lib/compiler-plugin.js.map +1 -1
  17. package/src/lib/fast-compile-plugin.js +0 -2
  18. package/src/lib/fast-compile-plugin.js.map +1 -1
  19. package/src/lib/host.d.ts +1 -0
  20. package/src/lib/host.js +19 -1
  21. package/src/lib/host.js.map +1 -1
  22. package/src/lib/hot-update-batch.d.ts +5 -0
  23. package/src/lib/hot-update-batch.js +176 -0
  24. package/src/lib/hot-update-batch.js.map +1 -0
  25. package/src/lib/router-plugin.js +6 -3
  26. package/src/lib/router-plugin.js.map +1 -1
  27. package/src/lib/utils/compilation-shared.d.ts +1 -0
  28. package/src/lib/utils/compilation-shared.js +15 -1
  29. package/src/lib/utils/compilation-shared.js.map +1 -1
  30. package/src/lib/utils/devkit.js +4 -1
  31. package/src/lib/utils/devkit.js.map +1 -1
  32. package/src/lib/utils/plugin-config.d.ts +1 -0
  33. package/src/lib/utils/plugin-config.js +2 -1
  34. package/src/lib/utils/plugin-config.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"js-emitter.js","names":[],"sources":["../../../../src/lib/compiler/js-emitter.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as o from '@angular/compiler';\n\n/** Shared printer — only used as fallback for complex WrappedNodeExpr (e.g. decorator args). */\nconst sharedPrinter = ts.createPrinter({ removeComments: true });\nconst emptySourceFile = ts.createSourceFile(\n '_.ts',\n '',\n ts.ScriptTarget.Latest,\n false,\n);\n\n// Operator metadata table — name, JS string, and precedence (higher = tighter\n// binding). Used to build version-aware lookup maps below.\n//\n// Why a runtime build instead of static `[o.BinaryOperator.Equals]: '=='`\n// literals: Angular's `BinaryOperator` enum gains members between major\n// versions (Assign and the 9 compound assignments were added in v21,\n// Exponentiation/In in v20, InstanceOf in v21). On older Angular versions\n// the missing members evaluate to `undefined` at module load time, and\n// every `[undefined]: '...'` entry collides on the single string key\n// `\"undefined\"` — last write wins. Pre-Phase-1, that gave the v19 install\n// `BINARY_OP_STR[\"undefined\"] === '??='`, so any expression with an\n// unknown operator emitted `??=` instead of failing loudly. Building the\n// table by iterating known names and skipping `undefined` values\n// eliminates the collision: members that don't exist on the installed\n// Angular are simply absent from the map.\n//\n// Precedence values match MDN's table, skipping levels not used by Angular\n// (bitwise XOR, shifts).\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence\nconst OP_DEFINITIONS: ReadonlyArray<\n readonly [name: string, str: string, precedence: number]\n> = [\n ['Assign', '=', 2],\n ['AdditionAssignment', '+=', 2],\n ['SubtractionAssignment', '-=', 2],\n ['MultiplicationAssignment', '*=', 2],\n ['DivisionAssignment', '/=', 2],\n ['RemainderAssignment', '%=', 2],\n ['ExponentiationAssignment', '**=', 2],\n ['AndAssignment', '&&=', 2],\n ['OrAssignment', '||=', 2],\n ['NullishCoalesceAssignment', '??=', 2],\n ['NullishCoalesce', '??', 4],\n ['Or', '||', 4],\n ['And', '&&', 5],\n ['BitwiseOr', '|', 6],\n ['BitwiseAnd', '&', 8],\n ['Equals', '==', 9],\n ['NotEquals', '!=', 9],\n ['Identical', '===', 9],\n ['NotIdentical', '!==', 9],\n ['Lower', '<', 10],\n ['LowerEquals', '<=', 10],\n ['Bigger', '>', 10],\n ['BiggerEquals', '>=', 10],\n ['In', 'in', 10],\n ['InstanceOf', 'instanceof', 10],\n ['Plus', '+', 12],\n ['Minus', '-', 12],\n ['Multiply', '*', 13],\n ['Divide', '/', 13],\n ['Modulo', '%', 13],\n ['Exponentiation', '**', 14],\n];\n\n/** Operator integer values that represent assignment forms (`=`, `+=`, etc.). */\nconst ASSIGNMENT_OP_NAMES: ReadonlySet<string> = new Set([\n 'Assign',\n 'AdditionAssignment',\n 'SubtractionAssignment',\n 'MultiplicationAssignment',\n 'DivisionAssignment',\n 'RemainderAssignment',\n 'ExponentiationAssignment',\n 'AndAssignment',\n 'OrAssignment',\n 'NullishCoalesceAssignment',\n]);\n\nconst BINARY_OP_STR = new Map<number, string>();\nconst BINARY_PRECEDENCE = new Map<number, number>();\nconst ASSIGNMENT_OP_VALUES = new Set<number>();\n\nfor (const [name, str, precedence] of OP_DEFINITIONS) {\n const value = (o.BinaryOperator as Record<string, unknown>)[name];\n if (typeof value !== 'number') continue;\n BINARY_OP_STR.set(value, str);\n BINARY_PRECEDENCE.set(value, precedence);\n if (ASSIGNMENT_OP_NAMES.has(name)) {\n ASSIGNMENT_OP_VALUES.add(value);\n }\n}\n\n/** Returns true when `op` represents any kind of assignment (`=`, `+=`, etc.). */\nfunction isAssignmentOperator(op: o.BinaryOperator): boolean {\n return ASSIGNMENT_OP_VALUES.has(op);\n}\n\n/**\n * Determine whether a child expression needs parentheses when it appears\n * as an operand of `parentOp`.\n */\nfunction childNeedsParens(\n parentOp: o.BinaryOperator,\n child: o.Expression,\n isRhs: boolean,\n): boolean {\n if (!(child instanceof o.BinaryOperatorExpr)) return false;\n\n const childOp = child.operator;\n const parentPrec = BINARY_PRECEDENCE.get(parentOp);\n const childPrec = BINARY_PRECEDENCE.get(childOp);\n if (parentPrec === undefined || childPrec === undefined) return false;\n\n // ?? cannot appear with || or && without explicit grouping (JS spec)\n if (\n (parentOp === o.BinaryOperator.NullishCoalesce &&\n (childOp === o.BinaryOperator.And || childOp === o.BinaryOperator.Or)) ||\n (childOp === o.BinaryOperator.NullishCoalesce &&\n (parentOp === o.BinaryOperator.And || parentOp === o.BinaryOperator.Or))\n ) {\n return true;\n }\n\n // Child has strictly lower precedence\n if (childPrec < parentPrec) return true;\n\n // Same precedence — depends on associativity and position\n if (childPrec === parentPrec) {\n // ** is right-associative: LHS same-prec needs parens, RHS does not\n if (parentOp === o.BinaryOperator.Exponentiation) return !isRhs;\n // All other ops are left-associative: RHS same-prec needs parens\n return isRhs;\n }\n\n return false;\n}\n\n/**\n * Wrap a receiver expression in parens when emitting `<receiver>.name` or\n * `<receiver>.name(args)`. Two cases produce a JS parse error otherwise:\n *\n * 1. A `BinaryOperatorExpr` receiver: `a / 3600.toFixed(2)` parses as\n * `a / 3600.toFixed(2)` where `3600.toFixed` is read as the start of a\n * decimal literal followed by an identifier — an \"Invalid characters\n * after number\" error. Wrapping gives `(a / 3600).toFixed(2)`.\n * 2. A non-negative integer `LiteralExpr` receiver: `42.toFixed(2)` is\n * invalid for the same decimal-literal-ambiguity reason. Wrapping gives\n * `(42).toFixed(2)`. Negative numbers are already emitted as `(-42)` by\n * `visitLiteralExpr`. Floats (e.g. `4.5.toFixed`) and strings parse fine.\n *\n * Other expression kinds either already self-wrap (`ConditionalExpr`,\n * `UnaryOperatorExpr`) or are primary forms that don't need parens\n * (`ReadVarExpr`, `ReadPropExpr`, `InvokeFunctionExpr`, etc.).\n */\nfunction emitReceiverForMemberAccess(\n receiver: o.Expression,\n emitted: string,\n): string {\n if (receiver instanceof o.BinaryOperatorExpr) return '(' + emitted + ')';\n if (\n receiver instanceof o.LiteralExpr &&\n typeof receiver.value === 'number' &&\n receiver.value >= 0\n ) {\n return '(' + emitted + ')';\n }\n return emitted;\n}\n\n/** Polyfill for `__makeTemplateObject` used in downleveled `$localize` calls. */\nconst MAKE_TEMPLATE_OBJECT_POLYFILL =\n '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,\"raw\",{value:t}):e.raw=t,e})';\n\nconst SINGLE_QUOTE_ESCAPE_RE = /[\\\\'\\n\\r]/g;\n\n/** Escape a string for use as a single-quoted string literal. */\nfunction escapeForLocalize(input: string): string {\n const body = input.replace(SINGLE_QUOTE_ESCAPE_RE, (match) => {\n if (match === '\\n') return '\\\\n';\n if (match === '\\r') return '\\\\r';\n return `\\\\${match}`;\n });\n return `'${body}'`;\n}\n\n/**\n * Emits Angular output AST directly to JavaScript strings, bypassing\n * ts.factory node creation and ts.Printer serialization (~4x faster).\n */\nclass JSEmitter implements o.ExpressionVisitor, o.StatementVisitor {\n /** Set by compile() so WrappedNodeExpr fallback can print with correct source context. */\n static _currentSourceFile: ts.SourceFile | undefined;\n /** Set by compile() so OXC-based WrappedNodeExpr can slice original source. */\n static _currentSourceCode: string | undefined;\n\n private emitExpr(e: any): string {\n if (!e) return 'null';\n if (typeof e.visitExpression === 'function')\n return e.visitExpression(this, null);\n // Angular v21 LiteralMapPropertyAssignment: {key, value, quoted}\n if ('key' in e && 'value' in e) {\n const key = e.quoted ? JSON.stringify(e.key) : e.key;\n return key + ': ' + this.emitExpr(e.value);\n }\n return 'null';\n }\n visitWrappedNodeExpr(ast: o.WrappedNodeExpr<any>) {\n const node = ast.node;\n\n // Raw source text: already resolved to a string at wrap time\n if (typeof node === 'string') return node;\n\n // OXC AST nodes: identified by string `type` property + numeric start/end\n if (typeof node.type === 'string' && typeof node.start === 'number') {\n const src = JSEmitter._currentSourceCode;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'StringLiteral') return JSON.stringify(node.value);\n if (node.type === 'NumericLiteral') return String(node.value);\n if (node.type === 'BooleanLiteral') return node.value ? 'true' : 'false';\n if (node.type === 'NullLiteral') return 'null';\n if (node.type === 'TemplateLiteral' && !node.expressions?.length)\n return '`' + node.quasis[0].value.raw + '`';\n // Fallback: slice original source for complex OXC nodes\n if (src) return src.slice(node.start, node.end);\n return 'null';\n }\n\n // TypeScript AST nodes: identified by numeric `kind` property\n if (node.kind === ts.SyntaxKind.Identifier)\n return (node as ts.Identifier).escapedText as string;\n if (node.kind === ts.SyntaxKind.StringLiteral)\n return JSON.stringify((node as ts.StringLiteral).text);\n if (node.kind === ts.SyntaxKind.NumericLiteral)\n return (node as ts.NumericLiteral).text;\n if (node.kind === ts.SyntaxKind.TrueKeyword) return 'true';\n if (node.kind === ts.SyntaxKind.FalseKeyword) return 'false';\n if (node.kind === ts.SyntaxKind.NullKeyword) return 'null';\n if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)\n return '`' + (node as ts.NoSubstitutionTemplateLiteral).text + '`';\n // Fallback for complex wrapped TS nodes (e.g. decorator arguments, array literals).\n // Use currentSourceFile when available for correct position-based printing.\n return sharedPrinter.printNode(\n ts.EmitHint.Unspecified,\n node,\n JSEmitter._currentSourceFile || emptySourceFile,\n );\n }\n visitExternalExpr(ast: o.ExternalExpr) {\n const name = ast.value.name;\n if (name === 'ngDevMode') return name;\n // When name is null/undefined, this is a bare module reference (e.g. ngImport: i0)\n if (!name) return 'i0';\n return 'i0.' + name;\n }\n visitLiteralExpr(ast: o.LiteralExpr) {\n const v = ast.value;\n if (typeof v === 'string') return JSON.stringify(v);\n if (typeof v === 'number') return v < 0 ? '(-' + -v + ')' : '' + v;\n if (typeof v === 'boolean') return v ? 'true' : 'false';\n if (v === undefined) return 'void 0';\n return 'null';\n }\n visitLiteralArrayExpr(ast: o.LiteralArrayExpr) {\n return '[' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + ']';\n }\n visitLiteralMapExpr(ast: o.LiteralMapExpr) {\n return '{' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + '}';\n }\n visitInvokeFunctionExpr(ast: o.InvokeFunctionExpr) {\n const fn = ast.fn.visitExpression(this, null);\n const args = ast.args.map((a: any) => this.emitExpr(a)).join(', ');\n // Wrap arrow/function expressions in parens for valid IIFE syntax. A\n // `WrappedNodeExpr` callee is a raw user expression (e.g. an\n // `@Injectable({ useFactory: (a, b) => … })` arrow); without parens the\n // argument list binds to the arrow's *body* (`… => new X(a, b)(args)`)\n // instead of invoking the arrow. Parenthesizing any wrapped callee is\n // always semantically safe.\n const call = ast.isOptional ? '?.(' : '(';\n\n if (\n ast.fn instanceof o.ArrowFunctionExpr ||\n ast.fn instanceof o.FunctionExpr ||\n ast.fn instanceof o.WrappedNodeExpr\n ) {\n return '(' + fn + ')' + call + args + ')';\n }\n return fn + call + args + ')';\n }\n visitReadVarExpr(ast: o.ReadVarExpr) {\n if (ast.name === 'this') return 'this';\n if (ast.name === 'super') return 'super';\n return ast.name!;\n }\n visitReadPropExpr(ast: o.ReadPropExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n (ast.isOptional ? '?.' : '.') +\n ast.name\n );\n }\n visitReadKeyExpr(ast: o.ReadKeyExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n (ast.isOptional ? '?.[' : '[') +\n ast.index.visitExpression(this, null) +\n ']'\n );\n }\n visitConditionalExpr(ast: o.ConditionalExpr) {\n return (\n '(' +\n ast.condition.visitExpression(this, null) +\n ' ? ' +\n ast.trueCase.visitExpression(this, null) +\n ' : ' +\n ast.falseCase!.visitExpression(this, null) +\n ')'\n );\n }\n visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr) {\n // `BINARY_OP_STR.get(...)` returns `undefined` when the operator value\n // doesn't exist in the installed Angular's `BinaryOperator` enum (the\n // enum is missing 13 members on v19, 11 on v20). Falling back to `'='`\n // would silently produce wrong code; instead, we throw so the error\n // surfaces in the DEBUG output and the calling test fails loudly.\n const op = BINARY_OP_STR.get(ast.operator);\n if (op === undefined) {\n throw new Error(\n `[fast-compile] Unsupported BinaryOperator value ${ast.operator} ` +\n `on @angular/compiler ${o.VERSION?.full ?? '(unknown version)'}`,\n );\n }\n\n const lhsRaw = ast.lhs.visitExpression(this, null);\n const rhsRaw = ast.rhs.visitExpression(this, null);\n\n const lhs = childNeedsParens(ast.operator, ast.lhs, false)\n ? '(' + lhsRaw + ')'\n : lhsRaw;\n const rhs = childNeedsParens(ast.operator, ast.rhs, true)\n ? '(' + rhsRaw + ')'\n : rhsRaw;\n\n const expr = lhs + ' ' + op + ' ' + rhs;\n\n // Wrap assignments in parens so they work correctly as ternary conditions:\n // (tmp = val) ? a : b vs tmp = val ? a : b\n //\n // `isAssignmentOperator` is built at module load time from the operator\n // names that actually exist on the installed Angular's enum. This\n // works whether `Assign` is present (v21+) or absent (v19/v20) — on\n // older versions the assignment branch is simply unreachable because\n // Angular's compiler never constructs an Assign-operator expression.\n if (isAssignmentOperator(ast.operator)) {\n return '(' + expr + ')';\n }\n return expr;\n }\n visitNotExpr(ast: o.NotExpr) {\n return '!(' + ast.condition.visitExpression(this, null) + ')';\n }\n visitFunctionExpr(ast: o.FunctionExpr) {\n return (\n '(' +\n ast.params.map((p: any) => p.name).join(', ') +\n ') => {' +\n ast.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n visitArrowFunctionExpr(ast: o.ArrowFunctionExpr) {\n const params = '(' + ast.params.map((p: any) => p.name).join(', ') + ')';\n if (Array.isArray(ast.body))\n return (\n params +\n ' => {' +\n ast.body.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n const bodyExpr = (ast.body as o.Expression).visitExpression(this, null);\n // Wrap object literals in parens so `() => {key: val}` isn't parsed\n // as a block with a labeled statement.\n if (ast.body instanceof o.LiteralMapExpr) {\n return params + ' => (' + bodyExpr + ')';\n }\n return params + ' => ' + bodyExpr;\n }\n // `Write*Expr` visitors must wrap the assignment in parentheses so that\n // it composes correctly when nested inside higher-precedence parents\n // (e.g. as the test of a `ConditionalExpr`). Without the wrapping,\n // tmp = ctx.data() ? 0 : -1\n // parses as `tmp = (ctx.data() ? 0 : -1)` because assignment binds\n // looser than the ternary, which silently assigns the wrong value to\n // `tmp`. Angular's own `AbstractEmitterVisitor.visitWriteVarExpr`\n // applies the same context-sensitive wrapping (it skips the parens\n // when the assignment is a top-level statement to avoid `(x = 1);`\n // noise; we always wrap for simplicity — the redundant parens at\n // statement level are harmless).\n //\n // This matters specifically on Angular v19/v20, where assignment is\n // represented in the IR via `WriteVarExpr` / `AssignTemporaryExpr →\n // WriteVarExpr`. On v21+ the same construct is represented via\n // `BinaryOperatorExpr(Assign, ...)`, which `visitBinaryOperatorExpr`\n // already wraps via `isAssignmentOperator`. Without these wrappers,\n // `@if (data(); as item)` and similar conditional alias forms emit\n // runtime-broken code on v19/v20.\n visitWriteVarExpr(ast: any) {\n return '(' + ast.name + ' = ' + ast.value.visitExpression(this, null) + ')';\n }\n visitWritePropExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '.' +\n ast.name +\n ' = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitWriteKeyExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '[' +\n ast.index.visitExpression(this, null) +\n '] = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitInvokeMethodExpr(ast: any) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n '.' +\n ast.name +\n '(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitTypeofExpr(ast: o.TypeofExpr) {\n return 'typeof ' + ast.expr.visitExpression(this, null);\n }\n visitUnaryOperatorExpr(ast: o.UnaryOperatorExpr) {\n return '-(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitInstantiateExpr(ast: o.InstantiateExpr) {\n return (\n 'new (' +\n ast.classExpr.visitExpression(this, null) +\n ')(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitCommaExpr(ast: o.CommaExpr) {\n return ast.parts.map((p: any) => p.visitExpression(this, null)).join(', ');\n }\n visitParenthesizedExpr(ast: o.ParenthesizedExpr) {\n return '(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitVoidExpr(ast: o.VoidExpr) {\n return 'void ' + ast.expr.visitExpression(this, null);\n }\n visitSpreadElementExpr(ast: o.SpreadElementExpr) {\n return '...' + (ast as any).expression.visitExpression(this, null);\n }\n visitDynamicImportExpr(ast: o.DynamicImportExpr) {\n return (\n 'import(' +\n (typeof ast.url === 'string'\n ? JSON.stringify(ast.url)\n : ast.url.visitExpression(this, null)) +\n ')'\n );\n }\n visitTemplateLiteralExpr(ast: o.TemplateLiteralExpr) {\n return (\n '`' +\n ast.elements[0].text +\n ast.expressions\n .map(\n (e: any, i: number) =>\n '${' +\n e.visitExpression(this, null) +\n '}' +\n ast.elements[i + 1].text,\n )\n .join('') +\n '`'\n );\n }\n visitTaggedTemplateLiteralExpr(ast: any) {\n const elements = ast.template.elements;\n const expressions = ast.template.expressions;\n const head = elements[0].text;\n const spans = expressions\n .map(\n (e: any, i: number) =>\n '${' + e.visitExpression(this, null) + '}' + elements[i + 1].text,\n )\n .join('');\n return ast.tag.visitExpression(this, null) + '`' + head + spans + '`';\n }\n visitLocalizedString(ast: o.LocalizedString) {\n // Emit the downleveled form:\n // $localize(makeTemplateObject(cooked, raw), expr1, expr2, ...)\n const parts: { cooked: string; raw: string }[] = [ast.serializeI18nHead()];\n for (let i = 1; i < ast.messageParts.length; i++) {\n parts.push(ast.serializeI18nTemplatePart(i));\n }\n const cooked = parts.map((p) => escapeForLocalize(p.cooked)).join(', ');\n const raw = parts.map((p) => escapeForLocalize(p.raw)).join(', ');\n const exprs = ast.expressions.map((e) => this.emitExpr(e));\n return (\n '$localize(' +\n MAKE_TEMPLATE_OBJECT_POLYFILL +\n '([' +\n cooked +\n '], [' +\n raw +\n '])' +\n (exprs.length > 0 ? ', ' + exprs.join(', ') : '') +\n ')'\n );\n }\n visitRegularExpressionLiteral(ast: any) {\n return '/' + (ast.body ?? ast.pattern) + '/' + ast.flags;\n }\n visitTemplateLiteralElementExpr(ast: o.TemplateLiteralElementExpr) {\n return JSON.stringify(ast.text);\n }\n // Statement visitors\n visitReturnStmt(stmt: o.ReturnStatement) {\n return 'return ' + stmt.value.visitExpression(this, null) + ';';\n }\n visitExpressionStmt(stmt: o.ExpressionStatement) {\n return stmt.expr.visitExpression(this, null) + ';';\n }\n visitIfStmt(stmt: o.IfStmt) {\n let s =\n 'if (' +\n stmt.condition.visitExpression(this, null) +\n ') {' +\n stmt.trueCase.map((s2: any) => s2.visitStatement(this, null)).join(' ') +\n '}';\n if (stmt.falseCase.length)\n s +=\n ' else {' +\n stmt.falseCase\n .map((s2: any) => s2.visitStatement(this, null))\n .join(' ') +\n '}';\n return s;\n }\n visitDeclareVarStmt(stmt: o.DeclareVarStmt) {\n const kw = stmt.hasModifier(o.StmtModifier.Final) ? 'const' : 'let';\n return (\n kw +\n ' ' +\n stmt.name +\n (stmt.value ? ' = ' + stmt.value.visitExpression(this, null) : '') +\n ';'\n );\n }\n visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt) {\n return (\n 'function ' +\n stmt.name +\n '(' +\n stmt.params.map((p: any) => p.name).join(', ') +\n ') {' +\n stmt.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n}\n\nconst stringEmitter = new JSEmitter();\n\n/** Emit Angular output AST expression directly to a JavaScript string. */\nexport function emitAngularExpr(expr: o.Expression): string {\n return expr.visitExpression(stringEmitter, null);\n}\n\n/** Emit Angular output AST statement directly to a JavaScript string. */\nexport function emitAngularStmt(stmt: o.Statement): string {\n return stmt.visitStatement(stringEmitter, null);\n}\n\n/** Set the current source file for WrappedNodeExpr fallback printing. */\nexport function setEmitterSourceFile(sf: ts.SourceFile | undefined): void {\n JSEmitter._currentSourceFile = sf;\n}\n\n/** Set the current source code for OXC-based WrappedNodeExpr slice fallback. */\nexport function setEmitterSourceCode(code: string | undefined): void {\n JSEmitter._currentSourceCode = code;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"js-emitter.js","names":[],"sources":["../../../../src/lib/compiler/js-emitter.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as o from '@angular/compiler';\n\n/** Shared printer — only used as fallback for complex WrappedNodeExpr (e.g. decorator args). */\nconst sharedPrinter = ts.createPrinter({ removeComments: true });\nconst emptySourceFile = ts.createSourceFile(\n '_.ts',\n '',\n ts.ScriptTarget.Latest,\n false,\n);\n\n// Operator metadata table — name, JS string, and precedence (higher = tighter\n// binding). Used to build version-aware lookup maps below.\n//\n// Why a runtime build instead of static `[o.BinaryOperator.Equals]: '=='`\n// literals: Angular's `BinaryOperator` enum gains members between major\n// versions (Assign and the 9 compound assignments were added in v21,\n// Exponentiation/In in v20, InstanceOf in v21). On older Angular versions\n// the missing members evaluate to `undefined` at module load time, and\n// every `[undefined]: '...'` entry collides on the single string key\n// `\"undefined\"` — last write wins. Pre-Phase-1, that gave the v19 install\n// `BINARY_OP_STR[\"undefined\"] === '??='`, so any expression with an\n// unknown operator emitted `??=` instead of failing loudly. Building the\n// table by iterating known names and skipping `undefined` values\n// eliminates the collision: members that don't exist on the installed\n// Angular are simply absent from the map.\n//\n// Precedence values match MDN's table, skipping levels not used by Angular\n// (bitwise XOR, shifts).\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence\nconst OP_DEFINITIONS: ReadonlyArray<\n readonly [name: string, str: string, precedence: number]\n> = [\n ['Assign', '=', 2],\n ['AdditionAssignment', '+=', 2],\n ['SubtractionAssignment', '-=', 2],\n ['MultiplicationAssignment', '*=', 2],\n ['DivisionAssignment', '/=', 2],\n ['RemainderAssignment', '%=', 2],\n ['ExponentiationAssignment', '**=', 2],\n ['AndAssignment', '&&=', 2],\n ['OrAssignment', '||=', 2],\n ['NullishCoalesceAssignment', '??=', 2],\n ['NullishCoalesce', '??', 4],\n ['Or', '||', 4],\n ['And', '&&', 5],\n ['BitwiseOr', '|', 6],\n ['BitwiseAnd', '&', 8],\n ['Equals', '==', 9],\n ['NotEquals', '!=', 9],\n ['Identical', '===', 9],\n ['NotIdentical', '!==', 9],\n ['Lower', '<', 10],\n ['LowerEquals', '<=', 10],\n ['Bigger', '>', 10],\n ['BiggerEquals', '>=', 10],\n ['In', 'in', 10],\n ['InstanceOf', 'instanceof', 10],\n ['Plus', '+', 12],\n ['Minus', '-', 12],\n ['Multiply', '*', 13],\n ['Divide', '/', 13],\n ['Modulo', '%', 13],\n ['Exponentiation', '**', 14],\n];\n\n/** Operator integer values that represent assignment forms (`=`, `+=`, etc.). */\nconst ASSIGNMENT_OP_NAMES: ReadonlySet<string> = new Set([\n 'Assign',\n 'AdditionAssignment',\n 'SubtractionAssignment',\n 'MultiplicationAssignment',\n 'DivisionAssignment',\n 'RemainderAssignment',\n 'ExponentiationAssignment',\n 'AndAssignment',\n 'OrAssignment',\n 'NullishCoalesceAssignment',\n]);\n\nconst BINARY_OP_STR = new Map<number, string>();\nconst BINARY_PRECEDENCE = new Map<number, number>();\nconst ASSIGNMENT_OP_VALUES = new Set<number>();\n\nfor (const [name, str, precedence] of OP_DEFINITIONS) {\n const value = (o.BinaryOperator as Record<string, unknown>)[name];\n if (typeof value !== 'number') continue;\n BINARY_OP_STR.set(value, str);\n BINARY_PRECEDENCE.set(value, precedence);\n if (ASSIGNMENT_OP_NAMES.has(name)) {\n ASSIGNMENT_OP_VALUES.add(value);\n }\n}\n\nconst UNARY_OP_STR = new Map<number, string>();\n\nfor (const [name, str] of [\n ['Plus', '+'],\n ['Minus', '-'],\n ['Increment', '++'],\n ['Decrement', '--'],\n] as const) {\n const value = (o.UnaryOperator as Record<string, unknown>)[name];\n if (typeof value !== 'number') continue;\n UNARY_OP_STR.set(value, str);\n}\n\n/** Returns true when `op` represents any kind of assignment (`=`, `+=`, etc.). */\nfunction isAssignmentOperator(op: o.BinaryOperator): boolean {\n return ASSIGNMENT_OP_VALUES.has(op);\n}\n\n/**\n * Determine whether a child expression needs parentheses when it appears\n * as an operand of `parentOp`.\n */\nfunction childNeedsParens(\n parentOp: o.BinaryOperator,\n child: o.Expression,\n isRhs: boolean,\n): boolean {\n if (!(child instanceof o.BinaryOperatorExpr)) return false;\n\n const childOp = child.operator;\n const parentPrec = BINARY_PRECEDENCE.get(parentOp);\n const childPrec = BINARY_PRECEDENCE.get(childOp);\n if (parentPrec === undefined || childPrec === undefined) return false;\n\n // ?? cannot appear with || or && without explicit grouping (JS spec)\n if (\n (parentOp === o.BinaryOperator.NullishCoalesce &&\n (childOp === o.BinaryOperator.And || childOp === o.BinaryOperator.Or)) ||\n (childOp === o.BinaryOperator.NullishCoalesce &&\n (parentOp === o.BinaryOperator.And || parentOp === o.BinaryOperator.Or))\n ) {\n return true;\n }\n\n // Child has strictly lower precedence\n if (childPrec < parentPrec) return true;\n\n // Same precedence — depends on associativity and position\n if (childPrec === parentPrec) {\n // ** is right-associative: LHS same-prec needs parens, RHS does not\n if (parentOp === o.BinaryOperator.Exponentiation) return !isRhs;\n // All other ops are left-associative: RHS same-prec needs parens\n return isRhs;\n }\n\n return false;\n}\n\n/**\n * Wrap a receiver expression in parens when emitting `<receiver>.name` or\n * `<receiver>.name(args)`. Two cases produce a JS parse error otherwise:\n *\n * 1. A `BinaryOperatorExpr` receiver: `a / 3600.toFixed(2)` parses as\n * `a / 3600.toFixed(2)` where `3600.toFixed` is read as the start of a\n * decimal literal followed by an identifier — an \"Invalid characters\n * after number\" error. Wrapping gives `(a / 3600).toFixed(2)`.\n * 2. A non-negative integer `LiteralExpr` receiver: `42.toFixed(2)` is\n * invalid for the same decimal-literal-ambiguity reason. Wrapping gives\n * `(42).toFixed(2)`. Negative numbers are already emitted as `(-42)` by\n * `visitLiteralExpr`. Floats (e.g. `4.5.toFixed`) and strings parse fine.\n *\n * Other expression kinds either already self-wrap (`ConditionalExpr`,\n * `UnaryOperatorExpr`) or are primary forms that don't need parens\n * (`ReadVarExpr`, `ReadPropExpr`, `InvokeFunctionExpr`, etc.).\n */\nfunction emitReceiverForMemberAccess(\n receiver: o.Expression,\n emitted: string,\n): string {\n if (receiver instanceof o.BinaryOperatorExpr) return '(' + emitted + ')';\n if (\n receiver instanceof o.LiteralExpr &&\n typeof receiver.value === 'number' &&\n receiver.value >= 0\n ) {\n return '(' + emitted + ')';\n }\n return emitted;\n}\n\n/** Polyfill for `__makeTemplateObject` used in downleveled `$localize` calls. */\nconst MAKE_TEMPLATE_OBJECT_POLYFILL =\n '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,\"raw\",{value:t}):e.raw=t,e})';\n\nconst SINGLE_QUOTE_ESCAPE_RE = /[\\\\'\\n\\r]/g;\n\n/** Escape a string for use as a single-quoted string literal. */\nfunction escapeForLocalize(input: string): string {\n const body = input.replace(SINGLE_QUOTE_ESCAPE_RE, (match) => {\n if (match === '\\n') return '\\\\n';\n if (match === '\\r') return '\\\\r';\n return `\\\\${match}`;\n });\n return `'${body}'`;\n}\n\n/**\n * Emits Angular output AST directly to JavaScript strings, bypassing\n * ts.factory node creation and ts.Printer serialization (~4x faster).\n */\nclass JSEmitter implements o.ExpressionVisitor, o.StatementVisitor {\n /** Set by compile() so WrappedNodeExpr fallback can print with correct source context. */\n static _currentSourceFile: ts.SourceFile | undefined;\n /** Set by compile() so OXC-based WrappedNodeExpr can slice original source. */\n static _currentSourceCode: string | undefined;\n\n private emitExpr(e: any): string {\n if (!e) return 'null';\n if (typeof e.visitExpression === 'function')\n return e.visitExpression(this, null);\n // Angular v21 LiteralMapPropertyAssignment: {key, value, quoted}\n if ('key' in e && 'value' in e) {\n const key = e.quoted ? JSON.stringify(e.key) : e.key;\n return key + ': ' + this.emitExpr(e.value);\n }\n return 'null';\n }\n visitWrappedNodeExpr(ast: o.WrappedNodeExpr<any>) {\n const node = ast.node;\n\n // Raw source text: already resolved to a string at wrap time\n if (typeof node === 'string') return node;\n\n // OXC AST nodes: identified by string `type` property + numeric start/end\n if (typeof node.type === 'string' && typeof node.start === 'number') {\n const src = JSEmitter._currentSourceCode;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'StringLiteral') return JSON.stringify(node.value);\n if (node.type === 'NumericLiteral') return String(node.value);\n if (node.type === 'BooleanLiteral') return node.value ? 'true' : 'false';\n if (node.type === 'NullLiteral') return 'null';\n if (node.type === 'TemplateLiteral' && !node.expressions?.length)\n return '`' + node.quasis[0].value.raw + '`';\n // Fallback: slice original source for complex OXC nodes\n if (src) return src.slice(node.start, node.end);\n return 'null';\n }\n\n // TypeScript AST nodes: identified by numeric `kind` property\n if (node.kind === ts.SyntaxKind.Identifier)\n return (node as ts.Identifier).escapedText as string;\n if (node.kind === ts.SyntaxKind.StringLiteral)\n return JSON.stringify((node as ts.StringLiteral).text);\n if (node.kind === ts.SyntaxKind.NumericLiteral)\n return (node as ts.NumericLiteral).text;\n if (node.kind === ts.SyntaxKind.TrueKeyword) return 'true';\n if (node.kind === ts.SyntaxKind.FalseKeyword) return 'false';\n if (node.kind === ts.SyntaxKind.NullKeyword) return 'null';\n if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)\n return '`' + (node as ts.NoSubstitutionTemplateLiteral).text + '`';\n // Fallback for complex wrapped TS nodes (e.g. decorator arguments, array literals).\n // Use currentSourceFile when available for correct position-based printing.\n return sharedPrinter.printNode(\n ts.EmitHint.Unspecified,\n node,\n JSEmitter._currentSourceFile || emptySourceFile,\n );\n }\n visitExternalExpr(ast: o.ExternalExpr) {\n const name = ast.value.name;\n if (name === 'ngDevMode') return name;\n // When name is null/undefined, this is a bare module reference (e.g. ngImport: i0)\n if (!name) return 'i0';\n return 'i0.' + name;\n }\n visitLiteralExpr(ast: o.LiteralExpr) {\n const v = ast.value;\n if (typeof v === 'string') return JSON.stringify(v);\n if (typeof v === 'number') return v < 0 ? '(-' + -v + ')' : '' + v;\n if (typeof v === 'boolean') return v ? 'true' : 'false';\n if (v === undefined) return 'void 0';\n return 'null';\n }\n visitLiteralArrayExpr(ast: o.LiteralArrayExpr) {\n return '[' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + ']';\n }\n visitLiteralMapExpr(ast: o.LiteralMapExpr) {\n return '{' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + '}';\n }\n visitInvokeFunctionExpr(ast: o.InvokeFunctionExpr) {\n const fn = ast.fn.visitExpression(this, null);\n const args = ast.args.map((a: any) => this.emitExpr(a)).join(', ');\n // Wrap arrow/function expressions in parens for valid IIFE syntax. A\n // `WrappedNodeExpr` callee is a raw user expression (e.g. an\n // `@Injectable({ useFactory: (a, b) => … })` arrow); without parens the\n // argument list binds to the arrow's *body* (`… => new X(a, b)(args)`)\n // instead of invoking the arrow. Parenthesizing any wrapped callee is\n // always semantically safe.\n const call = ast.isOptional ? '?.(' : '(';\n\n if (\n ast.fn instanceof o.ArrowFunctionExpr ||\n ast.fn instanceof o.FunctionExpr ||\n ast.fn instanceof o.WrappedNodeExpr\n ) {\n return '(' + fn + ')' + call + args + ')';\n }\n return fn + call + args + ')';\n }\n visitReadVarExpr(ast: o.ReadVarExpr) {\n if (ast.name === 'this') return 'this';\n if (ast.name === 'super') return 'super';\n return ast.name!;\n }\n visitReadPropExpr(ast: o.ReadPropExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n (ast.isOptional ? '?.' : '.') +\n ast.name\n );\n }\n visitReadKeyExpr(ast: o.ReadKeyExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n (ast.isOptional ? '?.[' : '[') +\n ast.index.visitExpression(this, null) +\n ']'\n );\n }\n visitConditionalExpr(ast: o.ConditionalExpr) {\n return (\n '(' +\n ast.condition.visitExpression(this, null) +\n ' ? ' +\n ast.trueCase.visitExpression(this, null) +\n ' : ' +\n ast.falseCase!.visitExpression(this, null) +\n ')'\n );\n }\n visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr) {\n // `BINARY_OP_STR.get(...)` returns `undefined` when the operator value\n // doesn't exist in the installed Angular's `BinaryOperator` enum (the\n // enum is missing 13 members on v19, 11 on v20). Falling back to `'='`\n // would silently produce wrong code; instead, we throw so the error\n // surfaces in the DEBUG output and the calling test fails loudly.\n const op = BINARY_OP_STR.get(ast.operator);\n if (op === undefined) {\n throw new Error(\n `[fast-compile] Unsupported BinaryOperator value ${ast.operator} ` +\n `on @angular/compiler ${o.VERSION?.full ?? '(unknown version)'}`,\n );\n }\n\n const lhsRaw = ast.lhs.visitExpression(this, null);\n const rhsRaw = ast.rhs.visitExpression(this, null);\n\n const lhs = childNeedsParens(ast.operator, ast.lhs, false)\n ? '(' + lhsRaw + ')'\n : lhsRaw;\n const rhs = childNeedsParens(ast.operator, ast.rhs, true)\n ? '(' + rhsRaw + ')'\n : rhsRaw;\n\n const expr = lhs + ' ' + op + ' ' + rhs;\n\n // Wrap assignments in parens so they work correctly as ternary conditions:\n // (tmp = val) ? a : b vs tmp = val ? a : b\n //\n // `isAssignmentOperator` is built at module load time from the operator\n // names that actually exist on the installed Angular's enum. This\n // works whether `Assign` is present (v21+) or absent (v19/v20) — on\n // older versions the assignment branch is simply unreachable because\n // Angular's compiler never constructs an Assign-operator expression.\n if (isAssignmentOperator(ast.operator)) {\n return '(' + expr + ')';\n }\n return expr;\n }\n visitNotExpr(ast: o.NotExpr) {\n return '!(' + ast.condition.visitExpression(this, null) + ')';\n }\n visitFunctionExpr(ast: o.FunctionExpr) {\n return (\n '(' +\n ast.params.map((p: any) => p.name).join(', ') +\n ') => {' +\n ast.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n visitArrowFunctionExpr(ast: o.ArrowFunctionExpr) {\n const params = '(' + ast.params.map((p: any) => p.name).join(', ') + ')';\n if (Array.isArray(ast.body))\n return (\n params +\n ' => {' +\n ast.body.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n const bodyExpr = (ast.body as o.Expression).visitExpression(this, null);\n // Wrap object literals in parens so `() => {key: val}` isn't parsed\n // as a block with a labeled statement.\n if (ast.body instanceof o.LiteralMapExpr) {\n return params + ' => (' + bodyExpr + ')';\n }\n return params + ' => ' + bodyExpr;\n }\n // `Write*Expr` visitors must wrap the assignment in parentheses so that\n // it composes correctly when nested inside higher-precedence parents\n // (e.g. as the test of a `ConditionalExpr`). Without the wrapping,\n // tmp = ctx.data() ? 0 : -1\n // parses as `tmp = (ctx.data() ? 0 : -1)` because assignment binds\n // looser than the ternary, which silently assigns the wrong value to\n // `tmp`. Angular's own `AbstractEmitterVisitor.visitWriteVarExpr`\n // applies the same context-sensitive wrapping (it skips the parens\n // when the assignment is a top-level statement to avoid `(x = 1);`\n // noise; we always wrap for simplicity — the redundant parens at\n // statement level are harmless).\n //\n // This matters specifically on Angular v19/v20, where assignment is\n // represented in the IR via `WriteVarExpr` / `AssignTemporaryExpr →\n // WriteVarExpr`. On v21+ the same construct is represented via\n // `BinaryOperatorExpr(Assign, ...)`, which `visitBinaryOperatorExpr`\n // already wraps via `isAssignmentOperator`. Without these wrappers,\n // `@if (data(); as item)` and similar conditional alias forms emit\n // runtime-broken code on v19/v20.\n visitWriteVarExpr(ast: any) {\n return '(' + ast.name + ' = ' + ast.value.visitExpression(this, null) + ')';\n }\n visitWritePropExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '.' +\n ast.name +\n ' = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitWriteKeyExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '[' +\n ast.index.visitExpression(this, null) +\n '] = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitInvokeMethodExpr(ast: any) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n '.' +\n ast.name +\n '(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitTypeofExpr(ast: o.TypeofExpr) {\n return 'typeof ' + ast.expr.visitExpression(this, null);\n }\n visitUnaryOperatorExpr(ast: o.UnaryOperatorExpr) {\n const op = UNARY_OP_STR.get(ast.operator);\n if (op === undefined) {\n throw new Error(\n `[fast-compile] Unsupported UnaryOperator value ${ast.operator} ` +\n `on @angular/compiler ${o.VERSION?.full ?? '(unknown version)'}`,\n );\n }\n\n const operand = '(' + ast.expr.visitExpression(this, null) + ')';\n const isPostfix = 'isPrefix' in ast && ast.isPrefix === false;\n return '(' + (isPostfix ? operand + op : op + operand) + ')';\n }\n visitInstantiateExpr(ast: o.InstantiateExpr) {\n return (\n 'new (' +\n ast.classExpr.visitExpression(this, null) +\n ')(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitCommaExpr(ast: o.CommaExpr) {\n return ast.parts.map((p: any) => p.visitExpression(this, null)).join(', ');\n }\n visitParenthesizedExpr(ast: o.ParenthesizedExpr) {\n return '(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitVoidExpr(ast: o.VoidExpr) {\n return 'void ' + ast.expr.visitExpression(this, null);\n }\n visitSpreadElementExpr(ast: o.SpreadElementExpr) {\n return '...' + (ast as any).expression.visitExpression(this, null);\n }\n visitDynamicImportExpr(ast: o.DynamicImportExpr) {\n return (\n 'import(' +\n (typeof ast.url === 'string'\n ? JSON.stringify(ast.url)\n : ast.url.visitExpression(this, null)) +\n ')'\n );\n }\n visitTemplateLiteralExpr(ast: o.TemplateLiteralExpr) {\n return (\n '`' +\n ast.elements[0].text +\n ast.expressions\n .map(\n (e: any, i: number) =>\n '${' +\n e.visitExpression(this, null) +\n '}' +\n ast.elements[i + 1].text,\n )\n .join('') +\n '`'\n );\n }\n visitTaggedTemplateLiteralExpr(ast: any) {\n const elements = ast.template.elements;\n const expressions = ast.template.expressions;\n const head = elements[0].text;\n const spans = expressions\n .map(\n (e: any, i: number) =>\n '${' + e.visitExpression(this, null) + '}' + elements[i + 1].text,\n )\n .join('');\n return ast.tag.visitExpression(this, null) + '`' + head + spans + '`';\n }\n visitLocalizedString(ast: o.LocalizedString) {\n // Emit the downleveled form:\n // $localize(makeTemplateObject(cooked, raw), expr1, expr2, ...)\n const parts: { cooked: string; raw: string }[] = [ast.serializeI18nHead()];\n for (let i = 1; i < ast.messageParts.length; i++) {\n parts.push(ast.serializeI18nTemplatePart(i));\n }\n const cooked = parts.map((p) => escapeForLocalize(p.cooked)).join(', ');\n const raw = parts.map((p) => escapeForLocalize(p.raw)).join(', ');\n const exprs = ast.expressions.map((e) => this.emitExpr(e));\n return (\n '$localize(' +\n MAKE_TEMPLATE_OBJECT_POLYFILL +\n '([' +\n cooked +\n '], [' +\n raw +\n '])' +\n (exprs.length > 0 ? ', ' + exprs.join(', ') : '') +\n ')'\n );\n }\n visitRegularExpressionLiteral(ast: any) {\n return '/' + (ast.body ?? ast.pattern) + '/' + ast.flags;\n }\n visitTemplateLiteralElementExpr(ast: o.TemplateLiteralElementExpr) {\n return JSON.stringify(ast.text);\n }\n // Statement visitors\n visitReturnStmt(stmt: o.ReturnStatement) {\n return 'return ' + stmt.value.visitExpression(this, null) + ';';\n }\n visitExpressionStmt(stmt: o.ExpressionStatement) {\n return stmt.expr.visitExpression(this, null) + ';';\n }\n visitIfStmt(stmt: o.IfStmt) {\n let s =\n 'if (' +\n stmt.condition.visitExpression(this, null) +\n ') {' +\n stmt.trueCase.map((s2: any) => s2.visitStatement(this, null)).join(' ') +\n '}';\n if (stmt.falseCase.length)\n s +=\n ' else {' +\n stmt.falseCase\n .map((s2: any) => s2.visitStatement(this, null))\n .join(' ') +\n '}';\n return s;\n }\n visitDeclareVarStmt(stmt: o.DeclareVarStmt) {\n const kw = stmt.hasModifier(o.StmtModifier.Final) ? 'const' : 'let';\n return (\n kw +\n ' ' +\n stmt.name +\n (stmt.value ? ' = ' + stmt.value.visitExpression(this, null) : '') +\n ';'\n );\n }\n visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt) {\n return (\n 'function ' +\n stmt.name +\n '(' +\n stmt.params.map((p: any) => p.name).join(', ') +\n ') {' +\n stmt.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n}\n\nconst stringEmitter = new JSEmitter();\n\n/** Emit Angular output AST expression directly to a JavaScript string. */\nexport function emitAngularExpr(expr: o.Expression): string {\n return expr.visitExpression(stringEmitter, null);\n}\n\n/** Emit Angular output AST statement directly to a JavaScript string. */\nexport function emitAngularStmt(stmt: o.Statement): string {\n return stmt.visitStatement(stringEmitter, null);\n}\n\n/** Set the current source file for WrappedNodeExpr fallback printing. */\nexport function setEmitterSourceFile(sf: ts.SourceFile | undefined): void {\n JSEmitter._currentSourceFile = sf;\n}\n\n/** Set the current source code for OXC-based WrappedNodeExpr slice fallback. */\nexport function setEmitterSourceCode(code: string | undefined): void {\n JSEmitter._currentSourceCode = code;\n}\n"],"mappings":"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"}
@@ -1,40 +1,46 @@
1
1
  import { JavaScriptTransformer } from "./utils/devkit.js";
2
2
  //#region packages/vite-plugin-angular/src/lib/compiler-plugin.ts
3
3
  function createCompilerPlugin(pluginOptions, isTest, closeTransformer, cache) {
4
- const javascriptTransformer = new JavaScriptTransformer({
5
- ...pluginOptions,
6
- jit: true
7
- }, 1, cache);
4
+ let javascriptTransformer;
5
+ function getTransformer() {
6
+ return javascriptTransformer ??= new JavaScriptTransformer({
7
+ ...pluginOptions,
8
+ jit: true
9
+ }, 1, cache);
10
+ }
8
11
  return {
9
12
  name: "analogjs-angular-esbuild-deps-optimizer-plugin",
10
13
  async setup(build) {
11
14
  if (!isTest) build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
12
15
  return {
13
- contents: await javascriptTransformer.transformFile(args.path),
16
+ contents: await getTransformer().transformFile(args.path),
14
17
  loader: "js"
15
18
  };
16
19
  });
17
- if (closeTransformer) build.onEnd(() => javascriptTransformer.close());
20
+ if (closeTransformer) build.onEnd(() => javascriptTransformer?.close());
18
21
  }
19
22
  };
20
23
  }
21
24
  function createRolldownCompilerPlugin(pluginOptions, isTest, closeTransformer, cache) {
22
- const javascriptTransformer = new JavaScriptTransformer({
23
- ...pluginOptions,
24
- jit: true
25
- }, 1, cache);
25
+ let javascriptTransformer;
26
+ function getTransformer() {
27
+ return javascriptTransformer ??= new JavaScriptTransformer({
28
+ ...pluginOptions,
29
+ jit: true
30
+ }, 1, cache);
31
+ }
26
32
  const plugin = { name: "analogjs-rolldown-deps-optimizer-plugin" };
27
33
  if (!isTest) plugin.load = {
28
34
  filter: { id: /\.[cm]?js$/ },
29
35
  async handler(id) {
30
- const contents = await javascriptTransformer.transformFile(id);
36
+ const contents = await getTransformer().transformFile(id);
31
37
  return {
32
38
  code: Buffer.from(contents).toString("utf-8"),
33
39
  loader: "js"
34
40
  };
35
41
  }
36
42
  };
37
- if (closeTransformer) plugin.buildEnd = () => javascriptTransformer.close();
43
+ if (closeTransformer) plugin.buildEnd = () => javascriptTransformer?.close();
38
44
  return plugin;
39
45
  }
40
46
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"compiler-plugin.js","names":[],"sources":["../../../src/lib/compiler-plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport type { DepOptimizationConfig, Rolldown } from 'vite';\nimport type { PluginBuild } from 'esbuild';\n\nimport {\n CompilerPluginOptions,\n JavaScriptTransformer,\n} from './utils/devkit.js';\nimport type { TransformCacheStore } from './utils/transform-cache.js';\n\ntype EsbuildOptions = NonNullable<DepOptimizationConfig['esbuildOptions']>;\ntype EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];\n\nexport function createCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n cache?: TransformCacheStore,\n): EsbuildPlugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n cache,\n );\n\n return {\n name: 'analogjs-angular-esbuild-deps-optimizer-plugin',\n async setup(build: PluginBuild) {\n if (!isTest) {\n build.onLoad({ filter: /\\.[cm]?js$/ }, async (args) => {\n const contents = await javascriptTransformer.transformFile(args.path);\n\n return {\n contents,\n loader: 'js',\n };\n });\n }\n\n if (closeTransformer) {\n build.onEnd(() => javascriptTransformer.close());\n }\n },\n };\n}\n\nexport function createRolldownCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n cache?: TransformCacheStore,\n): Rolldown.Plugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n cache,\n );\n\n const plugin: Rolldown.Plugin = {\n name: 'analogjs-rolldown-deps-optimizer-plugin',\n };\n\n if (!isTest) {\n plugin.load = {\n filter: {\n id: /\\.[cm]?js$/,\n },\n async handler(id) {\n const contents = await javascriptTransformer.transformFile(id);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n loader: 'js',\n } as any;\n },\n };\n }\n\n if (closeTransformer) {\n plugin.buildEnd = () => javascriptTransformer.close();\n }\n\n return plugin;\n}\n"],"mappings":";;AAoBA,SAAgB,qBACd,eACA,QACA,kBACA,OACe;CACf,MAAM,wBAAwB,IAAI,sBAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,GACA,MACD;AAED,QAAO;EACL,MAAM;EACN,MAAM,MAAM,OAAoB;AAC9B,OAAI,CAAC,OACH,OAAM,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO,SAAS;AAGrD,WAAO;KACL,UAHe,MAAM,sBAAsB,cAAc,KAAK,KAAK;KAInE,QAAQ;KACT;KACD;AAGJ,OAAI,iBACF,OAAM,YAAY,sBAAsB,OAAO,CAAC;;EAGrD;;AAGH,SAAgB,6BACd,eACA,QACA,kBACA,OACiB;CACjB,MAAM,wBAAwB,IAAI,sBAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,GACA,MACD;CAED,MAAM,SAA0B,EAC9B,MAAM,2CACP;AAED,KAAI,CAAC,OACH,QAAO,OAAO;EACZ,QAAQ,EACN,IAAI,cACL;EACD,MAAM,QAAQ,IAAI;GAChB,MAAM,WAAW,MAAM,sBAAsB,cAAc,GAAG;AAE9D,UAAO;IACL,MAAM,OAAO,KAAK,SAAS,CAAC,SAAS,QAAQ;IAC7C,QAAQ;IACT;;EAEJ;AAGH,KAAI,iBACF,QAAO,iBAAiB,sBAAsB,OAAO;AAGvD,QAAO"}
1
+ {"version":3,"file":"compiler-plugin.js","names":[],"sources":["../../../src/lib/compiler-plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport type { DepOptimizationConfig, Rolldown } from 'vite';\nimport type { PluginBuild } from 'esbuild';\n\nimport {\n CompilerPluginOptions,\n JavaScriptTransformer,\n} from './utils/devkit.js';\nimport type { TransformCacheStore } from './utils/transform-cache.js';\n\ntype EsbuildOptions = NonNullable<DepOptimizationConfig['esbuildOptions']>;\ntype EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];\n\nexport function createCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n cache?: TransformCacheStore,\n): EsbuildPlugin {\n let javascriptTransformer: InstanceType<typeof JavaScriptTransformer>;\n function getTransformer() {\n return (javascriptTransformer ??= new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n cache,\n ));\n }\n\n return {\n name: 'analogjs-angular-esbuild-deps-optimizer-plugin',\n async setup(build: PluginBuild) {\n if (!isTest) {\n build.onLoad({ filter: /\\.[cm]?js$/ }, async (args) => {\n const contents = await getTransformer().transformFile(args.path);\n\n return {\n contents,\n loader: 'js',\n };\n });\n }\n\n if (closeTransformer) {\n build.onEnd(() => javascriptTransformer?.close());\n }\n },\n };\n}\n\nexport function createRolldownCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n cache?: TransformCacheStore,\n): Rolldown.Plugin {\n let javascriptTransformer: InstanceType<typeof JavaScriptTransformer>;\n function getTransformer() {\n return (javascriptTransformer ??= new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n cache,\n ));\n }\n\n const plugin: Rolldown.Plugin = {\n name: 'analogjs-rolldown-deps-optimizer-plugin',\n };\n\n if (!isTest) {\n plugin.load = {\n filter: {\n id: /\\.[cm]?js$/,\n },\n async handler(id) {\n const contents = await getTransformer().transformFile(id);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n loader: 'js',\n } as any;\n },\n };\n }\n\n if (closeTransformer) {\n plugin.buildEnd = () => javascriptTransformer?.close();\n }\n\n return plugin;\n}\n"],"mappings":";;AAoBA,SAAgB,qBACd,eACA,QACA,kBACA,OACe;CACf,IAAI;CACJ,SAAS,iBAAiB;AACxB,SAAQ,0BAA0B,IAAI,sBACpC;GAAE,GAAG;GAAe,KAAK;GAAM,EAC/B,GACA,MACD;;AAGH,QAAO;EACL,MAAM;EACN,MAAM,MAAM,OAAoB;AAC9B,OAAI,CAAC,OACH,OAAM,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO,SAAS;AAGrD,WAAO;KACL,UAHe,MAAM,gBAAgB,CAAC,cAAc,KAAK,KAAK;KAI9D,QAAQ;KACT;KACD;AAGJ,OAAI,iBACF,OAAM,YAAY,uBAAuB,OAAO,CAAC;;EAGtD;;AAGH,SAAgB,6BACd,eACA,QACA,kBACA,OACiB;CACjB,IAAI;CACJ,SAAS,iBAAiB;AACxB,SAAQ,0BAA0B,IAAI,sBACpC;GAAE,GAAG;GAAe,KAAK;GAAM,EAC/B,GACA,MACD;;CAGH,MAAM,SAA0B,EAC9B,MAAM,2CACP;AAED,KAAI,CAAC,OACH,QAAO,OAAO;EACZ,QAAQ,EACN,IAAI,cACL;EACD,MAAM,QAAQ,IAAI;GAChB,MAAM,WAAW,MAAM,gBAAgB,CAAC,cAAc,GAAG;AAEzD,UAAO;IACL,MAAM,OAAO,KAAK,SAAS,CAAC,SAAS,QAAQ;IAC7C,QAAQ;IACT;;EAEJ;AAGH,KAAI,iBACF,QAAO,iBAAiB,uBAAuB,OAAO;AAGxD,QAAO"}
@@ -265,7 +265,6 @@ function fastCompilePlugin(pluginOptions) {
265
265
  const { styleExtensions } = inlined;
266
266
  for (const dep of inlined.resourceDependencies) resourceToSource.set(dep, id);
267
267
  const { program: oxcProgram } = parseSync(id, code);
268
- let resolvedStyles;
269
268
  let resolvedInlineStyles;
270
269
  const inlineExt = pluginOptions.inlineStylesExtension;
271
270
  const styleNeedsPreprocess = (ext) => ext !== "" && ext !== "css";
@@ -295,7 +294,6 @@ function fastCompilePlugin(pluginOptions) {
295
294
  }
296
295
  const result = compile(code, id, {
297
296
  registry: compileRegistry,
298
- resolvedStyles,
299
297
  resolvedInlineStyles,
300
298
  useDefineForClassFields,
301
299
  compilationMode: pluginOptions.fastCompileMode,
@@ -1 +1 @@
1
- {"version":3,"file":"fast-compile-plugin.js","names":[],"sources":["../../../src/lib/fast-compile-plugin.ts"],"sourcesContent":["import { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport { parseSync } from 'oxc-parser';\nimport * as vite from 'vite';\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { normalizePath, Plugin, preprocessCSS, ResolvedConfig } from 'vite';\n\nimport {\n compile,\n scanFile,\n scanPackageDts,\n collectImportedPackages,\n collectRelativeReExports,\n collectAllImports,\n jitTransform,\n inlineResourceUrls,\n extractInlineStyles,\n generateHmrCode,\n debugCompile,\n debugRegistry,\n ANGULAR_DECORATOR_CALL_RE,\n type ComponentRegistry,\n} from './compiler/index.js';\n\nimport {\n TS_EXT_REGEX,\n getTsConfigPath,\n createDepOptimizerConfig,\n isProdMode,\n type TsConfigResolutionContext,\n} from './utils/plugin-config.js';\nimport { releaseCssPreprocessorWorkers } from './utils/css-preprocessor-workers.js';\nimport { VIRTUAL_RAW_PREFIX, toVirtualRawId } from './utils/virtual-ids.js';\nimport {\n loadVirtualRawModule,\n rewriteHtmlRawImport,\n} from './utils/virtual-resources.js';\nimport { markStylePathSafe } from './utils/safe-module-paths.js';\nimport {\n discoverAnalogIntegrations,\n type ComponentRegistryEntries,\n type TransformFilter,\n} from './analog-plugin-interop.js';\n\nexport interface FastCompilePluginOptions {\n tsconfigGetter: () => string;\n workspaceRoot: string;\n inlineStylesExtension: string;\n jit: boolean;\n liveReload: boolean;\n supportedBrowsers: string[];\n isTest: boolean;\n isAstroIntegration: boolean;\n fastCompileMode?: 'full' | 'partial';\n}\n\n/**\n * Directory that `compilerOptions.paths` targets resolve against. Mirrors\n * TypeScript: `baseUrl` when set, otherwise the directory of the config\n * that declares `paths` (`pathsBasePath`, since `baseUrl` is optional\n * from TS 4.1).\n */\nexport function getPathsBasePath(\n options: { baseUrl?: string; pathsBasePath?: string } | undefined,\n fallback: string,\n): string {\n return options?.baseUrl ?? options?.pathsBasePath ?? fallback;\n}\n\nexport function fastCompilePlugin(\n pluginOptions: FastCompilePluginOptions,\n): Plugin {\n let resolvedConfig: ResolvedConfig;\n let transformFilter: TransformFilter | undefined;\n let componentRegistries: ComponentRegistryEntries[] = [];\n let tsConfigResolutionContext: TsConfigResolutionContext | null = null;\n let watchMode = false;\n\n // fast-compile plugin state\n const registry: ComponentRegistry = new Map();\n const resourceToSource = new Map<string, string>();\n const scannedDtsPackages = new Set<string>();\n let projectRoot = '';\n let useDefineForClassFields = true;\n\n /**\n * Scan a file into the registry, then recursively walk its relative\n * `export *` / `export { … } from './x'` chain so any underlying\n * directive classes also land in the registry. Used both at\n * `buildStart` (for tsconfig path entries) and at dev time (file\n * `add` and `handleHotUpdate`) so newly added barrels stay in sync\n * without requiring a server restart.\n *\n * The `visited` set prevents infinite recursion within a single\n * top-level call. Each fresh scan should pass an empty set (so HMR\n * re-scans aren't blocked by buildStart's earlier visits).\n *\n * `fileContents`/`scanResults` are cold-start dedup caches scoped to a\n * single `initFastCompile` call. HMR/watcher callers must omit them so\n * an edited file is always re-read from disk.\n */\n async function scanBarrelExports(\n file: string,\n visited: Set<string> = new Set(),\n overwrite = false,\n fileContents?: Map<string, string>,\n scanResults?: Map<string, ReturnType<typeof scanFile>>,\n ): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let code: string;\n try {\n code =\n fileContents?.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents?.set(file, code);\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: failed to read %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return;\n }\n // Single parse shared by scanFile and collectRelativeReExports. On a\n // parse error each consumer re-parses on its own, preserving their\n // individual failure semantics (scanFile throws past its pre-filter;\n // collectRelativeReExports swallows and returns []).\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults?.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults?.set(file, entries);\n }\n for (const entry of entries) {\n // At buildStart we want stable registry entries (don't overwrite\n // an earlier scan with a barrel re-scan); HMR explicitly asks\n // for overwrite so updated metadata replaces stale entries.\n if (overwrite || !registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n // Collect every relative re-export specifier via OXC AST so\n // recursive scans can't trip over each other (a shared `/g` regex\n // would have its `lastIndex` reset by each recursive call and\n // silently skip half of an outer barrel's re-exports, which\n // previously left directives like `HlmRadioGroup` unregistered).\n const dir = dirname(file);\n for (const rel of collectRelativeReExports(code, file, program)) {\n // NodeNext-style libraries write `export * from './foo.js'`\n // even though the source is `./foo.ts`. Strip the ESM\n // extension before probing or the candidates would be\n // `foo.js.ts` / `foo.js/index.ts`, which never exist.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const reExportCandidates = [\n resolve(dir, normalizedRel + '.ts'),\n resolve(dir, normalizedRel, 'index.ts'),\n ];\n let resolved = false;\n for (const candidate of reExportCandidates) {\n try {\n await fsPromises.access(candidate);\n await scanBarrelExports(\n candidate,\n visited,\n overwrite,\n fileContents,\n scanResults,\n );\n resolved = true;\n break;\n } catch {\n // try next candidate\n }\n }\n if (!resolved && debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: %s re-export %s did not resolve to %o',\n file,\n rel,\n reExportCandidates,\n );\n }\n }\n }\n\n async function initFastCompile() {\n if (pluginOptions.jit) return; // JIT: no registry scan needed\n\n // Scan all source files to build the registry\n registry.clear();\n scannedDtsPackages.clear();\n const resolvedTsConfigPath = resolveTsConfigPath();\n projectRoot = dirname(resolvedTsConfigPath);\n const config = compilerCli.readConfiguration(resolvedTsConfigPath);\n useDefineForClassFields = config.options?.useDefineForClassFields ?? true;\n\n // Collect candidate files: tsconfig rootNames PLUS the entry points\n // named in `compilerOptions.paths`. App tsconfigs typically only\n // include the app's own sources, so workspace library entry barrels\n // (e.g. `HlmSelectImports = [HlmSelect, HlmSelectContent, ...] as\n // const`) live outside `rootNames` and would otherwise miss the\n // initial scan. The compiler then can't see that `HlmSelectImports`\n // is a tuple barrel and emits the bare identifier into the parent\n // component's `dependencies()` list, where Angular's runtime\n // silently drops it because arrays don't have a directive def.\n const candidates = new Set<string>(config.rootNames);\n const tsPaths = config.options?.paths;\n const baseUrl = getPathsBasePath(config.options, projectRoot);\n // Cold-start dedup caches shared by the three scan phases below\n // (candidates scan, walkImports, scanBarrelExports). Scoped to this\n // init call only — HMR/watcher re-scans must hit disk fresh.\n const fileContents = new Map<string, string>();\n const scanResults = new Map<string, ReturnType<typeof scanFile>>();\n if (tsPaths) {\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n // Skip wildcard patterns — entry barrels are normally exact\n // file paths like \"libs/helm/select/src/index.ts\".\n if (target.includes('*')) continue;\n candidates.add(resolve(baseUrl, target));\n }\n }\n }\n const results = await Promise.all(\n Array.from(candidates).map(async (file) => {\n try {\n const code = await fsPromises.readFile(file, 'utf-8');\n fileContents.set(file, code);\n const entries = scanFile(code, file);\n scanResults.set(file, entries);\n return entries;\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'initFastCompile: skipping unreadable %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return []; // Skip unreadable files\n }\n }),\n );\n\n for (const entries of results) {\n for (const entry of entries) {\n registry.set(entry.className, entry);\n }\n }\n\n // Walk the transitive import graph from the root files so the registry also\n // contains declarations that live in files not directly in tsconfig\n // `files`/`include` (transitively-imported app sources) and in workspace\n // libraries reached through wildcard `paths` (e.g. `@bitwarden/*`). Without\n // this, a non-standalone component's owning module can't classify its\n // declarations and `ɵɵsetComponentScope` is never emitted for it. Only\n // relative imports and `paths`-mapped (project/workspace) bare specifiers are\n // followed; true `node_modules` packages are left to the lazy `.d.ts` scanner.\n // Return *all* candidate base paths a bare specifier maps to. A `paths`\n // entry can list several fallback targets (e.g. a built `dist` path first\n // and the workspace `src` second); the caller probes them in order.\n const resolvePathSpecifier = (spec: string): string[] => {\n if (!tsPaths) return [];\n for (const [key, targets] of Object.entries(tsPaths)) {\n const list = targets as string[];\n if (key.endsWith('/*')) {\n const prefix = key.slice(0, -1);\n if (spec.startsWith(prefix)) {\n // `split('*').join(...)` substitutes the single tsconfig `*`\n // wildcard without `String.replace`'s first-match-only behavior or\n // `$`-pattern interpretation of the replacement.\n return list.map((t) =>\n resolve(baseUrl, t.split('*').join(spec.slice(prefix.length))),\n );\n }\n } else if (key === spec) {\n return list.map((t) => resolve(baseUrl, t));\n }\n }\n return [];\n };\n const probeToSource = async (base: string): Promise<string | null> => {\n const candidates = base.endsWith('.ts')\n ? [base]\n : [base + '.ts', resolve(base, 'index.ts')];\n for (const candidate of candidates) {\n try {\n await fsPromises.access(candidate);\n return candidate;\n } catch {\n // try next candidate\n }\n }\n return null;\n };\n // Memoize fs probes per absolute base path. The cache stores the\n // Promise (not the settled value) so concurrent walks racing on the\n // same base collapse into a single probe.\n const baseResolveCache = new Map<string, Promise<string | null>>();\n const resolveToSource = (base: string): Promise<string | null> => {\n let probe = baseResolveCache.get(base);\n if (!probe) {\n probe = probeToSource(base);\n baseResolveCache.set(base, probe);\n }\n return probe;\n };\n // Probe each `paths` target in order; first one that resolves to source wins.\n const resolveFirstSource = async (\n bases: string[],\n ): Promise<string | null> => {\n for (const base of bases) {\n const resolved = await resolveToSource(base);\n if (resolved) return resolved;\n }\n return null;\n };\n const importWalkVisited = new Set<string>();\n // Paths-mapped resolution doesn't depend on the importer, so bare\n // specifiers can be memoized by their raw text. Relative specifiers\n // must NOT be — the same './foo' resolves differently per directory.\n const bareSpecResolveCache = new Map<string, Promise<string | null>>();\n const walkImports = async (file: string): Promise<void> => {\n if (importWalkVisited.has(file)) return;\n importWalkVisited.add(file);\n let code: string;\n try {\n code =\n fileContents.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents.set(file, code);\n } catch {\n return;\n }\n // Single parse shared by scanFile, collectImportedPackages, and\n // collectAllImports. On a parse error each consumer re-parses on\n // its own, preserving their individual failure semantics.\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults.set(file, entries);\n }\n for (const entry of entries) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n // Pre-scan the `.d.ts` of every external package this file imports (and,\n // transitively, packages those packages' NgModules re-export — e.g.\n // BrowserModule → CommonModule → NgIf). Doing this at buildStart means the\n // registry is complete before any component transforms, so non-standalone\n // component scope resolves regardless of file transform order.\n for (const pkg of collectImportedPackages(code, file, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n try {\n for (const entry of scanPackageDts(\n pkg,\n projectRoot,\n scannedDtsPackages,\n )) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n } catch {\n // Package may not have .d.ts or not be Angular\n }\n }\n const dir = dirname(file);\n const targets = await Promise.all(\n collectAllImports(code, file, program).map((spec) => {\n if (spec.startsWith('.')) {\n return resolveToSource(\n resolve(dir, spec.replace(/\\.(?:js|mjs)$/u, '')),\n );\n }\n let resolved = bareSpecResolveCache.get(spec);\n if (!resolved) {\n resolved = resolveFirstSource(resolvePathSpecifier(spec));\n bareSpecResolveCache.set(spec, resolved);\n }\n return resolved;\n }),\n );\n await Promise.all(\n targets.filter((t): t is string => !!t).map((t) => walkImports(t)),\n );\n };\n await Promise.all(config.rootNames.map((file) => walkImports(file)));\n\n // Library barrels typically `export * from './lib/...'` rather than\n // declaring directives directly, so the entry file alone gives us\n // the tuple consts but not the directive classes they reference.\n // Walk the relative `export *` chain so the underlying classes also\n // land in the registry. Use a SHARED visited set across all\n // barrels so recursive walks don't double-scan a file that's\n // re-exported from multiple entry points.\n const buildStartVisited = new Set<string>();\n if (tsPaths) {\n const barrelCandidates: string[] = [];\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n if (target.includes('*')) continue;\n barrelCandidates.push(resolve(baseUrl, target));\n }\n }\n await Promise.all(\n barrelCandidates.map((c) =>\n scanBarrelExports(\n c,\n buildStartVisited,\n false,\n fileContents,\n scanResults,\n ),\n ),\n );\n }\n debugRegistry(\n 'initFastCompile done: %d entries from %d candidate files',\n registry.size,\n candidates.size,\n );\n }\n\n function ensureDtsRegistryForSource(\n code: string,\n id: string,\n program?: ReturnType<typeof parseSync>['program'],\n ) {\n for (const pkg of collectImportedPackages(code, id, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n\n try {\n const dtsEntries = scanPackageDts(pkg, projectRoot, scannedDtsPackages);\n for (const entry of dtsEntries) {\n if (!registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n } catch {\n // Package may not have .d.ts files or may not be Angular\n }\n }\n }\n\n async function handleFastCompileTransform(\n code: string,\n id: string,\n ): Promise<{ code: string; map: any } | undefined> {\n if (!ANGULAR_DECORATOR_CALL_RE.test(code)) {\n // Non-Angular file — strip TS-only syntax ourselves so barrels\n // like `export { Foo, type Bar } from './x'` and other TS-only\n // forms don't leak unstripped to Rolldown. In rolldown-vite the\n // built-in `vite:oxc` strip is registered as a Rust-side native\n // plugin (`viteTransformPlugin` from `rolldown/experimental`); if\n // its hook-filter treats files our `transform.filter.id.include`\n // claimed as already-handled, no JS-side fallback runs and raw\n // TS reaches the parser → `SyntaxError: Unexpected identifier`.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(code, id, {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(code, id, {\n loader: 'ts',\n sourcemap: true,\n });\n return { code: stripped.code, map: stripped.map };\n }\n\n // JIT mode\n if (pluginOptions.jit) {\n const result = jitTransform(code, id);\n // Strip TypeScript-only syntax (e.g. `readonly`, parameter property\n // modifiers, type annotations on fields) so the output is valid JS\n // for Rolldown. `angularVitestSourcemapPlugin` normally runs this\n // strip downstream in tests, but it is intentionally skipped on\n // StackBlitz / WebContainer — and the production build pipeline\n // does not register it either — so the JIT path must self-strip\n // to stay safe across environments.\n //\n // Pass the jitTransform map as `inMap` so OXC/esbuild emit a map\n // composed with the original `.ts` source — without this, debug\n // stack traces and breakpoints land on the wrong lines once the\n // strip removes any TS-only token. `jitTransform` returns\n // `map: null` for files with no Angular class (no edits made);\n // passing that to OXC/esbuild as `inMap` throws, so coerce to\n // `undefined` in that case.\n const inMap = result.map ?? undefined;\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n inMap,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n inMap,\n );\n return { code: stripped.code, map: stripped.map };\n }\n\n // Inline external templateUrl/styleUrl(s) into the source before compilation.\n // `styleExtensions` carries the source extension of each inlined external\n // style so it can be preprocessed by its own file type (e.g. an external\n // `.scss` styleUrl) regardless of the `inlineStylesExtension` option.\n const inlined = await inlineResourceUrls(code, id);\n code = inlined.code;\n const { styleExtensions } = inlined;\n\n // Track inlined resources for HMR. `compile()` only reports resources it\n // reads through its own fallback (a templateUrl/styleUrl the inliner did\n // NOT already inline), so files inlined here must be recorded here or a\n // later edit to them never invalidates the owning module.\n for (const dep of inlined.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Single OXC parse of the post-inline source, shared by every AST\n // consumer below. `inlineResourceUrls` parsed the PRE-inline string,\n // so its program can never be reused here.\n const { program: oxcProgram } = parseSync(id, code);\n\n // Pre-resolve inline styles that need preprocessing (SCSS/Sass/Less). Run\n // whenever a style needs a non-`css` preprocessor — either the configured\n // `inlineStylesExtension` for truly-inline styles, or an external styleUrl's\n // own extension.\n let resolvedStyles: Map<string, string> | undefined;\n let resolvedInlineStyles: Map<number, string> | undefined;\n\n const inlineExt = pluginOptions.inlineStylesExtension;\n const styleNeedsPreprocess = (ext: string) => ext !== '' && ext !== 'css';\n\n if (styleNeedsPreprocess(inlineExt) || styleExtensions.size > 0) {\n const styleStrings = extractInlineStyles(code, id, oxcProgram);\n\n if (styleStrings.length > 0) {\n resolvedInlineStyles = new Map();\n for (let i = 0; i < styleStrings.length; i++) {\n // External styleUrls are preprocessed by their own extension; truly\n // inline `styles: [...]` fall back to `inlineStylesExtension`.\n const ext = styleExtensions.get(i) ?? inlineExt;\n if (!styleNeedsPreprocess(ext)) continue;\n try {\n const fakePath = id.replace(/\\.ts$/, `.inline-${i}.${ext}`);\n const processed = await preprocessCSS(\n styleStrings[i],\n fakePath,\n resolvedConfig,\n );\n resolvedInlineStyles.set(i, processed.code);\n } catch (e) {\n if (debugCompile.enabled) {\n debugCompile(\n 'inline style #%d preprocessing failed in %s: %s',\n i,\n id,\n (e as Error)?.message,\n );\n }\n // Skip styles that can't be preprocessed\n }\n }\n if (resolvedInlineStyles.size === 0) resolvedInlineStyles = undefined;\n }\n }\n\n ensureDtsRegistryForSource(code, id, oxcProgram);\n\n // Merge registries contributed through `analog.setup()` into this\n // compile's lookup view. Out-of-tree compilers register directive\n // metadata for classes fastCompile can't reach through its\n // tsconfig-driven scan (e.g. `.tsrx` files compiled by `@tsrx/analog`).\n // Without this merge, a TS `@Component({ imports: [X] })` that\n // references such a class hits `_unresolved-${className}` as its\n // selector and the tag never matches at runtime.\n let compileRegistry: ComponentRegistry = registry;\n if (componentRegistries.some((external) => external.size > 0)) {\n compileRegistry = new Map(registry);\n for (const external of componentRegistries) {\n for (const [k, v] of external) compileRegistry.set(k, v);\n }\n }\n\n const result = compile(code, id, {\n registry: compileRegistry,\n resolvedStyles,\n resolvedInlineStyles,\n useDefineForClassFields,\n compilationMode: pluginOptions.fastCompileMode,\n oxcProgram,\n });\n\n // Track resource dependencies for HMR\n for (const dep of result.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Strip TypeScript-only syntax and compose the compiler map with the\n // final generated code so downstream breakpoints map back to the source.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n result.map,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n result.map,\n );\n let outputCode = stripped.code;\n\n // Append HMR code in dev mode\n if (watchMode && pluginOptions.liveReload) {\n const fileDeclarations = [...registry.values()].filter(\n (e) => e.fileName === id,\n );\n if (fileDeclarations.length > 0) {\n const localDepClassNames = fileDeclarations.map((e) => e.className);\n outputCode += generateHmrCode(fileDeclarations, localDepClassNames);\n }\n }\n\n return { code: outputCode, map: stripped.map };\n }\n\n function resolveTsConfigPath() {\n const { root, isProd, isLib } = tsConfigResolutionContext!;\n return getTsConfigPath(\n root,\n pluginOptions.tsconfigGetter(),\n isProd,\n pluginOptions.isTest,\n isLib,\n pluginOptions.workspaceRoot,\n );\n }\n\n return {\n name: '@analogjs/vite-plugin-angular-fast-compile',\n api: { getTsConfigPath: resolveTsConfigPath },\n enforce: 'pre' as const,\n async config(config, { command }) {\n watchMode = command === 'serve';\n const isProd = isProdMode(config.mode);\n\n tsConfigResolutionContext = {\n root: config.root || '.',\n isProd,\n isLib: !!config?.build?.lib,\n };\n\n const preliminaryTsConfigPath = resolveTsConfigPath();\n\n const depOptimizer = createDepOptimizerConfig({\n tsconfig: preliminaryTsConfigPath,\n isProd,\n jit: pluginOptions.jit,\n watchMode,\n isTest: pluginOptions.isTest,\n isAstroIntegration: pluginOptions.isAstroIntegration,\n });\n\n // No `resolve.conditions` extension here: the `style` condition is\n // scoped to `.css`-extension requests by\n // `cssExtensionStyleResolverPlugin`, registered once at the\n // `angular()` factory level (which is the only public entry point\n // that wires this plugin in).\n return {\n ...(vite.rolldownVersion ? { oxc: {} as any } : { esbuild: false }),\n ...depOptimizer,\n };\n },\n async configResolved(config) {\n resolvedConfig = config;\n const integrations = await discoverAnalogIntegrations(config);\n transformFilter = integrations.transformFilter;\n componentRegistries = integrations.componentRegistries;\n },\n configureServer(server) {\n // Watch for new .ts files and scan them into the registry. Use\n // the barrel-aware scanner so a newly added re-export entry\n // (`export * from './x'`) also expands its underlying directive\n // classes — otherwise the registry stays stale until restart.\n server.watcher.on('add', async (filePath) => {\n if (\n filePath.endsWith('.ts') &&\n !filePath.endsWith('.spec.ts') &&\n !filePath.endsWith('.d.ts')\n ) {\n await scanBarrelExports(filePath, new Set(), true);\n }\n });\n },\n async buildStart() {\n await initFastCompile();\n },\n closeBundle() {\n if (!watchMode) {\n releaseCssPreprocessorWorkers();\n }\n },\n async handleHotUpdate(ctx) {\n // Resource file changes → invalidate parent .ts module\n if (resourceToSource.has(ctx.file)) {\n const parentSource = resourceToSource.get(ctx.file)!;\n const parentModule = ctx.server.moduleGraph.getModuleById(parentSource);\n if (parentModule) {\n return [parentModule];\n }\n }\n\n if (TS_EXT_REGEX.test(ctx.file)) {\n const [fileId] = ctx.file.split('?');\n\n // Remove old entries from this file\n const oldEntries = [...registry.entries()]\n .filter(([_, v]) => v.fileName === fileId)\n .map(([k]) => k);\n for (const key of oldEntries) {\n registry.delete(key);\n }\n\n // Rescan the changed file via the barrel-aware scanner so an\n // edited barrel re-export picks up newly-referenced files.\n // Pass overwrite=true so updated metadata replaces stale\n // entries from the previous scan.\n await scanBarrelExports(fileId, new Set(), true);\n }\n\n // Let Vite handle the rest — the transform hook will recompile\n return ctx.modules;\n },\n resolveId(id, importer) {\n if (id.startsWith(VIRTUAL_RAW_PREFIX)) {\n return `\\0${id}`;\n }\n\n if (pluginOptions.jit && id.startsWith('angular:jit:')) {\n const filePath = normalizePath(\n resolve(dirname(importer as string), id.split(';')[1]),\n );\n if (id.includes(':style')) {\n markStylePathSafe(resolvedConfig, filePath);\n return filePath + '?inline';\n }\n return toVirtualRawId(filePath);\n }\n\n const rawRewrite = rewriteHtmlRawImport(id, importer);\n if (rawRewrite) return rawRewrite;\n\n // User `.scss?inline` / `.css?inline` imports: resolve and mark\n // safe so Vite's native CSS pipeline handles them.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id) && importer) {\n const filePath = id.split('?')[0];\n const resolved = isAbsolute(filePath)\n ? normalizePath(filePath)\n : normalizePath(resolve(dirname(importer), filePath));\n markStylePathSafe(resolvedConfig, resolved);\n return resolved + '?inline';\n }\n\n return undefined;\n },\n async load(id) {\n const rawModule = await loadVirtualRawModule(this, id);\n if (rawModule !== undefined) return rawModule;\n\n // Vitest fallback: module-runner can skip resolveId, so the bare\n // ?inline query reaches load. Mark safe and let Vite handle it.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id)) {\n markStylePathSafe(resolvedConfig, id.split('?')[0]);\n }\n\n return;\n },\n transform: {\n filter: {\n id: {\n include: [TS_EXT_REGEX],\n // `?raw` ids already carry Vite's native raw-loader output\n // (`export default \"<source>\"`). Recompiling them as Angular/TS\n // would strip that default export, so leave them to Vite (#2356).\n exclude: [\n /node_modules/,\n 'type=script',\n '@ng/component',\n /[?&]raw\\b/,\n ],\n },\n },\n async handler(code, id) {\n if (transformFilter && !transformFilter(code, id)) {\n return;\n }\n\n if (id.includes('.ts?')) {\n id = id.replace(/\\?(.*)/, '');\n }\n return handleFastCompileTransform(code, id);\n },\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fast-compile-plugin.js","names":[],"sources":["../../../src/lib/fast-compile-plugin.ts"],"sourcesContent":["import { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport { parseSync } from 'oxc-parser';\nimport * as vite from 'vite';\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { normalizePath, Plugin, preprocessCSS, ResolvedConfig } from 'vite';\n\nimport {\n compile,\n scanFile,\n scanPackageDts,\n collectImportedPackages,\n collectRelativeReExports,\n collectAllImports,\n jitTransform,\n inlineResourceUrls,\n extractInlineStyles,\n generateHmrCode,\n debugCompile,\n debugRegistry,\n ANGULAR_DECORATOR_CALL_RE,\n type ComponentRegistry,\n} from './compiler/index.js';\n\nimport {\n TS_EXT_REGEX,\n getTsConfigPath,\n createDepOptimizerConfig,\n isProdMode,\n type TsConfigResolutionContext,\n} from './utils/plugin-config.js';\nimport { releaseCssPreprocessorWorkers } from './utils/css-preprocessor-workers.js';\nimport { VIRTUAL_RAW_PREFIX, toVirtualRawId } from './utils/virtual-ids.js';\nimport {\n loadVirtualRawModule,\n rewriteHtmlRawImport,\n} from './utils/virtual-resources.js';\nimport { markStylePathSafe } from './utils/safe-module-paths.js';\nimport {\n discoverAnalogIntegrations,\n type ComponentRegistryEntries,\n type TransformFilter,\n} from './analog-plugin-interop.js';\n\nexport interface FastCompilePluginOptions {\n tsconfigGetter: () => string;\n workspaceRoot: string;\n inlineStylesExtension: string;\n jit: boolean;\n liveReload: boolean;\n supportedBrowsers: string[];\n isTest: boolean;\n isAstroIntegration: boolean;\n fastCompileMode?: 'full' | 'partial';\n}\n\n/**\n * Directory that `compilerOptions.paths` targets resolve against. Mirrors\n * TypeScript: `baseUrl` when set, otherwise the directory of the config\n * that declares `paths` (`pathsBasePath`, since `baseUrl` is optional\n * from TS 4.1).\n */\nexport function getPathsBasePath(\n options: { baseUrl?: string; pathsBasePath?: string } | undefined,\n fallback: string,\n): string {\n return options?.baseUrl ?? options?.pathsBasePath ?? fallback;\n}\n\nexport function fastCompilePlugin(\n pluginOptions: FastCompilePluginOptions,\n): Plugin {\n let resolvedConfig: ResolvedConfig;\n let transformFilter: TransformFilter | undefined;\n let componentRegistries: ComponentRegistryEntries[] = [];\n let tsConfigResolutionContext: TsConfigResolutionContext | null = null;\n let watchMode = false;\n\n // fast-compile plugin state\n const registry: ComponentRegistry = new Map();\n const resourceToSource = new Map<string, string>();\n const scannedDtsPackages = new Set<string>();\n let projectRoot = '';\n let useDefineForClassFields = true;\n\n /**\n * Scan a file into the registry, then recursively walk its relative\n * `export *` / `export { … } from './x'` chain so any underlying\n * directive classes also land in the registry. Used both at\n * `buildStart` (for tsconfig path entries) and at dev time (file\n * `add` and `handleHotUpdate`) so newly added barrels stay in sync\n * without requiring a server restart.\n *\n * The `visited` set prevents infinite recursion within a single\n * top-level call. Each fresh scan should pass an empty set (so HMR\n * re-scans aren't blocked by buildStart's earlier visits).\n *\n * `fileContents`/`scanResults` are cold-start dedup caches scoped to a\n * single `initFastCompile` call. HMR/watcher callers must omit them so\n * an edited file is always re-read from disk.\n */\n async function scanBarrelExports(\n file: string,\n visited: Set<string> = new Set(),\n overwrite = false,\n fileContents?: Map<string, string>,\n scanResults?: Map<string, ReturnType<typeof scanFile>>,\n ): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let code: string;\n try {\n code =\n fileContents?.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents?.set(file, code);\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: failed to read %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return;\n }\n // Single parse shared by scanFile and collectRelativeReExports. On a\n // parse error each consumer re-parses on its own, preserving their\n // individual failure semantics (scanFile throws past its pre-filter;\n // collectRelativeReExports swallows and returns []).\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults?.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults?.set(file, entries);\n }\n for (const entry of entries) {\n // At buildStart we want stable registry entries (don't overwrite\n // an earlier scan with a barrel re-scan); HMR explicitly asks\n // for overwrite so updated metadata replaces stale entries.\n if (overwrite || !registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n // Collect every relative re-export specifier via OXC AST so\n // recursive scans can't trip over each other (a shared `/g` regex\n // would have its `lastIndex` reset by each recursive call and\n // silently skip half of an outer barrel's re-exports, which\n // previously left directives like `HlmRadioGroup` unregistered).\n const dir = dirname(file);\n for (const rel of collectRelativeReExports(code, file, program)) {\n // NodeNext-style libraries write `export * from './foo.js'`\n // even though the source is `./foo.ts`. Strip the ESM\n // extension before probing or the candidates would be\n // `foo.js.ts` / `foo.js/index.ts`, which never exist.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const reExportCandidates = [\n resolve(dir, normalizedRel + '.ts'),\n resolve(dir, normalizedRel, 'index.ts'),\n ];\n let resolved = false;\n for (const candidate of reExportCandidates) {\n try {\n await fsPromises.access(candidate);\n await scanBarrelExports(\n candidate,\n visited,\n overwrite,\n fileContents,\n scanResults,\n );\n resolved = true;\n break;\n } catch {\n // try next candidate\n }\n }\n if (!resolved && debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: %s re-export %s did not resolve to %o',\n file,\n rel,\n reExportCandidates,\n );\n }\n }\n }\n\n async function initFastCompile() {\n if (pluginOptions.jit) return; // JIT: no registry scan needed\n\n // Scan all source files to build the registry\n registry.clear();\n scannedDtsPackages.clear();\n const resolvedTsConfigPath = resolveTsConfigPath();\n projectRoot = dirname(resolvedTsConfigPath);\n const config = compilerCli.readConfiguration(resolvedTsConfigPath);\n useDefineForClassFields = config.options?.useDefineForClassFields ?? true;\n\n // Collect candidate files: tsconfig rootNames PLUS the entry points\n // named in `compilerOptions.paths`. App tsconfigs typically only\n // include the app's own sources, so workspace library entry barrels\n // (e.g. `HlmSelectImports = [HlmSelect, HlmSelectContent, ...] as\n // const`) live outside `rootNames` and would otherwise miss the\n // initial scan. The compiler then can't see that `HlmSelectImports`\n // is a tuple barrel and emits the bare identifier into the parent\n // component's `dependencies()` list, where Angular's runtime\n // silently drops it because arrays don't have a directive def.\n const candidates = new Set<string>(config.rootNames);\n const tsPaths = config.options?.paths;\n const baseUrl = getPathsBasePath(config.options, projectRoot);\n // Cold-start dedup caches shared by the three scan phases below\n // (candidates scan, walkImports, scanBarrelExports). Scoped to this\n // init call only — HMR/watcher re-scans must hit disk fresh.\n const fileContents = new Map<string, string>();\n const scanResults = new Map<string, ReturnType<typeof scanFile>>();\n if (tsPaths) {\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n // Skip wildcard patterns — entry barrels are normally exact\n // file paths like \"libs/helm/select/src/index.ts\".\n if (target.includes('*')) continue;\n candidates.add(resolve(baseUrl, target));\n }\n }\n }\n const results = await Promise.all(\n Array.from(candidates).map(async (file) => {\n try {\n const code = await fsPromises.readFile(file, 'utf-8');\n fileContents.set(file, code);\n const entries = scanFile(code, file);\n scanResults.set(file, entries);\n return entries;\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'initFastCompile: skipping unreadable %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return []; // Skip unreadable files\n }\n }),\n );\n\n for (const entries of results) {\n for (const entry of entries) {\n registry.set(entry.className, entry);\n }\n }\n\n // Walk the transitive import graph from the root files so the registry also\n // contains declarations that live in files not directly in tsconfig\n // `files`/`include` (transitively-imported app sources) and in workspace\n // libraries reached through wildcard `paths` (e.g. `@bitwarden/*`). Without\n // this, a non-standalone component's owning module can't classify its\n // declarations and `ɵɵsetComponentScope` is never emitted for it. Only\n // relative imports and `paths`-mapped (project/workspace) bare specifiers are\n // followed; true `node_modules` packages are left to the lazy `.d.ts` scanner.\n // Return *all* candidate base paths a bare specifier maps to. A `paths`\n // entry can list several fallback targets (e.g. a built `dist` path first\n // and the workspace `src` second); the caller probes them in order.\n const resolvePathSpecifier = (spec: string): string[] => {\n if (!tsPaths) return [];\n for (const [key, targets] of Object.entries(tsPaths)) {\n const list = targets as string[];\n if (key.endsWith('/*')) {\n const prefix = key.slice(0, -1);\n if (spec.startsWith(prefix)) {\n // `split('*').join(...)` substitutes the single tsconfig `*`\n // wildcard without `String.replace`'s first-match-only behavior or\n // `$`-pattern interpretation of the replacement.\n return list.map((t) =>\n resolve(baseUrl, t.split('*').join(spec.slice(prefix.length))),\n );\n }\n } else if (key === spec) {\n return list.map((t) => resolve(baseUrl, t));\n }\n }\n return [];\n };\n const probeToSource = async (base: string): Promise<string | null> => {\n const candidates = base.endsWith('.ts')\n ? [base]\n : [base + '.ts', resolve(base, 'index.ts')];\n for (const candidate of candidates) {\n try {\n await fsPromises.access(candidate);\n return candidate;\n } catch {\n // try next candidate\n }\n }\n return null;\n };\n // Memoize fs probes per absolute base path. The cache stores the\n // Promise (not the settled value) so concurrent walks racing on the\n // same base collapse into a single probe.\n const baseResolveCache = new Map<string, Promise<string | null>>();\n const resolveToSource = (base: string): Promise<string | null> => {\n let probe = baseResolveCache.get(base);\n if (!probe) {\n probe = probeToSource(base);\n baseResolveCache.set(base, probe);\n }\n return probe;\n };\n // Probe each `paths` target in order; first one that resolves to source wins.\n const resolveFirstSource = async (\n bases: string[],\n ): Promise<string | null> => {\n for (const base of bases) {\n const resolved = await resolveToSource(base);\n if (resolved) return resolved;\n }\n return null;\n };\n const importWalkVisited = new Set<string>();\n // Paths-mapped resolution doesn't depend on the importer, so bare\n // specifiers can be memoized by their raw text. Relative specifiers\n // must NOT be — the same './foo' resolves differently per directory.\n const bareSpecResolveCache = new Map<string, Promise<string | null>>();\n const walkImports = async (file: string): Promise<void> => {\n if (importWalkVisited.has(file)) return;\n importWalkVisited.add(file);\n let code: string;\n try {\n code =\n fileContents.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents.set(file, code);\n } catch {\n return;\n }\n // Single parse shared by scanFile, collectImportedPackages, and\n // collectAllImports. On a parse error each consumer re-parses on\n // its own, preserving their individual failure semantics.\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults.set(file, entries);\n }\n for (const entry of entries) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n // Pre-scan the `.d.ts` of every external package this file imports (and,\n // transitively, packages those packages' NgModules re-export — e.g.\n // BrowserModule → CommonModule → NgIf). Doing this at buildStart means the\n // registry is complete before any component transforms, so non-standalone\n // component scope resolves regardless of file transform order.\n for (const pkg of collectImportedPackages(code, file, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n try {\n for (const entry of scanPackageDts(\n pkg,\n projectRoot,\n scannedDtsPackages,\n )) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n } catch {\n // Package may not have .d.ts or not be Angular\n }\n }\n const dir = dirname(file);\n const targets = await Promise.all(\n collectAllImports(code, file, program).map((spec) => {\n if (spec.startsWith('.')) {\n return resolveToSource(\n resolve(dir, spec.replace(/\\.(?:js|mjs)$/u, '')),\n );\n }\n let resolved = bareSpecResolveCache.get(spec);\n if (!resolved) {\n resolved = resolveFirstSource(resolvePathSpecifier(spec));\n bareSpecResolveCache.set(spec, resolved);\n }\n return resolved;\n }),\n );\n await Promise.all(\n targets.filter((t): t is string => !!t).map((t) => walkImports(t)),\n );\n };\n await Promise.all(config.rootNames.map((file) => walkImports(file)));\n\n // Library barrels typically `export * from './lib/...'` rather than\n // declaring directives directly, so the entry file alone gives us\n // the tuple consts but not the directive classes they reference.\n // Walk the relative `export *` chain so the underlying classes also\n // land in the registry. Use a SHARED visited set across all\n // barrels so recursive walks don't double-scan a file that's\n // re-exported from multiple entry points.\n const buildStartVisited = new Set<string>();\n if (tsPaths) {\n const barrelCandidates: string[] = [];\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n if (target.includes('*')) continue;\n barrelCandidates.push(resolve(baseUrl, target));\n }\n }\n await Promise.all(\n barrelCandidates.map((c) =>\n scanBarrelExports(\n c,\n buildStartVisited,\n false,\n fileContents,\n scanResults,\n ),\n ),\n );\n }\n debugRegistry(\n 'initFastCompile done: %d entries from %d candidate files',\n registry.size,\n candidates.size,\n );\n }\n\n function ensureDtsRegistryForSource(\n code: string,\n id: string,\n program?: ReturnType<typeof parseSync>['program'],\n ) {\n for (const pkg of collectImportedPackages(code, id, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n\n try {\n const dtsEntries = scanPackageDts(pkg, projectRoot, scannedDtsPackages);\n for (const entry of dtsEntries) {\n if (!registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n } catch {\n // Package may not have .d.ts files or may not be Angular\n }\n }\n }\n\n async function handleFastCompileTransform(\n code: string,\n id: string,\n ): Promise<{ code: string; map: any } | undefined> {\n if (!ANGULAR_DECORATOR_CALL_RE.test(code)) {\n // Non-Angular file — strip TS-only syntax ourselves so barrels\n // like `export { Foo, type Bar } from './x'` and other TS-only\n // forms don't leak unstripped to Rolldown. In rolldown-vite the\n // built-in `vite:oxc` strip is registered as a Rust-side native\n // plugin (`viteTransformPlugin` from `rolldown/experimental`); if\n // its hook-filter treats files our `transform.filter.id.include`\n // claimed as already-handled, no JS-side fallback runs and raw\n // TS reaches the parser → `SyntaxError: Unexpected identifier`.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(code, id, {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(code, id, {\n loader: 'ts',\n sourcemap: true,\n });\n return { code: stripped.code, map: stripped.map };\n }\n\n // JIT mode\n if (pluginOptions.jit) {\n const result = jitTransform(code, id);\n // Strip TypeScript-only syntax (e.g. `readonly`, parameter property\n // modifiers, type annotations on fields) so the output is valid JS\n // for Rolldown. `angularVitestSourcemapPlugin` normally runs this\n // strip downstream in tests, but it is intentionally skipped on\n // StackBlitz / WebContainer — and the production build pipeline\n // does not register it either — so the JIT path must self-strip\n // to stay safe across environments.\n //\n // Pass the jitTransform map as `inMap` so OXC/esbuild emit a map\n // composed with the original `.ts` source — without this, debug\n // stack traces and breakpoints land on the wrong lines once the\n // strip removes any TS-only token. `jitTransform` returns\n // `map: null` for files with no Angular class (no edits made);\n // passing that to OXC/esbuild as `inMap` throws, so coerce to\n // `undefined` in that case.\n const inMap = result.map ?? undefined;\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n inMap,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n inMap,\n );\n return { code: stripped.code, map: stripped.map };\n }\n\n // Inline external templateUrl/styleUrl(s) into the source before compilation.\n // `styleExtensions` carries the source extension of each inlined external\n // style so it can be preprocessed by its own file type (e.g. an external\n // `.scss` styleUrl) regardless of the `inlineStylesExtension` option.\n const inlined = await inlineResourceUrls(code, id);\n code = inlined.code;\n const { styleExtensions } = inlined;\n\n // Track inlined resources for HMR. `compile()` only reports resources it\n // reads through its own fallback (a templateUrl/styleUrl the inliner did\n // NOT already inline), so files inlined here must be recorded here or a\n // later edit to them never invalidates the owning module.\n for (const dep of inlined.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Single OXC parse of the post-inline source, shared by every AST\n // consumer below. `inlineResourceUrls` parsed the PRE-inline string,\n // so its program can never be reused here.\n const { program: oxcProgram } = parseSync(id, code);\n\n // Pre-resolve inline styles that need preprocessing (SCSS/Sass/Less). Run\n // whenever a style needs a non-`css` preprocessor — either the configured\n // `inlineStylesExtension` for truly-inline styles, or an external styleUrl's\n // own extension.\n let resolvedInlineStyles: Map<number, string> | undefined;\n\n const inlineExt = pluginOptions.inlineStylesExtension;\n const styleNeedsPreprocess = (ext: string) => ext !== '' && ext !== 'css';\n\n if (styleNeedsPreprocess(inlineExt) || styleExtensions.size > 0) {\n const styleStrings = extractInlineStyles(code, id, oxcProgram);\n\n if (styleStrings.length > 0) {\n resolvedInlineStyles = new Map();\n for (let i = 0; i < styleStrings.length; i++) {\n // External styleUrls are preprocessed by their own extension; truly\n // inline `styles: [...]` fall back to `inlineStylesExtension`.\n const ext = styleExtensions.get(i) ?? inlineExt;\n if (!styleNeedsPreprocess(ext)) continue;\n try {\n const fakePath = id.replace(/\\.ts$/, `.inline-${i}.${ext}`);\n const processed = await preprocessCSS(\n styleStrings[i],\n fakePath,\n resolvedConfig,\n );\n resolvedInlineStyles.set(i, processed.code);\n } catch (e) {\n if (debugCompile.enabled) {\n debugCompile(\n 'inline style #%d preprocessing failed in %s: %s',\n i,\n id,\n (e as Error)?.message,\n );\n }\n // Skip styles that can't be preprocessed\n }\n }\n if (resolvedInlineStyles.size === 0) resolvedInlineStyles = undefined;\n }\n }\n\n ensureDtsRegistryForSource(code, id, oxcProgram);\n\n // Merge registries contributed through `analog.setup()` into this\n // compile's lookup view. Out-of-tree compilers register directive\n // metadata for classes fastCompile can't reach through its\n // tsconfig-driven scan (e.g. `.tsrx` files compiled by `@tsrx/analog`).\n // Without this merge, a TS `@Component({ imports: [X] })` that\n // references such a class hits `_unresolved-${className}` as its\n // selector and the tag never matches at runtime.\n let compileRegistry: ComponentRegistry = registry;\n if (componentRegistries.some((external) => external.size > 0)) {\n compileRegistry = new Map(registry);\n for (const external of componentRegistries) {\n for (const [k, v] of external) compileRegistry.set(k, v);\n }\n }\n\n const result = compile(code, id, {\n registry: compileRegistry,\n resolvedInlineStyles,\n useDefineForClassFields,\n compilationMode: pluginOptions.fastCompileMode,\n oxcProgram,\n });\n\n // Track resource dependencies for HMR\n for (const dep of result.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Strip TypeScript-only syntax and compose the compiler map with the\n // final generated code so downstream breakpoints map back to the source.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n result.map,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n result.map,\n );\n let outputCode = stripped.code;\n\n // Append HMR code in dev mode\n if (watchMode && pluginOptions.liveReload) {\n const fileDeclarations = [...registry.values()].filter(\n (e) => e.fileName === id,\n );\n if (fileDeclarations.length > 0) {\n const localDepClassNames = fileDeclarations.map((e) => e.className);\n outputCode += generateHmrCode(fileDeclarations, localDepClassNames);\n }\n }\n\n return { code: outputCode, map: stripped.map };\n }\n\n function resolveTsConfigPath() {\n const { root, isProd, isLib } = tsConfigResolutionContext!;\n return getTsConfigPath(\n root,\n pluginOptions.tsconfigGetter(),\n isProd,\n pluginOptions.isTest,\n isLib,\n pluginOptions.workspaceRoot,\n );\n }\n\n return {\n name: '@analogjs/vite-plugin-angular-fast-compile',\n api: { getTsConfigPath: resolveTsConfigPath },\n enforce: 'pre' as const,\n async config(config, { command }) {\n watchMode = command === 'serve';\n const isProd = isProdMode(config.mode);\n\n tsConfigResolutionContext = {\n root: config.root || '.',\n isProd,\n isLib: !!config?.build?.lib,\n };\n\n const preliminaryTsConfigPath = resolveTsConfigPath();\n\n const depOptimizer = createDepOptimizerConfig({\n tsconfig: preliminaryTsConfigPath,\n isProd,\n jit: pluginOptions.jit,\n watchMode,\n isTest: pluginOptions.isTest,\n isAstroIntegration: pluginOptions.isAstroIntegration,\n });\n\n // No `resolve.conditions` extension here: the `style` condition is\n // scoped to `.css`-extension requests by\n // `cssExtensionStyleResolverPlugin`, registered once at the\n // `angular()` factory level (which is the only public entry point\n // that wires this plugin in).\n return {\n ...(vite.rolldownVersion ? { oxc: {} as any } : { esbuild: false }),\n ...depOptimizer,\n };\n },\n async configResolved(config) {\n resolvedConfig = config;\n const integrations = await discoverAnalogIntegrations(config);\n transformFilter = integrations.transformFilter;\n componentRegistries = integrations.componentRegistries;\n },\n configureServer(server) {\n // Watch for new .ts files and scan them into the registry. Use\n // the barrel-aware scanner so a newly added re-export entry\n // (`export * from './x'`) also expands its underlying directive\n // classes — otherwise the registry stays stale until restart.\n server.watcher.on('add', async (filePath) => {\n if (\n filePath.endsWith('.ts') &&\n !filePath.endsWith('.spec.ts') &&\n !filePath.endsWith('.d.ts')\n ) {\n await scanBarrelExports(filePath, new Set(), true);\n }\n });\n },\n async buildStart() {\n await initFastCompile();\n },\n closeBundle() {\n if (!watchMode) {\n releaseCssPreprocessorWorkers();\n }\n },\n async handleHotUpdate(ctx) {\n // Resource file changes → invalidate parent .ts module\n if (resourceToSource.has(ctx.file)) {\n const parentSource = resourceToSource.get(ctx.file)!;\n const parentModule = ctx.server.moduleGraph.getModuleById(parentSource);\n if (parentModule) {\n return [parentModule];\n }\n }\n\n if (TS_EXT_REGEX.test(ctx.file)) {\n const [fileId] = ctx.file.split('?');\n\n // Remove old entries from this file\n const oldEntries = [...registry.entries()]\n .filter(([_, v]) => v.fileName === fileId)\n .map(([k]) => k);\n for (const key of oldEntries) {\n registry.delete(key);\n }\n\n // Rescan the changed file via the barrel-aware scanner so an\n // edited barrel re-export picks up newly-referenced files.\n // Pass overwrite=true so updated metadata replaces stale\n // entries from the previous scan.\n await scanBarrelExports(fileId, new Set(), true);\n }\n\n // Let Vite handle the rest — the transform hook will recompile\n return ctx.modules;\n },\n resolveId(id, importer) {\n if (id.startsWith(VIRTUAL_RAW_PREFIX)) {\n return `\\0${id}`;\n }\n\n if (pluginOptions.jit && id.startsWith('angular:jit:')) {\n const filePath = normalizePath(\n resolve(dirname(importer as string), id.split(';')[1]),\n );\n if (id.includes(':style')) {\n markStylePathSafe(resolvedConfig, filePath);\n return filePath + '?inline';\n }\n return toVirtualRawId(filePath);\n }\n\n const rawRewrite = rewriteHtmlRawImport(id, importer);\n if (rawRewrite) return rawRewrite;\n\n // User `.scss?inline` / `.css?inline` imports: resolve and mark\n // safe so Vite's native CSS pipeline handles them.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id) && importer) {\n const filePath = id.split('?')[0];\n const resolved = isAbsolute(filePath)\n ? normalizePath(filePath)\n : normalizePath(resolve(dirname(importer), filePath));\n markStylePathSafe(resolvedConfig, resolved);\n return resolved + '?inline';\n }\n\n return undefined;\n },\n async load(id) {\n const rawModule = await loadVirtualRawModule(this, id);\n if (rawModule !== undefined) return rawModule;\n\n // Vitest fallback: module-runner can skip resolveId, so the bare\n // ?inline query reaches load. Mark safe and let Vite handle it.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id)) {\n markStylePathSafe(resolvedConfig, id.split('?')[0]);\n }\n\n return;\n },\n transform: {\n filter: {\n id: {\n include: [TS_EXT_REGEX],\n // `?raw` ids already carry Vite's native raw-loader output\n // (`export default \"<source>\"`). Recompiling them as Angular/TS\n // would strip that default export, so leave them to Vite (#2356).\n exclude: [\n /node_modules/,\n 'type=script',\n '@ng/component',\n /[?&]raw\\b/,\n ],\n },\n },\n async handler(code, id) {\n if (transformFilter && !transformFilter(code, id)) {\n return;\n }\n\n if (id.includes('.ts?')) {\n id = id.replace(/\\?(.*)/, '');\n }\n return handleFastCompileTransform(code, id);\n },\n },\n };\n}\n"],"mappings":"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"}
package/src/lib/host.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as ts from "typescript";
2
2
  import { type StylePreprocessor } from "./style-preprocessor.js";
3
3
  import { AnalogStylesheetRegistry } from "./stylesheet-registry.js";
4
4
  import type { SourceFileCache } from "./utils/source-file-cache.js";
5
+ export declare function augmentHostWithModuleResolution(host: ts.CompilerHost, options: ts.CompilerOptions): void;
5
6
  export declare function augmentHostWithResources(host: ts.CompilerHost, transform: (code: string, id: string, options?: {
6
7
  ssr?: boolean;
7
8
  }) => ReturnType<any> | null, options: {
package/src/lib/host.js CHANGED
@@ -1,10 +1,28 @@
1
1
  import { debugStyles } from "./utils/debug.js";
2
+ import { EXCLUDED_TS_EXT_REGEX, TS_EXT_REGEX } from "./utils/plugin-config.js";
2
3
  import { normalizeStylesheetDependencies } from "./style-preprocessor.js";
3
4
  import { preprocessStylesheetResult, registerStylesheetContent } from "./stylesheet-registry.js";
4
5
  import { createHash } from "node:crypto";
5
6
  import path from "node:path";
6
7
  import { normalizePath } from "vite";
8
+ import * as ts from "typescript";
7
9
  //#region packages/vite-plugin-angular/src/lib/host.ts
10
+ function augmentHostWithModuleResolution(host, options) {
11
+ const resolutionCache = ts.createModuleResolutionCache(host.getCurrentDirectory(), host.getCanonicalFileName.bind(host), options);
12
+ host.getModuleResolutionCache = () => resolutionCache;
13
+ host.resolveModuleNameLiterals = (literals, containingFile, redirectedReference, compilerOptions, containingSourceFile) => literals.map((literal) => {
14
+ const resolution = ts.resolveModuleName(literal.text, containingFile, compilerOptions, host, resolutionCache, redirectedReference, ts.getModeForUsageLocation(containingSourceFile, literal, compilerOptions));
15
+ const resolvedModule = resolution.resolvedModule;
16
+ if (resolvedModule?.isExternalLibraryImport && TS_EXT_REGEX.test(resolvedModule.resolvedFileName) && !EXCLUDED_TS_EXT_REGEX.test(resolvedModule.resolvedFileName) && !normalizePath(resolvedModule.resolvedFileName).includes("/node_modules/")) return {
17
+ ...resolution,
18
+ resolvedModule: {
19
+ ...resolvedModule,
20
+ isExternalLibraryImport: false
21
+ }
22
+ };
23
+ return resolution;
24
+ });
25
+ }
8
26
  function augmentHostWithResources(host, transform, options) {
9
27
  const resourceHost = host;
10
28
  resourceHost.readResource = async function(fileName) {
@@ -113,6 +131,6 @@ function hasStyleExtension(file) {
113
131
  }
114
132
  }
115
133
  //#endregion
116
- export { augmentHostWithCaching, augmentHostWithResources, augmentProgramWithVersioning, mergeTransformers };
134
+ export { augmentHostWithCaching, augmentHostWithModuleResolution, augmentHostWithResources, augmentProgramWithVersioning, mergeTransformers };
117
135
 
118
136
  //# sourceMappingURL=host.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","names":[],"sources":["../../../src/lib/host.ts"],"sourcesContent":["import type { CompilerHost } from '@angular/compiler-cli';\nimport { normalizePath } from 'vite';\n\nimport * as ts from 'typescript';\n\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport {\n normalizeStylesheetDependencies,\n type StylePreprocessor,\n} from './style-preprocessor.js';\nimport {\n AnalogStylesheetRegistry,\n preprocessStylesheetResult,\n registerStylesheetContent,\n} from './stylesheet-registry.js';\nimport { debugStyles } from './utils/debug.js';\nimport type { SourceFileCache } from './utils/source-file-cache.js';\n\nexport function augmentHostWithResources(\n host: ts.CompilerHost,\n transform: (\n code: string,\n id: string,\n options?: { ssr?: boolean },\n ) => ReturnType<any> | null,\n options: {\n inlineStylesExtension: string;\n isProd?: boolean;\n stylesheetRegistry?: AnalogStylesheetRegistry;\n sourceFileCache?: SourceFileCache;\n stylePreprocessor?: StylePreprocessor;\n },\n): void {\n const resourceHost = host as CompilerHost;\n\n resourceHost.readResource = async function (fileName: string) {\n const filePath = normalizePath(fileName);\n\n const content = (this as any).readFile(filePath);\n\n if (content === undefined) {\n throw new Error('Unable to locate component resource: ' + fileName);\n }\n\n return content;\n };\n\n resourceHost.getModifiedResourceFiles = function () {\n return options?.sourceFileCache?.modifiedFiles;\n };\n\n resourceHost.transformResource = async function (data, context) {\n // Only style resources are supported currently\n if (context.type !== 'style') {\n return null;\n }\n\n const filename =\n context.resourceFile ??\n context.containingFile.replace(\n '.ts',\n `.${options?.inlineStylesExtension}`,\n );\n const preprocessed = preprocessStylesheetResult(\n data,\n filename,\n options.stylePreprocessor,\n {\n filename,\n containingFile: context.containingFile,\n resourceFile: context.resourceFile ?? undefined,\n className: context.className,\n order: context.order,\n inline: !context.resourceFile,\n },\n );\n\n // Externalized path: store preprocessed CSS for Vite's serve-time pipeline.\n // CSS must NOT be transformed here — the load hook returns it into\n // Vite's transform pipeline where PostCSS / Tailwind process it once.\n if (options.stylesheetRegistry) {\n const stylesheetId = registerStylesheetContent(\n options.stylesheetRegistry,\n {\n code: preprocessed.code,\n dependencies: normalizeStylesheetDependencies(\n preprocessed.dependencies,\n ),\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n containingFile: context.containingFile,\n className: context.className,\n order: context.order,\n inlineStylesExtension: options.inlineStylesExtension,\n resourceFile: context.resourceFile ?? undefined,\n },\n );\n debugStyles('NgtscProgram: stylesheet deferred to Vite pipeline', {\n stylesheetId,\n resourceFile: context.resourceFile ?? '(inline)',\n dependencies: preprocessed.dependencies,\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n });\n return { content: stylesheetId };\n }\n\n // Non-externalized: CSS is returned directly to the Angular compiler\n // and never re-enters Vite's pipeline, so transform eagerly.\n debugStyles('NgtscProgram: stylesheet processed inline via transform', {\n filename,\n resourceFile: context.resourceFile ?? '(inline)',\n dataLength: preprocessed.code.length,\n });\n let stylesheetResult;\n\n try {\n stylesheetResult = await transform(\n preprocessed.code,\n `${filename}?direct`,\n );\n } catch (e) {\n debugStyles('NgtscProgram: stylesheet transform error', {\n filename,\n resourceFile: context.resourceFile ?? '(inline)',\n error: String(e),\n });\n }\n\n if (!stylesheetResult?.code) {\n return null;\n }\n\n return { content: stylesheetResult.code };\n };\n\n resourceHost.resourceNameToFileName = function (\n resourceName,\n containingFile,\n fallbackResolve,\n ) {\n // Angular's fallbackResolve callback expects (resourceUrl, containingFile),\n // NOT (directory, resourceName). Use it correctly or fall back to\n // path.join for simple relative paths.\n let resolved: string | null = null;\n if (fallbackResolve) {\n resolved = fallbackResolve(path.dirname(containingFile), resourceName);\n }\n const resolvedPath = normalizePath(\n resolved ?? path.join(path.dirname(containingFile), resourceName),\n );\n\n // All resource names that have template file extensions are assumed to be templates\n if (!options.stylesheetRegistry || !hasStyleExtension(resolvedPath)) {\n return resolvedPath;\n }\n\n // Register the hash-based external mapping so the resolveId hook can\n // resolve Angular's compiled stylesheet references back to the source.\n const externalId = createHash('sha256').update(resolvedPath).digest('hex');\n const filename = externalId + path.extname(resolvedPath);\n\n options.stylesheetRegistry.registerExternalRequest(filename, resolvedPath);\n debugStyles('NgtscProgram: external stylesheet ID mapped for resolveId', {\n resourceName,\n resolvedPath,\n filename,\n });\n\n // Return the real path so Angular can read the file during analysis.\n // Previously, returning the hash-based filename caused \"Could not find\n // stylesheet file\" errors because the hash doesn't exist on disk,\n // preventing AOT compilation for any component with styleUrls. (#2293)\n return resolvedPath;\n };\n}\n\nexport function augmentProgramWithVersioning(program: ts.Program): void {\n const baseGetSourceFiles = program.getSourceFiles;\n program.getSourceFiles = function (...parameters) {\n const files: readonly (ts.SourceFile & { version?: string })[] =\n baseGetSourceFiles(...parameters);\n\n for (const file of files) {\n file.version ??= createHash('sha256').update(file.text).digest('hex');\n }\n\n return files;\n };\n}\n\nexport function augmentHostWithCaching(\n host: ts.CompilerHost,\n cache: Map<string, ts.SourceFile>,\n): void {\n const baseGetSourceFile = host.getSourceFile;\n host.getSourceFile = function (\n fileName,\n languageVersion,\n onError,\n shouldCreateNewSourceFile,\n ...parameters\n ) {\n if (!shouldCreateNewSourceFile && cache.has(fileName)) {\n return cache.get(fileName);\n }\n\n const file = baseGetSourceFile.call(\n host,\n fileName,\n languageVersion,\n onError,\n true,\n ...parameters,\n );\n\n if (file) {\n cache.set(fileName, file);\n }\n\n return file;\n };\n}\n\nexport function mergeTransformers(\n first: ts.CustomTransformers,\n second: ts.CustomTransformers,\n): ts.CustomTransformers {\n const result: ts.CustomTransformers = {};\n\n if (first.before || second.before) {\n result.before = [...(first.before || []), ...(second.before || [])];\n }\n\n if (first.after || second.after) {\n result.after = [...(first.after || []), ...(second.after || [])];\n }\n\n if (first.afterDeclarations || second.afterDeclarations) {\n result.afterDeclarations = [\n ...(first.afterDeclarations || []),\n ...(second.afterDeclarations || []),\n ];\n }\n\n return result;\n}\n\nfunction hasStyleExtension(file: string): boolean {\n const extension = path.extname(file).toLowerCase();\n\n switch (extension) {\n case '.css':\n case '.scss':\n return true;\n default:\n return false;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"host.js","names":[],"sources":["../../../src/lib/host.ts"],"sourcesContent":["import type { CompilerHost } from '@angular/compiler-cli';\nimport { normalizePath } from 'vite';\n\nimport * as ts from 'typescript';\n\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport {\n normalizeStylesheetDependencies,\n type StylePreprocessor,\n} from './style-preprocessor.js';\nimport {\n AnalogStylesheetRegistry,\n preprocessStylesheetResult,\n registerStylesheetContent,\n} from './stylesheet-registry.js';\nimport { debugStyles } from './utils/debug.js';\nimport type { SourceFileCache } from './utils/source-file-cache.js';\nimport { EXCLUDED_TS_EXT_REGEX, TS_EXT_REGEX } from './utils/plugin-config.js';\n\nexport function augmentHostWithModuleResolution(\n host: ts.CompilerHost,\n options: ts.CompilerOptions,\n): void {\n const resolutionCache = ts.createModuleResolutionCache(\n host.getCurrentDirectory(),\n host.getCanonicalFileName.bind(host),\n options,\n );\n host.getModuleResolutionCache = () => resolutionCache;\n host.resolveModuleNameLiterals = (\n literals,\n containingFile,\n redirectedReference,\n compilerOptions,\n containingSourceFile,\n ) =>\n literals.map((literal) => {\n const resolution: ts.ResolvedModuleWithFailedLookupLocations =\n ts.resolveModuleName(\n literal.text,\n containingFile,\n compilerOptions,\n host,\n resolutionCache,\n redirectedReference,\n ts.getModeForUsageLocation(\n containingSourceFile,\n literal,\n compilerOptions,\n ),\n );\n const resolvedModule = resolution.resolvedModule;\n if (\n resolvedModule?.isExternalLibraryImport &&\n TS_EXT_REGEX.test(resolvedModule.resolvedFileName) &&\n !EXCLUDED_TS_EXT_REGEX.test(resolvedModule.resolvedFileName) &&\n !normalizePath(resolvedModule.resolvedFileName).includes(\n '/node_modules/',\n )\n ) {\n // A workspace symlink resolves to source outside node_modules.\n // Classify it before program creation so TypeScript emits it.\n return {\n ...resolution,\n resolvedModule: {\n ...resolvedModule,\n isExternalLibraryImport: false,\n },\n };\n }\n return resolution;\n });\n}\n\nexport function augmentHostWithResources(\n host: ts.CompilerHost,\n transform: (\n code: string,\n id: string,\n options?: { ssr?: boolean },\n ) => ReturnType<any> | null,\n options: {\n inlineStylesExtension: string;\n isProd?: boolean;\n stylesheetRegistry?: AnalogStylesheetRegistry;\n sourceFileCache?: SourceFileCache;\n stylePreprocessor?: StylePreprocessor;\n },\n): void {\n const resourceHost = host as CompilerHost;\n\n resourceHost.readResource = async function (fileName: string) {\n const filePath = normalizePath(fileName);\n\n const content = (this as any).readFile(filePath);\n\n if (content === undefined) {\n throw new Error('Unable to locate component resource: ' + fileName);\n }\n\n return content;\n };\n\n resourceHost.getModifiedResourceFiles = function () {\n return options?.sourceFileCache?.modifiedFiles;\n };\n\n resourceHost.transformResource = async function (data, context) {\n // Only style resources are supported currently\n if (context.type !== 'style') {\n return null;\n }\n\n const filename =\n context.resourceFile ??\n context.containingFile.replace(\n '.ts',\n `.${options?.inlineStylesExtension}`,\n );\n const preprocessed = preprocessStylesheetResult(\n data,\n filename,\n options.stylePreprocessor,\n {\n filename,\n containingFile: context.containingFile,\n resourceFile: context.resourceFile ?? undefined,\n className: context.className,\n order: context.order,\n inline: !context.resourceFile,\n },\n );\n\n // Externalized path: store preprocessed CSS for Vite's serve-time pipeline.\n // CSS must NOT be transformed here — the load hook returns it into\n // Vite's transform pipeline where PostCSS / Tailwind process it once.\n if (options.stylesheetRegistry) {\n const stylesheetId = registerStylesheetContent(\n options.stylesheetRegistry,\n {\n code: preprocessed.code,\n dependencies: normalizeStylesheetDependencies(\n preprocessed.dependencies,\n ),\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n containingFile: context.containingFile,\n className: context.className,\n order: context.order,\n inlineStylesExtension: options.inlineStylesExtension,\n resourceFile: context.resourceFile ?? undefined,\n },\n );\n debugStyles('NgtscProgram: stylesheet deferred to Vite pipeline', {\n stylesheetId,\n resourceFile: context.resourceFile ?? '(inline)',\n dependencies: preprocessed.dependencies,\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n });\n return { content: stylesheetId };\n }\n\n // Non-externalized: CSS is returned directly to the Angular compiler\n // and never re-enters Vite's pipeline, so transform eagerly.\n debugStyles('NgtscProgram: stylesheet processed inline via transform', {\n filename,\n resourceFile: context.resourceFile ?? '(inline)',\n dataLength: preprocessed.code.length,\n });\n let stylesheetResult;\n\n try {\n stylesheetResult = await transform(\n preprocessed.code,\n `${filename}?direct`,\n );\n } catch (e) {\n debugStyles('NgtscProgram: stylesheet transform error', {\n filename,\n resourceFile: context.resourceFile ?? '(inline)',\n error: String(e),\n });\n }\n\n if (!stylesheetResult?.code) {\n return null;\n }\n\n return { content: stylesheetResult.code };\n };\n\n resourceHost.resourceNameToFileName = function (\n resourceName,\n containingFile,\n fallbackResolve,\n ) {\n // Angular's fallbackResolve callback expects (resourceUrl, containingFile),\n // NOT (directory, resourceName). Use it correctly or fall back to\n // path.join for simple relative paths.\n let resolved: string | null = null;\n if (fallbackResolve) {\n resolved = fallbackResolve(path.dirname(containingFile), resourceName);\n }\n const resolvedPath = normalizePath(\n resolved ?? path.join(path.dirname(containingFile), resourceName),\n );\n\n // All resource names that have template file extensions are assumed to be templates\n if (!options.stylesheetRegistry || !hasStyleExtension(resolvedPath)) {\n return resolvedPath;\n }\n\n // Register the hash-based external mapping so the resolveId hook can\n // resolve Angular's compiled stylesheet references back to the source.\n const externalId = createHash('sha256').update(resolvedPath).digest('hex');\n const filename = externalId + path.extname(resolvedPath);\n\n options.stylesheetRegistry.registerExternalRequest(filename, resolvedPath);\n debugStyles('NgtscProgram: external stylesheet ID mapped for resolveId', {\n resourceName,\n resolvedPath,\n filename,\n });\n\n // Return the real path so Angular can read the file during analysis.\n // Previously, returning the hash-based filename caused \"Could not find\n // stylesheet file\" errors because the hash doesn't exist on disk,\n // preventing AOT compilation for any component with styleUrls. (#2293)\n return resolvedPath;\n };\n}\n\nexport function augmentProgramWithVersioning(program: ts.Program): void {\n const baseGetSourceFiles = program.getSourceFiles;\n program.getSourceFiles = function (...parameters) {\n const files: readonly (ts.SourceFile & { version?: string })[] =\n baseGetSourceFiles(...parameters);\n\n for (const file of files) {\n file.version ??= createHash('sha256').update(file.text).digest('hex');\n }\n\n return files;\n };\n}\n\nexport function augmentHostWithCaching(\n host: ts.CompilerHost,\n cache: Map<string, ts.SourceFile>,\n): void {\n const baseGetSourceFile = host.getSourceFile;\n host.getSourceFile = function (\n fileName,\n languageVersion,\n onError,\n shouldCreateNewSourceFile,\n ...parameters\n ) {\n if (!shouldCreateNewSourceFile && cache.has(fileName)) {\n return cache.get(fileName);\n }\n\n const file = baseGetSourceFile.call(\n host,\n fileName,\n languageVersion,\n onError,\n true,\n ...parameters,\n );\n\n if (file) {\n cache.set(fileName, file);\n }\n\n return file;\n };\n}\n\nexport function mergeTransformers(\n first: ts.CustomTransformers,\n second: ts.CustomTransformers,\n): ts.CustomTransformers {\n const result: ts.CustomTransformers = {};\n\n if (first.before || second.before) {\n result.before = [...(first.before || []), ...(second.before || [])];\n }\n\n if (first.after || second.after) {\n result.after = [...(first.after || []), ...(second.after || [])];\n }\n\n if (first.afterDeclarations || second.afterDeclarations) {\n result.afterDeclarations = [\n ...(first.afterDeclarations || []),\n ...(second.afterDeclarations || []),\n ];\n }\n\n return result;\n}\n\nfunction hasStyleExtension(file: string): boolean {\n const extension = path.extname(file).toLowerCase();\n\n switch (extension) {\n case '.css':\n case '.scss':\n return true;\n default:\n return false;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function createHotUpdateBatcher(compile: (ids: string[]) => Promise<void>): {
2
+ schedule(file: string, ids: string[]);
3
+ wait();
4
+ close();
5
+ };