Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Playwright.Tests/InterceptionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ bool URLMatches(string baseURL, string url, string glob)
Assert.True(URLMatches("http://playwright.dev/", "file://path/to/file", "file://**"));
}

// See https://github.com/microsoft/playwright-dotnet/issues/3433
[PlaywrightTest]
public void ShouldReplaceOnlyTheSchemeOfAWebSocketBaseURL()
{
Assert.AreEqual("ws://app/proxy?to=http://api", URLMatch.ToWebSocketBaseURL("http://app/proxy?to=http://api"));
Assert.AreEqual("wss://app/proxy?to=https://api", URLMatch.ToWebSocketBaseURL("https://app/proxy?to=https://api"));

// A base URL that has another URL in its path still matches a relative glob.
var matcher = new URLMatch() { baseURL = "http://app/proxy/http://api/", glob = "./socket", isWebSocketUrl = true };
Assert.True(matcher.Match("ws://app/proxy/http://api/socket"));
}

[PlaywrightTest("interception.spec.ts", "should intercept by glob")]
public async Task ShouldInterceptByGlob()
{
Expand Down
14 changes: 14 additions & 0 deletions src/Playwright.Tests/PageEvaluateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -847,4 +847,18 @@ public async Task ShouldParsePublicFields()
Assert.AreEqual(400, result.Height);
Assert.AreEqual(0, ShapeWithFields.Count);
}

// See https://github.com/microsoft/playwright-dotnet/issues/3437
[PlaywrightTest]
public async Task ShouldTransferMessagesLargerThanTheReadBuffer()
{
// 3 MB of text that differs at every position, so that a chunk lost, repeated or put
// out of order while the message is read from the driver would show. Its size is not
// a multiple of the read buffer, and it goes both ways.
var expected = string.Join("|", Enumerable.Range(0, 300_001).Select(i => i.ToString("D9", System.Globalization.CultureInfo.InvariantCulture)));
var fromPage = await Page.EvaluateAsync<string>("() => Array.from({ length: 300001 }, (_, i) => String(i).padStart(9, '0')).join('|')");
Assert.AreEqual(expected, fromPage);
var echoed = await Page.EvaluateAsync<string>("s => s", expected);
Assert.AreEqual(expected, echoed);
}
}
1 change: 1 addition & 0 deletions src/Playwright/Core/Locator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

namespace Microsoft.Playwright.Core;

[DebuggerDisplay("Locator@{_selector,nq}")]
internal class Locator : ILocator
{
internal readonly Frame _frame;
Expand Down
3 changes: 2 additions & 1 deletion src/Playwright/Helpers/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ string getArgs(string? args)
{
return !string.IsNullOrEmpty(args) ? $"\"{cliEntrypoint}\" {args}" : cliEntrypoint;
}
var nodePath = Environment.GetEnvironmentVariable("PLAYWRIGHT_NODEJS_PATH");
return (
Environment.GetEnvironmentVariable("PLAYWRIGHT_NODEJS_PATH") ?? Path.GetFullPath(Path.Combine(driversPath, ".playwright", "node", platformId, nodeExecutable)),
!string.IsNullOrEmpty(nodePath) ? nodePath : Path.GetFullPath(Path.Combine(driversPath, ".playwright", "node", platformId, nodeExecutable)),
getArgs);
}
}
7 changes: 4 additions & 3 deletions src/Playwright/Helpers/URLMatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,15 @@ internal static string ConstructURLBasedOnBaseURL(string? baseUrl, string url)
{
return baseURL;
}
// Allow http(s) baseURL to match ws(s) urls.
// Allow http(s) baseURL to match ws(s) urls. Only the scheme changes: the rest of the
// URL may contain another URL, in its path or in its query.
if (baseURL.StartsWith("http://"))
{
return baseURL.Replace("http://", "ws://");
return "ws://" + baseURL.Substring("http://".Length);
}
if (baseURL.StartsWith("https://"))
{
return baseURL.Replace("https://", "wss://");
return "wss://" + baseURL.Substring("https://".Length);
}
return baseURL;
}
Expand Down
9 changes: 7 additions & 2 deletions src/Playwright/Transport/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ internal class Connection : IDisposable
internal const string ErrorDetailsDataKey = "playwright.errorDetails";
internal const string LogDataKey = "playwright.log";

// The value of the DEBUG environment variable when the last connection was created.
private static volatile string? _debugLogLevels;

private readonly ConcurrentDictionary<string, ConnectionCallback> _callbacks = new();
private readonly Root _rootObject;
private readonly TaskQueue _queue = new();
Expand All @@ -59,6 +62,8 @@ internal class Connection : IDisposable

public Connection(LocalUtils? localUtils = null)
{
// Read here and not for every message. The driver also reads DEBUG once, when it starts.
_debugLogLevels = Environment.GetEnvironmentVariable("DEBUG");
_rootObject = new(null, this, string.Empty);
LocalUtils = localUtils;

Expand Down Expand Up @@ -513,12 +518,12 @@ private void Dispose(bool disposing)

internal static void TraceMessage(string logLevel, byte[] rawMessage)
{
string actualLogLevel = Environment.GetEnvironmentVariable("DEBUG");
string? actualLogLevel = _debugLogLevels;
if (string.IsNullOrEmpty(actualLogLevel))
{
return;
}
if (!actualLogLevel.Contains(logLevel))
if (!actualLogLevel!.Contains(logLevel))
{
return;
}
Expand Down
4 changes: 3 additions & 1 deletion src/Playwright/Transport/StdIOTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ namespace Microsoft.Playwright.Transport;

internal class StdIOTransport : IDisposable
{
private const int DefaultBufferSize = 1024; // Byte buffer size
// One read takes what the pipe holds, up to this size. A pipe holds 64 KB on Linux and macOS,
// so a message of 10 MB arrives in about 160 reads.
private const int DefaultBufferSize = 64 * 1024;
private readonly Process _process;
private readonly CancellationTokenSource _readerCancellationSource = new();
private readonly Task _getResponseTask;
Expand Down
Loading