<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: [v1.35]</li>
<li>Operating System: Windows 10</li>
<li>Browser: Chromium</li>
<li>Other info: Tested in both .NET 6 and .NET 7 project in Visual Studio 2022 17.6.4</li>
</ul>
<h3 dir="auto">Source code</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[TestFixture]
public class PlaywrightPOCTest
{
    private static IPlaywright playwright;
    private static IBrowser browser;
    private static IBrowserContext context;
    private static IPage page;

    [OneTimeSetUp]
    public static async Task DownloadBrowsers()
    {
        var exitCode = Microsoft.Playwright.Program.Main(new[] { &quot;install&quot; });
        if (exitCode != 0)
        {
            throw new Exception($&quot;Playwright exited with code {exitCode}&quot;);
        }

        playwright = await Playwright.CreateAsync();
    }

    [OneTimeSetUp]
    public static async Task EdgeDriverInitialize()
    {
        browser = await playwright.Chromium.LaunchAsync(
            new BrowserTypeLaunchOptions 
            { Channel = &quot;msedge&quot;, Headless = true, /*SlowMo = 2000 */}
            );

        context = await browser.NewContextAsync(); 

        page = await context.NewPageAsync();
    }

    [Test]
    public static async Task PlaywrightFileUpload()
    {
        var frame = page.MainFrame;

        await frame.GotoAsync(@&quot;http://www.fileconvoy.com/&quot;);
        Console.Log($&quot;Memory usage before upload: {System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64}&quot;);
        await frame.Locator(&quot;id=upfile_0&quot;).SetInputFilesAsync(@&quot;C:\Users\testuser\Downloads\19588.pdf&quot;);
        Console.Log($&quot;Memory usage after upload: {System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64}&quot;);
        await frame.Locator(&quot;id=readTermsOfUse&quot;).CheckAsync();
        await frame.GetByRole(AriaRole.Button).GetByText(&quot;Upload&quot;).ClickAsync();
        Console.Log($&quot;Memory usage after page navigation: {System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64}&quot;);
    }

    [OneTimeTearDown]
    public static async Task EdgeDriverCleanup()
    {
        await context?.CloseAsync();
        await browser?.CloseAsync();
        playwright.Dispose();
    }
}"><pre class="notranslate"><code class="notranslate">[TestFixture]
public class PlaywrightPOCTest
{
    private static IPlaywright playwright;
    private static IBrowser browser;
    private static IBrowserContext context;
    private static IPage page;

    [OneTimeSetUp]
    public static async Task DownloadBrowsers()
    {
        var exitCode = Microsoft.Playwright.Program.Main(new[] { "install" });
        if (exitCode != 0)
        {
            throw new Exception($"Playwright exited with code {exitCode}");
        }

        playwright = await Playwright.CreateAsync();
    }

    [OneTimeSetUp]
    public static async Task EdgeDriverInitialize()
    {
        browser = await playwright.Chromium.LaunchAsync(
            new BrowserTypeLaunchOptions 
            { Channel = "msedge", Headless = true, /*SlowMo = 2000 */}
            );

        context = await browser.NewContextAsync(); 

        page = await context.NewPageAsync();
    }

    [Test]
    public static async Task PlaywrightFileUpload()
    {
        var frame = page.MainFrame;

        await frame.GotoAsync(@"http://www.fileconvoy.com/");
        Console.Log($"Memory usage before upload: {System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64}");
        await frame.Locator("id=upfile_0").SetInputFilesAsync(@"C:\Users\testuser\Downloads\19588.pdf");
        Console.Log($"Memory usage after upload: {System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64}");
        await frame.Locator("id=readTermsOfUse").CheckAsync();
        await frame.GetByRole(AriaRole.Button).GetByText("Upload").ClickAsync();
        Console.Log($"Memory usage after page navigation: {System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64}");
    }

    [OneTimeTearDown]
    public static async Task EdgeDriverCleanup()
    {
        await context?.CloseAsync();
        await browser?.CloseAsync();
        playwright.Dispose();
    }
}
</code></pre></div>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I provided exact source code that allows reproducing the issue locally.</li>
</ul>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>Download this ~30MB PDF from here: <a href="https://research.nhm.org/pdfs/19588/19588.pdf" rel="nofollow">https://research.nhm.org/pdfs/19588/19588.pdf</a></li>
<li>Update path in SetInputFilesAsync() method to your file location</li>
<li>Run PlaywrightFileUpload() test</li>
</ul>
<p dir="auto"><strong>Expected</strong></p>
<p dir="auto">I would expect memory usage to increase temporarily by the uploaded filesize (~30MB) and then go away or be cleaned up fairly soon after page navigation occurs.</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto">Memory usage jumps from about 40MB to &gt;700MB just from the file upload and persists for quite a long time in other tests which do not involve file uploads. Sometimes I can get it to drop by forcing a GC using GC.Collect() several minutes later, but I definitely should not be doing that.</p>
<p dir="auto">This has had an impact on long running scenarios where we are doing a file upload as the first dependency and then running several tests on a web app after the upload. It also affects concurrent runs in our framework due to out of memory issues. Fwiw, I took a memory snapshot inside VS, and it shows up as a large number of dead char[] objects which are outside of my code.</p>
<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: 1.35.1</li>
<li>Operating System: macOs 13.4 (22F66)</li>
<li>Browser: Chrome</li>
<li>Other info: UI mode</li>
</ul>
<h3 dir="auto">Source code</h3>
<p dir="auto"><strong>Config file</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// playwright.config.ts
import type { PlaywrightTestConfig } from '@playwright/test';

const config: PlaywrightTestConfig = {
  testDir: 'tests',
};

export default config;"><pre class="notranslate"><span class="pl-c">// playwright.config.ts</span>
<span class="pl-k">import</span> <span class="pl-s1">type</span> <span class="pl-kos">{</span> <span class="pl-v">PlaywrightTestConfig</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'@playwright/test'</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">config</span>: <span class="pl-v">PlaywrightTestConfig</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">testDir</span>: <span class="pl-s">'tests'</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-s1">config</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">(edited to add <code class="notranslate">export default config;</code> which I forgot to copy across initially)</p>
<p dir="auto"><strong>Test file (self-contained)</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="test.only('exceptions inside a test are swallowed', async () =&gt; {
  expect(1).toBe(1); // this is reached and displayed in UI mode
  try {
    undefinedVariable1 = 'this throws an exception';
  } catch (e) {
    expect(e).toBeTruthy(); // this is reached and displayed in UI mode
  }
  undefinedVariable1 = 'this throws an exception';
  expect(1).toBe(1); // never reached, no indication of what went wrong
});"><pre class="notranslate"><span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">only</span><span class="pl-kos">(</span><span class="pl-s">'exceptions inside a test are swallowed'</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-en">expect</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBe</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// this is reached and displayed in UI mode</span>
  <span class="pl-k">try</span> <span class="pl-kos">{</span>
    <span class="pl-s1">undefinedVariable1</span> <span class="pl-c1">=</span> <span class="pl-s">'this throws an exception'</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBeTruthy</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// this is reached and displayed in UI mode</span>
  <span class="pl-kos">}</span>
  <span class="pl-s1">undefinedVariable1</span> <span class="pl-c1">=</span> <span class="pl-s">'this throws an exception'</span><span class="pl-kos">;</span>
  <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBe</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// never reached, no indication of what went wrong</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 test in UI mode</li>
<li>Observe that the test fails</li>
<li>Observe that you are not told why it fails</li>
</ul>
<p dir="auto"><strong>Expected</strong></p>
<p dir="auto">Ideally:</p>
<ul dir="auto">
<li>We should see that the test itself threw an exception</li>
<li>We should see the content of the exception (eg <code class="notranslate">ReferenceError: undefinedVariable1 is not defined</code>)</li>
<li>We should see the line of code where the exception was thrown</li>
</ul>
<p dir="auto">Note: if you run the tests on the command line, you do get helpful output:<br>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/19584280/247822966-956112b7-a03d-4243-b90e-cd8d2058e570.png"><img width="716" alt="Screenshot 2023-06-22 at 2 29 09 pm" src="https://user-images.githubusercontent.com/19584280/247822966-956112b7-a03d-4243-b90e-cd8d2058e570.png" style="max-width: 100%;"></a></p>
<p dir="auto"><strong>Actual</strong></p>
<ul dir="auto">
<li>The test is marked as failing</li>
<li>But, there is no explanation why it failed</li>
</ul>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/19584280/247823191-1e56e713-0b82-4c32-acec-4346aa998d1a.png"><img width="648" alt="247822621-ba7d9040-383a-42b4-af64-00e3a7b60c31" src="https://user-images.githubusercontent.com/19584280/247823191-1e56e713-0b82-4c32-acec-4346aa998d1a.png" style="max-width: 100%;"></a>