|
@@ -1,3 +1,4 @@
|
|
|
|
+using System;
|
|
using System.Collections;
|
|
using System.Collections;
|
|
using System.Globalization;
|
|
using System.Globalization;
|
|
using System.Reflection;
|
|
using System.Reflection;
|
|
@@ -10,18 +11,20 @@ using Jint.Runtime.Interop.Reflection;
|
|
|
|
|
|
namespace Jint.Runtime.Interop
|
|
namespace Jint.Runtime.Interop
|
|
{
|
|
{
|
|
- /// <summary>
|
|
|
|
- /// Wraps a CLR instance
|
|
|
|
- /// </summary>
|
|
|
|
- public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper, IEquatable<ObjectWrapper>
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Wraps a CLR instance
|
|
|
|
+ /// </summary>
|
|
|
|
+ public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper, IEquatable<ObjectWrapper>
|
|
{
|
|
{
|
|
private readonly TypeDescriptor _typeDescriptor;
|
|
private readonly TypeDescriptor _typeDescriptor;
|
|
|
|
+ private readonly Type _clrType;
|
|
|
|
|
|
- public ObjectWrapper(Engine engine, object obj)
|
|
|
|
|
|
+ public ObjectWrapper(Engine engine, object obj, Type? type = null)
|
|
: base(engine)
|
|
: base(engine)
|
|
{
|
|
{
|
|
Target = obj;
|
|
Target = obj;
|
|
- _typeDescriptor = TypeDescriptor.Get(obj.GetType());
|
|
|
|
|
|
+ _clrType = ClrType(obj, type);
|
|
|
|
+ _typeDescriptor = TypeDescriptor.Get(_clrType);
|
|
if (_typeDescriptor.LengthProperty is not null)
|
|
if (_typeDescriptor.LengthProperty is not null)
|
|
{
|
|
{
|
|
// create a forwarder to produce length from Count or Length if one of them is present
|
|
// create a forwarder to produce length from Count or Length if one of them is present
|
|
@@ -48,7 +51,7 @@ namespace Jint.Runtime.Interop
|
|
if (_properties is null || !_properties.ContainsKey(member))
|
|
if (_properties is null || !_properties.ContainsKey(member))
|
|
{
|
|
{
|
|
// can try utilize fast path
|
|
// can try utilize fast path
|
|
- var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, Target.GetType(), member, forWrite: true);
|
|
|
|
|
|
+ var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, _clrType, member, forWrite: true);
|
|
|
|
|
|
if (ReferenceEquals(accessor, ConstantValueAccessor.NullAccessor))
|
|
if (ReferenceEquals(accessor, ConstantValueAccessor.NullAccessor))
|
|
{
|
|
{
|
|
@@ -160,7 +163,7 @@ namespace Jint.Runtime.Interop
|
|
else if (includeStrings)
|
|
else if (includeStrings)
|
|
{
|
|
{
|
|
// we take public properties and fields
|
|
// we take public properties and fields
|
|
- var type = Target.GetType();
|
|
|
|
|
|
+ var type = _clrType;
|
|
foreach (var p in type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public))
|
|
foreach (var p in type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public))
|
|
{
|
|
{
|
|
var indexParameters = p.GetIndexParameters();
|
|
var indexParameters = p.GetIndexParameters();
|
|
@@ -232,7 +235,7 @@ namespace Jint.Runtime.Interop
|
|
return new PropertyDescriptor(result, PropertyFlag.OnlyEnumerable);
|
|
return new PropertyDescriptor(result, PropertyFlag.OnlyEnumerable);
|
|
}
|
|
}
|
|
|
|
|
|
- var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, Target.GetType(), member);
|
|
|
|
|
|
+ var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, _clrType, member);
|
|
var descriptor = accessor.CreatePropertyDescriptor(_engine, Target, enumerable: !isDictionary);
|
|
var descriptor = accessor.CreatePropertyDescriptor(_engine, Target, enumerable: !isDictionary);
|
|
if (!isDictionary && !ReferenceEquals(descriptor, PropertyDescriptor.Undefined))
|
|
if (!isDictionary && !ReferenceEquals(descriptor, PropertyDescriptor.Undefined))
|
|
{
|
|
{
|
|
@@ -259,6 +262,26 @@ namespace Jint.Runtime.Interop
|
|
return engine.Options.Interop.TypeResolver.GetAccessor(engine, target.GetType(), member.Name, Factory).CreatePropertyDescriptor(engine, target);
|
|
return engine.Options.Interop.TypeResolver.GetAccessor(engine, target.GetType(), member.Name, Factory).CreatePropertyDescriptor(engine, target);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public static Type ClrType(object obj, Type? type)
|
|
|
|
+ {
|
|
|
|
+ if (type is null || type == typeof(object))
|
|
|
|
+ {
|
|
|
|
+ return obj.GetType();
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ var underlyingType = Nullable.GetUnderlyingType(type);
|
|
|
|
+ if (underlyingType is not null)
|
|
|
|
+ {
|
|
|
|
+ return underlyingType;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ return type;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private static JsValue Iterator(JsValue thisObject, JsValue[] arguments)
|
|
private static JsValue Iterator(JsValue thisObject, JsValue[] arguments)
|
|
{
|
|
{
|
|
var wrapper = (ObjectWrapper) thisObject;
|
|
var wrapper = (ObjectWrapper) thisObject;
|
|
@@ -296,12 +319,15 @@ namespace Jint.Runtime.Interop
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- return Equals(Target, other.Target);
|
|
|
|
|
|
+ return Equals(Target, other.Target) && Equals(_clrType, other._clrType);
|
|
}
|
|
}
|
|
|
|
|
|
public override int GetHashCode()
|
|
public override int GetHashCode()
|
|
{
|
|
{
|
|
- return Target?.GetHashCode() ?? 0;
|
|
|
|
|
|
+ var hashCode = -1468639730;
|
|
|
|
+ hashCode = hashCode * -1521134295 + Target.GetHashCode();
|
|
|
|
+ hashCode = hashCode * -1521134295 + _clrType.GetHashCode();
|
|
|
|
+ return hashCode;
|
|
}
|
|
}
|
|
|
|
|
|
private sealed class DictionaryIterator : IteratorInstance
|
|
private sealed class DictionaryIterator : IteratorInstance
|