Skip to content

Commit 99f62f9

Browse files
Meir017kblok
authored andcommitted
Remove dynamic evaluate functions (#167)
1 parent 362bbee commit 99f62f9

File tree

7 files changed

+152
-42
lines changed

7 files changed

+152
-42
lines changed

lib/PuppeteerSharp.Tests/Frame/WaitForSelectorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,4 @@ public async Task ShouldReturnTheElementHandle()
214214
Assert.Equal("anything", await Page.EvaluateFunctionAsync<string>("x => x.textContent", await waitForSelector));
215215
}
216216
}
217-
}
217+
}

lib/PuppeteerSharp.Tests/Page/CloseTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ public async Task ShouldRejectAllPromisesWhenPageIsClosed()
1111
{
1212
var newPage = await Browser.NewPageAsync();
1313
var neverResolves = newPage.EvaluateFunctionAsync("() => new Promise(r => {})");
14-
14+
1515
// Put into a var to avoid warning
1616
var t = newPage.CloseAsync();
1717

1818
var exception = await Assert.ThrowsAsync<TargetClosedException>(async () => await neverResolves);
19-
19+
2020
Assert.Contains("Protocol error", exception.Message);
2121
}
2222
}

lib/PuppeteerSharp.Tests/Page/CookiesTests.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ public async Task ShouldGetAndSetCookies()
1414
await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html");
1515
Assert.Empty(await Page.GetCookiesAsync());
1616

17-
await Page.EvaluateFunctionAsync(@"() =>
18-
{
19-
document.cookie = 'username=John Doe';
20-
}");
17+
await Page.EvaluateExpressionAsync("document.cookie = 'username=John Doe'");
2118
var cookie = Assert.Single(await Page.GetCookiesAsync());
2219
Assert.Equal("username", cookie.Name);
2320
Assert.Equal("John Doe", cookie.Value);

lib/PuppeteerSharp.Tests/Page/EvaluateTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,19 @@ public async Task ShouldProperlySerializeNullFields()
9494
Assert.True(result.ContainsKey("a"));
9595
Assert.Null(result["a"]);
9696
}
97+
98+
[Fact]
99+
public async Task EvaluateExpressionBigObject()
100+
{
101+
var window = await Page.EvaluateExpressionAsync("window");
102+
Assert.Null(window);
103+
}
104+
105+
[Fact]
106+
public async Task EvaluateFunctionBigObject()
107+
{
108+
var window = await Page.EvaluateFunctionAsync("() => window");
109+
Assert.Null(window);
110+
}
97111
}
98112
}

lib/PuppeteerSharp/ExecutionContext.cs

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.Threading.Tasks;
44
using System.Linq;
5-
using Newtonsoft.Json.Linq;
65

76
namespace PuppeteerSharp
87
{
@@ -24,27 +23,63 @@ public ExecutionContext(Session client, ContextPayload contextPayload, Func<dyna
2423
public string FrameId { get; internal set; }
2524
public bool IsDefault { get; internal set; }
2625

27-
public async Task<object> EvaluateExpressionAsync(string script)
28-
=> await EvaluateExpressionAsync<object>(script);
29-
30-
public async Task<T> EvaluateExpressionAsync<T>(string script)
31-
{
32-
var handle = await EvaluateExpressionHandleAsync(script);
33-
var result = await handle.JsonValue<T>();
34-
await handle.Dispose();
35-
return result;
36-
}
37-
38-
public async Task<object> EvaluateFunctionAsync(string script, params object[] args)
39-
=> await EvaluateFunctionAsync<object>(script, args);
40-
41-
public async Task<T> EvaluateFunctionAsync<T>(string script, params object[] args)
42-
{
43-
var handle = await EvaluateFunctionHandleAsync(script, args);
44-
var result = await handle.JsonValue<T>();
45-
await handle.Dispose();
46-
return result;
47-
}
26+
/// <summary>
27+
/// Executes a script in browser context
28+
/// </summary>
29+
/// <param name="script">Script to be evaluated in browser context</param>
30+
/// <remarks>
31+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
32+
/// </remarks>
33+
/// <seealso cref="EvaluateFunctionAsync(string, object[])"/>
34+
/// <seealso cref="EvaluateExpressionHandleAsync(string)"/>
35+
/// <returns>Task which resolves to script return value</returns>
36+
public Task<object> EvaluateExpressionAsync(string script)
37+
=> EvaluateExpressionAsync<object>(script);
38+
39+
/// <summary>
40+
/// Executes a script in browser context
41+
/// </summary>
42+
/// <typeparam name="T">The type to deserialize the result to</typeparam>
43+
/// <param name="script">Script to be evaluated in browser context</param>
44+
/// <remarks>
45+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
46+
/// </remarks>
47+
/// <seealso cref="EvaluateFunctionAsync{T}(string, object[])"/>
48+
/// <seealso cref="EvaluateExpressionHandleAsync(string)"/>
49+
/// <returns>Task which resolves to script return value</returns>
50+
public Task<T> EvaluateExpressionAsync<T>(string script)
51+
=> EvaluateAsync<T>(EvaluateExpressionHandleAsync(script));
52+
53+
/// <summary>
54+
/// Executes a function in browser context
55+
/// </summary>
56+
/// <param name="script">Script to be evaluated in browser context</param>
57+
/// <param name="args">Arguments to pass to script</param>
58+
/// <remarks>
59+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
60+
/// <see cref="JSHandle"/> instances can be passed as arguments
61+
/// </remarks>
62+
/// <seealso cref="EvaluateExpressionAsync(string)"/>
63+
/// <seealso cref="EvaluateFunctionHandleAsync(string, object[])"/>
64+
/// <returns>Task which resolves to script return value</returns>
65+
public Task<object> EvaluateFunctionAsync(string script, params object[] args)
66+
=> EvaluateFunctionAsync<object>(script, args);
67+
68+
/// <summary>
69+
/// Executes a function in browser context
70+
/// </summary>
71+
/// <typeparam name="T">The type to deserialize the result to</typeparam>
72+
/// <param name="script">Script to be evaluated in browser context</param>
73+
/// <param name="args">Arguments to pass to script</param>
74+
/// <remarks>
75+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
76+
/// <see cref="JSHandle"/> instances can be passed as arguments
77+
/// </remarks>
78+
/// <seealso cref="EvaluateExpressionAsync{T}(string)"/>
79+
/// <seealso cref="EvaluateFunctionHandleAsync(string, object[])"/>
80+
/// <returns>Task which resolves to script return value</returns>
81+
public Task<T> EvaluateFunctionAsync<T>(string script, params object[] args)
82+
=> EvaluateAsync<T>(EvaluateFunctionHandleAsync(script, args));
4883

4984
internal async Task<JSHandle> EvaluateExpressionHandleAsync(string script)
5085
{
@@ -79,6 +114,16 @@ internal async Task<JSHandle> EvaluateFunctionHandleAsync(string script, params
79114
});
80115
}
81116

117+
private async Task<T> EvaluateAsync<T>(Task<JSHandle> handleEvaluator)
118+
{
119+
var handle = await handleEvaluator;
120+
var result = await handle.JsonValue<T>()
121+
.ContinueWith(jsonTask => jsonTask.Exception != null ? default(T) : jsonTask.Result);
122+
123+
await handle.Dispose();
124+
return result;
125+
}
126+
82127
private async Task<JSHandle> EvaluateHandleAsync(string method, dynamic args)
83128
{
84129
dynamic response = await _client.SendAsync(method, args);
@@ -136,6 +181,5 @@ public async Task<dynamic> QueryObjects(JSHandle prototypeHandle)
136181

137182
return ObjectHandleFactory(response.objects);
138183
}
139-
140184
}
141-
}
185+
}

lib/PuppeteerSharp/Frame.cs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Threading.Tasks;
4-
using PuppeteerSharp.Input;
54

65
namespace PuppeteerSharp
76
{
@@ -50,24 +49,66 @@ public Frame(Session client, Page page, Frame parentFrame, string frameId)
5049

5150
#region Public Methods
5251

52+
/// <summary>
53+
/// Executes a script in browser context
54+
/// </summary>
55+
/// <param name="script">Script to be evaluated in browser context</param>
56+
/// <remarks>
57+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
58+
/// </remarks>
59+
/// <seealso cref="EvaluateFunctionAsync(string, object[])"/>
60+
/// <returns>Task which resolves to script return value</returns>
5361
public async Task<dynamic> EvaluateExpressionAsync(string script)
5462
{
5563
var context = await GetExecutionContextAsync();
5664
return await context.EvaluateExpressionAsync(script);
5765
}
5866

67+
/// <summary>
68+
/// Executes a script in browser context
69+
/// </summary>
70+
/// <typeparam name="T">The type to deserialize the result to</typeparam>
71+
/// <param name="script">Script to be evaluated in browser context</param>
72+
/// <remarks>
73+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
74+
/// </remarks>
75+
/// <seealso cref="EvaluateFunctionAsync{T}(string, object[])"/>
76+
/// <returns>Task which resolves to script return value</returns>
5977
public async Task<T> EvaluateExpressionAsync<T>(string script)
6078
{
6179
var context = await GetExecutionContextAsync();
6280
return await context.EvaluateExpressionAsync<T>(script);
6381
}
6482

83+
/// <summary>
84+
/// Executes a function in browser context
85+
/// </summary>
86+
/// <param name="script">Script to be evaluated in browser context</param>
87+
/// <param name="args">Arguments to pass to script</param>
88+
/// <remarks>
89+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
90+
/// <see cref="JSHandle"/> instances can be passed as arguments
91+
/// </remarks>
92+
/// <seealso cref="EvaluateExpressionAsync(string)"/>
93+
/// <returns>Task which resolves to script return value</returns>
6594
public async Task<dynamic> EvaluateFunctionAsync(string script, params object[] args)
6695
{
6796
var context = await GetExecutionContextAsync();
6897
return await context.EvaluateFunctionAsync(script, args);
6998
}
7099

100+
/// <summary>
101+
/// Executes a function in browser context
102+
/// </summary>
103+
/// <typeparam name="T">The type to deserialize the result to</typeparam>
104+
/// <param name="script">Script to be evaluated in browser context</param>
105+
/// <param name="args">Arguments to pass to script</param>
106+
/// <remarks>
107+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
108+
/// <see cref="JSHandle"/> instances can be passed as arguments
109+
/// </remarks>
110+
/// <seealso cref="EvaluateExpressionAsync{T}(string)"/>
111+
/// <returns>Task which resolves to script return value</returns>
71112
public async Task<T> EvaluateFunctionAsync<T>(string script, params object[] args)
72113
{
73114
var context = await GetExecutionContextAsync();
@@ -122,28 +163,25 @@ internal Task<ElementHandle> AddScriptTag(dynamic options)
122163
throw new NotImplementedException();
123164
}
124165

125-
internal async Task<string> GetContentAsync()
126-
{
127-
return await EvaluateFunctionAsync<string>(@"() => {
166+
internal Task<string> GetContentAsync()
167+
=> EvaluateFunctionAsync<string>(@"() => {
128168
let retVal = '';
129169
if (document.doctype)
130170
retVal = new XMLSerializer().serializeToString(document.doctype);
131171
if (document.documentElement)
132172
retVal += document.documentElement.outerHTML;
133173
return retVal;
134174
}");
135-
}
136175

137-
internal async Task SetContentAsync(string html)
138-
{
139-
await EvaluateFunctionAsync(@"html => {
176+
internal Task SetContentAsync(string html)
177+
=> EvaluateFunctionAsync(@"html => {
140178
document.open();
141179
document.write(html);
142180
document.close();
143181
}", html);
144-
}
145182

146-
internal async Task<string> GetTitleAsync() => await EvaluateExpressionAsync<string>("document.title");
183+
184+
internal Task<string> GetTitleAsync() => EvaluateExpressionAsync<string>("document.title");
147185

148186
internal void OnLifecycleEvent(string loaderId, string name)
149187
{

lib/PuppeteerSharp/Page.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,29 @@ public async Task<ElementHandle> GetElementAsync(string selector)
155155
public async Task<IEnumerable<ElementHandle>> GetElementsAsync(string selector)
156156
=> await MainFrame.GetElementsAsync(selector);
157157

158+
/// <summary>
159+
/// Executes a script in browser context
160+
/// </summary>
161+
/// <param name="script">Script to be evaluated in browser context</param>
162+
/// <remarks>
163+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
164+
/// </remarks>
165+
/// <returns>Task which resolves to script return value</returns>
158166
public async Task<JSHandle> EvaluateExpressionHandleAsync(string script)
159167
{
160168
var context = await MainFrame.GetExecutionContextAsync();
161169
return await context.EvaluateExpressionHandleAsync(script);
162170
}
163171

172+
/// <summary>
173+
/// Executes a script in browser context
174+
/// </summary>
175+
/// <param name="script">Script to be evaluated in browser context</param>
176+
/// <remarks>
177+
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
178+
/// <see cref="JSHandle"/> instances can be passed as arguments
179+
/// </remarks>
180+
/// <returns>Task which resolves to script return value</returns>
164181
public async Task<JSHandle> EvaluateFunctionHandleAsync(string pageFunction, params object[] args)
165182
{
166183
var context = await MainFrame.GetExecutionContextAsync();
@@ -521,7 +538,7 @@ public Task CloseAsync()
521538

522539
return Task.CompletedTask;
523540
}
524-
541+
525542
public Task<dynamic> EvaluateExpressionAsync(string script)
526543
=> _frameManager.MainFrame.EvaluateExpressionAsync(script);
527544

0 commit comments

Comments
 (0)