Skip to content

v19.0.0

Compare
Choose a tag to compare
@kblok kblok released this 20 Aug 12:34
· 35 commits to master since this release
9aa23f3

Welcome System.Text.Json and AOT support!

What's new

Full AOT Support.

v19 comes with one of the most significant changes made to this library. We are moving away from Newtonsoft JSON in favor of System.Text.Json. The motivation behind this change is that it would get us closer to AOT support.

If you are using your own classes to interact with the browser through EvaluateFunctionAsync or similar, you will have to provide your own JsonSerializerContext to puppeteer using the static Puppeteer.ExtraJsonSerializerContext property.

For instance.

Puppeteer.ExtraJsonSerializerContext = DemoJsonSerializationContext.Default;
await using var browser = await Puppeteer.LaunchAsync();
await using var page = await browser.NewPageAsync();
var result = await page.EvaluateFunctionAsync<TestClass>("test => test", new TestClass { Name = "Dario"});
Console.WriteLine($"Name evaluated to {result.Name}");

The serializer would look like this:

public class TestClass
{
    public string Name { get; set; }
}

[JsonSerializable(typeof(TestClass))]
public partial class DemoJsonSerializationContext : JsonSerializerContext
{}

For more information about JsonSerializerContext see How to use source generation in System.Text.Json.

Breaking changes

JSON is critical for PuppeteerSharp. It's how we communicate with the browser, so changing the library used to perform this communication is quite risky.
Newtonsoft JSON classes were also used in our API, so your code might have some breaking changes.

Newtonsoft's JToken was replaced with JsonElement

JToken was the default type for functions like EvaluationFunctionAsync, EvaluateExpressionAsync or JsonAsync, when the generic function was not used.

Before:

var objectPopulated = await Page.EvaluateExpressionAsync("var obj = {a:1}; obj;");
Assert.AreEqual(1, objectPopulated["a"]);

Now:

var objectPopulated = await Page.EvaluateExpressionAsync("var obj = {a:1}; obj;");
Assert.AreEqual(1, objectPopulated.Value.GetProperty("a").GetInt32());

Use JsonElement instead of object

I found that it's easy to consume JsonElement instead of objects that are really JsonElements.

Before

var result = await Page.EvaluateExpressionAsync<object[]>("result");
Assert.AreEqual("Meta", result[0]);
Assert.AreEqual("MetaLeft", result[1]);
Assert.AreEqual(true, result[2]);

After

var result = await Page.EvaluateExpressionAsync<JsonElement[]>("result");
Assert.AreEqual("Meta", result[0].GetString());
Assert.AreEqual("MetaLeft", result[1].GetString());
Assert.AreEqual(true, result[2].GetBoolean());

Aria selector changes

Previously, Puppeteer incorrectly normalized whitespaces in ARIA selectors in a way that did not not allow distinguishing between the following two HTML structures:

<p>  text<p>
<p><span>&nbsp;</span><span>&nbsp;</span>text<p>

In the first case, the spaces are not part of the element's textual content, and the element should be found via aria/text.

In the second case, the spaces are part of the p element and the query aria/\u00A0\u00A0text should find it while aria/text should not. The whitespace normalization in Puppeteer would previously prevent searching for the element with whitespaces in the textual content.

Related: the step 2.F of https://www.w3.org/TR/accname-1.2/#computation-steps defines how child elements contribute to the parent element's computed name.

If you need the old behavior, apply selector.replace(/ +/g, ' ').trim() to your ARIA selector.

IgnoreHTTPErrors was renamed to AcceptInsecureCerts

This change will get us closer to WebDriver Bidi Support.