Esempio n. 1
0
        internal HostItem GetOrCreateHostItem(HostTarget target, HostItemFlags flags, Func <ScriptEngine, HostTarget, HostItemFlags, HostItem> createHostItem)
        {
            var hostObject = target as HostObject;

            if (hostObject != null)
            {
                return(GetOrCreateHostItemForHostTarget(hostObject, flags, createHostItem));
            }

            var hostType = target as HostType;

            if (hostType != null)
            {
                return(GetOrCreateHostItemForHostType(hostType, flags, createHostItem));
            }

            var hostMethod = target as HostMethod;

            if (hostMethod != null)
            {
                return(GetOrCreateHostItemForHostTarget(hostMethod, flags, createHostItem));
            }

            var hostIndexedProperty = target as HostIndexedProperty;

            if (hostIndexedProperty != null)
            {
                return(GetOrCreateHostItemForHostTarget(hostIndexedProperty, flags, createHostItem));
            }

            return(createHostItem(this, target, flags));
        }
        internal override void AddHostItem(string itemName, HostItemFlags flags, object item)
        {
            VerifyNotDisposed();

            var globalMembers = flags.HasFlag(HostItemFlags.GlobalMembers);

            if (globalMembers && engineFlags.HasFlag(V8ScriptEngineFlags.DisableGlobalMembers))
            {
                throw new InvalidOperationException("GlobalMembers support is disabled in this script engine");
            }

            MiscHelpers.VerifyNonNullArgument(itemName, "itemName");
            Debug.Assert(item != null);

            ScriptInvoke(() =>
            {
                var marshaledItem = MarshalToScript(item, flags);
                if (!(marshaledItem is HostItem))
                {
                    throw new InvalidOperationException("Invalid host item");
                }

                proxy.AddGlobalItem(itemName, marshaledItem, globalMembers);
            });
        }
Esempio n. 3
0
        internal override object MarshalToScript(object obj, HostItemFlags flags)
        {
            if (obj == null)
            {
                return(DBNull.Value);
            }

            if (obj is Undefined)
            {
                return(null);
            }

            if (obj is Nonexistent)
            {
                return(obj);
            }

            if (obj is Nothing)
            {
                return(null);
            }

            if (engineFlags.HasFlag(V8ScriptEngineFlags.EnableDateTimeConversion) && (obj is DateTime))
            {
                return(obj);
            }

            var hostItem = obj as HostItem;

            if (hostItem != null)
            {
                if ((hostItem.Engine == this) && (hostItem.Flags == flags))
                {
                    return(obj);
                }

                obj = hostItem.Target;
            }

            var hostTarget = obj as HostTarget;

            if ((hostTarget != null) && !(hostTarget is IHostVariable))
            {
                obj = hostTarget.Target;
            }

            var scriptItem = obj as ScriptItem;

            if (scriptItem != null)
            {
                if (scriptItem.Engine == this)
                {
                    return(scriptItem.Unwrap());
                }
            }

            return(HostItem.Wrap(this, hostTarget ?? obj, flags));
        }
Esempio n. 4
0
        private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
        {
            if (!MiscHelpers.PlatformIsWindows())
            {
                return(new HostItem(engine, target, flags));
            }

            return(TargetSupportsExpandoMembers(target, flags) ? new DispatchExHostItem(engine, target, flags) : new HostItem(engine, target, flags));
        }
Esempio n. 5
0
        private HostItem GetOrCreateHostItemForHostType(HostType hostType, HostItemFlags flags, Func <ScriptEngine, HostTarget, HostItemFlags, HostItem> createHostItem)
        {
            if (hostType.Types.Length != 1)
            {
                return(createHostItem(this, hostType, flags));
            }

            var cacheEntry = hostTypeHostItemCache.GetOrCreateValue(hostType.Types[0]);

            List <WeakReference> activeWeakRefs = null;
            var staleWeakRefCount = 0;

            foreach (var weakRef in cacheEntry)
            {
                var hostItem = weakRef.Target as HostItem;
                if (hostItem == null)
                {
                    staleWeakRefCount++;
                }
                else
                {
                    if (hostItem.Flags == flags)
                    {
                        return(hostItem);
                    }

                    if (activeWeakRefs == null)
                    {
                        activeWeakRefs = new List <WeakReference>(cacheEntry.Count);
                    }

                    activeWeakRefs.Add(weakRef);
                }
            }

            if (staleWeakRefCount > 4)
            {
                cacheEntry.Clear();
                if (activeWeakRefs != null)
                {
                    cacheEntry.Capacity = activeWeakRefs.Count + 1;
                    cacheEntry.AddRange(activeWeakRefs);
                }
            }

            var newHostItem = createHostItem(this, hostType, flags);

            cacheEntry.Add(new WeakReference(newHostItem));
            return(newHostItem);
        }
Esempio n. 6
0
        internal override object MarshalToScript(object obj, HostItemFlags flags)
        {
            if (obj == null)
            {
                return(DBNull.Value);
            }

            if (obj is Undefined)
            {
                return(null);
            }

            if (obj is Nonexistent)
            {
                return(null);
            }

            var hostItem = obj as HostItem;

            if (hostItem != null)
            {
                if ((hostItem.Engine == this) && (hostItem.Flags == flags))
                {
                    return(obj);
                }

                obj = hostItem.Target;
            }

            var hostTarget = obj as HostTarget;

            if (hostTarget != null)
            {
                obj = hostTarget.Target;
            }

            var scriptItem = obj as ScriptItem;

            if (scriptItem != null)
            {
                if (scriptItem.Engine == this)
                {
                    return(scriptItem.Unwrap());
                }
            }

            return(HostItem.Wrap(this, hostTarget ?? obj, flags));
        }
Esempio n. 7
0
        internal override void AddHostItem(string itemName, HostItemFlags flags, object item)
        {
            VerifyNotDisposed();

            MiscHelpers.VerifyNonNullArgument(itemName, "itemName");
            Debug.Assert(item != null);

            ScriptInvoke(() =>
            {
                object marshaledItem;
                if (!flags.HasFlag(HostItemFlags.DirectAccess) || !GetDirectAccessItem(item, out marshaledItem))
                {
                    marshaledItem = MarshalToScript(item, flags);
                    if (!(marshaledItem is HostItem))
                    {
                        throw new InvalidOperationException("Invalid host item");
                    }
                }

                var oldItem           = ((IDictionary)hostItemMap)[itemName];
                hostItemMap[itemName] = marshaledItem;

                var nativeFlags = ScriptItemFlags.IsVisible;
                if (flags.HasFlag(HostItemFlags.GlobalMembers))
                {
                    nativeFlags |= ScriptItemFlags.GlobalMembers;
                }

                try
                {
                    activeScript.AddNamedItem(itemName, nativeFlags);
                }
                catch (Exception)
                {
                    if (oldItem != null)
                    {
                        hostItemMap[itemName] = oldItem;
                    }
                    else
                    {
                        hostItemMap.Remove(itemName);
                    }

                    throw;
                }
            });
        }
Esempio n. 8
0
        private static bool TargetSupportsExpandoMembers(HostTarget target, HostItemFlags flags)
        {
            if (!TargetSupportsSpecialTargets(target))
            {
                return(false);
            }

            if (typeof(IDynamic).IsAssignableFrom(target.Type))
            {
                return(true);
            }

            if (target is IHostVariable)
            {
                if (target.Type.IsImport)
                {
                    return(true);
                }
            }
            else
            {
                if ((target.InvokeTarget is IDispatchEx dispatchEx) && dispatchEx.GetType().IsCOMObject)
                {
                    return(true);
                }
            }

            if (typeof(IPropertyBag).IsAssignableFrom(target.Type))
            {
                return(true);
            }

            if (!flags.HasFlag(HostItemFlags.HideDynamicMembers) && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(target.Type))
            {
                return(true);
            }

            return(false);
        }
Esempio n. 9
0
 /// <summary>
 /// Exposes a host object to script code with the specified options.
 /// </summary>
 /// <param name="itemName">A name for the new global script item that will represent the object.</param>
 /// <param name="flags">A value that selects options for the operation.</param>
 /// <param name="target">The object to expose.</param>
 /// <remarks>
 /// Once a host object is exposed to script code, its members are accessible via the script
 /// language's native syntax for member access. The following table provides details about
 /// the mapping between host members and script-accessible properties and methods.
 /// <para>
 /// <list type="table">
 ///     <listheader>
 ///         <term>Member&#xA0;Type</term>
 ///         <term>Exposed&#xA0;As</term>
 ///         <description>Remarks</description>
 ///     </listheader>
 ///     <item>
 ///         <term><b>Constructor</b></term>
 ///         <term>N/A</term>
 ///         <description>
 ///         To invoke a constructor from script code, call
 ///         <see cref="HostFunctions.newObj{T}">HostFunctions.newObj(T)</see>.
 ///         </description>
 ///     </item>
 ///     <item>
 ///         <term><b>Property/Field</b></term>
 ///         <term><b>Property</b></term>
 ///         <description>N/A</description>
 ///     </item>
 ///     <item>
 ///         <term><b>Method</b></term>
 ///         <term><b>Method</b></term>
 ///         <description>
 ///         Overloaded host methods are merged into a single script-callable method. At
 ///         runtime the correct host method is selected based on the argument types.
 ///         </description>
 ///     </item>
 ///     <item>
 ///         <term><b>Generic&#xA0;Method</b></term>
 ///         <term><b>Method</b></term>
 ///         <description>
 ///         The ClearScript library supports dynamic C#-like type inference when invoking
 ///         generic methods. However, some methods require explicit type arguments. To call
 ///         such a method from script code, you must place the required number of
 ///         <see cref="AddHostType(string, HostItemFlags, Type)">host type objects</see>
 ///         at the beginning of the argument list. Doing so for methods that do not require
 ///         explicit type arguments is optional.
 ///         </description>
 ///     </item>
 ///     <item>
 ///         <term><b>Extension&#xA0;Method</b></term>
 ///         <term><b>Method</b></term>
 ///         <description>
 ///         Extension methods are available if the type that implements them has been
 ///         exposed in the current script engine.
 ///         </description>
 ///     </item>
 ///     <item>
 ///         <term><b>Indexer</b></term>
 ///         <term><b>Property</b></term>
 ///         <description>
 ///         Indexers appear as properties named "Item" that accept one or more index values
 ///         as arguments. In addition, objects that implement <see cref="IList"/> expose
 ///         properties with numeric names that match their valid indices. This includes
 ///         one-dimensional host arrays and other collections. Multidimensional host arrays
 ///         do not expose functional indexers; you must use
 ///         <see href="http://msdn.microsoft.com/en-us/library/system.array.getvalue.aspx">Array.GetValue</see>
 ///         and
 ///         <see href="http://msdn.microsoft.com/en-us/library/system.array.setvalue.aspx">Array.SetValue</see>
 ///         instead.
 ///         </description>
 ///     </item>
 ///     <item>
 ///         <term><b>Event</b></term>
 ///         <term><b>Property</b></term>
 ///         <description>
 ///         Events are exposed as read-only properties of type <see cref="EventSource{T}"/>.
 ///         </description>
 ///     </item>
 /// </list>
 /// </para>
 /// </remarks>
 public void AddHostObject(string itemName, HostItemFlags flags, object target)
 {
     MiscHelpers.VerifyNonNullArgument(target, "target");
     AddHostItem(itemName, flags, target);
 }
Esempio n. 10
0
 private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
 {
     return(new HostItem(engine, target, flags));
 }
Esempio n. 11
0
 internal abstract object MarshalToScript(object obj, HostItemFlags flags);
Esempio n. 12
0
 internal abstract void AddHostItem(string itemName, HostItemFlags flags, object item);
Esempio n. 13
0
 /// <summary>
 /// Exposes a host type to script code with the specified options. The type is specified by
 /// type name and assembly name.
 /// </summary>
 /// <param name="itemName">A name for the new global script item that will represent the type.</param>
 /// <param name="flags">A value that selects options for the operation.</param>
 /// <param name="typeName">The fully qualified name of the type to expose.</param>
 /// <param name="assemblyName">The name of the assembly that contains the type to expose.</param>
 /// <param name="typeArgs">Optional generic type arguments.</param>
 /// <remarks>
 /// Host types are exposed to script code in the form of objects whose properties and
 /// methods are bound to the type's static members and nested types. If the type has
 /// generic parameters, the corresponding object will be invocable with type arguments to
 /// yield a specific type.
 /// <para>
 /// For more information about the mapping between host members and script-callable
 /// properties and methods, see <see cref="AddHostObject(string, HostItemFlags, object)"/>.
 /// </para>
 /// </remarks>
 public void AddHostType(string itemName, HostItemFlags flags, string typeName, string assemblyName, params Type[] typeArgs)
 {
     AddHostItem(itemName, flags, TypeHelpers.ImportType(typeName, assemblyName, true, typeArgs));
 }
Esempio n. 14
0
 internal override object MarshalToScript(object obj, HostItemFlags flags)
 {
     throw new PlatformNotSupportedException();
 }
 private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
 {
     return(TargetSupportsExpandoMembers(target, flags) ? new DispatchExHostItem(engine, target, flags) : new HostItem(engine, target, flags));
 }
Esempio n. 16
0
 internal override object MarshalToScript(object obj, HostItemFlags flags)
 {
     return(MarshalToScriptInternal(obj, flags, null));
 }
Esempio n. 17
0
 public DispatchExHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags)
     : base(engine, target, flags)
 {
     EnsurePatched();
 }
Esempio n. 18
0
        private object MarshalToScriptInternal(object obj, HostItemFlags flags, HashSet <Array> marshaledArraySet)
        {
            if (obj == null)
            {
                if (engineFlags.HasFlag(WindowsScriptEngineFlags.MarshalNullAsDispatch))
                {
                    return(nullDispatch);
                }

                return(DBNull.Value);
            }

            if (obj is Undefined)
            {
                return(null);
            }

            if (obj is Nonexistent)
            {
                return(null);
            }

            if (engineFlags.HasFlag(WindowsScriptEngineFlags.MarshalDecimalAsCurrency) && (obj is decimal))
            {
                return(new CurrencyWrapper(obj));
            }

            var hostItem = obj as HostItem;

            if (hostItem != null)
            {
                if ((hostItem.Engine == this) && (hostItem.Flags == flags))
                {
                    return(obj);
                }

                obj = hostItem.Target;
            }

            var hostTarget = obj as HostTarget;

            if ((hostTarget != null) && !(hostTarget is IHostVariable))
            {
                obj = hostTarget.Target;
            }

            var scriptItem = obj as ScriptItem;

            if (scriptItem != null)
            {
                if (scriptItem.Engine == this)
                {
                    return(scriptItem.Unwrap());
                }
            }

            if (engineFlags.HasFlag(WindowsScriptEngineFlags.MarshalArraysByValue))
            {
                var array = obj as Array;
                if ((array != null) && ((hostTarget == null) || (typeof(Array).IsAssignableFrom(hostTarget.Type))))
                {
                    bool alreadyMarshaled;
                    if (marshaledArraySet != null)
                    {
                        alreadyMarshaled = marshaledArraySet.Contains(array);
                    }
                    else
                    {
                        marshaledArraySet = new HashSet <Array>();
                        alreadyMarshaled  = false;
                    }

                    if (!alreadyMarshaled)
                    {
                        marshaledArraySet.Add(array);
                        var dimensions     = Enumerable.Range(0, array.Rank).ToArray();
                        var marshaledArray = Array.CreateInstance(typeof(object), dimensions.Select(array.GetLength).ToArray(), dimensions.Select(array.GetLowerBound).ToArray());
                        array.Iterate(indices => marshaledArray.SetValue(MarshalToScriptInternal(array.GetValue(indices), flags, marshaledArraySet), indices));
                        return(marshaledArray);
                    }

                    // COM interop can't handle circularly referenced arrays
                    return(MarshalToScriptInternal(null, flags, marshaledArraySet));
                }
            }

            return(HostItem.Wrap(this, hostTarget ?? obj, flags));
        }
Esempio n. 19
0
 /// <summary>
 /// Exposes a host object to script code with the specified type restriction and options.
 /// </summary>
 /// <typeparam name="T">The type whose members are to be made accessible from script code.</typeparam>
 /// <param name="itemName">A name for the new global script item that will represent the object.</param>
 /// <param name="flags">A value that selects options for the operation.</param>
 /// <param name="target">The object to expose.</param>
 /// <remarks>
 /// This method can be used to restrict script access to the members of a particular
 /// interface or base class.
 /// <para>
 /// For information about the mapping between host members and script-callable properties
 /// and methods, see <see cref="AddHostObject(string, HostItemFlags, object)"/>.
 /// </para>
 /// </remarks>
 public void AddRestrictedHostObject <T>(string itemName, HostItemFlags flags, T target)
 {
     AddHostItem(itemName, flags, HostItem.Wrap(this, target, typeof(T)));
 }
Esempio n. 20
0
 internal override void AddHostItem(string itemName, HostItemFlags flags, object item)
 {
     throw new PlatformNotSupportedException();
 }
Esempio n. 21
0
 /// <summary>
 /// Exposes a host type to script code with the specified options.
 /// </summary>
 /// <param name="itemName">A name for the new global script item that will represent the type.</param>
 /// <param name="flags">A value that selects options for the operation.</param>
 /// <param name="type">The type to expose.</param>
 /// <remarks>
 /// Host types are exposed to script code in the form of objects whose properties and
 /// methods are bound to the type's static members and nested types. If the type has
 /// generic parameters, the corresponding object will be invocable with type arguments to
 /// yield a specific type.
 /// <para>
 /// For more information about the mapping between host members and script-callable
 /// properties and methods, see <see cref="AddHostObject(string, HostItemFlags, object)"/>.
 /// </para>
 /// </remarks>
 public void AddHostType(string itemName, HostItemFlags flags, Type type)
 {
     MiscHelpers.VerifyNonNullArgument(type, "type");
     AddHostItem(itemName, flags, HostType.Wrap(type));
 }
Esempio n. 22
0
 /// <summary>
 /// Exposes a host type to script code with the specified options. The type is specified by name.
 /// </summary>
 /// <param name="itemName">A name for the new global script item that will represent the type.</param>
 /// <param name="flags">A value that selects options for the operation.</param>
 /// <param name="typeName">The fully qualified name of the type to expose.</param>
 /// <param name="typeArgs">Optional generic type arguments.</param>
 /// <remarks>
 /// Host types are exposed to script code in the form of objects whose properties and
 /// methods are bound to the type's static members and nested types. If the type has
 /// generic parameters, the corresponding object will be invocable with type arguments to
 /// yield a specific type.
 /// <para>
 /// For more information about the mapping between host members and script-callable
 /// properties and methods, see <see cref="AddHostObject(string, HostItemFlags, object)"/>.
 /// </para>
 /// </remarks>
 public void AddHostType(string itemName, HostItemFlags flags, string typeName, params Type[] typeArgs)
 {
     AddHostItem(itemName, flags, TypeHelpers.ImportType(typeName, null, false, typeArgs));
 }
Esempio n. 23
0
            // ReSharper disable MemberCanBeProtected.Local

            public ExpandoHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags)
                : base(engine, target, flags)
            {
            }