Skip to content

Commit

Permalink
Added the EmbedHostType method (embeds a host type to script code)
Browse files Browse the repository at this point in the history
  • Loading branch information
Taritsyn committed Feb 26, 2016
1 parent 6c288c3 commit 3d8246f
Show file tree
Hide file tree
Showing 24 changed files with 1,356 additions and 689 deletions.
456 changes: 397 additions & 59 deletions src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.cs

Large diffs are not rendered by default.

494 changes: 0 additions & 494 deletions src/MsieJavaScriptEngine/ActiveScript/ActiveScriptSiteWrapper.cs

This file was deleted.

10 changes: 10 additions & 0 deletions src/MsieJavaScriptEngine/Constants/SpecialMemberName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MsieJavaScriptEngine.Constants
{
/// <summary>
/// Special member names
/// </summary>
internal static class SpecialMemberName
{
public const string Default = "[DISPID=0]";
}
}
184 changes: 184 additions & 0 deletions src/MsieJavaScriptEngine/HostItemBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
namespace MsieJavaScriptEngine
{
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;

/// <summary>
/// Base class of item, that implements <see cref="IReflect"/> interface
/// </summary>
internal abstract class HostItemBase : IReflect
{
/// <summary>
/// Target type
/// </summary>
protected readonly Type _type;

/// <summary>
/// Target object
/// </summary>
protected readonly object _target;

/// <summary>
/// JavaScript engine mode
/// </summary>
protected readonly JsEngineMode _engineMode;

/// <summary>
/// List of fields
/// </summary>
private readonly FieldInfo[] _fields;

/// <summary>
/// List of properties
/// </summary>
private readonly PropertyInfo[] _properties;

/// <summary>
/// List of methods
/// </summary>
private readonly MethodInfo[] _methods;

/// <summary>
/// Gets a target object
/// </summary>
public object Target
{
get { return _target; }
}


/// <summary>
/// Constructs an instance of the wrapper for item, that implements <see cref="IReflect"/> interface
/// </summary>
/// <param name="type">Target type</param>
/// <param name="target">Target object</param>
/// <param name="engineMode">JavaScript engine mode</param>
/// <param name="instance">Flag for whether to allow access to members of the instance</param>
protected HostItemBase(Type type, object target, JsEngineMode engineMode, bool instance)
{
_type = type;
_target = target;
_engineMode = engineMode;

BindingFlags bindingFlags = BindingFlags.Public;
if (instance)
{
bindingFlags |= BindingFlags.Instance;
}
else
{
bindingFlags |= BindingFlags.Static;
}

_fields = _type.GetFields(bindingFlags);
_properties = _type.GetProperties(bindingFlags);
_methods = _type.GetMethods(bindingFlags);
}


protected abstract object InnerInvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters);

protected object InvokeStandardMember(string name, BindingFlags invokeAttr, Binder binder, object target,
object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
BindingFlags processedInvokeAttr = invokeAttr;
if ((processedInvokeAttr.HasFlag(BindingFlags.GetProperty)
|| processedInvokeAttr.HasFlag(BindingFlags.PutDispProperty))
&& !_properties.Any(p => p.Name == name)
&& _fields.Any(p => p.Name == name))
{
if (processedInvokeAttr.HasFlag(BindingFlags.GetProperty))
{
processedInvokeAttr &= ~BindingFlags.GetProperty;
processedInvokeAttr |= BindingFlags.GetField;
}
else if (processedInvokeAttr.HasFlag(BindingFlags.PutDispProperty))
{
processedInvokeAttr &= ~BindingFlags.PutDispProperty;
processedInvokeAttr |= BindingFlags.SetField;
}
}

object result = _type.InvokeMember(name, processedInvokeAttr, binder, target,
args, modifiers, culture, namedParameters);

return result;
}

#region IReflect implementation

Type IReflect.UnderlyingSystemType
{
get { throw new NotImplementedException(); }
}


FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
{
FieldInfo field = _fields.SingleOrDefault(f => f.Name == name);

return field;
}

FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
{
return _fields;
}

MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
{
throw new NotImplementedException();
}

MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
{
throw new NotImplementedException();
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
{
MethodInfo method = _methods.SingleOrDefault(m => m.Name == name);

return method;
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}

MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
{
return _methods;
}

PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
{
return _properties;
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
{
PropertyInfo property = _properties.SingleOrDefault(p => p.Name == name);

return property;
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder,
Type returnType, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}

object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
return InnerInvokeMember(name, invokeAttr, binder,target, args, modifiers, culture, namedParameters);
}

#endregion
}
}
156 changes: 22 additions & 134 deletions src/MsieJavaScriptEngine/HostObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,172 +5,60 @@
using System.Linq;
using System.Reflection;

using Constants;
using Helpers;

/// <summary>
/// Wrapper for object, that implements <see cref="IReflect"/> interface
/// </summary>
internal class HostObject : IReflect
internal sealed class HostObject : HostItemBase
{
/// <summary>
/// Target object
/// </summary>
private readonly object _target;

/// <summary>
/// Target type
/// </summary>
private readonly Type _type;

/// <summary>
/// JavaScript engine mode
/// </summary>
private readonly JsEngineMode _engineMode;

/// <summary>
/// List of fields
/// </summary>
private readonly FieldInfo[] _fields;

/// <summary>
/// List of properties
/// </summary>
private readonly PropertyInfo[] _properties;

/// <summary>
/// List of methods
/// </summary>
private readonly MethodInfo[] _methods;

/// <summary>
/// Gets a target object
/// </summary>
public object Target
{
get { return _target; }
}


/// <summary>
/// Constructs an instance of the wrapper for object, that implements <see cref="IReflect"/> interface
/// </summary>
/// <param name="target">Target object</param>
/// <param name="engineMode">JavaScript engine mode</param>
public HostObject(object target, JsEngineMode engineMode)
{
_target = target;
_type = target.GetType();
_engineMode = engineMode;

var defaultBindingFlags = BindingFlags.Instance | BindingFlags.Public;
_fields = _type.GetFields(defaultBindingFlags);
_properties = _type.GetProperties(defaultBindingFlags);
_methods = _type.GetMethods(defaultBindingFlags);
}

#region IReflect implementation

Type IReflect.UnderlyingSystemType
{
get { throw new NotImplementedException(); }
}
: base(target.GetType(), target, engineMode, true)
{ }


FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
private object InvokeDelegate(Delegate del, object[] args)
{
FieldInfo field = _fields.SingleOrDefault(f => f.Name == name);

return field;
}

FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
{
return _fields;
}

MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
{
throw new NotImplementedException();
}

MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
{
throw new NotImplementedException();
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
{
MethodInfo method = _methods.SingleOrDefault(m => m.Name == name);

return method;
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
if (del == null)
{
throw new ArgumentNullException("del");
}

MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
{
return _methods;
}
object[] processedArgs = args;

PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
{
return _properties;
}
if (_engineMode == JsEngineMode.Classic && processedArgs.Length > 0)
{
processedArgs = processedArgs.Skip(1).ToArray();
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
{
PropertyInfo property = _properties.SingleOrDefault(p => p.Name == name);
object result = del.DynamicInvoke(processedArgs);

return property;
return result;
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder,
Type returnType, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
#region HostItemBase implementation

object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
protected override object InnerInvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
object result;
object processedTarget = TypeMappingHelpers.MapToHostType(target);
object[] processedArgs = TypeMappingHelpers.MapToHostType(args);

var del = processedTarget as Delegate;
if (del != null)
if (name == SpecialMemberName.Default && processedTarget is Delegate)
{
if (_engineMode == JsEngineMode.Classic && processedArgs.Length > 0)
{
processedArgs = processedArgs.Skip(1).ToArray();
}

result = del.DynamicInvoke(processedArgs);
var del = (Delegate)processedTarget;
result = InvokeDelegate(del, processedArgs);
}
else
{
BindingFlags processedInvokeAttr = invokeAttr;
if ((processedInvokeAttr.HasFlag(BindingFlags.GetProperty)
|| processedInvokeAttr.HasFlag(BindingFlags.PutDispProperty))
&& !_properties.Any(p => p.Name == name)
&& _fields.Any(p => p.Name == name))
{
if (processedInvokeAttr.HasFlag(BindingFlags.GetProperty))
{
processedInvokeAttr &= ~BindingFlags.GetProperty;
processedInvokeAttr |= BindingFlags.GetField;
}
else if (processedInvokeAttr.HasFlag(BindingFlags.PutDispProperty))
{
processedInvokeAttr &= ~BindingFlags.PutDispProperty;
processedInvokeAttr |= BindingFlags.SetField;
}
}

result = _type.InvokeMember(name, processedInvokeAttr, binder, processedTarget,
result = InvokeStandardMember(name, invokeAttr, binder, processedTarget,
processedArgs, modifiers, culture, namedParameters);
}

Expand Down
Loading

0 comments on commit 3d8246f

Please sign in to comment.