// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.ClearScript.Util;
namespace Microsoft.ClearScript
{
///
/// Provides the base implementation for all script engines.
///
public abstract class ScriptEngine : IDisposable
{
#region data
private Type accessContext;
private ScriptAccess defaultAccess;
private bool enforceAnonymousTypeAccess;
private bool exposeHostObjectStaticMembers;
private DocumentSettings documentSettings;
private readonly DocumentSettings defaultDocumentSettings = new DocumentSettings();
private static readonly IUniqueNameManager nameManager = new UniqueNameManager();
private static readonly object nullHostObjectProxy = new object();
[ThreadStatic] private static ScriptEngine currentEngine;
#endregion
#region constructors
///
/// Initializes a new script engine instance.
///
/// A name to associate with the instance. Currently this name is used only as a label in presentation contexts such as debugger user interfaces.
[Obsolete("Use ScriptEngine(string name, string fileNameExtensions) instead.")]
protected ScriptEngine(string name)
: this(name, null)
{
}
///
/// Initializes a new script engine instance with the specified list of supported file name extensions.
///
/// A name to associate with the instance. Currently this name is used only as a label in presentation contexts such as debugger user interfaces.
/// A semicolon-delimited list of supported file name extensions.
protected ScriptEngine(string name, string fileNameExtensions)
{
Name = nameManager.GetUniqueName(name, GetType().GetRootName());
defaultDocumentSettings.FileNameExtensions = fileNameExtensions;
extensionMethodTable = realExtensionMethodTable = new ExtensionMethodTable();
}
#endregion
#region public members
///
/// Gets the name associated with the script engine instance.
///
public string Name { get; }
///
/// Gets the script engine that is invoking a host member on the current thread.
///
///
/// If multiple script engines are invoking host members on the current thread, this
/// property gets the one responsible for the most deeply nested invocation. If no script
/// engines are invoking host members on the current thread, this property returns
/// null.
///
public static ScriptEngine Current => currentEngine;
///
/// Gets the script engine's recommended file name extension for script files.
///
public abstract string FileNameExtension { get; }
///
/// Allows script code to access non-public host resources.
///
///
/// By setting this property to a type you declare that script code running in the current
/// script engine is to be treated as if it were part of that type's implementation. Doing
/// so does not expose any host resources to script code, but it affects which host
/// resources are importable and which members of exposed resources are accessible.
///
public Type AccessContext
{
get => accessContext;
set
{
accessContext = value;
OnAccessSettingsChanged();
}
}
///
/// Gets or sets the default script access setting for all members of exposed objects.
///
///
/// Use , , or
/// their subclasses to override this property for individual types and members. Note that
/// this property has no effect on the method binding algorithm. If a script-based call is
/// bound to a method that is blocked by this property, it will be rejected even if an
/// overload exists that could receive the call.
///
public ScriptAccess DefaultAccess
{
get => defaultAccess;
set
{
defaultAccess = value;
OnAccessSettingsChanged();
}
}
///
/// Enables or disables access restrictions for anonymous types.
///
///
/// Anonymous types are
/// internal
/// and therefore accessible only within the same assembly, but ClearScript 5.5.3 and
/// earlier permitted access to the public properties of an object even if its type was
/// internal. Newer versions strictly enforce , but because
/// anonymous types are particularly useful for scripting, ClearScript by default continues
/// to expose their properties to external contexts. To override this behavior and enable
/// normal access restrictions for anonymous types, set this property to true.
///
public bool EnforceAnonymousTypeAccess
{
get => enforceAnonymousTypeAccess;
set
{
enforceAnonymousTypeAccess = value;
OnAccessSettingsChanged();
}
}
///
/// Controls whether host objects provide access to the static members of their exposed types to script code.
///
public bool ExposeHostObjectStaticMembers
{
get => exposeHostObjectStaticMembers;
set
{
exposeHostObjectStaticMembers = value;
OnAccessSettingsChanged();
}
}
///
/// Enables or disables extension method support.
///
public bool DisableExtensionMethods
{
get => extensionMethodTable == emptyExtensionMethodTable;
set
{
var newExtensionMethodTable = value ? emptyExtensionMethodTable : realExtensionMethodTable;
if (newExtensionMethodTable != extensionMethodTable)
{
ScriptInvoke(() =>
{
if (newExtensionMethodTable != extensionMethodTable)
{
extensionMethodTable = newExtensionMethodTable;
bindCache.Clear();
OnAccessSettingsChanged();
}
});
}
}
}
///
/// Enables or disables script code formatting.
///
///
/// When this property is set to true, the script engine may format script code
/// before executing or compiling it. This is intended to facilitate interactive debugging.
/// The formatting operation currently includes stripping leading and trailing blank lines
/// and removing global indentation.
///
public bool FormatCode { get; set; }
///
/// Controls whether script code is permitted to use reflection.
///
///
/// When this property is set to true, script code running in the current script
/// engine is permitted to use reflection. This affects
/// Object.GetType(),
/// Exception.GetType(),
/// Delegate.Method,
/// and .
/// By default, any attempt to invoke these members from script code results in an
/// exception.
///
public bool AllowReflection { get; set; }
///
/// Enables or disables type restriction for field, property, and method return values.
///
///
/// When this property is set to true, script code running in the current script
/// engine has access to the runtime types of all exposed host resources, which by default
/// are restricted to their declared types. The default behavior is a general requirement
/// for correct method binding, so setting this property to true is not recommended.
///
///
public bool DisableTypeRestriction { get; set; }
///
/// Enables or disables type restriction for array and list elements retrieved by index.
///
///
/// In ClearScript 5.4.4 and earlier, indexed array and list elements were exempt from type
/// restriction. ClearScript 5.4.5 introduced a breaking change to correct this, but you can
/// set this property to true to restore the exemption if you have older script code
/// that depends on it.
///
///
public bool DisableListIndexTypeRestriction { get; set; }
///
/// Enables or disables null wrapping for field, property, and method return values.
///
///
/// When this property is set to true, all field, property, and method return values
/// are marshaled with full .NET type information even if they are null. Note that
/// such values will always fail equality comparison with JavaScript's
/// null,
/// VBScript's
/// Nothing,
/// and other similar values. Instead, use or
/// to perform such a comparison.
///
///
///
public bool EnableNullResultWrapping { get; set; }
///
/// Enables or disables floating point narrowing.
///
///
/// When this property is set to true, no attempt is made to convert floating-point
/// values imported from the script engine to the narrowest equivalent .NET representation.
/// The default behavior is more likely to result in successful method binding in specific
/// scenarios, so setting this property to true is not recommended.
///
public bool DisableFloatNarrowing { get; set; }
///
/// Enables or disables the use of reflection-based method binding as a fallback.
///
///
/// When this property is set to true, the script engine attempts to use
/// reflection-based method binding when the default method binding algorithm fails. This
/// approach reduces type safety, but it may be useful for running legacy scripts that rely
/// on the specific behavior of reflection-based method binding.
///
public bool UseReflectionBindFallback { get; set; }
///
/// Enables or disables automatic host variable tunneling for by-reference arguments to script functions and delegates.
///
///
/// When this property is set to true, the script engine replaces by-reference
/// arguments to script functions and delegates with host variables, allowing script code
/// to simulate output arguments if the script language does not support them natively.
///
///
public bool EnableAutoHostVariables { get; set; }
///
/// Gets or sets the engine's undefined import value.
///
///
/// Some script languages support one or more special non-null values that represent
/// nonexistent, missing, unknown, or undefined data. When such a value is marshaled to the
/// host, the script engine maps it to the value of this property. The default value is
/// .
///
public object UndefinedImportValue { get; set; } = Undefined.Value;
///
/// Gets or sets a callback that can be used to halt script execution.
///
///
/// During script execution the script engine periodically invokes this callback to
/// determine whether it should continue. If the callback returns false, the script
/// engine terminates script execution and throws an exception.
///
public ContinuationCallback ContinuationCallback { get; set; }
///
/// Allows the host to access script resources dynamically.
///
///
/// The value of this property is an object that is bound to the script engine's root
/// namespace. It dynamically supports properties and methods that correspond to global
/// script objects and functions.
///
public abstract dynamic Script { get; }
///
/// Allows the host to access script resources.
///
///
/// The value of this property is an object that is bound to the script engine's root
/// namespace. It allows you to access global script resources via the
/// class interface. Doing so is likely to perform better than
/// dynamic access via .
///
public abstract ScriptObject Global { get; }
///
/// Gets or sets the script engine's document settings.
///
public DocumentSettings DocumentSettings
{
get => documentSettings ?? defaultDocumentSettings;
set => documentSettings = value;
}
///
/// Exposes a host object to script code.
///
/// A name for the new global script item that will represent the object.
/// The object to expose.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddHostObject(string itemName, object target)
{
AddHostObject(itemName, HostItemFlags.None, target);
}
///
/// Exposes a host object to script code with the specified options.
///
/// A name for the new global script item that will represent the object.
/// A value that selects options for the operation.
/// The object to expose.
///
///
/// 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.
///
///
///
///
/// Member Type
/// Exposed As
/// Remarks
///
///
/// Constructor
/// N/A
///
/// To invoke a constructor from script code, call
/// HostFunctions.newObj(T).
///
///
///
/// Property/Field
/// Property
/// N/A
///
///
/// Method
/// Method
///
/// Overloaded host methods are merged into a single script-callable method. At
/// runtime the correct host method is selected based on the argument types.
///
///
///
/// Generic Method
/// Method
///
/// 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
/// host type objects
/// at the beginning of the argument list. Doing so for methods that do not require
/// explicit type arguments is optional.
///
///
///
/// Extension Method
/// Method
///
/// Extension methods are available if the type that implements them has been
/// exposed in the current script engine.
///
///
///
/// Indexer
/// Property
///
/// Indexers appear as properties named "Item" that accept one or more index values
/// as arguments. In addition, objects that implement 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
/// Array.GetValue
/// and
/// Array.SetValue
/// instead.
///
///
///
/// Event
/// Property
///
/// Events are exposed as read-only properties of type .
///
///
///
///
///
public void AddHostObject(string itemName, HostItemFlags flags, object target)
{
MiscHelpers.VerifyNonNullArgument(target, nameof(target));
AddHostItem(itemName, flags, target);
}
///
/// Exposes a host object to script code with the specified type restriction.
///
/// The type whose members are to be made accessible from script code.
/// A name for the new global script item that will represent the object.
/// The object to expose.
///
///
/// This method can be used to restrict script access to the members of a particular
/// interface or base class.
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddRestrictedHostObject(string itemName, T target)
{
AddRestrictedHostObject(itemName, HostItemFlags.None, target);
}
///
/// Exposes a host object to script code with the specified type restriction and options.
///
/// The type whose members are to be made accessible from script code.
/// A name for the new global script item that will represent the object.
/// A value that selects options for the operation.
/// The object to expose.
///
///
/// This method can be used to restrict script access to the members of a particular
/// interface or base class.
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddRestrictedHostObject(string itemName, HostItemFlags flags, T target)
{
AddHostItem(itemName, flags, HostItem.Wrap(this, target, typeof(T)));
}
///
/// Creates a COM/ActiveX object and exposes it to script code. The registered class is
/// specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the object.
/// The programmatic identifier (ProgID) of the registered class to instantiate.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMObject(string itemName, string progID)
{
AddCOMObject(itemName, HostItemFlags.None, progID);
}
///
/// Creates a COM/ActiveX object on the specified server and exposes it to script code. The
/// registered class is specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the object.
/// The programmatic identifier (ProgID) of the registered class to instantiate.
/// The name of the server on which to create the object.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMObject(string itemName, string progID, string serverName)
{
AddCOMObject(itemName, HostItemFlags.None, progID, serverName);
}
///
/// Creates a COM/ActiveX object and exposes it to script code with the specified options.
/// The registered class is specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the object.
/// A value that selects options for the operation.
/// The programmatic identifier (ProgID) of the registered class to instantiate.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMObject(string itemName, HostItemFlags flags, string progID)
{
AddCOMObject(itemName, flags, progID, null);
}
///
/// Creates a COM/ActiveX object on the specified server and exposes it to script code with
/// the specified options. The registered class is specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the object.
/// A value that selects options for the operation.
/// The programmatic identifier (ProgID) of the registered class to instantiate.
/// The name of the server on which to create the object.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMObject(string itemName, HostItemFlags flags, string progID, string serverName)
{
AddHostItem(itemName, flags, MiscHelpers.CreateCOMObject(progID, serverName));
}
///
/// Creates a COM/ActiveX object and exposes it to script code. The registered class is
/// specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the object.
/// The class identifier (CLSID) of the registered class to instantiate.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMObject(string itemName, Guid clsid)
{
AddCOMObject(itemName, HostItemFlags.None, clsid);
}
///
/// Creates a COM/ActiveX object on the specified server and exposes it to script code. The
/// registered class is specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the object.
/// The class identifier (CLSID) of the registered class to instantiate.
/// The name of the server on which to create the object.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMObject(string itemName, Guid clsid, string serverName)
{
AddCOMObject(itemName, HostItemFlags.None, clsid, serverName);
}
///
/// Creates a COM/ActiveX object and exposes it to script code with the specified options.
/// The registered class is specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the object.
/// A value that selects options for the operation.
/// The class identifier (CLSID) of the registered class to instantiate.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMObject(string itemName, HostItemFlags flags, Guid clsid)
{
AddCOMObject(itemName, flags, clsid, null);
}
///
/// Creates a COM/ActiveX object on the specified server and exposes it to script code with
/// the specified options. The registered class is specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the object.
/// A value that selects options for the operation.
/// The class identifier (CLSID) of the registered class to instantiate.
/// The name of the server on which to create the object.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMObject(string itemName, HostItemFlags flags, Guid clsid, string serverName)
{
AddHostItem(itemName, flags, MiscHelpers.CreateCOMObject(clsid, serverName));
}
///
/// Exposes a host type to script code with a default name.
///
/// The type to expose.
///
///
/// This method uses 's name for the new global script item that
/// will represent it.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(Type type)
{
AddHostType(HostItemFlags.None, type);
}
///
/// Exposes a host type to script code with a default name and the specified options.
///
/// A value that selects options for the operation.
/// The type to expose.
///
///
/// This method uses 's name for the new global script item that
/// will represent it.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(HostItemFlags flags, Type type)
{
AddHostType(type.GetRootName(), flags, type);
}
///
/// Exposes a host type to script code.
///
/// A name for the new global script item that will represent the type.
/// The type to expose.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(string itemName, Type type)
{
AddHostType(itemName, HostItemFlags.None, type);
}
///
/// Exposes a host type to script code with the specified options.
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The type to expose.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(string itemName, HostItemFlags flags, Type type)
{
MiscHelpers.VerifyNonNullArgument(type, nameof(type));
AddHostItem(itemName, flags, HostType.Wrap(type));
}
///
/// Exposes a host type to script code. The type is specified by name.
///
/// A name for the new global script item that will represent the type.
/// The fully qualified name of the type to expose.
/// Optional generic type arguments.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(string itemName, string typeName, params Type[] typeArgs)
{
AddHostType(itemName, HostItemFlags.None, typeName, typeArgs);
}
///
/// Exposes a host type to script code with the specified options. The type is specified by name.
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The fully qualified name of the type to expose.
/// Optional generic type arguments.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(string itemName, HostItemFlags flags, string typeName, params Type[] typeArgs)
{
AddHostItem(itemName, flags, TypeHelpers.ImportType(typeName, null, false, typeArgs));
}
///
/// Exposes a host type to script code. The type is specified by type name and assembly name.
///
/// A name for the new global script item that will represent the type.
/// The fully qualified name of the type to expose.
/// The name of the assembly that contains the type to expose.
/// Optional generic type arguments.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(string itemName, string typeName, string assemblyName, params Type[] typeArgs)
{
AddHostType(itemName, HostItemFlags.None, typeName, assemblyName, typeArgs);
}
///
/// Exposes a host type to script code with the specified options. The type is specified by
/// type name and assembly name.
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The fully qualified name of the type to expose.
/// The name of the assembly that contains the type to expose.
/// Optional generic type arguments.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostType(string itemName, HostItemFlags flags, string typeName, string assemblyName, params Type[] typeArgs)
{
AddHostItem(itemName, flags, TypeHelpers.ImportType(typeName, assemblyName, true, typeArgs));
}
///
/// Exposes host types to script code.
///
/// The types to expose.
///
///
/// This method uses each specified type's name for the new global script item that will
/// represent it.
///
///
/// 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.
///
///
/// For more information about the mapping between host members and script-callable
/// properties and methods, see .
///
///
public void AddHostTypes(params Type[] types)
{
if (types != null)
{
foreach (var type in types)
{
if (type != null)
{
AddHostType(type);
}
}
}
}
///
/// Imports a COM/ActiveX type and exposes it to script code. The registered class is
/// specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the type.
/// The programmatic identifier (ProgID) of the registered class to import.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMType(string itemName, string progID)
{
AddCOMType(itemName, HostItemFlags.None, progID);
}
///
/// Imports a COM/ActiveX type from the specified server and exposes it to script code. The
/// registered class is specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the type.
/// The programmatic identifier (ProgID) of the registered class to import.
/// The name of the server from which to import the type.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMType(string itemName, string progID, string serverName)
{
AddCOMType(itemName, HostItemFlags.None, progID, serverName);
}
///
/// Imports a COM/ActiveX type and exposes it to script code with the specified options.
/// The registered class is specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The programmatic identifier (ProgID) of the registered class to import.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMType(string itemName, HostItemFlags flags, string progID)
{
AddCOMType(itemName, flags, progID, null);
}
///
/// Imports a COM/ActiveX type from the specified server and exposes it to script code with
/// the specified options. The registered class is specified by programmatic identifier (ProgID).
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The programmatic identifier (ProgID) of the registered class to import.
/// The name of the server from which to import the type.
///
///
/// The argument can be a class identifier (CLSID) in standard
/// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}").
///
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
///
public void AddCOMType(string itemName, HostItemFlags flags, string progID, string serverName)
{
AddHostItem(itemName, flags, HostType.Wrap(MiscHelpers.GetCOMType(progID, serverName)));
}
///
/// Imports a COM/ActiveX type and exposes it to script code. The registered class is
/// specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the type.
/// The class identifier (CLSID) of the registered class to import.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMType(string itemName, Guid clsid)
{
AddCOMType(itemName, HostItemFlags.None, clsid);
}
///
/// Imports a COM/ActiveX type from the specified server and exposes it to script code. The
/// registered class is specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the type.
/// The class identifier (CLSID) of the registered class to import.
/// The name of the server from which to import the type.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMType(string itemName, Guid clsid, string serverName)
{
AddCOMType(itemName, HostItemFlags.None, clsid, serverName);
}
///
/// Imports a COM/ActiveX type and exposes it to script code with the specified options.
/// The registered class is specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The class identifier (CLSID) of the registered class to import.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMType(string itemName, HostItemFlags flags, Guid clsid)
{
AddCOMType(itemName, flags, clsid, null);
}
///
/// Imports a COM/ActiveX type from the specified server and exposes it to script code with
/// the specified options. The registered class is specified by class identifier (CLSID).
///
/// A name for the new global script item that will represent the type.
/// A value that selects options for the operation.
/// The class identifier (CLSID) of the registered class to import.
/// The name of the server from which to import the type.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see .
///
public void AddCOMType(string itemName, HostItemFlags flags, Guid clsid, string serverName)
{
AddHostItem(itemName, flags, HostType.Wrap(MiscHelpers.GetCOMType(clsid, serverName)));
}
///
/// Executes script code.
///
/// The script code to execute.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as a statement.
///
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with an automatically selected name. This document will not be discarded
/// after execution.
///
///
public void Execute(string code)
{
Execute(null, code);
}
///
/// Executes script code with an associated document name.
///
/// A document name for the script code. Currently this name is used only as a label in presentation contexts such as debugger user interfaces.
/// The script code to execute.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as a statement.
///
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with the specified name. This document will not be discarded after execution.
///
///
public void Execute(string documentName, string code)
{
Execute(documentName, false, code);
}
///
/// Executes script code with an associated document name, optionally discarding the document after execution.
///
/// A document name for the script code. Currently this name is used only as a label in presentation contexts such as debugger user interfaces.
/// True to discard the script document after execution, false otherwise.
/// The script code to execute.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as a statement.
///
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with the specified name. Discarding this document removes it from view but
/// has no effect on the script engine. Only Windows Script engines honor
/// .
///
///
public void Execute(string documentName, bool discard, string code)
{
Execute(new DocumentInfo(documentName) { Flags = discard ? DocumentFlags.IsTransient : DocumentFlags.None }, code);
}
///
/// Executes script code with the specified document meta-information.
///
/// A structure containing meta-information for the script document.
/// The script code to execute.
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as a statement.
///
public void Execute(DocumentInfo documentInfo, string code)
{
Execute(documentInfo.MakeUnique(this), code, false);
}
///
/// Loads and executes a script document.
///
/// A string specifying the document to be loaded and executed.
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets script code loaded from the specified document as a statement.
///
public void ExecuteDocument(string specifier)
{
ExecuteDocument(specifier, null);
}
///
/// Loads and executes a document with the specified category.
///
/// A string specifying the document to be loaded and executed.
/// An optional category for the requested document.
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets script code loaded from the specified document as a statement.
///
public void ExecuteDocument(string specifier, DocumentCategory category)
{
ExecuteDocument(specifier, category, null);
}
///
/// Loads and executes a document with the specified category and context callback.
///
/// A string specifying the document to be loaded and executed.
/// An optional category for the requested document.
/// An optional context callback for the requested document.
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets script code loaded from the specified document as a statement.
///
public void ExecuteDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback)
{
MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier");
var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback);
Execute(document.Info, document.GetTextContents());
}
///
/// Executes script code as a command.
///
/// The script command to execute.
/// The command output.
///
/// This method is similar to but optimized for command
/// consoles. The specified command must be limited to a single expression or statement.
/// Script engines can override this method to customize command execution as well as the
/// process of converting the result to a string for console output.
///
public virtual string ExecuteCommand(string command)
{
var documentInfo = new DocumentInfo("Command") { Flags = DocumentFlags.IsTransient };
return GetCommandResultString(Evaluate(documentInfo.MakeUnique(this), command, false));
}
///
/// Evaluates script code.
///
/// The script code to evaluate.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as an expression.
///
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with an automatically selected name. This document will be discarded after
/// execution.
///
///
/// For information about the types of result values that script code can return, see
/// .
///
///
public object Evaluate(string code)
{
return Evaluate(null, code);
}
///
/// Evaluates script code with an associated document name.
///
/// A document name for the script code. Currently this name is used only as a label in presentation contexts such as debugger user interfaces.
/// The script code to evaluate.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as an expression.
///
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with the specified name. This document will be discarded after execution.
///
///
/// For information about the types of result values that script code can return, see
/// .
///
///
public object Evaluate(string documentName, string code)
{
return Evaluate(documentName, true, code);
}
///
/// Evaluates script code with an associated document name, optionally discarding the document after execution.
///
/// A document name for the script code. Currently this name is used only as a label in presentation contexts such as debugger user interfaces.
/// True to discard the script document after execution, false otherwise.
/// The script code to evaluate.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as an expression.
///
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with the specified name. Discarding this document removes it from view but
/// has no effect on the script engine. Only Windows Script engines honor
/// .
///
///
/// The following table summarizes the types of result values that script code can return.
///
///
/// Type
/// Returned As
/// Remarks
///
///
/// String
/// System.String
/// N/A
///
///
/// Boolean
/// System.Boolean
/// N/A
///
///
/// Number
/// System.Int32 or System.Double
///
/// Other numeric types are possible. The exact conversions between script and .NET
/// numeric types are defined by the script engine.
///
///
///
/// Null Reference
/// null
/// N/A
///
///
/// Undefined
///
///
/// This represents JavaScript's
/// undefined,
/// VBScript's
/// Empty,
/// etc.
///
///
///
/// Void
///
///
/// This is returned when script code forwards the result of a host method that returns no value.
///
///
///
/// Host Object
/// Native .NET type
///
/// This includes all .NET types not mentioned above, including value types (enums,
/// structs, etc.), and instances of all other classes. Script code can only create
/// these objects by invoking a host method or constructor. They are returned to
/// the host in their native .NET form.
///
///
///
/// Script Object
///
///
/// This includes all native script objects that have no .NET representation. C#'s
/// dynamic
/// keyword provides a convenient way to access them.
///
///
///
/// Other
/// Unspecified
///
/// This includes host types and other ClearScript-specific objects intended for
/// script code use only. It may also include language-specific values that the
/// ClearScript library does not support.
///
///
///
///
///
public object Evaluate(string documentName, bool discard, string code)
{
return Evaluate(new DocumentInfo(documentName) { Flags = discard ? DocumentFlags.IsTransient : DocumentFlags.None }, code);
}
///
/// Evaluates script code with the specified document meta-information.
///
/// A structure containing meta-information for the script document.
/// The script code to evaluate.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets the specified script code as an expression.
///
///
/// For information about the types of result values that script code can return, see
/// .
///
///
public object Evaluate(DocumentInfo documentInfo, string code)
{
return Evaluate(documentInfo.MakeUnique(this, DocumentFlags.IsTransient), code, true);
}
///
/// Loads and evaluates a script document.
///
/// A string specifying the document to be loaded and evaluated.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets script code loaded from the specified document as an expression.
///
///
/// For information about the types of result values that script code can return, see
/// .
///
///
public object EvaluateDocument(string specifier)
{
return EvaluateDocument(specifier, null);
}
///
/// Loads and evaluates a document with the specified category.
///
/// A string specifying the document to be loaded and evaluated.
/// An optional category for the requested document.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets script code loaded from the specified document as an expression.
///
///
/// For information about the types of result values that script code can return, see
/// .
///
///
public object EvaluateDocument(string specifier, DocumentCategory category)
{
return EvaluateDocument(specifier, category, null);
}
///
/// Loads and evaluates a document with the specified category and context callback.
///
/// A string specifying the document to be loaded and evaluated.
/// An optional category for the requested document.
/// An optional context callback for the requested document.
/// The result value.
///
///
/// In some script languages the distinction between statements and expressions is
/// significant but ambiguous for certain syntactic elements. This method always
/// interprets script code loaded from the specified document as an expression.
///
///
/// For information about the types of result values that script code can return, see
/// .
///
///
public object EvaluateDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback)
{
MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier");
var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback);
return Evaluate(document.Info, document.GetTextContents());
}
///
/// Invokes a global function or procedure.
///
/// The name of the global function or procedure to invoke.
/// Optional invocation arguments.
/// The return value if a function was invoked, an undefined value otherwise.
public object Invoke(string funcName, params object[] args)
{
MiscHelpers.VerifyNonBlankArgument(funcName, nameof(funcName), "Invalid function name");
return ((IDynamic)Script).InvokeMethod(funcName, args ?? ArrayHelpers.GetEmptyArray