tsx: ReferenceError: __name is not defined

Bug description

I’m trying to use Playwright screenshot function w/ tsx from command line. This has worked in previous versions and works with tsm but doesn’t work w/ tsx.

Reproduction

// test.ts

import { chromium } from 'playwright-chromium'
;(async () => {
  const url = 'https://www.unessa.net'

  const browser = await chromium.launch({
    headless: true,
  })
  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto(url)
  await page.screenshot({
    path: 'test-screenshot.png',
    fullPage: true,
  })

  await browser.close()
})()

Runing npx tsx src/testfn.ts produces following error:

page.screenshot: ReferenceError: __name is not defined
    at eval (eval at evaluate (:190:30), <anonymous>:1:102)
    at UtilityScript.evaluate (<anonymous>:192:17)
    at UtilityScript.<anonymous> (<anonymous>:1:44)
=========================== logs ===========================
taking page screenshot
============================================================
    at null.<anonymous> (/../test.ts:12:14)

Environment

<!--
  Run and paste the output of:
  
  npx envinfo --system --npmPackages tsx --binaries

–>

  System:
    OS: macOS 12.6
    CPU: (8) arm64 Apple M1
    Memory: 83.13 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.15.1 - ~/.nvm/versions/node/v16.15.1/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.15.1/bin/npm
    Watchman: 2022.09.19.00 - /opt/homebrew/bin/watchman
  npmPackages:
    tsx: 3.9.0 => 3.9.0 


### Can you contribute a fix?

- [ ] I’m interested in opening a pull request for this issue.

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 23
  • Comments: 25 (13 by maintainers)

Most upvoted comments

Thanks for the reproduction. This is happening because esbuild’s --keep-names option applies __name to functions to preserve the original name. The bug occurs when playwright stringifies the functions and evals them without the __name declaration.

This is a stated limitation so I wouldn’t consider it a bug.

It probably works with tsm because it doesn’t have --keep-names enabled, but it’s necessary to preserve certain functionality in case esbuild renames variables, which can happen with variable shadowing.

Example

https://hyrious.me/esbuild-repl/?version=0.15.10&mode=transform&input=function+fn()+{ ++function+fn()+{} ++console.log(fn.name+%3D%3D%3D+'fn')+%2F%2F+should+be+true }&options=--keep-names

In this example, the inner fn is renamed to fn2. Without --keep-names, the assertion inside fails.


To fix this problem, I filed a feature request to only apply __name when the function is actually renamed: https://github.com/evanw/esbuild/issues/2605

Alternatively, I can also shim globalThis.eval to always include a declaration for __name. However, it’s a pretty frail solution that can break as soon as the variable __name is declared in user-code.

With https://github.com/privatenumber/tsx/releases/tag/v4.0.0 released, this will likely no longer be an issue in the majority of cases.

Hope it works well for yall!

Keeping this issue open but labelled “Blocked” because the root issue is in esbuild.

It’s linked in the conversation above