Skip to content

Linker emits duplicate _c0 constant names when component has both <ng-content> and host styles #59

@tomer953

Description

@tomer953

Description

The OXC Angular linker generates duplicate const _c0 declarations at module scope when linking a component that has both content projection (<ng-content>) and a host style binding (host: { '[style]': '...' }).

The standard Angular compiler uses incrementing names (_c0, _c1, _c2, …) for each generated constant. The OXC linker resets the counter, producing two const _c0 declarations in the same scope, which causes a parse error.

Minimal Reproduction

Given this partial-compilation .mjs file (simplified from @spartan-ng/brain):

import * as i0 from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';

class MyCheckbox {
  static ɵfac = i0.ɵɵngDeclareFactory({
    minVersion: "12.0.0", version: "19.2.8", ngImport: i0,
    type: MyCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component
  });
  static ɵcmp = i0.ɵɵngDeclareComponent({
    minVersion: "14.0.0", version: "19.2.8", ngImport: i0,
    type: MyCheckbox, isStandalone: true, selector: "my-checkbox",
    host: {
      properties: { "style": "{display: \"contents\"}" }
    },
    template: `<button><ng-content /></button>`,
    isInline: true,
    changeDetection: i0.ChangeDetectionStrategy.OnPush
  });
}

export { MyCheckbox };

Expected Output

The linker should produce unique constant names:

const _c0 = ["*"];                          // ng-content projection selectors
const _c1 = () => ({ display: "contents" }); // host style factory

// ... component definition using _c0 and _c1 respectively

Actual Output

const _c0 = ["*"];                          // ng-content projection selectors
// ...
}const _c0 = () => ({display:"contents"});  // ❌ DUPLICATE — same name!

Error

[PARSE_ERROR] Error: Identifier `_c0` has already been declared
     ╭─[input.mjs:X:7]
     │
   X │ const _c0 = ["*"];
     │       ─┬─
     │        ╰─── `_c0` has already been declared here
     │
   Y │ }const _c0 = () =>({display:"contents"});
     │        ─┬─
     │         ╰─── It can not be redeclared here
─────╯

https://github.com/spartan-ng/spartan/blob/main/libs/brain/checkbox/src/lib/brn-checkbox.ts

Workaround

Post-process the linker output to rename duplicate _cN constants:

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions