Skip to content

Commit

Permalink
Set "SA1116" to "Error" and resolved compiler errors (hardkoded#1828)
Browse files Browse the repository at this point in the history
* Set "SA1116" to "Error" and resolved compiler errors.

* Update lib/PuppeteerSharp/ElementHandle.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/ElementHandle.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/ElementHandle.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/ElementHandle.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/Helpers/AsyncMessageQueue.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/JSHandle.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/Page.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Update lib/PuppeteerSharp/DOMWorld.cs

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>

* Corrected trailing whitespace analyzer errors.

Co-authored-by: Darío Kondratiuk <dariokondratiuk@gmail.com>
  • Loading branch information
kgar and kblok authored Oct 4, 2021
1 parent 7775605 commit 62aaa7a
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 136 deletions.
2 changes: 1 addition & 1 deletion lib/PuppeteerSharp.ruleset
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<Rule Id="SA1614" Action="None" /> <!-- Error SA1614: Element parameter documentation should have text (SA1614)-->
<Rule Id="SA1627" Action="None" /> <!-- Error SA1627: The documentation text within the \'exception\' tag should not be empty. (SA1627)-->
<Rule Id="SA1622" Action="None" /> <!-- Error SA1622: Generic type parameter documentation should have text. (SA1622)-->
<Rule Id="SA1116" Action="None" /> <!-- Error SA1116: The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (SA1116)-->
<Rule Id="SA1116" Action="Error" /> <!-- Error SA1116: The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (SA1116)-->
<Rule Id="SA1111" Action="Error" /> <!-- Error SA1111: Closing parenthesis should be on line of last parameter (SA1111)-->
<Rule Id="SA1505" Action="Error" /> <!-- Error SA1505: An opening brace should not be followed by a blank line. (SA1505) -->
<Rule Id="SA1612" Action="Error" /> <!-- Error SA1612: The parameter documentation for 'filePaths' should be at position 2. (SA1612) -->
Expand Down
15 changes: 9 additions & 6 deletions lib/PuppeteerSharp/DOMWorld.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ internal async Task<ElementHandle[]> XPathAsync(string expression)
return value;
}

internal Task<string> GetContentAsync() => EvaluateFunctionAsync<string>(@"() => {
internal Task<string> GetContentAsync() => EvaluateFunctionAsync<string>(
@"() => {
let retVal = '';
if (document.doctype)
retVal = new XMLSerializer().serializeToString(document.doctype);
Expand All @@ -143,11 +144,13 @@ internal async Task SetContentAsync(string html, NavigationOptions options = nul

// We rely upon the fact that document.open() will reset frame lifecycle with "init"
// lifecycle event. @see https://crrev.com/608658
await EvaluateFunctionAsync(@"html => {
document.open();
document.write(html);
document.close();
}", html).ConfigureAwait(false);
await EvaluateFunctionAsync(
@"html => {
document.open();
document.write(html);
document.close();
}",
html).ConfigureAwait(false);

using (var watcher = new LifecycleWatcher(_frameManager, Frame, waitUntil, timeout))
{
Expand Down
108 changes: 58 additions & 50 deletions lib/PuppeteerSharp/ElementHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,11 @@ public async Task<string> ScreenshotBase64Async(ScreenshotOptions options)
await Page.SetViewportAsync(newRawViewport.ToObject<ViewPortOptions>(true)).ConfigureAwait(false);
needsViewportReset = true;
}
await ExecutionContext.EvaluateFunctionAsync(@"function(element) {
element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant'});
}", this).ConfigureAwait(false);
await ExecutionContext.EvaluateFunctionAsync(
@"function(element) {
element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant'});
}",
this).ConfigureAwait(false);

await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);
boundingBox = await BoundingBoxAsync().ConfigureAwait(false);
Expand Down Expand Up @@ -454,19 +456,21 @@ public async Task<Frame> ContentFrameAsync()
/// </summary>
/// <returns>A task which resolves to true if the element is visible in the current viewport.</returns>
public Task<bool> IsIntersectingViewportAsync()
=> ExecutionContext.EvaluateFunctionAsync<bool>(@"async element =>
{
const visibleRatio = await new Promise(resolve =>
=> ExecutionContext.EvaluateFunctionAsync<bool>(
@"async element =>
{
const observer = new IntersectionObserver(entries =>
const visibleRatio = await new Promise(resolve =>
{
resolve(entries[0].intersectionRatio);
observer.disconnect();
const observer = new IntersectionObserver(entries =>
{
resolve(entries[0].intersectionRatio);
observer.disconnect();
});
observer.observe(element);
});
observer.observe(element);
});
return visibleRatio > 0;
}", this);
return visibleRatio > 0;
}",
this);

/// <summary>
/// Triggers a `change` and `input` event once all the provided options have been selected.
Expand All @@ -481,22 +485,24 @@ public Task<bool> IsIntersectingViewportAsync()
/// <param name="values">Values of options to select. If the `select` has the `multiple` attribute, all values are considered, otherwise only the first one is taken into account.</param>
/// <returns>A task that resolves to an array of option values that have been successfully selected.</returns>
public Task<string[]> SelectAsync(params string[] values)
=> EvaluateFunctionAsync<string[]>(@"(element, values) =>
{
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');
const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple)
break;
}
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}", new[] { values });
=> EvaluateFunctionAsync<string[]>(
@"(element, values) =>
{
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');
const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple)
break;
}
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}",
new[] { values });

/// <summary>
/// This method creates and captures a dragevent from the element.
Expand Down Expand Up @@ -653,27 +659,29 @@ private IEnumerable<BoxModelPoint> IntersectQuadWithViewport(IEnumerable<BoxMode

private async Task ScrollIntoViewIfNeededAsync()
{
var errorMessage = await EvaluateFunctionAsync<string>(@"async(element, pageJavascriptEnabled) => {
if (!element.isConnected)
return 'Node is detached from document';
if (element.nodeType !== Node.ELEMENT_NODE)
return 'Node is not of type HTMLElement';
// force-scroll if page's javascript is disabled.
if (!pageJavascriptEnabled) {
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
return null;
}
const visibleRatio = await new Promise(resolve => {
const observer = new IntersectionObserver(entries => {
resolve(entries[0].intersectionRatio);
observer.disconnect();
});
observer.observe(element);
});
if (visibleRatio !== 1.0)
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
return null;
}", Page.JavascriptEnabled).ConfigureAwait(false);
var errorMessage = await EvaluateFunctionAsync<string>(
@"async(element, pageJavascriptEnabled) => {
if (!element.isConnected)
return 'Node is detached from document';
if (element.nodeType !== Node.ELEMENT_NODE)
return 'Node is not of type HTMLElement';
// force-scroll if page's javascript is disabled.
if (!pageJavascriptEnabled) {
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
return null;
}
const visibleRatio = await new Promise(resolve => {
const observer = new IntersectionObserver(entries => {
resolve(entries[0].intersectionRatio);
observer.disconnect();
});
observer.observe(element);
});
if (visibleRatio !== 1.0)
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
return null;
}",
Page.JavascriptEnabled).ConfigureAwait(false);

if (errorMessage != null)
{
Expand Down
9 changes: 5 additions & 4 deletions lib/PuppeteerSharp/Helpers/AsyncDictionaryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace PuppeteerSharp.Helpers
internal class AsyncDictionaryHelper<TKey, TValue>
{
private readonly string _timeoutMessage;
private MultiMap<TKey, TaskCompletionSource<TValue>> _pendingRequests;
private ConcurrentDictionary<TKey, TValue> _dictionary;
private readonly MultiMap<TKey, TaskCompletionSource<TValue>> _pendingRequests;
private readonly ConcurrentDictionary<TKey, TValue> _dictionary;

public AsyncDictionaryHelper(ConcurrentDictionary<TKey, TValue> dictionary, string timeoutMessage)
{
Expand All @@ -29,8 +29,9 @@ internal async Task<TValue> GetItemAsync(TKey key)
return item;
}

return await tcs.Task.WithTimeout(new Action(() =>
throw new PuppeteerException(string.Format(CultureInfo.CurrentCulture, _timeoutMessage, key))), 1000).ConfigureAwait(false);
return await tcs.Task.WithTimeout(
new Action(() =>
throw new PuppeteerException(string.Format(CultureInfo.CurrentCulture, _timeoutMessage, key))), 1000).ConfigureAwait(false);
}

internal async Task<TValue> TryGetItemAsync(TKey key)
Expand Down
31 changes: 17 additions & 14 deletions lib/PuppeteerSharp/Helpers/AsyncMessageQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,26 @@ public void Enqueue(MessageTask callback, ConnectionResponse obj)
var task = Task.Run(() => HandleAsyncMessage(callback, obj));

// Unhandled error handler
task.ContinueWith(t =>
{
_logger.LogError(t.Exception, "Failed to complete async handling of SendAsync for {callback}", callback.Method);
callback.TaskWrapper.TrySetException(t.Exception!); // t.Exception is available since this runs only on faulted
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);
task.ContinueWith(
t =>
{
_logger.LogError(t.Exception, "Failed to complete async handling of SendAsync for {callback}", callback.Method);
callback.TaskWrapper.TrySetException(t.Exception!); // t.Exception is available since this runs only on faulted
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);

// Always remove from the queue when done, regardless of outcome.
task.ContinueWith(_ =>
{
lock (_pendingTasks)
task.ContinueWith(
_ =>
{
_pendingTasks.Remove(callback);
}
}, TaskScheduler.Default);
lock (_pendingTasks)
{
_pendingTasks.Remove(callback);
}
},
TaskScheduler.Default);
}

public void Dispose()
Expand Down
12 changes: 7 additions & 5 deletions lib/PuppeteerSharp/JSHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ internal JSHandle(ExecutionContext context, CDPSession client, RemoteObject remo
/// <returns>Task of <see cref="JSHandle"/></returns>
public async Task<JSHandle> GetPropertyAsync(string propertyName)
{
var objectHandle = await EvaluateFunctionHandleAsync(@"(object, propertyName) => {
const result = { __proto__: null};
result[propertyName] = object[propertyName];
return result;
}", propertyName).ConfigureAwait(false);
var objectHandle = await EvaluateFunctionHandleAsync(
@"(object, propertyName) => {
const result = { __proto__: null};
result[propertyName] = object[propertyName];
return result;
}",
propertyName).ConfigureAwait(false);
var properties = await objectHandle.GetPropertiesAsync().ConfigureAwait(false);
properties.TryGetValue(propertyName, out var result);
await objectHandle.DisposeAsync().ConfigureAwait(false);
Expand Down
45 changes: 25 additions & 20 deletions lib/PuppeteerSharp/Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,20 @@ private Page(

_screenshotTaskQueue = screenshotTaskQueue;

_ = target.CloseTask.ContinueWith(_ =>
{
try
{
Close?.Invoke(this, EventArgs.Empty);
}
finally
_ = target.CloseTask.ContinueWith(
_ =>
{
IsClosed = true;
_closeCompletedTcs.TrySetResult(true);
}
},
TaskScheduler.Default);
try
{
Close?.Invoke(this, EventArgs.Empty);
}
finally
{
IsClosed = true;
_closeCompletedTcs.TrySetResult(true);
}
},
TaskScheduler.Default);
}

/// <summary>
Expand Down Expand Up @@ -2499,14 +2500,18 @@ private async Task ExposeFunctionAsync(string name, Delegate puppeteerFunction)
Source = expression
}).ConfigureAwait(false);

await Task.WhenAll(Frames.Select(frame => frame.EvaluateExpressionAsync(expression)
.ContinueWith(task =>
{
if (task.IsFaulted)
{
_logger.LogError(task.Exception.ToString());
}
}, TaskScheduler.Default)))
await Task.WhenAll(Frames.Select(
frame => frame
.EvaluateExpressionAsync(expression)
.ContinueWith(
task =>
{
if (task.IsFaulted)
{
_logger.LogError(task.Exception.ToString());
}
},
TaskScheduler.Default)))
.ConfigureAwait(false);
}

Expand Down
43 changes: 22 additions & 21 deletions lib/PuppeteerSharp/Target.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,29 @@ internal Target(
BrowserContext = browserContext;
PageTask = null;

_ = _initializedTaskWrapper.Task.ContinueWith(async initializedTask =>
{
var success = initializedTask.Result;
if (!success)
{
return;
}

var openerPageTask = Opener?.PageTask;
if (openerPageTask == null || Type != TargetType.Page)
{
return;
}
var openerPage = await openerPageTask.ConfigureAwait(false);
if (!openerPage.HasPopupEventListeners)
_ = _initializedTaskWrapper.Task.ContinueWith(
async initializedTask =>
{
return;
}
var popupPage = await PageAsync().ConfigureAwait(false);
openerPage.OnPopup(popupPage);
},
TaskScheduler.Default);
var success = initializedTask.Result;
if (!success)
{
return;
}

var openerPageTask = Opener?.PageTask;
if (openerPageTask == null || Type != TargetType.Page)
{
return;
}
var openerPage = await openerPageTask.ConfigureAwait(false);
if (!openerPage.HasPopupEventListeners)
{
return;
}
var popupPage = await PageAsync().ConfigureAwait(false);
openerPage.OnPopup(popupPage);
},
TaskScheduler.Default);

CloseTaskWrapper = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
IsInitialized = TargetInfo.Type != TargetType.Page || !string.IsNullOrEmpty(TargetInfo.Url);
Expand Down
3 changes: 2 additions & 1 deletion lib/PuppeteerSharp/WaitTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ internal async Task Rerun()
var context = await _world.GetExecutionContextAsync().ConfigureAwait(false);
try
{
success = await context.EvaluateFunctionHandleAsync(WaitForPredicatePageFunction,
success = await context.EvaluateFunctionHandleAsync(
WaitForPredicatePageFunction,
new object[] { _predicateBody, _pollingInterval ?? (object)_polling, _timeout }.Concat(_args).ToArray()).ConfigureAwait(false);
}
catch (Exception ex)
Expand Down
Loading

0 comments on commit 62aaa7a

Please sign in to comment.