Skip to content

fix(playwright): add retainLines to preserve source line numbers#39257

Closed
omarshibli wants to merge 2 commits intomicrosoft:mainfrom
omarshibli:fix/babel-retain-lines-v2
Closed

fix(playwright): add retainLines to preserve source line numbers#39257
omarshibli wants to merge 2 commits intomicrosoft:mainfrom
omarshibli:fix/babel-retain-lines-v2

Conversation

@omarshibli
Copy link

Problem

Babel's compact: false expands destructured parameters across multiple lines in the compiled output, causing cumulative line drift:

Source line 7:  test('first', async ({ foo, bar, baz }) => {
Source line 10: test('second', async ({ foo, bar, baz }) => {
Source line 13: test('third', async ({ foo, bar, baz }) => {

Compiled (without retainLines) — 15 source lines become 30 compiled lines:
Line 9:  test('first', async ({    → +2 drift
Line 16: test('second', async ({   → +6 drift
Line 23: test('third', async ({    → +10 drift

Each destructured pattern with N parameters expands from 1 line to N+2 lines. The drift grows with each pattern, compounding across the file.

Why source maps alone don't cover this

While sourceMapSupport correctly resolves line numbers in the test report path (wrapFunctionWithLocationsourceMapSupport.wrapCallSite), the Playwright Inspector (PWDEBUG=1) uses a different code path:

  1. captureRawStack() captures Error.stackparseStackFrame() extracts line numbers
  2. Line numbers are sent as metadata.location to the server
  3. Recorder._updateUserSources() uses metadata.location.line directly to highlight lines in the source file

Additionally, retainLines: true makes the source map trivially correct (1:1 line mapping), eliminating any potential for source map inaccuracies with complex transformations.

Fix

One-line change: add retainLines: true to babel transform options. This tells babel to keep statements on their original lines, preserving line number alignment between source and compiled output.

Test

The test calls babelTransform() directly and verifies that test() calls with destructured TypeScript parameters remain on their original source lines (7, 10, 13) in the compiled output. This test fails without retainLines: true (lines shift to 9, 16, 23).

Related Issues

Without retainLines, babel expands destructured parameters across
multiple lines causing cumulative line drift in compiled output:

  Source line 7:  test('first', async ({ foo, bar, baz }) => {
  Source line 10: test('second', async ({ foo, bar, baz }) => {
  Source line 13: test('third', async ({ foo, bar, baz }) => {

  Compiled without retainLines:
  Line 9:  test('first', async ({    (+2 drift)
  Line 16: test('second', async ({   (+6 drift)
  Line 23: test('third', async ({    (+10 drift)

This breaks the Playwright Inspector (PWDEBUG=1) which uses compiled
line numbers from captureRawStack() to highlight lines in the source
file via metadata.location in the Recorder.
@omarshibli
Copy link
Author

I've made previous attempt to fix it here #39217 but got it rejected, i've revisited the tests and fix the issues raised in the previous PR.

@omarshibli omarshibli changed the title fix(babel): add retainLines to preserve source line numbers fix(playwright): add retainLines to preserve source line numbers Feb 13, 2026
@Skn0tt
Copy link
Member

Skn0tt commented Feb 13, 2026

As per #39217 (comment), please start with filing a bug report. Thank you.

@Skn0tt Skn0tt closed this Feb 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants