vite: Error `Unexpected token '{'` after upgrade vite@4.3.9 to vite@4.4.0

Describe the bug

I tried to upgrade vite@4.3.9 to vite@4.4.0 but Cypress could not longer run tests because of the error Unexpected token '{' (see logs section for more detailed stack trace).

Reproduction

sorry none at this time

Steps to reproduce

I will write more detailed steps to reproduce if this upgrade becomes more important.

I suspect the following would work:

  1. Create a react app using TypeScript
  2. yarn add cypress@8.5.0 (note, I’m stuck on this old Cypress version)
  3. Create a simple Cypress test
  4. Try to run the Cypress test against the react app
  5. Observe error in the Cypress console

System Info

"cypress": "8.5.0",
"vite-tsconfig-paths": "^4.2.0",

Used Package Manager

yarn

Logs

Vite Logs

See google doc, it was too long to paste into the message body.

Cypress Console Log

Error seen in Cypress console:

SyntaxError: Unexpected token '{'

More detail by printing the Cypress log to the console log:

cypress_runner.js:190988 SyntaxError: The following error originated from your application code, not from Cypress.

  > Unexpected token '{'

When Cypress detects uncaught errors originating from your application it will automatically fail the current test.

This behavior is configurable, and you can choose to turn this off by listening to the `uncaught:exception` event.
SyntaxError: The following error originated from your application code, not from Cypress.

  > Unexpected token '{'

When Cypress detects uncaught errors originating from your application it will automatically fail the current test.

This behavior is configurable, and you can choose to turn this off by listening to the `uncaught:exception` event.
From previous event:
    at Object.run (http://localhost:3000/__cypress/runner/cypress_runner.js:182821:23)
    at Object.run (http://localhost:3000/__cypress/runner/cypress_runner.js:168727:17)
    at $Cy.cy.<computed> [as wait] (http://localhost:3000/__cypress/runner/cypress_runner.js:169897:19)
    at __stackReplacementMarker (http://localhost:3000/__cypress/runner/cypress_runner.js:169205:13)
    at Context.runnable.fn (http://localhost:3000/__cypress/runner/cypress_runner.js:170121:23)
    at callFn (http://localhost:3000/__cypress/runner/cypress_runner.js:122959:21)
    at Test.../driver/node_modules/mocha/lib/runnable.js.Runnable.run (http://localhost:3000/__cypress/runner/cypress_runner.js:122946:7)
    at http://localhost:3000/__cypress/runner/cypress_runner.js:176663:30
From previous event:
    at Object.onRunnableRun (http://localhost:3000/__cypress/runner/cypress_runner.js:176648:19)
    at $Cypress.action (http://localhost:3000/__cypress/runner/cypress_runner.js:166202:28)
    at Test.Runnable.run (http://localhost:3000/__cypress/runner/cypress_runner.js:174382:13)
    at Runner.../driver/node_modules/mocha/lib/runner.js.Runner.runTest (http://localhost:3000/__cypress/runner/cypress_runner.js:123618:10)
    at http://localhost:3000/__cypress/runner/cypress_runner.js:123744:12
    at next (http://localhost:3000/__cypress/runner/cypress_runner.js:123527:14)
    at http://localhost:3000/__cypress/runner/cypress_runner.js:123537:7
    at next (http://localhost:3000/__cypress/runner/cypress_runner.js:123439:14)
    at http://localhost:3000/__cypress/runner/cypress_runner.js:123505:5
    at timeslice (http://localhost:3000/__cypress/runner/cypress_runner.js:117431:27)

Validations

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 23 (5 by maintainers)

Most upvoted comments

Changing the compiler options target on 4.3.9 is definitely changing my output JS.

Given this typescript:

import { Controller } from '@hotwired/stimulus'
import { useClickOutside } from 'stimulus-use'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { enter, leave } from 'el-transition'

export default class extends Controller {
  static targets = ['menu']

  declare menuTarget: HTMLElement

  connect() {
    useClickOutside(this, { element: this.menuTarget })
  }

  show() {
    this.menuTarget.classList.remove('hidden')
    enter(this.menuTarget)
  }

  hide() {
    Promise.all([leave(this.menuTarget)]).then(() => {
      this.menuTarget.classList.add('hidden')
    })
  }

  toggle() {
    if (this.menuTarget.classList.contains('hidden')) {
      this.show()
    } else {
      this.hide()
    }
  }

  clickOutside() {
    this.hide()
  }
}

And this section of tsconfig.json:

{
  "compilerOptions": {
    "target": "es2015",
  }
}

es2015

import { Controller } from "/vite-dev/@fs/.../node_modules/.vite/deps/@hotwired_stimulus.js?v=11d7a1aa";
import { useClickOutside } from "/vite-dev/@fs/.../node_modules/.vite/deps/stimulus-use.js?v=11d7a1aa";
import { enter, leave } from "/vite-dev/@fs/.../node_modules/.vite/deps/el-transition.js?v=11d7a1aa";
export default class dropdown_menu_controller_default extends Controller {
    connect()
    {
        useClickOutside(this, {
            element: this.menuTarget
        });
    }
    show()
    {
        this.menuTarget.classList.remove("hidden");
        enter(this.menuTarget);
    }
    hide()
    {
        Promise.all([leave(this.menuTarget)]).then(() => {
            this.menuTarget.classList.add("hidden");
        });
    }
    toggle()
    {
        if (this.menuTarget.classList.contains("hidden")) {
            this.show();
        } else {
            this.hide();
        }
    }
    clickOutside()
    {
        this.hide();
    }
}
dropdown_menu_controller_default.targets = ["menu"];

esnext

import { Controller } from "/vite-dev/@fs/.../node_modules/.vite/deps/@hotwired_stimulus.js?v=11d7a1aa";
import { useClickOutside } from "/vite-dev/@fs/.../node_modules/.vite/deps/stimulus-use.js?v=11d7a1aa";
import { enter, leave } from "/vite-dev/@fs/.../node_modules/.vite/deps/el-transition.js?v=11d7a1aa";
export default class extends Controller {
  static targets = ["menu"];
  connect() {
    useClickOutside(this, { element: this.menuTarget });
  }
  show() {
    this.menuTarget.classList.remove("hidden");
    enter(this.menuTarget);
  }
  hide() {
    Promise.all([leave(this.menuTarget)]).then(() => {
      this.menuTarget.classList.add("hidden");
    });
  }
  toggle() {
    if (this.menuTarget.classList.contains("hidden")) {
      this.show();
    } else {
      this.hide();
    }
  }
  clickOutside() {
    this.hide();
  }
}

Omitting the compilerOptions:

import { Controller } from "/vite-dev/@fs/.../node_modules/.vite/deps/@hotwired_stimulus.js?v=11d7a1aa";
import { useClickOutside } from "/vite-dev/@fs/.../node_modules/.vite/deps/stimulus-use.js?v=11d7a1aa";
import { enter, leave } from "/vite-dev/@fs/.../node_modules/.vite/deps/el-transition.js?v=11d7a1aa";
export default class dropdown_menu_controller_default extends Controller {
    connect()
    {
        useClickOutside(this, {
            element: this.menuTarget
        });
    }
    show()
    {
        this.menuTarget.classList.remove("hidden");
        enter(this.menuTarget);
    }
    hide()
    {
        Promise.all([leave(this.menuTarget)]).then(() => {
            this.menuTarget.classList.add("hidden");
        });
    }
    toggle()
    {
        if (this.menuTarget.classList.contains("hidden")) {
            this.show();
        } else {
            this.hide();
        }
    }
    clickOutside()
    {
        this.hide();
    }
}
dropdown_menu_controller_default.targets = ["menu"];

It’s worth noting, every time I change my tsconfig.json while my server is running, I see this log line:

3:48:41 PM [vite] changed tsconfig file detected: /my_path/tsconfig.json - Clearing cache and forcing full-reload to ensure TypeScript is compiled with updated config values.

On Vite 4.4.7, with “es2015” the file is:

import { Controller } from "/vite-dev/@fs/.../node_modules/.vite/deps/@hotwired_stimulus.js?v=c8bdaac7";
import { useClickOutside } from "/vite-dev/@fs/.../node_modules/.vite/deps/stimulus-use.js?v=24b8e4a2";
import { enter, leave } from "/vite-dev/@fs/.../node_modules/.vite/deps/el-transition.js?v=b7575016";
export default class extends Controller {
  static {
    this.targets = ["menu"];
  }
  connect() {
    useClickOutside(this, { element: this.menuTarget });
  }
  show() {
    this.menuTarget.classList.remove("hidden");
    enter(this.menuTarget);
  }
  hide() {
    Promise.all([leave(this.menuTarget)]).then(() => {
      this.menuTarget.classList.add("hidden");
    });
  }
  toggle() {
    if (this.menuTarget.classList.contains("hidden")) {
      this.show();
    } else {
      this.hide();
    }
  }
  clickOutside() {
    this.hide();
  }
}

This errors. Safari does not seem to understand this part:

static {
}

I tried “esnext” and the file is:

import { Controller } from "/vite-dev/@fs/.../node_modules/.vite/deps/@hotwired_stimulus.js?v=a996cf86";
import { useClickOutside } from "/vite-dev/@fs/.../node_modules/.vite/deps/stimulus-use.js?v=a996cf86";
import { enter, leave } from "/vite-dev/@fs/.../node_modules/.vite/deps/el-transition.js?v=a996cf86";
export default class extends Controller {
  static targets = ["menu"];
  connect() {
    useClickOutside(this, { element: this.menuTarget });
  }
  show() {
    this.menuTarget.classList.remove("hidden");
    enter(this.menuTarget);
  }
  hide() {
    Promise.all([leave(this.menuTarget)]).then(() => {
      this.menuTarget.classList.add("hidden");
    });
  }
  toggle() {
    if (this.menuTarget.classList.contains("hidden")) {
      this.show();
    } else {
      this.hide();
    }
  }
  clickOutside() {
    this.hide();
  }
}

I tried a bunch of different values for compilerOptions target, and es2021 errors (same output as es2015), but es2022 works fine (same output as esnext).

This is so strange.

I’m sure it’s obvious, but by updating Vite from 4.3 to 4.4, it also updated esbuild from 0.17 to 0.18.

So far I’ve been unable to put together a reproduction from scratch. So I think I’m gonna work the other way around: take my project, make a branch, and start cutting chunks away until the problem goes away. Then I’ll have a better idea of how to create a reproduction—hopefully.

We’re getting this error as well, only in Safari 15 and earlier (in our Astro + Vue app). @mosofsky would you mind updating the title of this issue, since it’s not just about Cypress? It affects production applications.