Skip to content

Commit a4537d1

Browse files
committed
In version for .NET Framework improved a performance of the embedding of objects and types
1 parent 0e6b776 commit a4537d1

File tree

8 files changed

+81
-60
lines changed

8 files changed

+81
-60
lines changed

src/MsieJavaScriptEngine/Helpers/ReflectionHelpers.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
#if NETSTANDARD
2-
using System;
1+
using System;
2+
#if NETSTANDARD
33
using System.Collections.Generic;
44
using System.Linq;
5+
#endif
56
using System.Reflection;
7+
#if NETSTANDARD
68

79
using MsieJavaScriptEngine.Utilities;
10+
#endif
811

912
namespace MsieJavaScriptEngine.Helpers
1013
{
@@ -28,6 +31,21 @@ public static BindingFlags GetDefaultBindingFlags(bool instance)
2831
return bindingFlags;
2932
}
3033

34+
public static bool IsFullyFledgedMethod(MethodInfo method)
35+
{
36+
if (!method.Attributes.HasFlag(MethodAttributes.SpecialName))
37+
{
38+
return true;
39+
}
40+
41+
string name = method.Name;
42+
bool isFullyFledged = !(name.StartsWith("get_", StringComparison.Ordinal)
43+
|| name.StartsWith("set_", StringComparison.Ordinal));
44+
45+
return isFullyFledged;
46+
}
47+
#if NETSTANDARD
48+
3149
public static void FixFieldValueType(ref object value, FieldInfo field)
3250
{
3351
Type valueType = value.GetType();
@@ -208,6 +226,6 @@ public ushort CompatibilityScore
208226
set;
209227
}
210228
}
229+
#endif
211230
}
212-
}
213-
#endif
231+
}

src/MsieJavaScriptEngine/HostItemBase.cs

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#if !NETSTANDARD
22
using System;
33
using System.Globalization;
4-
using System.Linq;
54
using System.Reflection;
65

6+
using MsieJavaScriptEngine.Helpers;
7+
78
namespace MsieJavaScriptEngine
89
{
910
/// <summary>
@@ -22,7 +23,7 @@ internal abstract class HostItemBase : IReflect
2223
protected readonly object _target;
2324

2425
/// <summary>
25-
/// JavaScript engine mode
26+
/// JS engine mode
2627
/// </summary>
2728
protected readonly JsEngineMode _engineMode;
2829

@@ -31,6 +32,11 @@ internal abstract class HostItemBase : IReflect
3132
/// </summary>
3233
private readonly FieldInfo[] _fields;
3334

35+
/// <summary>
36+
/// List of field names
37+
/// </summary>
38+
private string[] _fieldNames;
39+
3440
/// <summary>
3541
/// List of properties
3642
/// </summary>
@@ -63,19 +69,18 @@ protected HostItemBase(Type type, object target, JsEngineMode engineMode, bool i
6369
_target = target;
6470
_engineMode = engineMode;
6571

66-
BindingFlags bindingFlags = BindingFlags.Public;
67-
if (instance)
68-
{
69-
bindingFlags |= BindingFlags.Instance;
70-
}
71-
else
72-
{
73-
bindingFlags |= BindingFlags.Static;
74-
}
75-
76-
_fields = _type.GetFields(bindingFlags);
77-
_properties = _type.GetProperties(bindingFlags);
78-
_methods = _type.GetMethods(bindingFlags);
72+
BindingFlags defaultBindingFlags = ReflectionHelpers.GetDefaultBindingFlags(instance);
73+
FieldInfo[] fields = _type.GetFields(defaultBindingFlags);
74+
string[] fieldNames = fields.Length > 0 ? Array.ConvertAll(fields, f => f.Name) : new string[0];
75+
PropertyInfo[] properties = _type.GetProperties(defaultBindingFlags);
76+
MethodInfo[] methods = _type.GetMethods(defaultBindingFlags);
77+
MethodInfo[] fullyFledgedMethods = methods.Length > 0 ?
78+
Array.FindAll(methods, ReflectionHelpers.IsFullyFledgedMethod) : methods;
79+
80+
_fields = fields;
81+
_fieldNames = fieldNames;
82+
_properties = properties;
83+
_methods = fullyFledgedMethods;
7984
}
8085

8186

@@ -89,8 +94,7 @@ protected object InvokeStandardMember(string name, BindingFlags invokeAttr, Bind
8994
if ((processedInvokeAttr.HasFlag(BindingFlags.GetProperty)
9095
|| processedInvokeAttr.HasFlag(BindingFlags.SetProperty)
9196
|| processedInvokeAttr.HasFlag(BindingFlags.PutDispProperty))
92-
&& !_properties.Any(p => p.Name == name)
93-
&& _fields.Any(p => p.Name == name))
97+
&& Array.IndexOf(_fieldNames, name) != -1)
9498
{
9599
if (processedInvokeAttr.HasFlag(BindingFlags.GetProperty))
96100
{
@@ -125,9 +129,7 @@ Type IReflect.UnderlyingSystemType
125129

126130
FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
127131
{
128-
FieldInfo field = _fields.SingleOrDefault(f => f.Name == name);
129-
130-
return field;
132+
throw new NotImplementedException();
131133
}
132134

133135
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
@@ -147,9 +149,7 @@ MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
147149

148150
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
149151
{
150-
MethodInfo method = _methods.SingleOrDefault(m => m.Name == name);
151-
152-
return method;
152+
throw new NotImplementedException();
153153
}
154154

155155
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
@@ -169,9 +169,7 @@ PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
169169

170170
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
171171
{
172-
PropertyInfo property = _properties.SingleOrDefault(p => p.Name == name);
173-
174-
return property;
172+
throw new NotImplementedException();
175173
}
176174

177175
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder,

src/MsieJavaScriptEngine/HostObject.cs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,52 +14,58 @@ namespace MsieJavaScriptEngine
1414
/// </summary>
1515
internal sealed class HostObject : HostItemBase
1616
{
17+
/// <summary>
18+
/// Number of delegate parameters
19+
/// </summary>
20+
private int _delegateParameterCount = int.MinValue;
21+
22+
1723
/// <summary>
1824
/// Constructs an instance of the wrapper for object, that implements <see cref="IReflect"/> interface
1925
/// </summary>
2026
/// <param name="target">Target object</param>
2127
/// <param name="engineMode">JS engine mode</param>
2228
public HostObject(object target, JsEngineMode engineMode)
2329
: base(target.GetType(), target, engineMode, true)
24-
{ }
25-
26-
27-
private object InvokeDelegate(Delegate del, object[] args)
2830
{
29-
if (del == null)
30-
{
31-
throw new ArgumentNullException(nameof(del));
32-
}
33-
34-
object[] processedArgs = args;
35-
36-
if (_engineMode == JsEngineMode.Classic && processedArgs.Length > 0
37-
&& del.Method.ReturnType != typeof(void))
31+
if (_engineMode == JsEngineMode.Classic)
3832
{
39-
processedArgs = processedArgs.Skip(1).ToArray();
33+
var del = _target as Delegate;
34+
if (del != null)
35+
{
36+
_delegateParameterCount = del.Method.GetParameters().Length;
37+
}
4038
}
41-
42-
object result = del.DynamicInvoke(processedArgs);
43-
44-
return result;
4539
}
4640

41+
4742
#region HostItemBase overrides
4843

4944
protected override object InnerInvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
5045
object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
5146
{
5247
object result;
5348
object processedTarget = TypeMappingHelpers.MapToHostType(target);
54-
object[] processedArgs = TypeMappingHelpers.MapToHostType(args);
5549

5650
if (name == SpecialMemberName.Default && processedTarget is Delegate)
5751
{
5852
var del = (Delegate)processedTarget;
59-
result = InvokeDelegate(del, processedArgs);
53+
object[] processedArgs = args;
54+
55+
if (_engineMode == JsEngineMode.Classic
56+
&& processedArgs.Length > 0
57+
&& (processedArgs.Length - _delegateParameterCount) == 1)
58+
{
59+
processedArgs = processedArgs.Skip(1).ToArray();
60+
}
61+
processedArgs = TypeMappingHelpers.MapToHostType(processedArgs);
62+
63+
result = del.DynamicInvoke(processedArgs);
6064
}
6165
else
6266
{
67+
object[] processedArgs = TypeMappingHelpers.MapToHostType(args);
68+
6369
result = InvokeStandardMember(name, invokeAttr, binder, processedTarget,
6470
processedArgs, modifiers, culture, namedParameters);
6571
}

src/MsieJavaScriptEngine/HostType.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,24 @@ public HostType(Type type, JsEngineMode engineMode)
2929
protected override object InnerInvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
3030
object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
3131
{
32-
object[] processedArgs = TypeMappingHelpers.MapToHostType(args);
3332
object result;
3433

3534
if (name == SpecialMemberName.Default && invokeAttr.HasFlag(BindingFlags.CreateInstance))
3635
{
36+
object[] processedArgs = args;
37+
3738
if (_engineMode != JsEngineMode.Classic && processedArgs.Length > 0)
3839
{
3940
processedArgs = processedArgs.Skip(1).ToArray();
4041
}
42+
processedArgs = TypeMappingHelpers.MapToHostType(processedArgs);
4143

4244
result = Activator.CreateInstance(_type, processedArgs);
4345
}
4446
else
4547
{
48+
object[] processedArgs = TypeMappingHelpers.MapToHostType(args);
49+
4650
result = InvokeStandardMember(name, invokeAttr, binder, target,
4751
processedArgs, modifiers, culture, namedParameters);
4852
}

src/MsieJavaScriptEngine/JsRt/Edge/EdgeTypeMapper.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,7 @@ private void ProjectMethods(EdgeEmbeddedItem externalItem)
556556
string typeName = type.FullName;
557557
BindingFlags defaultBindingFlags = ReflectionHelpers.GetDefaultBindingFlags(instance);
558558
IEnumerable<MethodInfo> methods = type.GetMethods(defaultBindingFlags)
559-
.Where(m => !(m.Attributes.HasFlag(MethodAttributes.SpecialName)
560-
&& (m.Name.StartsWith("get_") || m.Name.StartsWith("set_"))))
561-
;
559+
.Where(ReflectionHelpers.IsFullyFledgedMethod);
562560
IEnumerable<IGrouping<string, MethodInfo>> methodGroups = methods.GroupBy(m => m.Name);
563561

564562
foreach (IGrouping<string, MethodInfo> methodGroup in methodGroups)

src/MsieJavaScriptEngine/JsRt/Ie/IeTypeMapper.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,7 @@ private void ProjectMethods(IeEmbeddedItem externalItem)
553553
string typeName = type.FullName;
554554
BindingFlags defaultBindingFlags = ReflectionHelpers.GetDefaultBindingFlags(instance);
555555
IEnumerable<MethodInfo> methods = type.GetMethods(defaultBindingFlags)
556-
.Where(m => !(m.Attributes.HasFlag(MethodAttributes.SpecialName)
557-
&& (m.Name.StartsWith("get_") || m.Name.StartsWith("set_"))))
558-
;
556+
.Where(ReflectionHelpers.IsFullyFledgedMethod);
559557
IEnumerable<IGrouping<string, MethodInfo>> methodGroups = methods.GroupBy(m => m.Name);
560558

561559
foreach (IGrouping<string, MethodInfo> methodGroup in methodGroups)

src/MsieJavaScriptEngine/MsieJavaScriptEngine.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<PackageTags>JavaScript;ECMAScript;MSIE;IE;Edge;Chakra</PackageTags>
2424
<PackageReleaseNotes>1. Fixed a error, that occurred in the `Classic` mode during calling an embedded delegate, which does not return a result;
2525
2. Fixed a error, that occurred during setting a value to field of embedded type;
26-
3. In version for .NET Core improved a performance of the embedding of objects and types.</PackageReleaseNotes>
26+
3. Improved a performance of the embedding of objects and types.</PackageReleaseNotes>
2727
<NeutralLanguage>en-US</NeutralLanguage>
2828
<PackageOutputPath>../../nuget</PackageOutputPath>
2929
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

src/MsieJavaScriptEngine/readme.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
delegate, which does not return a result;
2626
2. Fixed a error, that occurred during setting a value to field of embedded
2727
type;
28-
3. In version for .NET Core improved a performance of the embedding of objects
29-
and types.
28+
3. Improved a performance of the embedding of objects and types.
3029

3130
============
3231
PROJECT SITE

0 commit comments

Comments
 (0)