I have a series of async page.evaluate()
functions that I want to run before each page starts executing its own javascript. The page class provides something similar to inject a javascript file to each page / before before the client code is executed via page.add_init_script(script[, arg])
). I'm trying to replicate that same logic via pure python.
A naive hook into frameattached and framenavigated works if the function quickly executes, but as soon as the async is actually awaiting it continues to evaluate the page script. Is there a way to block the frame from processing client-side javascript until handle_frame
has returned?
Working code (sans race condition):
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
async def handle_frame(frame):
await sleep(4)
await frame.evaluate("Math.random = () => 42;")
page.on("frameattached", handle_frame)
page.on("framenavigated", handle_frame)
await page.goto("about:blank")
random_value = await page.evaluate("Math.random()")
print(random_value) # == 42
Non-Working code:
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
async def handle_frame(frame):
await frame.evaluate("Math.random = () => 42;")
page.on("frameattached", handle_frame)
page.on("framenavigated", handle_frame)
await page.goto("about:blank")
random_value = await page.evaluate("Math.random()")
print(random_value) # == 0.63 ie. random