// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using System.Reflection; using System.Runtime.InteropServices.ComTypes; using Microsoft.ClearScript.Util; namespace Microsoft.ClearScript { internal sealed class HostObject : HostTarget { #region data private readonly object target; private readonly Type type; private static readonly MethodInfo getNullWrapperGenericMethod = typeof(HostObject).GetMethod("GetNullWrapperGeneric", BindingFlags.NonPublic | BindingFlags.Static); #endregion #region constructors private HostObject(object target, Type type, bool isCanonicalRef) { if (!isCanonicalRef) { target = CanonicalRefTable.GetCanonicalRef(target); } if (type is null) { type = target.GetType(); } if (type.IsUnknownCOMObject()) { if (target is IEnumVARIANT enumVariant) { target = new ScriptableEnumeratorOnEnumVariant(enumVariant); type = typeof(IScriptableEnumerator); } } this.target = target; this.type = type; } #endregion #region wrappers public static HostObject Wrap(object target) { return Wrap(target, null); } public static HostObject Wrap(object target, Type type) { return Wrap(target, type, false); } public static HostObject Wrap(object target, Type type, bool isCanonicalRef) { return (target is not null) ? new HostObject(target, type, isCanonicalRef) : null; } public static object WrapResult(object result, Type type, bool wrapNull) { if ((result is IScriptMarshalWrapper) || (result is HostTarget)) { return result; } if (result is null) { return wrapNull ? GetNullWrapper(type) : null; } if ((type == typeof(void)) || (type == typeof(object)) || type.IsNullable()) { return result; } if ((type == result.GetType()) || (Type.GetTypeCode(type) != TypeCode.Object)) { return result; } return Wrap(result, type); } #endregion #region internal members private static HostObject GetNullWrapper(Type type) { return (HostObject)getNullWrapperGenericMethod.MakeGenericMethod(type).Invoke(null, ArrayHelpers.GetEmptyArray