Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃悰 BUG: Wrangler + Angular SSR (prerender: false) + Private properties = TypeError: Class constructor t cannot be invoked without 'new' #5263

Open
nunoarruda opened this issue Mar 15, 2024 · 2 comments
Labels
bug Something that isn't working

Comments

@nunoarruda
Copy link

nunoarruda commented Mar 15, 2024

Which Cloudflare product(s) does this pertain to?

Pages

What version(s) of the tool(s) are you using?

2.14.2 [create-cloudflare]

What version of Node are you using?

20.11.1

What operating system and version are you using?

macOS Sonoma 14.4

Describe the Bug

Observed behavior

I noticed that:

  1. When using the command npm create cloudflare@latest my-angular-app -- --framework=angular, an Angular SSR app is created with additional files and changes to make it work with Cloudflare Workers/Pages.
  2. Static Site Generation (SSG) is enabled by default ("prerender": true on angular.json)
  3. If you turn off SSG ("prerender": false), so everything is Server Side Rendered (SSR), and add a private property, things break.

Expected behavior

SSR should just work and not break with private properties.

Steps to reproduce

  1. Create a Cloudflare version of an Angular app npm create cloudflare@latest my-angular-app -- --framework=angular
  2. Turn off Static Site Generation (SSG) by setting "prerender": false on angular.json
  3. Add a private property (like, for example, #test = 'test')
  4. Run the app: npm run start and press b

cc: @petebacondarwin @alan-agius4 @JeanMeche

Please provide a link to a minimal reproduction

https://github.com/nunoarruda/my-angular-app

Please provide any relevant error logs

[wrangler:err] TypeError: Class constructor t cannot be invoked without 'new'
    at t.handleNavigationRequest (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ZK4POREG.mjs:2:47542)
    at t.scheduleNavigation (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ZK4POREG.mjs:2:63103)
    at t.navigateToSyncWithBrowser (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ZK4POREG.mjs:2:61042)
    at t.initialNavigation (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ZK4POREG.mjs:2:60522)
    at s (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ZK4POREG.mjs:2:64001)
    at null.<anonymous> (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ES3Z552B.mjs:34:29056)
    at [object Object]
    at e._loadComponent (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ES3Z552B.mjs:34:29045)
    at e.bootstrap (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ES3Z552B.mjs:34:28076)
    at null.<anonymous> (file:///Users/nunoarruda/Desktop/my-angular-app/.wrangler/tmp/pages-3oJJr3/chunk-ES3Z552B.mjs:34:35938)
[wrangler:inf] GET / 500 Internal Server Error
Screenshot 2024-03-15 at 16 00 36
@nunoarruda nunoarruda added the bug Something that isn't working label Mar 15, 2024
@nunoarruda nunoarruda changed the title 馃悰 BUG: Wrangler + Angular SSR (prerender: false) + http request = TypeError: Class constructor t cannot be invoked without 'new' 馃悰 BUG: Wrangler + Angular SSR (prerender: false) + Private properties = TypeError: Class constructor t cannot be invoked without 'new' Mar 20, 2024
@alan-agius4
Copy link
Contributor

alan-agius4 commented Apr 9, 2024

The issue arises when re-running esbuild on an already bundled output, as it appears esbuild is incorrectly updating the references.

Angular CLI code:

  let M = class M {
    get hasRequestedNavigation() {
      return this.navigationId !== 0;
    }
    constructor() {
      //
    }
    complete() {
      this.transitions?.complete();
    }
    handleNavigationRequest(n) {
      let i = ++this.navigationId;
      this.transitions?.next(M(Object.assign(Object.assign({}, this.transitions.value), n), { id: i }));
    }

Wrangler Code:

  let t13 = class t {
    get hasRequestedNavigation() {
      return this.navigationId !== 0;
    }
    constructor() {
     //
    }
    complete() {
      this.transitions?.complete();
    }
    handleNavigationRequest(n) {
      let i = ++this.navigationId;
      this.transitions?.next(t(s(s({}, this.transitions.value), n), { id: i }));
    }

The problem lies in the handleNavigationRequest method, where the first parameter of this.transitions?.next is t(). However, in this context, t refers to the local class, whereas in the original code generated by Angular CLI, it's M, referencing a completely different function.

Certainly, resolving this issue would indeed require further investigation to determine the best course of action and probably provide a minimal reproduction to esbuild folks.

In this case, using a private field causes the problem because the private field is downleveled to a WeakMap which causes a change in the symbols names.

@alan-agius4
Copy link
Contributor

alan-agius4 commented Apr 9, 2024

Update: I managed to create a minimal reproduction and created an issue in the esbuild tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something that isn't working
Projects
Status: Untriaged
Development

No branches or pull requests

2 participants