Skip to content

[Bug]: page.evaluate with exposeFunctions and world: "utility" fails with an internal TypeError #42686

Description

Filing this as an issue as asked in #42649.

Version

1.64.0-next. Originally reproduced at aeebee1d2; packages/playwright-core/src/client/jsHandle.ts has not been touched since that commit, so it still applies.

Steps to reproduce

exposeFunctions and the world option added in #42635 cannot be combined, but passing both crashes inside the injected code rather than saying so.

await page.evaluate(async ({ cb }) => await cb(17), { cb: x => x * 2 },
    { exposeFunctions: true, world: 'utility' });
// page.evaluate: TypeError: Cannot read properties of undefined (reading 'callBinding')

Same error from frame.evaluate and locator.evaluate. Reproduced on chromium, firefox and webkit.

Why it happens

PageBinding.createInitScript installs the bindings controller as an init script, and init scripts only run in the main world, so globalThis[kBindingsControllerProperty] is undefined in the utility world. Runtime.addBinding is registered without a world, so the transport is there but the controller that dispatches through it is not.

That also makes a documented claim false. docs/src/api/params.md says an exposed function is "technically accessible from all frames and worlds of the page", in both js-evaluate-expose-functions and js-init-script-expose-functions:

await page.exposeFunction('f', x => x * 2);
await page.evaluate(() => window.f?.(21) ?? 'NOT PRESENT');                                   // 42
await page.evaluate(() => window.f?.(21) ?? 'NOT PRESENT', undefined, { world: 'utility' });  // 'NOT PRESENT'

Possible directions

Either make bindings reachable from the utility world, or reject the combination with a clear error the way JSHandleDispatcher.evaluateExpression already does for a world it cannot serve. Either way the two doc sentences want correcting, since they promise worlds today.

I had a patch for the second option in #42649 with the guard in assertEvaluateOptions, which every evaluate entry point already calls, plus the doc correction and one test. Happy to reopen that, rework it toward the first option, or leave it entirely, whichever you prefer. I have no view on which layer you want this solved at.

I am a freshman in college trying to make myself useful on real projects, so if I have misread the intent here just say and I will drop it.

Activity

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