Skip to content
Merged
75 changes: 31 additions & 44 deletions lib/PuppeteerSharp/Bidi/BidiDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ public static object Deserialize(RemoteValue value)
return null;
}

return value.Type switch
return value switch
{
"undefined" => null,
"null" => null,
"string" => value.Value,
"number" => DeserializeNumber(value.Value),
"boolean" => value.Value,
"bigint" => value.Value != null ? Convert.ToInt64(value.Value, CultureInfo.InvariantCulture) : null,
UndefinedRemoteValue or NullRemoteValue => null,
StringRemoteValue s => s.Value,
BooleanRemoteValue b => (object)b.Value,
NumberRemoteValue n => (object)n.Value,
ValueHoldingRemoteValue v when value.Type == RemoteValueType.BigInt =>
v.ValueObject != null ? Convert.ToInt64(v.ValueObject, CultureInfo.InvariantCulture) : null,
_ => null,
};
}
Expand All @@ -59,13 +59,13 @@ public static object ToPrettyPrint(this RemoteValue value)

switch (value.Type)
{
case "array":
case "set":
if (value.Value is IEnumerable<RemoteValue> enumerable)
case RemoteValueType.Array:
case RemoteValueType.Set:
if (value is CollectionRemoteValue collection)
{
var list = new List<object>();

foreach (var item in enumerable)
foreach (var item in collection.Value)
{
list.Add(item.ToPrettyPrint());
}
Expand All @@ -74,45 +74,32 @@ public static object ToPrettyPrint(this RemoteValue value)
}

return Array.Empty<object>();
case "object":
case "map":
case RemoteValueType.Object:
case RemoteValueType.Map:
// TODO
return value.Value;
case "regexp":
case "date":
return value is ValueHoldingRemoteValue vhMap ? vhMap.ValueObject : null;
case RemoteValueType.RegExp:
case RemoteValueType.Date:
// TODO
return value.Value;
case "promise":
return value is ValueHoldingRemoteValue vhDate ? vhDate.ValueObject : null;
case RemoteValueType.Promise:
return "{}";
case "undefined":
case RemoteValueType.Undefined:
return "undefined";
case "null":
case RemoteValueType.Null:
return "null";
case "number":
return DeserializeNumber(value.Value);
case "bigint":
return Convert.ToInt64(value.Value, CultureInfo.InvariantCulture);
case "boolean":
return Convert.ToBoolean(value.Value, CultureInfo.InvariantCulture);
case RemoteValueType.Number:
return value is ValueHoldingRemoteValue vhNum ? vhNum.ValueObject : null;
case RemoteValueType.BigInt:
return value is ValueHoldingRemoteValue vhBigInt
? Convert.ToInt64(vhBigInt.ValueObject, CultureInfo.InvariantCulture)
: null;
case RemoteValueType.Boolean:
return value is BooleanRemoteValue b
? (object)b.Value
: null;
default:
return value.Value;
}
}

private static object DeserializeNumber(object value)
{
switch (value)
{
case "-0":
return -0;
case "NaN":
return double.NaN;
case "Infinity":
return double.PositiveInfinity;
case "-Infinity":
return double.NegativeInfinity;
default:
return value;
return value is ValueHoldingRemoteValue vh ? vh.ValueObject : null;
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/PuppeteerSharp/Bidi/BidiElementHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ public override async Task<IFrame> ContentFrameAsync()

await handle.DisposeAsync().ConfigureAwait(false);

if (value?.Type == "window" && value.Value is WindowProxyProperties windowProxy)
if (value?.Type == RemoteValueType.Window && value is WindowProxyRemoteValue windowProxyValue)
{
var contextId = windowProxy.Context;
var contextId = windowProxyValue.Value.Context;
return BidiFrame.BidiPage.Frames.FirstOrDefault(frame => frame.Id == contextId);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/PuppeteerSharp/Bidi/BidiFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -599,15 +599,15 @@ internal async Task RemoveExposedFunctionAsync(string name)
internal async Task SetFilesAsync(BidiElementHandle element, string[] files)
{
await BrowsingContext.SetFilesAsync(
element.Value.ToSharedReference(),
element.Value.ConvertTo<NodeRemoteValue>().ToSharedReference(),
files).ConfigureAwait(false);
}

internal async Task<IList<RemoteValue>> LocateNodesAsync(BidiElementHandle element, BidiLocator locator)
internal async Task<IList<NodeRemoteValue>> LocateNodesAsync(BidiElementHandle element, BidiLocator locator)
{
return await BrowsingContext.LocateNodesAsync(
locator,
[element.Value.ToSharedReference()]).ConfigureAwait(false);
[element.Value.ConvertTo<NodeRemoteValue>().ToSharedReference()]).ConfigureAwait(false);
}

/// <inheritdoc />
Expand Down Expand Up @@ -995,7 +995,7 @@ private void Initialize()
return BidiDeserializer.Deserialize(jsHandle.RemoteValue);
}

if (arg is BidiJSHandle { RemoteValue.Type: "error" } && !string.IsNullOrEmpty(logEntryText))
if (arg is BidiJSHandle { RemoteValue.Type: RemoteValueType.Error } && !string.IsNullOrEmpty(logEntryText))
{
return (object)logEntryText.Split('\n')[0];
}
Expand Down
38 changes: 33 additions & 5 deletions lib/PuppeteerSharp/Bidi/BidiJSHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ public bool IsPrimitiveValue
{
return RemoteValue.Type switch
{
"string" or "number" or "bigint" or "boolean" or "undefined" or "null" => true,
RemoteValueType.String or RemoteValueType.Number or RemoteValueType.BigInt or RemoteValueType.Boolean or RemoteValueType.Undefined or RemoteValueType.Null => true,
_ => false,
};
}
}

internal string Id => RemoteValue.Handle;
internal string Id => (RemoteValue as IObjectReferenceRemoteValue)?.Handle;

internal override Realm Realm { get; } = realm;

Expand All @@ -55,12 +55,40 @@ public static BidiJSHandle From(RemoteValue value, BidiRealm realm)
return new BidiJSHandle(value, realm);
}

public override Task<IJSHandle> GetPropertyAsync(string propertyName)
{
// For handleless objects (e.g. from log events), look up the property
// directly from the RemoteValue dictionary to avoid a browser round-trip
// that would fail due to serialization issues
if (string.IsNullOrEmpty(Id) && RemoteValue is KeyValuePairCollectionRemoteValue kvp && kvp.Value != null)
{
foreach (var entry in kvp.Value)
{
if (entry.Key?.ToString() == propertyName)
{
return Task.FromResult<IJSHandle>(BidiJSHandle.From(entry.Value, realm));
}
}

return base.GetPropertyAsync(propertyName);
}

return base.GetPropertyAsync(propertyName);
}

public override async Task<T> JsonValueAsync<T>()
{
// If it's a primitive value or doesn't have a handle, deserialize directly
if (IsPrimitiveValue || string.IsNullOrEmpty(Id))
{
return DeserializeValue<T>(RemoteValue.Value);
var valueObject = RemoteValue switch
{
ValueHoldingRemoteValue vh => vh.ValueObject,
CollectionRemoteValue crv => crv.Value,
KeyValuePairCollectionRemoteValue kvp => (object)kvp.Value,
_ => null,
};
return DeserializeValue<T>(valueObject);
}

// Otherwise, use evaluation for objects with handles
Expand All @@ -75,7 +103,7 @@ public override string ToString()
return "JSHandle:" + RemoteValue.ToPrettyPrint();
}

return "JSHandle@" + RemoteValue.Type;
return "JSHandle@" + RemoteValue.Type.ToString().ToLowerInvariant();
}

/// <inheritdoc/>
Expand Down Expand Up @@ -127,7 +155,7 @@ private T DeserializeValue<T>(object value)
return (T)(object)Convert.ToDecimal(value, CultureInfo.InvariantCulture);
}

if (typeof(T) == typeof(DateTime) && RemoteValue.Type == "date")
if (typeof(T) == typeof(DateTime) && RemoteValue.Type == RemoteValueType.Date)
{
return (T)(object)DateTime.Parse(value.ToString(), CultureInfo.InvariantCulture);
}
Expand Down
18 changes: 7 additions & 11 deletions lib/PuppeteerSharp/Bidi/BidiPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -598,8 +598,9 @@ public override async Task SetGeolocationAsync(GeolocationOption options)
/// <inheritdoc />
public override async Task SetJavaScriptEnabledAsync(bool enabled)
{
var commandParameters = new WebDriverBiDi.Emulation.SetScriptingEnabledCommandParameters(enabled)
var commandParameters = new WebDriverBiDi.Emulation.SetScriptingEnabledCommandParameters
{
IsScriptingEnabled = enabled,
Contexts = [BidiMainFrame.BrowsingContext.Id],
};

Expand All @@ -619,9 +620,8 @@ await BidiMainFrame.Client.SendAsync(
/// <inheritdoc />
public override async Task SetCacheEnabledAsync(bool enabled = true)
{
var commandParameters = new SetCacheBehaviorCommandParameters
var commandParameters = new SetCacheBehaviorCommandParameters(enabled ? CacheBehavior.Default : CacheBehavior.Bypass)
{
CacheBehavior = enabled ? CacheBehavior.Default : CacheBehavior.Bypass,
Contexts = [BidiMainFrame.BrowsingContext.Id],
};

Expand Down Expand Up @@ -1107,16 +1107,12 @@ win.document.activeElement instanceof win.HTMLFrameElement
_ => null,
};

if (remoteValue?.Type == "window")
if (remoteValue is WindowProxyRemoteValue windowProxyRemoteValue)
{
var windowProxy = remoteValue.ValueAs<WindowProxyProperties>();
if (windowProxy != null)
var frame = Frames.OfType<BidiFrame>().FirstOrDefault(f => f.Id == windowProxyRemoteValue.Value.Context);
if (frame != null)
{
var frame = Frames.OfType<BidiFrame>().FirstOrDefault(f => f.Id == windowProxy.Context);
if (frame != null)
{
return frame;
}
return frame;
}
}

Expand Down
Loading
Loading