Skip to content
Draft
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
11 changes: 11 additions & 0 deletions ClearScript/V8/FastProxy/V8FastArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,17 @@ internal V8FastArgs(V8ScriptEngine engine, in ReadOnlySpan<V8Value.FastArg> args
/// </remarks>
public T Get<T>(int index, string name = null) => V8FastArgImpl.Get<T>(args[index], GetObject(index), argKind, name);

/// <summary>
///
/// </summary>
/// <param name="index"></param>
/// <param name="name"></param>
/// <returns></returns>
public V8Object GetV8Object(int index, string name = null)
{
return new V8Object((V8Object.Handle)args[index].data.PtrOrHandle, args[index].data.IdentityHash);
}

private static void EnsureObjects(ref object[] objects, int count)
{
if (objects is null)
Expand Down
1 change: 1 addition & 0 deletions ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ internal interface IV8SplitProxyNative
#region V8 object methods

object V8Object_GetNamedProperty(V8Object.Handle hObject, string name);
void V8Object_GetNamedProperty(V8Object.Handle hObject, string name, V8Value.Ptr pValue);
bool V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value);
void V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value);
bool V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name);
Expand Down
131 changes: 99 additions & 32 deletions ClearScript/V8/SplitProxy/V8SplitProxyHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using Microsoft.ClearScript.Util;
using Microsoft.ClearScript.V8.FastProxy;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
Expand All @@ -9,8 +12,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.ClearScript.Util;
using Microsoft.ClearScript.V8.FastProxy;
using System.Xml.Linq;

namespace Microsoft.ClearScript.V8.SplitProxy
{
Expand Down Expand Up @@ -876,29 +878,32 @@ public readonly struct Ptr
#endregion
}

internal static class V8Value
/// <summary>
///
/// </summary>
public static class V8Value
{
public const int Size = 16;
internal const int Size = 16;

private const short positiveOrZero = 0;
private const short negative = 1;

public static ValueScope<Ptr> CreateScope()
internal static ValueScope<Ptr> CreateScope()
{
return ScopeFactory.Create(
static () => V8SplitProxyNative.InvokeRaw(static instance => instance.V8Value_New()),
static pV8Value => V8SplitProxyNative.InvokeNoThrow(static (instance, pV8Value) => instance.V8Value_Delete(pV8Value), pV8Value)
);
}

public static ValueScope<Ptr> CreateScope(object obj)
internal static ValueScope<Ptr> CreateScope(object obj)
{
var scope = CreateScope();
Set(scope.Value, obj);
return scope;
}

public static void Set(Ptr pV8Value, object obj)
internal static void Set(Ptr pV8Value, object obj)
{
if (obj is Nonexistent)
{
Expand Down Expand Up @@ -990,7 +995,7 @@ public static void Set(Ptr pV8Value, object obj)
}
}

public static object Get(Ptr pV8Value)
internal static object Get(Ptr pV8Value)
{
return V8SplitProxyNative.InvokeRaw(
static (instance, pV8Value) =>
Expand Down Expand Up @@ -1074,7 +1079,7 @@ private static void SetHostObject(Ptr pV8Value, IHostItem hostObject)

#region Nested type: Type

public enum Type : byte
internal enum Type : byte
{
// IMPORTANT: maintain bitwise equivalence with native enum V8Value::Type
Nonexistent,
Expand All @@ -1093,7 +1098,7 @@ public enum Type : byte

#region Nested type: Subtype

public enum Subtype : byte
internal enum Subtype : byte
{
// IMPORTANT: maintain bitwise equivalence with native enum V8Value::Subtype
None,
Expand Down Expand Up @@ -1121,7 +1126,7 @@ public enum Subtype : byte
#region Nested type: Flags

[Flags]
public enum Flags : ushort
internal enum Flags : ushort
{
// IMPORTANT: maintain bitwise equivalence with native enum V8Value::Flags
None = 0,
Expand All @@ -1133,14 +1138,14 @@ public enum Flags : ushort
Rejected = 0x0010
}

public static bool HasAllFlags(this Flags value, Flags flags) => (value & flags) == flags;
public static bool HasAnyFlag(this Flags value, Flags flags) => (value & flags) != 0;
internal static bool HasAllFlags(this Flags value, Flags flags) => (value & flags) == flags;
internal static bool HasAnyFlag(this Flags value, Flags flags) => (value & flags) != 0;

#endregion

#region Nested type: Ptr

public readonly struct Ptr
internal readonly struct Ptr
{
private readonly IntPtr bits;

Expand All @@ -1167,7 +1172,7 @@ public readonly struct Ptr
#region Nested type: WireData

[StructLayout(LayoutKind.Explicit)]
public struct WireData
internal struct WireData
{
// IMPORTANT: maintain bitwise equivalence with native struct V8Value::WireData
[FieldOffset(0)] public Type Type;
Expand Down Expand Up @@ -1213,10 +1218,10 @@ public readonly bool TryCreateBigInteger(out BigInteger value)
#region Nested type: Decoded

[StructLayout(LayoutKind.Explicit)]
public struct Decoded
internal struct Decoded
{
// IMPORTANT: maintain bitwise equivalence with native struct V8Value::Decoded
[FieldOffset(0)] private WireData data;
[FieldOffset(0)] internal WireData data;

public object Get()
{
Expand Down Expand Up @@ -1303,17 +1308,25 @@ public readonly struct Ptr

#region Nested type: FastArg

/// <summary>
///
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public readonly struct FastArg
{
internal FastArg(WireData data)
{
this.data = data;
}

// IMPORTANT: maintain bitwise equivalence with native struct V8Value::FastArg
[FieldOffset(0)] private readonly WireData data;
[FieldOffset(0)] internal readonly WireData data;

public bool IsUndefined() => (data.Type == Type.Undefined) || (data.Type == Type.Nonexistent);
internal bool IsUndefined() => (data.Type == Type.Undefined) || (data.Type == Type.Nonexistent);

public bool IsNull() => data.Type == Type.Null;
internal bool IsNull() => data.Type == Type.Null;

public bool TryGetBoolean(out bool value)
internal bool TryGetBoolean(out bool value)
{
if (data.Type == Type.Boolean)
{
Expand All @@ -1325,7 +1338,7 @@ public bool TryGetBoolean(out bool value)
return false;
}

public bool TryGetNumber(out double value)
internal bool TryGetNumber(out double value)
{
if (data.Type == Type.Number)
{
Expand All @@ -1337,7 +1350,7 @@ public bool TryGetNumber(out double value)
return false;
}

public bool TryGetString(out string value)
internal bool TryGetString(out string value)
{
if (data.Type == Type.String)
{
Expand All @@ -1349,7 +1362,7 @@ public bool TryGetString(out string value)
return false;
}

public unsafe bool TryGetCharSpan(out ReadOnlySpan<char> value)
internal unsafe bool TryGetCharSpan(out ReadOnlySpan<char> value)
{
if (data.Type == Type.String)
{
Expand All @@ -1361,7 +1374,7 @@ public unsafe bool TryGetCharSpan(out ReadOnlySpan<char> value)
return false;
}

public bool TryGetDateTime(out DateTime value)
internal bool TryGetDateTime(out DateTime value)
{
if (data.Type == Type.DateTime)
{
Expand All @@ -1373,7 +1386,7 @@ public bool TryGetDateTime(out DateTime value)
return false;
}

public bool TryGetBigInteger(out BigInteger value)
internal bool TryGetBigInteger(out BigInteger value)
{
if (data.Type == Type.BigInt)
{
Expand All @@ -1384,7 +1397,7 @@ public bool TryGetBigInteger(out BigInteger value)
return false;
}

public bool TryGetV8Object(out V8ObjectImpl v8Object)
internal bool TryGetV8Object(out V8ObjectImpl v8Object)
{
if (data.Type == Type.V8Object)
{
Expand All @@ -1396,7 +1409,7 @@ public bool TryGetV8Object(out V8ObjectImpl v8Object)
return false;
}

public bool TryGetHostObject(out object hostObject)
internal bool TryGetHostObject(out object hostObject)
{
if (data.Type == Type.HostObject)
{
Expand All @@ -1411,7 +1424,7 @@ public bool TryGetHostObject(out object hostObject)
#region Nested type: Ptr

// ReSharper disable once MemberHidesStaticFromOuterClass
public readonly struct Ptr
internal readonly struct Ptr
{
private readonly IntPtr bits;

Expand Down Expand Up @@ -1444,7 +1457,7 @@ public readonly struct Ptr
#region Nested type: FastResult

[StructLayout(LayoutKind.Explicit)]
public struct FastResult
internal struct FastResult
{
// IMPORTANT: maintain bitwise equivalence with native struct V8Value::FastResult
[FieldOffset(0)] private WireData data;
Expand Down Expand Up @@ -2000,11 +2013,65 @@ public readonly struct Handle
#endregion
}

internal static class V8Object
/// <summary>
///
/// </summary>
public readonly ref struct V8Object
{
internal readonly Handle handle;
private readonly int identityHash;

internal V8Object(Handle hObject, int identityHash)
{
if (hObject == Handle.Empty)
throw new ArgumentNullException(nameof(hObject));

handle = hObject;
this.identityHash = identityHash;
}

/// <summary>
/// Return the identity hash of the JavaScript object.
/// </summary>
/// <returns>The identity hash of the JavaScript object.</returns>
public override int GetHashCode()
{
return identityHash;
}

/// <summary>
/// Obtain the value of a named property of the wrapped JavaScript object.
/// </summary>
/// <param name="name">The name of the property.</param>
/// <param name="storage"></param>
/// <returns></returns>
public unsafe V8FastArg GetProperty(string name, ref V8Value.FastArg storage)
{
if (handle == Handle.Empty)
throw new NullReferenceException("V8 object is uninitialized");

if (name == null)
throw new ArgumentNullException(nameof(name));

V8Value.Decoded decoded = V8SplitProxyNative.InvokeRaw((instance, arg) =>
{
V8Value.Ptr pValue = instance.V8Value_New();
instance.V8Object_GetNamedProperty(arg.handle, arg.name, pValue);
instance.V8Value_Decode(pValue, out var decoded);
instance.V8Value_Delete(pValue);
return decoded;
}, (handle, name));

storage = new V8Value.FastArg(decoded.data);

return new V8FastArg((V8ScriptEngine)ScriptEngine.Current,
(V8Value.FastArg.Ptr)(IntPtr)Unsafe.AsPointer(ref storage),
V8FastArgKind.PropertyValue);
}

#region Nested type: Handle

public readonly struct Handle
internal readonly struct Handle
{
private readonly IntPtr guts;

Expand Down
8 changes: 8 additions & 0 deletions ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,14 @@ namespace Microsoft.ClearScript.V8.SplitProxy
}
}

void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name, V8Value.Ptr pValue)
{
using (var nameScope = StdString.CreateScope(name))
{
V8Object_GetNamedProperty(hObject, nameScope.Value, pValue);
}
}

bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value)
{
using (var nameScope = StdString.CreateScope(name))
Expand Down
Loading