microsoft/playwright

[Bug]: tsx >= 4.15.0 breaks context.addInitScript

RunOrVeith opened this issue · 2 comments

Version

1.45.1

Steps to reproduce

  1. Clone repo at https://github.com/RunOrVeith/tsxPlaywrightBug
  2. npm i
  3. npx playwright install
  4. npx tsx index.ts (or use the provided launch file in vscode)

Expected behavior

I expect "5" to be printed to the terminal

Actual behavior

The init script is not added to the window with this error:

node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

page.evaluate: TypeError: Cannot read properties of undefined (reading 'foo')
    at eval (eval at evaluate (:226:30), <anonymous>:1:20)
    at UtilityScript.evaluate (<anonymous>:228:17)
    at UtilityScript.<anonymous> (<anonymous>:1:44)
    at main (/home/veith/projects/tsxPlaywrightBug/index.ts:16:28)

Additional context

tsx 4.15.0 is the first version where this is a problem, and it persists up to the latest version of tsx 4.16.2.
If you replace the version inside package.json with "4.14.1" (the last version before 4.15.0), and run npm iand npx tsx index.ts again, you get the desired and expected output.

npx tsx index.ts
5

This only happens if you have a function defined in your init script. If you replace foo to be a number and not a function returning a number it works fine in the newer versions.

declare global {
  interface Window {
    example: {foo:  number}; // <-- not a function anymore
  }
}

const main = async (): Promise<void> => {
    const browser = await chromium.launch();  
    const context = await browser.newContext({});
    await context.addInitScript(() => {
        window.example = { foo: 5}
    })
    const page = await context.newPage();
    console.log(await page.evaluate(() => window.example.foo))
};

This correctly prints 5.

There are no additional errors in the browser console if you start it with { headless: false } in this example, but in my real-life use case where this is a problem I get this error in the browser console with the newer versions.
I don't know how to easily reproduce that..

Uncaught ReferenceError: __name is not defined
    at <anonymous>:1:16935
    at <anonymous>:1:18781

I've noticed this error before even with the working versions of tsx when defining a function with a const keyword directly inside the init script. If you replace the init script with

    await context.addInitScript(() => {
        window.example = { foo: () => {
            const getNumber = () => {return 5}
            return getNumber()
        }}
    })

you don't get any output from running npx tsx index.ts anymore, even when using tsx 4.14.1. But if you look at the browser console when starting it in headed mode, you get a similar error to the one above. In this case example is defined, but the code can not be parsed:

window.example.foo()
VM11:7 Uncaught ReferenceError: __name is not defined
    at Object.foo (eval at evaluate (:226:30), <anonymous>:7:54)
    at <anonymous>:1:16

As far as I am aware and according to the docs, this should work, but it never has for me (for at least the last year, not sure if it worked before). I don't know if this is related to the tsx issue, but it feels close enough that I want to report it.
I could always get it to work by wrapping the function in another object, but it feels like a bug. So this works:

  await context.addInitScript(() => {
        window.example = { foo: () => {
            const numberGetter = {getNumber: () => {return 5} }
            return numberGetter.getNumber()
        }}
    })

Environment

System:
    OS: Linux 6.5 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
    CPU: (20) x64 13th Gen Intel(R) Core(TM) i9-13900H
    Memory: 53.12 GB / 62.44 GB
    Container: Yes
  Binaries:
    Node: 20.14.0 - ~/.nvm/versions/node/v20.14.0/bin/node
    npm: 10.8.1 - ~/.nvm/versions/node/v20.14.0/bin/npm
    pnpm: 9.4.0 - ~/.nvm/versions/node/v20.14.0/bin/pnpm
  IDEs:
    VSCode: 1.91.0 - /snap/bin/code
  Languages:
    Bash: 5.1.16 - /usr/bin/bash
  npmPackages:
    playwright: ^1.45.1 => 1.45.1

This looks more like a bug in tsx/esbuild rather than a Playwright bug. Since the code gets transpiled incorrectly and then the browser when evaluating it doesn't know what to do with the __name variable. When running your same code with Node.js, it works as expected.

See e.g. privatenumber/tsx#113

I recommend filing it at their end / finding the exact version which breaks it. If its 4.15.0 - then its most likely caused by an esbuild version bump: https://github.com/privatenumber/tsx/releases/tag/v4.15.0

Looks like they have a workaround: evanw/esbuild#2605 (comment)

Closing as per above.