Skip to content

NG_BUILD_OPTIMIZE_CHUNKS can cause variable name collisions #32764

@austinw-fineart

Description

@austinw-fineart

Command

build

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

Yes NG_BUILD_OPTIMIZE_CHUNKS is still experimental. This is just a bug I came across while testing it for #27715. I hit a rather nasty edge case with it on where two variable names ended up colliding inside main.js, one from a core Angular package, and the other being one of my components. Thankfully it broke the runtime early on cause otherwise I never would've caught it.

The mangled variable name that got hit was Wb. The first occurrence appears to be from https://github.com/angular/angular/blob/17d8a88ddcce3f850b8ab72252e05720e1f3a8be/packages/core/src/render3/definition.ts#L398-L436

function Wb(e){return ro$3(()=>({type:e.type,bootstrap:e.bootstrap||ce$4,declarations:e.declarations||ce$4,imports:e.imports||ce$4,exports:e.exports||ce$4,transitiveCompileScopes:null,schemas:e.schemas||null,id:e.id||null}))}

The second occurrence comes from one of my components (snippet under reproduction)

var Wb=[`open`,`opening`,`toggle`],Fi=class o{constructor(e,t){this._document=e;this._elementRef=t;let r=Wb.map(i=>$U(ea(this._document,i,{capture:!0,passive:!0}).pipe(Pe$11(s=>s.target instanceof Element&&s.target!==this._elementRef.nativeElement&&!s.target.tagName.toLowerCase().startsWith(`md-menu`)))));

Wb breaks upon calling it on the third occurrence in the same line as the previous (which I assume means the same chunk), which appears to be from https://github.com/angular/components/blob/main/src/cdk-experimental/scrolling/scrolling-module.ts

static ɵdir=Qb({type:o,selectors:[[`cdk-virtual-scroll-viewport`,`autosize`,``]],inputs:{minBufferPx:`minBufferPx`,maxBufferPx:`maxBufferPx`},features:[mw([{provide:bi$1,useFactory:D_,deps:[ci$5(()=>o)]}]),TI]})}return o})(),Jh=(()=>{class o{static ɵfac=function(r){return new(r||o)};static ɵmod=Wb({type:o});

Minimal Reproduction

The mangled names appear to follow a deterministic sequence so you just have to hit it with enough variable declarations and some luck. Best I can offer is the component that got hit:

import {
  ChangeDetectionStrategy,
  Component,
  DOCUMENT,
  ElementRef,
  Inject,
} from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { filter, fromEvent } from 'rxjs';

const POPOVER_EVENTS = ['open', 'opening', 'toggle'];

@Component({
  selector: 'md-menu',
  styleUrl: './menu.component.scss',
  templateUrl: './menu.component.html',
})
export class MenuComponent {
  constructor(
    @Inject(DOCUMENT) private readonly _document: Document,
    private readonly _elementRef: ElementRef<HTMLElement>,
  ) {
    const signals = POPOVER_EVENTS.map((name) =>
      toSignal(
        fromEvent(this._document, name, { capture: true, passive: true }).pipe(
          filter(
            (value) =>
              value.target instanceof Element &&
              value.target !== this._elementRef.nativeElement &&
              !value.target.tagName.toLowerCase().startsWith('md-menu'),
          ),
        ),
      ),
    );
  }
}

Exception or Error

Uncaught TypeError: Wb is not a function
    at <static_initializer> (main-3IQSYYTY.js:1066:5353)
    at main-3IQSYYTY.js:1066:5278
    at main-3IQSYYTY.js:1066:5399
    at main-3IQSYYTY.js:1:101
    at main-3IQSYYTY.js:1068:36238

Your Environment

Angular CLI       : 21.2.2
Angular           : 21.1.5
Node.js           : 24.14.0
Package Manager   : pnpm 10.32.1
Operating System  : win32 x64

Anything else relevant?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs: repro stepsWe cannot reproduce the issue with the information given

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions