<p dir="auto">I have noticed on several websites, that exposed functions are not working. Below is a working example of this issue on one URL. If you need more URLs where this occurs, just comment and I'll provide.</p>
<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: Version 1.32.3</li>
<li>Operating System: Tested on Ubuntu 22.04</li>
<li>Browser: Chromium</li>
<li>Other info:</li>
</ul>
<h3 dir="auto">Source code</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I provided exact source code that allows reproducing the issue locally.</li>
</ul>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// repro.js
const { chromium } = require('playwright');

(async () =&gt; {
  function testInitScript(){
    if(window !== window.top) {
       return; // only run init script on root
    }

    setTimeout(function(){
        window.TestExposedFunction('This is a test');
    }, 2000);

  }
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();
  await page.exposeFunction(&quot;TestExposedFunction&quot;, (text) =&gt; console.log('TestExposedFunction', text));
  await page.addInitScript(testInitScript);

  await page.goto(&quot;https://essen.vienna.at/&quot;); // ⬅️ This will cause an exception in the browser when calling the TestExposedFunction
  //await page.goto(&quot;https://www.google.com/&quot;); // ⬅️ This will work just fine, and console.log the TestExposedFunction text

  await new Promise(resolve =&gt; setTimeout(resolve, 10000)); // Poor man's way of being able to wait a bit with the browser open
  
  await browser.close();
})();"><pre class="notranslate"><span class="pl-c">// repro.js</span>
<span class="pl-k">const</span> <span class="pl-kos">{</span> chromium <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'playwright'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">function</span> <span class="pl-en">testInitScript</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">{</span>
    <span class="pl-k">if</span><span class="pl-kos">(</span><span class="pl-smi">window</span> <span class="pl-c1">!==</span> <span class="pl-smi">window</span><span class="pl-kos">.</span><span class="pl-c1">top</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
       <span class="pl-k">return</span><span class="pl-kos">;</span> <span class="pl-c">// only run init script on root</span>
    <span class="pl-kos">}</span>

    <span class="pl-en">setTimeout</span><span class="pl-kos">(</span><span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">{</span>
        <span class="pl-smi">window</span><span class="pl-kos">.</span><span class="pl-en">TestExposedFunction</span><span class="pl-kos">(</span><span class="pl-s">'This is a test'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-c1">2000</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-kos">}</span>
  <span class="pl-k">const</span> <span class="pl-s1">browser</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">chromium</span><span class="pl-kos">.</span><span class="pl-en">launch</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">headless</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">const</span> <span class="pl-s1">page</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">browser</span><span class="pl-kos">.</span><span class="pl-en">newPage</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">exposeFunction</span><span class="pl-kos">(</span><span class="pl-s">"TestExposedFunction"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">text</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'TestExposedFunction'</span><span class="pl-kos">,</span> <span class="pl-s1">text</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">addInitScript</span><span class="pl-kos">(</span><span class="pl-s1">testInitScript</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s">"https://essen.vienna.at/"</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// ⬅️ This will cause an exception in the browser when calling the TestExposedFunction</span>
  <span class="pl-c">//await page.goto("https://www.google.com/"); // ⬅️ This will work just fine, and console.log the TestExposedFunction text</span>

  <span class="pl-k">await</span> <span class="pl-k">new</span> <span class="pl-v">Promise</span><span class="pl-kos">(</span><span class="pl-s1">resolve</span> <span class="pl-c1">=&gt;</span> <span class="pl-en">setTimeout</span><span class="pl-kos">(</span><span class="pl-s1">resolve</span><span class="pl-kos">,</span> <span class="pl-c1">10000</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Poor man's way of being able to wait a bit with the browser open</span>
  
  <span class="pl-k">await</span> <span class="pl-s1">browser</span><span class="pl-kos">.</span><span class="pl-en">close</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>Run the repro.js (<code class="notranslate">node repro.js</code>) with each page.goto()</li>
</ul>
<p dir="auto"><strong>Expected</strong></p>
<ul dir="auto">
<li>Both URLs should give the same result (logging 'TestExposedFunction' with the text)</li>
</ul>
<p dir="auto"><strong>Actual</strong></p>
<ul dir="auto">
<li>
<p dir="auto">essen.vienna.at does not console.log, but instead throw below exception:<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/1552175/232809385-36cfa090-9600-4293-8e96-a12cfd7196e1.png"><img src="https://user-images.githubusercontent.com/1552175/232809385-36cfa090-9600-4293-8e96-a12cfd7196e1.png" alt="image" style="max-width: 100%;"></a></p>
</li>
<li>
<p dir="auto">google.com correctly outputs: <code class="notranslate">TestExposedFunction This is a test</code></p>
</li>
</ul>
<p dir="auto">In Playwright's doc, there is great mentioning on Page Object Model. However, when I try to follow this model (using TypeScript), I encounter a problem. For common page components, like menu or navigation bar, which appreas on every page on my website, if I create web elements for them in each page object, there will be lots of duplications.<br>
So what's a good way to implement such common components to avoid duplications?</p>