Skip to content

[Bug]: 1.63 regression - Locator.highlight does not work with custom selector engines that rely on global variables #42849

Closed

Description

@DetachHead

Version

1.63.0

Steps to reproduce

import { test as base } from '@playwright/test'

declare global {
    interface Window {
        selectorEngineEnabled?: true | undefined
    }
}

export const test = base.extend<{}, { selectorRegistration: void }>({
    selectorRegistration: [
        async ({ playwright }, use) => {
            await playwright.selectors.register('tag', () => ({
                queryAll: (root: Element | Document, selector: string) => {
                    if (typeof window.selectorEngineEnabled === 'boolean') {
                        return Array.from(root.querySelectorAll(selector))
                    }
                    return []
                },
                query: (root: Element | Document, selector: string) => {
                    if (typeof window.selectorEngineEnabled === 'boolean') {
                        return root.querySelector(selector)
                    }
                    return []
                },
            }))
            await use()
        },
        { scope: 'worker', auto: true },
    ],
})

test('selector engine test', async ({ page }) => {
    await page.evaluate(() => (window.selectorEngineEnabled = true))
    await page.setContent('<button>asdf</button>')
    const button = page.locator('tag=button')
    await button.highlight() // doesn't work
    await button.click() // does work
})

Expected behavior

both button.highlight and button.click should work

Actual behavior

only button.click works.

it seems that window.selectorEngineEnabled is undefined when called by locator.highlight, but not when called by locator.click.

my guess is that maybe locator.highlight is incorrectly running the selector inside an isolated content script, even though the selector engine is not being registered with {contentScript: true}?

Additional context

the use case is my playwright-ui5 selector engine. it works by accessing the ui5 api via window.sap.ui.core. when calling locator.highlight with a ui5 selector, it fails because window.sap is not defined for some reason.

Environment

System:
    OS: Windows 11 10.0.22631
    CPU: (12) x64 11th Gen Intel(R) Core(TM) i5-11500H @ 2.90GHz
    Memory: 9.94 GB / 31.20 GB
  Binaries:
    Node: 26.3.1 - C:\Users\user\AppData\Roaming\node\node.EXE
    npm: 11.16.0 - C:\Users\user\AppData\Roaming\node\npm.CMD
  IDEs:
    VSCode: 1.134.0 - C:\Users\user\AppData\Local\Programs\Microsoft VS Code\bin\code.CMD
  npmPackages:
    @playwright/test: 1.63.0 => 1.63.0 
    playwright-core: ^1.43.0 => 1.63.0

Activity

  1. ashrafiucse commented on Sep 22, 2026

    @ashrafiucse
    Contributor

    Confirmed on main with a small variation of the repro — a custom engine whose queryAll gates on a global set via page.evaluate, and click() resolves fine while .highlight() draws nothing.

    The difference between the two is which world they run in. Selectors that use an engine registered without contentScript: true are parsed with world: 'main', so actions evaluate them in the main world where window.selectorEngineEnabled (or window.sap in the ui5 case) is visible. The HighlightController from #42277 only renders in the utility world though — _resolve() goes through frame.existingContext('utility'), and the injected highlight re-queries the selector there on every animation frame. In the isolated world those globals are undefined, so the engine matches nothing and there's nothing to draw.

    I've just sent #42854 for the sibling #42850 (wrong-frame highlights) — this one is a separate defect and still reproduces with that fix applied. The plan here is to apply each highlight in the world its selector resolved to (the resolution step already computes info.world), and to make hideHighlights() clear both worlds, since the screenshotter relies on that before capturing. Happy to take this one unless someone is already on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions