diff --git a/ClearScript/ClearScript.csproj b/ClearScript/ClearScript.csproj
index 99ff84c6a..79cee5c62 100644
--- a/ClearScript/ClearScript.csproj
+++ b/ClearScript/ClearScript.csproj
@@ -81,12 +81,16 @@
+
+
+
+
diff --git a/ClearScript/DelegateFactory.Generated.cs b/ClearScript/DelegateFactory.Generated.cs
index 34871c038..877242b04 100644
--- a/ClearScript/DelegateFactory.Generated.cs
+++ b/ClearScript/DelegateFactory.Generated.cs
@@ -73,10 +73,11 @@ internal static partial class DelegateFactory
private const int maxArgCount = 16;
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = true;
private readonly object target;
private readonly Delegate del;
@@ -91,7 +92,22 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget()
{
- Invoke(() => ((dynamic)target)());
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)());
+ }
+ else
+ {
+
+ try
+ {
+ Invoke(() => ((dynamic)target)());
+ }
+ finally
+ {
+
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -106,10 +122,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1));
private readonly object target;
private readonly Delegate del;
@@ -124,7 +141,22 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1)
{
- Invoke(() => ((dynamic)target)(a1));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -139,10 +171,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2));
private readonly object target;
private readonly Delegate del;
@@ -157,7 +190,24 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2)
{
- Invoke(() => ((dynamic)target)(a1, a2));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -172,10 +222,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3));
private readonly object target;
private readonly Delegate del;
@@ -190,7 +241,26 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -205,10 +275,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4));
private readonly object target;
private readonly Delegate del;
@@ -223,7 +294,28 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -238,10 +330,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
private readonly object target;
private readonly Delegate del;
@@ -256,7 +349,30 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -271,10 +387,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6));
private readonly object target;
private readonly Delegate del;
@@ -289,7 +406,32 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -304,10 +446,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7));
private readonly object target;
private readonly Delegate del;
@@ -322,7 +465,34 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -337,10 +507,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8));
private readonly object target;
private readonly Delegate del;
@@ -355,7 +526,36 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -370,10 +570,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9));
private readonly object target;
private readonly Delegate del;
@@ -388,7 +589,38 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -403,10 +635,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10));
private readonly object target;
private readonly Delegate del;
@@ -421,7 +654,40 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -436,10 +702,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11));
private readonly object target;
private readonly Delegate del;
@@ -454,7 +721,42 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -469,10 +771,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12));
private readonly object target;
private readonly Delegate del;
@@ -487,7 +790,44 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -502,10 +842,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13));
private readonly object target;
private readonly Delegate del;
@@ -520,7 +861,46 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -535,10 +915,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14));
private readonly object target;
private readonly Delegate del;
@@ -553,7 +934,48 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ var v14 = GetArgValue(a14);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ SetArgValue(a14, v14);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -568,10 +990,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15));
private readonly object target;
private readonly Delegate del;
@@ -586,7 +1009,50 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ var v14 = GetArgValue(a14);
+ var v15 = GetArgValue(a15);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ SetArgValue(a14, v14);
+ SetArgValue(a15, v15);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -601,10 +1067,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15), typeof(T16));
private readonly object target;
private readonly Delegate del;
@@ -619,7 +1086,52 @@ public ProcShim(ScriptEngine engine, object target)
public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15, T16 a16)
{
- Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16));
+ }
+ else
+ {
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ var v14 = GetArgValue(a14);
+ var v15 = GetArgValue(a15);
+ var v16 = GetArgValue(a16);
+ try
+ {
+ Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15, ref v16));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ SetArgValue(a14, v14);
+ SetArgValue(a15, v15);
+ SetArgValue(a16, v16);
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -635,10 +1147,11 @@ public override Delegate Delegate
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = true;
private readonly object target;
private readonly Delegate del;
@@ -653,7 +1166,20 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget()
{
- return Invoke(() => (TResult)((dynamic)target)());
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)());
+ }
+
+
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)());
+ }
+ finally
+ {
+
+ }
}
// ReSharper restore UnusedMember.Local
@@ -668,10 +1194,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1));
private readonly object target;
private readonly Delegate del;
@@ -686,7 +1213,20 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1)
{
- return Invoke(() => (TResult)((dynamic)target)(a1));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1));
+ }
+
+ var v1 = GetArgValue(a1);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -701,10 +1241,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2));
private readonly object target;
private readonly Delegate del;
@@ -719,7 +1260,22 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -734,10 +1290,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3));
private readonly object target;
private readonly Delegate del;
@@ -752,7 +1309,24 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -767,10 +1341,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4));
private readonly object target;
private readonly Delegate del;
@@ -785,7 +1360,26 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -800,10 +1394,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
private readonly object target;
private readonly Delegate del;
@@ -818,7 +1413,28 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -833,10 +1449,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6));
private readonly object target;
private readonly Delegate del;
@@ -851,7 +1468,30 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -866,10 +1506,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7));
private readonly object target;
private readonly Delegate del;
@@ -884,7 +1525,32 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -899,10 +1565,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8));
private readonly object target;
private readonly Delegate del;
@@ -917,7 +1584,34 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -932,10 +1626,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9));
private readonly object target;
private readonly Delegate del;
@@ -950,7 +1645,36 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -965,10 +1689,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10));
private readonly object target;
private readonly Delegate del;
@@ -983,7 +1708,38 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -998,10 +1754,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11));
private readonly object target;
private readonly Delegate del;
@@ -1016,7 +1773,40 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -1031,10 +1821,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12));
private readonly object target;
private readonly Delegate del;
@@ -1049,7 +1840,42 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -1064,10 +1890,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13));
private readonly object target;
private readonly Delegate del;
@@ -1082,7 +1909,44 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -1097,10 +1961,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14));
private readonly object target;
private readonly Delegate del;
@@ -1115,7 +1980,46 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ var v14 = GetArgValue(a14);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ SetArgValue(a14, v14);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -1130,10 +2034,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15));
private readonly object target;
private readonly Delegate del;
@@ -1148,7 +2053,48 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ var v14 = GetArgValue(a14);
+ var v15 = GetArgValue(a15);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ SetArgValue(a14, v14);
+ SetArgValue(a15, v15);
+ }
}
// ReSharper restore UnusedMember.Local
@@ -1163,10 +2109,11 @@ public override Delegate Delegate
#endregion
}
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15), typeof(T16));
private readonly object target;
private readonly Delegate del;
@@ -1181,7 +2128,50 @@ public FuncShim(ScriptEngine engine, object target)
public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15, T16 a16)
{
- return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16));
+ }
+
+ var v1 = GetArgValue(a1);
+ var v2 = GetArgValue(a2);
+ var v3 = GetArgValue(a3);
+ var v4 = GetArgValue(a4);
+ var v5 = GetArgValue(a5);
+ var v6 = GetArgValue(a6);
+ var v7 = GetArgValue(a7);
+ var v8 = GetArgValue(a8);
+ var v9 = GetArgValue(a9);
+ var v10 = GetArgValue(a10);
+ var v11 = GetArgValue(a11);
+ var v12 = GetArgValue(a12);
+ var v13 = GetArgValue(a13);
+ var v14 = GetArgValue(a14);
+ var v15 = GetArgValue(a15);
+ var v16 = GetArgValue(a16);
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15, ref v16));
+ }
+ finally
+ {
+ SetArgValue(a1, v1);
+ SetArgValue(a2, v2);
+ SetArgValue(a3, v3);
+ SetArgValue(a4, v4);
+ SetArgValue(a5, v5);
+ SetArgValue(a6, v6);
+ SetArgValue(a7, v7);
+ SetArgValue(a8, v8);
+ SetArgValue(a9, v9);
+ SetArgValue(a10, v10);
+ SetArgValue(a11, v11);
+ SetArgValue(a12, v12);
+ SetArgValue(a13, v13);
+ SetArgValue(a14, v14);
+ SetArgValue(a15, v15);
+ SetArgValue(a16, v16);
+ }
}
// ReSharper restore UnusedMember.Local
diff --git a/ClearScript/DelegateFactory.cs b/ClearScript/DelegateFactory.cs
index 07b7f6fea..e31a02d49 100644
--- a/ClearScript/DelegateFactory.cs
+++ b/ClearScript/DelegateFactory.cs
@@ -116,7 +116,7 @@ public static Delegate CreateDelegate(ScriptEngine engine, object target, Type d
throw new ArgumentException("Invalid delegate type (parameter count too large)");
}
- var paramTypes = parameters.Select(parameter => parameter.ParameterType).ToArray();
+ var paramTypes = parameters.Select(param => param.ParameterType).ToArray();
if (paramTypes.Any(paramType => paramType.IsByRef))
{
return CreateComplexDelegate(engine, target, delegateType);
@@ -128,7 +128,7 @@ public static Delegate CreateDelegate(ScriptEngine engine, object target, Type d
private static Delegate CreateSimpleDelegate(ScriptEngine engine, object target, Type delegateType)
{
var method = delegateType.GetMethod("Invoke");
- var paramTypes = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray();
+ var paramTypes = method.GetParameters().Select(param => param.ParameterType).ToArray();
Type shimType;
if (method.ReturnType == typeof(void))
@@ -153,7 +153,7 @@ private static Delegate CreateComplexDelegate(ScriptEngine engine, object target
var method = delegateType.GetMethod("Invoke");
var parameters = method.GetParameters();
- var paramTypes = parameters.Select(parameter => parameter.ParameterType).ToArray();
+ var paramTypes = parameters.Select(param => param.ParameterType).ToArray();
var innerParamTypes = new Type[parameters.Length];
for (var index = 0; index < parameters.Length; index++)
@@ -232,6 +232,33 @@ private abstract class DelegateShim
{
public abstract Delegate Delegate { get; }
+ protected ScriptEngine Engine { get; private set; }
+
+ protected DelegateShim(ScriptEngine engine)
+ {
+ Engine = engine;
+ }
+
+ protected static bool GetAllByValue(params Type[] types)
+ {
+ return !types.Any(type => typeof(IByRefArg).IsAssignableFrom(type));
+ }
+
+ protected static object GetArgValue(object arg)
+ {
+ var byRefArg = arg as IByRefArg;
+ return (byRefArg != null) ? byRefArg.Value : arg;
+ }
+
+ protected static void SetArgValue(object arg, object value)
+ {
+ var byRefArg = arg as IByRefArg;
+ if (byRefArg != null)
+ {
+ byRefArg.Value = value;
+ }
+ }
+
protected static object GetCompatibleTarget(Type delegateType, object target)
{
var del = target as Delegate;
@@ -257,6 +284,7 @@ private abstract class ProcShim : DelegateShim
private readonly Action invoker;
protected ProcShim(ScriptEngine engine)
+ : base(engine)
{
if (engine == null)
{
@@ -279,6 +307,7 @@ private abstract class FuncShim : DelegateShim
private readonly Func, TResult> invoker;
protected FuncShim(ScriptEngine engine)
+ : base(engine)
{
if (engine == null)
{
diff --git a/ClearScript/DelegateFactory.tt b/ClearScript/DelegateFactory.tt
index 03c5849e9..7e709b4af 100644
--- a/ClearScript/DelegateFactory.tt
+++ b/ClearScript/DelegateFactory.tt
@@ -81,14 +81,19 @@ namespace Microsoft.ClearScript
for (var count = 0; count <= maxArgCount; count++)
{
var typeParamList = (count == 0) ? "" : "<" + string.Join(", ", Enumerable.Range(1, count).Select(index => "T" + index)) + ", TDelegate>";
+ var allByValueExpr = (count == 0) ? "true" : "GetAllByValue(" + string.Join(", ", Enumerable.Range(1, count).Select(index => "typeof(T" + index + ")")) + ")";
var methodParamList = string.Join(", ", Enumerable.Range(1, count).Select(index => "T" + index + " a" + index));
- var methodArgList = string.Join(", ", Enumerable.Range(1, count).Select(index => "a" + index));
+ var argList = string.Join(", ", Enumerable.Range(1, count).Select(index => "a" + index));
+ var varDeclList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "var v" + index + " = GetArgValue(a" + index + ");"));
+ var byRefArgList = string.Join(", ", Enumerable.Range(1, count).Select(index => "ref v" + index));
+ var varAssignList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "SetArgValue(a" + index + ", v" + index + ");"));
#>
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class ProcShim<#= typeParamList #> : ProcShim
{
private static readonly MethodInfo method = typeof(ProcShim<#= typeParamList #>).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = <#= allByValueExpr #>;
private readonly object target;
private readonly Delegate del;
@@ -103,7 +108,22 @@ namespace Microsoft.ClearScript
public void InvokeTarget(<#= methodParamList #>)
{
- Invoke(() => ((dynamic)target)(<#= methodArgList #>));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ Invoke(() => ((dynamic)target)(<#= argList #>));
+ }
+ else
+ {
+ <#= varDeclList #>
+ try
+ {
+ Invoke(() => ((dynamic)target)(<#= byRefArgList #>));
+ }
+ finally
+ {
+ <#= varAssignList #>
+ }
+ }
}
// ReSharper restore UnusedMember.Local
@@ -125,14 +145,19 @@ namespace Microsoft.ClearScript
for (var count = 0; count <= maxArgCount; count++)
{
var typeParamList = (count == 0) ? "" : "<" + string.Join(", ", Enumerable.Range(1, count).Select(index => "T" + index)) + ", TResult, TDelegate>";
+ var allByValueExpr = (count == 0) ? "true" : "GetAllByValue(" + string.Join(", ", Enumerable.Range(1, count).Select(index => "typeof(T" + index + ")")) + ")";
var methodParamList = string.Join(", ", Enumerable.Range(1, count).Select(index => "T" + index + " a" + index));
- var methodArgList = string.Join(", ", Enumerable.Range(1, count).Select(index => "a" + index));
+ var argList = string.Join(", ", Enumerable.Range(1, count).Select(index => "a" + index));
+ var varDeclList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "var v" + index + " = GetArgValue(a" + index + ");"));
+ var byRefArgList = string.Join(", ", Enumerable.Range(1, count).Select(index => "ref v" + index));
+ var varAssignList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "SetArgValue(a" + index + ", v" + index + ");"));
#>
- [ExcludeFromCodeCoverage]
+ [ExcludeFromCodeCoverage]
private class FuncShim<#= typeParamList #> : FuncShim
{
private static readonly MethodInfo method = typeof(FuncShim<#= typeParamList #>).GetMethod("InvokeTarget");
+ private static readonly bool allByValue = <#= allByValueExpr #>;
private readonly object target;
private readonly Delegate del;
@@ -147,7 +172,20 @@ namespace Microsoft.ClearScript
public TResult InvokeTarget(<#= methodParamList #>)
{
- return Invoke(() => (TResult)((dynamic)target)(<#= methodArgList #>));
+ if (allByValue || Engine.EnableAutoHostVariables)
+ {
+ return Invoke(() => (TResult)((dynamic)target)(<#= argList #>));
+ }
+
+ <#= varDeclList #>
+ try
+ {
+ return Invoke(() => (TResult)((dynamic)target)(<#= byRefArgList #>));
+ }
+ finally
+ {
+ <#= varAssignList #>
+ }
}
// ReSharper restore UnusedMember.Local
diff --git a/ClearScript/Exports/VersionSymbols.h b/ClearScript/Exports/VersionSymbols.h
index f260246c5..3d5b0c74e 100644
--- a/ClearScript/Exports/VersionSymbols.h
+++ b/ClearScript/Exports/VersionSymbols.h
@@ -63,5 +63,5 @@
#pragma once
-#define CLEARSCRIPT_VERSION_STRING "5.4.0.0"
-#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,4,0,0
+#define CLEARSCRIPT_VERSION_STRING "5.4.1.0"
+#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,4,1,0
diff --git a/ClearScript/HostFunctions.cs b/ClearScript/HostFunctions.cs
index 229c7adbd..da4629536 100644
--- a/ClearScript/HostFunctions.cs
+++ b/ClearScript/HostFunctions.cs
@@ -206,11 +206,11 @@ public object newObj(IDynamicMetaObjectProvider target, params object[] args)
}
///
- /// Creates a host array.
+ /// Creates a host array with the specified element type.
///
/// The element type of the array to create.
/// One or more integers representing the array dimension lengths.
- /// A new host array.
+ /// A new host array with the specified element type.
///
/// For information about the mapping between host members and script-callable properties
/// and methods, see
@@ -226,12 +226,29 @@ public object newObj(IDynamicMetaObjectProvider target, params object[] args)
/// var array = host.newArr(StringT, 5, 3);
///
///
+ ///
///
public object newArr(params int[] lengths)
{
return Array.CreateInstance(typeof(T), lengths);
}
+ ///
+ /// Creates a host array with as the element type.
+ ///
+ /// One or more integers representing the array dimension lengths.
+ /// A new host array with as the element type.
+ ///
+ /// For information about the mapping between host members and script-callable properties
+ /// and methods, see
+ /// AddHostObject.
+ ///
+ ///
+ public object newArr(params int[] lengths)
+ {
+ return newArr
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 a callback that can be used to halt script execution.
///
@@ -1109,12 +1135,32 @@ internal void CheckReflection()
internal virtual void HostInvoke(Action action)
{
- action();
+ var previousEngine = currentEngine;
+ currentEngine = this;
+
+ try
+ {
+ action();
+ }
+ finally
+ {
+ currentEngine = previousEngine;
+ }
}
internal virtual T HostInvoke(Func func)
{
- return func();
+ var previousEngine = currentEngine;
+ currentEngine = this;
+
+ try
+ {
+ return func();
+ }
+ finally
+ {
+ currentEngine = previousEngine;
+ }
}
#endregion
@@ -1125,7 +1171,7 @@ internal virtual T HostInvoke(Func func)
internal virtual void ScriptInvoke(Action action)
{
- var prevScriptFrame = CurrentScriptFrame;
+ var previousScriptFrame = CurrentScriptFrame;
CurrentScriptFrame = new ScriptFrame();
try
@@ -1134,13 +1180,13 @@ internal virtual void ScriptInvoke(Action action)
}
finally
{
- CurrentScriptFrame = prevScriptFrame;
+ CurrentScriptFrame = previousScriptFrame;
}
}
internal virtual T ScriptInvoke(Func func)
{
- var prevScriptFrame = CurrentScriptFrame;
+ var previousScriptFrame = CurrentScriptFrame;
CurrentScriptFrame = new ScriptFrame();
try
@@ -1149,7 +1195,7 @@ internal virtual T ScriptInvoke(Func func)
}
finally
{
- CurrentScriptFrame = prevScriptFrame;
+ CurrentScriptFrame = previousScriptFrame;
}
}
@@ -1235,7 +1281,7 @@ internal HostItem GetOrCreateHostItem(HostTarget target, HostItemFlags flags, Fu
var hostObject = target as HostObject;
if (hostObject != null)
{
- return GetOrCreateHostItemForHostTarget(hostObject, flags, createHostItem);
+ return GetOrCreateHostItemForHostObject(hostObject, hostObject.Target, flags, createHostItem);
}
var hostType = target as HostType;
@@ -1247,21 +1293,27 @@ internal HostItem GetOrCreateHostItem(HostTarget target, HostItemFlags flags, Fu
var hostMethod = target as HostMethod;
if (hostMethod != null)
{
- return GetOrCreateHostItemForHostTarget(hostMethod, flags, createHostItem);
+ return GetOrCreateHostItemForHostObject(hostMethod, hostMethod, flags, createHostItem);
+ }
+
+ var hostVariable = target as HostVariableBase;
+ if (hostVariable != null)
+ {
+ return GetOrCreateHostItemForHostObject(hostVariable, hostVariable, flags, createHostItem);
}
var hostIndexedProperty = target as HostIndexedProperty;
if (hostIndexedProperty != null)
{
- return GetOrCreateHostItemForHostTarget(hostIndexedProperty, flags, createHostItem);
+ return GetOrCreateHostItemForHostObject(hostIndexedProperty, hostIndexedProperty, flags, createHostItem);
}
return createHostItem(this, target, flags);
}
- private HostItem GetOrCreateHostItemForHostTarget(HostTarget hostTarget, HostItemFlags flags, Func createHostItem)
+ private HostItem GetOrCreateHostItemForHostObject(HostTarget hostTarget, object target, HostItemFlags flags, Func createHostItem)
{
- var cacheEntry = hostObjectHostItemCache.GetOrCreateValue(hostTarget.Target);
+ var cacheEntry = hostObjectHostItemCache.GetOrCreateValue(target);
List activeWeakRefs = null;
var staleWeakRefCount = 0;
diff --git a/ClearScript/ScriptItem.cs b/ClearScript/ScriptItem.cs
index 162fac4e4..94614dc31 100644
--- a/ClearScript/ScriptItem.cs
+++ b/ClearScript/ScriptItem.cs
@@ -78,8 +78,6 @@ internal abstract class ScriptItem : DynamicObject, IExpando, IDynamic, IScriptM
private static readonly MethodInfo clearLastScriptErrorMethod = typeof(ScriptItem).GetMethod("ClearLastScriptError");
[ThreadStatic] private static IScriptEngineException lastScriptError;
- public abstract ScriptEngine Engine { get; }
-
public static void ThrowLastScriptError()
{
var scriptError = lastScriptError;
@@ -106,12 +104,18 @@ protected virtual object[] AdjustInvokeArgs(object[] args)
return args;
}
- private bool TryWrappedBindAndInvoke(DynamicMetaObjectBinder binder, object[] args, out object result)
+ private bool TryWrappedBindAndInvoke(DynamicMetaObjectBinder binder, object[] wrappedArgs, out object result)
{
+ object[] args = null;
+ object[] savedArgs = null;
+
object tempResult = null;
var succeeded = Engine.ScriptInvoke(() =>
{
- if (!TryBindAndInvoke(binder, Engine.MarshalToScript(args), out tempResult))
+ args = Engine.MarshalToScript(wrappedArgs);
+ savedArgs = (object[])args.Clone();
+
+ if (!TryBindAndInvoke(binder, args, out tempResult))
{
if ((Engine.CurrentScriptFrame != null) && (lastScriptError == null))
{
@@ -126,6 +130,15 @@ private bool TryWrappedBindAndInvoke(DynamicMetaObjectBinder binder, object[] ar
if (succeeded)
{
+ for (var index = 0; index < args.Length; index++)
+ {
+ var arg = args[index];
+ if (!ReferenceEquals(arg, savedArgs[index]))
+ {
+ wrappedArgs[index] = Engine.MarshalToHost(args[index], false);
+ }
+ }
+
result = Engine.MarshalToHost(tempResult, false).ToDynamicResult(Engine);
return true;
}
@@ -139,7 +152,7 @@ private bool TryWrappedInvokeOrInvokeMember(DynamicMetaObjectBinder binder, Para
Type[] paramTypes = null;
if ((parameters != null) && (parameters.Length >= args.Length))
{
- paramTypes = parameters.Skip(parameters.Length - args.Length).Select(parameter => parameter.ParameterType).ToArray();
+ paramTypes = parameters.Skip(parameters.Length - args.Length).Select(param => param.ParameterType).ToArray();
}
if (paramTypes != null)
@@ -190,9 +203,9 @@ private DynamicMetaObject PostProcessBindResult(DynamicMetaObject result)
#region DynamicObject overrides
- public override DynamicMetaObject GetMetaObject(Expression parameter)
+ public override DynamicMetaObject GetMetaObject(Expression param)
{
- return new MetaScriptItem(this, base.GetMetaObject(parameter));
+ return new MetaScriptItem(this, base.GetMetaObject(param));
}
public override IEnumerable GetDynamicMemberNames()
@@ -225,7 +238,7 @@ public override bool TrySetIndex(SetIndexBinder binder, object[] indices, object
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
ParameterInfo[] parameters = null;
- if (binder.GetType().FullName.StartsWith("Microsoft.CSharp.", StringComparison.Ordinal))
+ if (Engine.EnableAutoHostVariables)
{
parameters = new StackFrame(1, false).GetMethod().GetParameters();
}
@@ -236,7 +249,7 @@ public override bool TryInvoke(InvokeBinder binder, object[] args, out object re
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
ParameterInfo[] parameters = null;
- if (binder.GetType().FullName.StartsWith("Microsoft.CSharp.", StringComparison.Ordinal))
+ if (Engine.EnableAutoHostVariables)
{
parameters = new StackFrame(1, false).GetMethod().GetParameters();
}
@@ -406,6 +419,8 @@ public object GetProperty(string name, out bool isCacheable)
#region IScriptMarshalWrapper implementation (abstract)
+ public abstract ScriptEngine Engine { get; }
+
public abstract object Unwrap();
#endregion
@@ -426,6 +441,11 @@ public MetaScriptItem(ScriptItem scriptItem, DynamicMetaObject metaDynamic)
#region DynamicMetaObject overrides
+ public override IEnumerable GetDynamicMemberNames()
+ {
+ return metaDynamic.GetDynamicMemberNames();
+ }
+
public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
{
return scriptItem.PostProcessBindResult(metaDynamic.BindBinaryOperation(binder, arg));
diff --git a/ClearScript/Util/COMDispatch.cs b/ClearScript/Util/COMDispatch.cs
index 1b2613b3e..b3f9b3f31 100644
--- a/ClearScript/Util/COMDispatch.cs
+++ b/ClearScript/Util/COMDispatch.cs
@@ -61,7 +61,7 @@
using System;
using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.CustomMarshalers;
+using System.Runtime.InteropServices.ComTypes;
using DISPPARAMS = System.Runtime.InteropServices.ComTypes.DISPPARAMS;
using EXCEPINFO = System.Runtime.InteropServices.ComTypes.EXCEPINFO;
@@ -138,7 +138,7 @@ [Out] out uint count
int GetTypeInfo(
[In] uint index,
[In] int lcid,
- [Out] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out Type typeInfo
+ [Out] [MarshalAs(UnmanagedType.Interface)] out ITypeInfo typeInfo
);
void GetIDsOfNames(
@@ -177,7 +177,7 @@ [Out] out uint count
int GetTypeInfo(
[In] uint index,
[In] int lcid,
- [Out] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out Type typeInfo
+ [Out] [MarshalAs(UnmanagedType.Interface)] out ITypeInfo typeInfo
);
void GetIDsOfNames(
diff --git a/ClearScript/Util/COMDispatchHelpers.cs b/ClearScript/Util/COMDispatchHelpers.cs
index 148f76684..cf006edad 100644
--- a/ClearScript/Util/COMDispatchHelpers.cs
+++ b/ClearScript/Util/COMDispatchHelpers.cs
@@ -73,7 +73,7 @@ public static object GetProperty(this IDispatchEx dispatchEx, string name, bool
int dispid;
Marshal.ThrowExceptionForHR(dispatchEx.GetDispID(name, ignoreCase ? DispatchNameFlags.CaseInsensitive : DispatchNameFlags.CaseSensitive, out dispid));
- using (var argVariantArrayBlock = new CoTaskMemVariantArrayBlock(args))
+ using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args))
{
using (var resultVariantBlock = new CoTaskMemVariantBlock())
{
@@ -100,7 +100,7 @@ public static void SetProperty(this IDispatchEx dispatchEx, string name, bool ig
}
Marshal.ThrowExceptionForHR(result);
- using (var argVariantArrayBlock = new CoTaskMemVariantArrayBlock(args))
+ using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args))
{
using (var namedArgDispidBlock = new CoTaskMemBlock(sizeof(int)))
{
@@ -114,7 +114,7 @@ public static void SetProperty(this IDispatchEx dispatchEx, string name, bool ig
public static object Invoke(this IDispatchEx dispatchEx, object[] args)
{
- using (var argVariantArrayBlock = new CoTaskMemVariantArrayBlock(args))
+ using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
{
using (var resultVariantBlock = new CoTaskMemVariantBlock())
{
@@ -131,7 +131,7 @@ public static object InvokeMethod(this IDispatchEx dispatchEx, string name, bool
int dispid;
Marshal.ThrowExceptionForHR(dispatchEx.GetDispID(name, ignoreCase ? DispatchNameFlags.CaseInsensitive : DispatchNameFlags.CaseSensitive, out dispid));
- using (var argVariantArrayBlock = new CoTaskMemVariantArrayBlock(args))
+ using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
{
using (var resultVariantBlock = new CoTaskMemVariantBlock())
{
diff --git a/ClearScript/Util/CoTaskMemBlock.cs b/ClearScript/Util/CoTaskMemBlock.cs
index fbfa94d2a..5af59cd2b 100644
--- a/ClearScript/Util/CoTaskMemBlock.cs
+++ b/ClearScript/Util/CoTaskMemBlock.cs
@@ -156,21 +156,11 @@ protected override void Dispose(bool disposing)
#endregion
}
- internal class CoTaskMemVariantArrayBlock : CoTaskMemBlock
+ internal class CoTaskMemVariantArgsBlock : CoTaskMemBlock
{
private readonly int length;
- public CoTaskMemVariantArrayBlock(int length)
- : base(RawCOMHelpers.VariantSize * length)
- {
- this.length = length;
- for (var index = 0; index < length; index++)
- {
- NativeMethods.VariantInit(GetAddrInternal(index));
- }
- }
-
- public CoTaskMemVariantArrayBlock(object[] args)
+ public CoTaskMemVariantArgsBlock(object[] args)
: base(args.Length * RawCOMHelpers.VariantSize)
{
length = args.Length;
@@ -192,7 +182,7 @@ public IntPtr GetAddr(int index)
throw new ObjectDisposedException(ToString());
}
- return GetAddrInternal(index);
+ return GetAddrInternal(length - 1 - index);
}
private IntPtr GetAddrInternal(int index)
@@ -217,4 +207,63 @@ protected override void Dispose(bool disposing)
#endregion
}
+
+ internal class CoTaskMemVariantArgsByRefBlock : CoTaskMemBlock
+ {
+ private readonly object[] args;
+
+ public CoTaskMemVariantArgsByRefBlock(object[] args)
+ : base(args.Length * 2 * RawCOMHelpers.VariantSize)
+ {
+ this.args = args;
+ for (var index = 0; index < args.Length; index++)
+ {
+ var pArg = GetAddrInternal(args.Length + index);
+ Marshal.GetNativeVariantForObject(args[index], pArg);
+
+ var pArgRef = GetAddrInternal(args.Length - 1 - index);
+ NativeMethods.VariantInit(pArgRef);
+ Marshal.WriteInt16(pArgRef, 0, 0x400C /*VT_BYREF | VT_VARIANT*/);
+ Marshal.WriteIntPtr(pArgRef, sizeof(ushort) * 4, pArg);
+ }
+ }
+ public IntPtr GetAddr(int index)
+ {
+ if ((index < 0) || (index >= args.Length))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ if (Addr == IntPtr.Zero)
+ {
+ throw new ObjectDisposedException(ToString());
+ }
+
+ return GetAddrInternal(args.Length - 1 - index);
+ }
+
+ private IntPtr GetAddrInternal(int index)
+ {
+ return Addr + (index * RawCOMHelpers.VariantSize);
+ }
+
+ #region CoTaskMemBlock overrides
+
+ protected override void Dispose(bool disposing)
+ {
+ if (Addr != IntPtr.Zero)
+ {
+ for (var index = 0; index < args.Length; index++)
+ {
+ var pArg = GetAddrInternal(args.Length + index);
+ args[index] = Marshal.GetObjectForNativeVariant(pArg);
+ NativeMethods.VariantClear(pArg);
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ #endregion
+ }
}
diff --git a/ClearScript/Util/DisposedFlag.cs b/ClearScript/Util/DisposedFlag.cs
new file mode 100644
index 000000000..c5dd43345
--- /dev/null
+++ b/ClearScript/Util/DisposedFlag.cs
@@ -0,0 +1,80 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+using System.Threading;
+
+namespace Microsoft.ClearScript.Util
+{
+ internal struct DisposedFlag
+ {
+ private int disposed;
+
+ public bool IsSet()
+ {
+ return disposed != 0;
+ }
+
+ public bool Set()
+ {
+ return Interlocked.Exchange(ref disposed, 1) == 0;
+ }
+ }
+}
diff --git a/ClearScript/Util/IScriptMarshalWrapper.cs b/ClearScript/Util/IScriptMarshalWrapper.cs
index c2f80d89a..787703226 100644
--- a/ClearScript/Util/IScriptMarshalWrapper.cs
+++ b/ClearScript/Util/IScriptMarshalWrapper.cs
@@ -63,6 +63,7 @@ namespace Microsoft.ClearScript.Util
{
internal interface IScriptMarshalWrapper
{
+ ScriptEngine Engine { get; }
object Unwrap();
}
}
diff --git a/ClearScript/Util/MiscHelpers.cs b/ClearScript/Util/MiscHelpers.cs
index 1f374cfb6..10b420ca7 100644
--- a/ClearScript/Util/MiscHelpers.cs
+++ b/ClearScript/Util/MiscHelpers.cs
@@ -326,6 +326,33 @@ public static string GetDispIDName(int dispid)
return FormatInvariant("[DISPID={0}]", dispid);
}
+ public static bool Try(Action action)
+ {
+ try
+ {
+ action();
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ public static bool Try(out T result, Func func)
+ {
+ try
+ {
+ result = func();
+ return true;
+ }
+ catch (Exception)
+ {
+ result = default(T);
+ return false;
+ }
+ }
+
#region Nested type: EmptyArray
private static class EmptyArray
diff --git a/ClearScript/Util/NativeMethods.cs b/ClearScript/Util/NativeMethods.cs
index 9876647cd..254d36952 100644
--- a/ClearScript/Util/NativeMethods.cs
+++ b/ClearScript/Util/NativeMethods.cs
@@ -71,6 +71,10 @@ public static extern IntPtr LoadLibraryW(
[In] [MarshalAs(UnmanagedType.LPWStr)] string path
);
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool FreeLibrary(IntPtr hLibrary);
+
[DllImport("ole32.dll", ExactSpelling = true)]
public static extern uint CLSIDFromProgID(
[In] [MarshalAs(UnmanagedType.LPWStr)] string progID,
diff --git a/ClearScript/Util/ObjectHelpers.cs b/ClearScript/Util/ObjectHelpers.cs
index cf8739a11..7c2089e8f 100644
--- a/ClearScript/Util/ObjectHelpers.cs
+++ b/ClearScript/Util/ObjectHelpers.cs
@@ -61,13 +61,19 @@
using System;
using System.Linq;
+using System.Reflection;
using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.CustomMarshalers;
+using System.Runtime.InteropServices.ComTypes;
+using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
+using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR;
namespace Microsoft.ClearScript.Util
{
internal static class ObjectHelpers
{
+ // GUID_ManagedName (um\cor.h)
+ private static readonly Guid managedNameGuid = new Guid("{0f21f359-ab84-41e8-9a78-36d110e6d2f9}");
+
public static Type GetTypeOrTypeInfo(this object value)
{
var type = value.GetType();
@@ -84,10 +90,10 @@ public static Type GetTypeOrTypeInfo(this object value)
uint count;
if (RawCOMHelpers.HResult.Succeeded(dispatch.GetTypeInfoCount(out count)) && (count > 0))
{
- Type tempTypeInfo;
+ ITypeInfo tempTypeInfo;
if (RawCOMHelpers.HResult.Succeeded(dispatch.GetTypeInfo(0, 0, out tempTypeInfo)))
{
- typeInfo = tempTypeInfo;
+ typeInfo = GetTypeForTypeInfo(tempTypeInfo);
}
}
}
@@ -97,10 +103,10 @@ public static Type GetTypeOrTypeInfo(this object value)
var provideClassInfo = value as IProvideClassInfo;
if (provideClassInfo != null)
{
- Type tempTypeInfo;
+ ITypeInfo tempTypeInfo;
if (RawCOMHelpers.HResult.Succeeded(provideClassInfo.GetClassInfo(out tempTypeInfo)))
{
- typeInfo = tempTypeInfo;
+ typeInfo = GetTypeForTypeInfo(tempTypeInfo);
}
}
}
@@ -187,6 +193,176 @@ public static object ToDynamicResult(this object result, ScriptEngine engine)
return result;
}
+ private static Type GetTypeForTypeInfo(ITypeInfo typeInfo)
+ {
+ // ReSharper disable EmptyGeneralCatchClause
+
+ try
+ {
+ ITypeLib typeLib;
+ int index;
+ typeInfo.GetContainingTypeLib(out typeLib, out index);
+
+ var assembly = LoadPrimaryInteropAssembly(typeLib);
+ if (assembly != null)
+ {
+ var name = GetManagedTypeInfoName(typeInfo, typeLib);
+ var guid = GetTypeInfoGuid(typeInfo);
+
+ var type = assembly.GetType(name, false /*throwOnError*/);
+ if ((type != null) && (type.GUID == guid))
+ {
+ return type;
+ }
+
+ var types = assembly.GetTypes();
+ if ((index >= 0) && (index < types.Length))
+ {
+ type = types[index];
+ if ((type.GUID == guid) && (type.FullName == name))
+ {
+ return type;
+ }
+ }
+
+ type = types.FirstOrDefault(testType => (testType.GUID == guid) && (testType.FullName == name));
+ if (type != null)
+ {
+ return type;
+ }
+ }
+
+ var pTypeInfo = RawCOMHelpers.QueryInterface(Marshal.GetIUnknownForObject(typeInfo));
+ try
+ {
+ return Marshal.GetTypeForITypeInfo(pTypeInfo);
+ }
+ finally
+ {
+ Marshal.Release(pTypeInfo);
+ }
+ }
+ catch (Exception)
+ {
+ }
+
+ return null;
+
+ // ReSharper restore EmptyGeneralCatchClause
+ }
+
+ private static Assembly LoadPrimaryInteropAssembly(ITypeLib typeLib)
+ {
+ // ReSharper disable EmptyGeneralCatchClause
+
+ try
+ {
+ IntPtr pAttr;
+ typeLib.GetLibAttr(out pAttr);
+ try
+ {
+ var attr = (TYPELIBATTR)Marshal.PtrToStructure(pAttr, typeof(TYPELIBATTR));
+
+ string name;
+ string codeBase;
+ if (new TypeLibConverter().GetPrimaryInteropAssembly(attr.guid, attr.wMajorVerNum, attr.wMinorVerNum, attr.lcid, out name, out codeBase))
+ {
+ return Assembly.Load(new AssemblyName(name) { CodeBase = codeBase });
+ }
+ }
+ finally
+ {
+ typeLib.ReleaseTLibAttr(pAttr);
+ }
+ }
+ catch (Exception)
+ {
+ }
+
+ return null;
+
+ // ReSharper restore EmptyGeneralCatchClause
+ }
+
+ private static string GetManagedTypeInfoName(ITypeInfo typeInfo, ITypeLib typeLib)
+ {
+ var typeInfo2 = typeInfo as ITypeInfo2;
+ if (typeInfo2 != null)
+ {
+ // ReSharper disable EmptyGeneralCatchClause
+
+ try
+ {
+ var guid = managedNameGuid;
+ object data;
+ typeInfo2.GetCustData(ref guid, out data);
+
+ var name = data as string;
+ if (name != null)
+ {
+ return name.Trim();
+ }
+ }
+ catch (Exception)
+ {
+ }
+
+ // ReSharper restore EmptyGeneralCatchClause
+ }
+
+ return GetManagedTypeLibName(typeLib) + "." + Marshal.GetTypeInfoName(typeInfo);
+ }
+
+ private static string GetManagedTypeLibName(ITypeLib typeLib)
+ {
+ var typeLib2 = typeLib as ITypeLib2;
+ if (typeLib2 != null)
+ {
+ // ReSharper disable EmptyGeneralCatchClause
+
+ try
+ {
+ var guid = managedNameGuid;
+ object data;
+ typeLib2.GetCustData(ref guid, out data);
+
+ var name = data as string;
+ if (name != null)
+ {
+ name = name.Trim();
+ if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
+ {
+ return name.Substring(0, name.Length - 4);
+ }
+
+ return name;
+ }
+ }
+ catch (Exception)
+ {
+ }
+
+ // ReSharper restore EmptyGeneralCatchClause
+ }
+
+ return Marshal.GetTypeLibName(typeLib);
+ }
+
+ private static Guid GetTypeInfoGuid(ITypeInfo typeInfo)
+ {
+ IntPtr pAttr;
+ typeInfo.GetTypeAttr(out pAttr);
+ try
+ {
+ var attr = (TYPEATTR)Marshal.PtrToStructure(pAttr, typeof(TYPEATTR));
+ return attr.guid;
+ }
+ finally
+ {
+ typeInfo.ReleaseTypeAttr(pAttr);
+ }
+ }
+
#region Nested type: IProvideClassInfo
[ComImport]
@@ -196,7 +372,7 @@ private interface IProvideClassInfo
{
[PreserveSig]
int GetClassInfo(
- [Out] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out Type typeInfo
+ [Out] [MarshalAs(UnmanagedType.Interface)] out ITypeInfo typeInfo
);
}
diff --git a/ClearScript/Util/SocketHelpers.cs b/ClearScript/Util/SocketHelpers.cs
new file mode 100644
index 000000000..2d8be22eb
--- /dev/null
+++ b/ClearScript/Util/SocketHelpers.cs
@@ -0,0 +1,135 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+using System;
+using System.Net.Sockets;
+
+namespace Microsoft.ClearScript.Util
+{
+ internal static class SocketHelpers
+ {
+ public static void SendBytesAsync(this Socket socket, byte[] bytes, Action callback)
+ {
+ socket.SendBytesAsync(bytes, 0, bytes.Length, callback);
+ }
+
+ public static void SendBytesAsync(this Socket socket, byte[] bytes, int offset, int count, Action callback)
+ {
+ if (!MiscHelpers.Try(() => socket.BeginSend(bytes, offset, count, SocketFlags.None, result => socket.OnBytesSent(result, bytes, offset, count, callback), null)))
+ {
+ callback(false);
+ }
+ }
+
+ public static void OnBytesSent(this Socket socket, IAsyncResult result, byte[] bytes, int offset, int count, Action callback)
+ {
+ int sentCount;
+ if (MiscHelpers.Try(out sentCount, () => socket.EndReceive(result)) && (sentCount > 0))
+ {
+ if (sentCount >= count)
+ {
+ callback(true);
+ }
+ else
+ {
+ socket.SendBytesAsync(bytes, offset + sentCount, count - sentCount, callback);
+ }
+ }
+ else
+ {
+ callback(false);
+ }
+ }
+
+ public static void ReceiveBytesAsync(this Socket socket, int count, Action callback)
+ {
+ socket.ReceiveBytesAsync(new byte[count], 0, count, callback);
+ }
+
+ public static void ReceiveBytesAsync(this Socket socket, byte[] bytes, int offset, int count, Action callback)
+ {
+ if (!MiscHelpers.Try(() => socket.BeginReceive(bytes, offset, count, SocketFlags.None, result => socket.OnBytesReceived(result, bytes, offset, count, callback), null)))
+ {
+ callback(null);
+ }
+ }
+
+ public static void OnBytesReceived(this Socket socket, IAsyncResult result, byte[] bytes, int offset, int count, Action callback)
+ {
+ int receivedCount;
+ if (MiscHelpers.Try(out receivedCount, () => socket.EndReceive(result)) && (receivedCount > 0))
+ {
+ if (receivedCount >= count)
+ {
+ callback(bytes);
+ }
+ else
+ {
+ socket.ReceiveBytesAsync(bytes, offset + receivedCount, count - receivedCount, callback);
+ }
+ }
+ else
+ {
+ callback(null);
+ }
+ }
+ }
+}
diff --git a/ClearScript/Util/TypeHelpers.cs b/ClearScript/Util/TypeHelpers.cs
index d288c7f17..d9fea1e37 100644
--- a/ClearScript/Util/TypeHelpers.cs
+++ b/ClearScript/Util/TypeHelpers.cs
@@ -338,18 +338,12 @@ public static IEnumerable GetScriptableProperties(this Type type,
public static PropertyInfo GetScriptableProperty(this Type type, string name, BindingFlags bindFlags, object[] bindArgs)
{
- var properties = type.GetScriptableProperties(name, bindFlags).ToArray();
-
+ var properties = type.GetScriptableProperties(name, bindFlags).Distinct(PropertySignatureComparer.Instance).ToArray();
if (properties.Length < 1)
{
return null;
}
- if (bindArgs.Length < 1)
- {
- return properties.FirstOrDefault(property => property.GetIndexParameters().Length < 1);
- }
-
var result = Type.DefaultBinder.SelectProperty(bindFlags, properties, null, bindArgs.Select(GetPropertyIndexType).ToArray(), null);
if (result != null)
{
@@ -357,9 +351,13 @@ public static PropertyInfo GetScriptableProperty(this Type type, string name, Bi
}
// the default binder fails to bind to some COM properties because of by-ref parameter types
- if ((properties.Length == 1) && (properties[0].GetIndexParameters().Length == bindArgs.Length))
+ if (properties.Length == 1)
{
- return properties[0];
+ var parameters = properties[0].GetIndexParameters();
+ if ((bindArgs.Length == parameters.Length) || ((bindArgs.Length > 0) && (parameters.Length >= bindArgs.Length)))
+ {
+ return properties[0];
+ }
}
return null;
@@ -554,5 +552,40 @@ private static Type GetPropertyIndexType(object bindArg)
throw new InvalidOperationException("Property index value must not be null");
}
+
+ #region Nested type: PropertySignatureComparer
+
+ private class PropertySignatureComparer : IEqualityComparer
+ {
+ private static readonly PropertySignatureComparer instance = new PropertySignatureComparer();
+
+ public static PropertySignatureComparer Instance { get { return instance; } }
+
+ #region IEqualityComparer implementation
+
+ public bool Equals(PropertyInfo first, PropertyInfo second)
+ {
+ var firstParamTypes = first.GetIndexParameters().Select(param => param.ParameterType);
+ var secondParamTypes = second.GetIndexParameters().Select(param => param.ParameterType);
+ return firstParamTypes.SequenceEqual(secondParamTypes);
+ }
+
+ public int GetHashCode(PropertyInfo property)
+ {
+ var hashCode = 0;
+
+ var parameters = property.GetIndexParameters();
+ foreach (var param in parameters)
+ {
+ hashCode = unchecked((hashCode * 31) + param.ParameterType.GetHashCode());
+ }
+
+ return hashCode;
+ }
+
+ #endregion
+ }
+
+ #endregion
}
}
diff --git a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj
index 8b800fe03..2a0b40301 100644
--- a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj
+++ b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj
@@ -29,12 +29,9 @@
true
Unicode
-
+
v120
-
- v110
-
@@ -115,6 +112,10 @@
+
+ false
+ false
+
false
@@ -137,6 +138,7 @@
false
+
false
@@ -203,6 +205,7 @@
+
@@ -217,6 +220,7 @@
+
diff --git a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters
index 8ea4f12c4..fecc7c3ea 100644
--- a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters
+++ b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters
@@ -52,6 +52,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -175,5 +181,11 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj
index ca1520161..5ba108ddc 100644
--- a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj
+++ b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj
@@ -29,12 +29,9 @@
true
Unicode
-
+
v120
-
- v110
-
@@ -116,6 +113,10 @@
+
+ false
+ false
+
false
@@ -138,6 +139,7 @@
false
+
false
@@ -204,6 +206,7 @@
+
@@ -218,6 +221,7 @@
+
diff --git a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters
index 41d03be66..d0d37bc8c 100644
--- a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters
+++ b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters
@@ -52,6 +52,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -175,5 +181,11 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/ClearScript/V8/ClearScriptV8/ClearScriptV8Managed.h b/ClearScript/V8/ClearScriptV8/ClearScriptV8Managed.h
index 41966b677..efdee757f 100644
--- a/ClearScript/V8/ClearScriptV8/ClearScriptV8Managed.h
+++ b/ClearScript/V8/ClearScriptV8/ClearScriptV8Managed.h
@@ -84,3 +84,4 @@
#include "V8ContextProxyImpl.h"
#include "V8ObjectImpl.h"
#include "V8ScriptImpl.h"
+#include "V8DebugListenerImpl.h"
diff --git a/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h b/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h
index c2f43e31e..8aae6435d 100644
--- a/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h
+++ b/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h
@@ -88,3 +88,4 @@
#include "V8WeakContextBinding.h"
#include "V8ObjectHolderImpl.h"
#include "V8ScriptHolderImpl.h"
+#include "HighResolutionClock.h"
diff --git a/ClearScript/V8/ClearScriptV8/CommonPlatform.h b/ClearScript/V8/ClearScriptV8/CommonPlatform.h
index e74a99a14..75b3502ab 100644
--- a/ClearScript/V8/ClearScriptV8/CommonPlatform.h
+++ b/ClearScript/V8/ClearScriptV8/CommonPlatform.h
@@ -124,3 +124,43 @@
} \
while (false) \
__pragma(warning(pop))
+
+//-----------------------------------------------------------------------------
+// PulseValueScope
+//-----------------------------------------------------------------------------
+
+template
+class PulseValueScope
+{
+ PROHIBIT_COPY(PulseValueScope)
+ PROHIBIT_HEAP(PulseValueScope)
+
+public:
+
+ PulseValueScope(T* pValue, T&& value):
+ m_pValue(pValue),
+ m_OriginalValue(std::move(*pValue))
+ {
+ *m_pValue = std::move(value);
+ }
+
+ ~PulseValueScope()
+ {
+ *m_pValue = std::move(m_OriginalValue);
+ }
+
+private:
+
+ T* m_pValue;
+ T m_OriginalValue;
+};
+
+//-----------------------------------------------------------------------------
+
+#define BEGIN_PULSE_VALUE_SCOPE(ADDRESS, VALUE) \
+ { \
+ PulseValueScope::type> t_PulseValueScope((ADDRESS), (VALUE));
+
+#define END_PULSE_VALUE_SCOPE \
+ IGNORE_UNUSED(t_PulseValueScope); \
+ }
diff --git a/ClearScript/V8/ClearScriptV8/HighResolutionClock.cpp b/ClearScript/V8/ClearScriptV8/HighResolutionClock.cpp
new file mode 100644
index 000000000..49f186f6d
--- /dev/null
+++ b/ClearScript/V8/ClearScriptV8/HighResolutionClock.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+#include "ClearScriptV8Native.h"
+#include
+
+//-----------------------------------------------------------------------------
+// HighResolutionClock implementation
+//-----------------------------------------------------------------------------
+
+static std::once_flag s_InitializationFlag;
+static LARGE_INTEGER s_TicksPerSecond;
+
+//-----------------------------------------------------------------------------
+
+double HighResolutionClock::GetRelativeSeconds()
+{
+ std::call_once(s_InitializationFlag, []
+ {
+ ASSERT_EVAL(::QueryPerformanceFrequency(&s_TicksPerSecond));
+ });
+
+ LARGE_INTEGER tickCount;
+ ASSERT_EVAL(::QueryPerformanceCounter(&tickCount));
+
+ auto wholeSeconds = tickCount.QuadPart / s_TicksPerSecond.QuadPart;
+ auto remainingTicks = tickCount.QuadPart % s_TicksPerSecond.QuadPart;
+
+ return wholeSeconds + (static_cast(remainingTicks) / s_TicksPerSecond.QuadPart);
+}
diff --git a/ClearScript/V8/ClearScriptV8/HighResolutionClock.h b/ClearScript/V8/ClearScriptV8/HighResolutionClock.h
new file mode 100644
index 000000000..f2eb0dac6
--- /dev/null
+++ b/ClearScript/V8/ClearScriptV8/HighResolutionClock.h
@@ -0,0 +1,75 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+#pragma once
+
+//-----------------------------------------------------------------------------
+// HighResolutionClock
+//-----------------------------------------------------------------------------
+
+class HighResolutionClock
+{
+ PROHIBIT_CONSTRUCT(HighResolutionClock)
+
+public:
+
+ static double GetRelativeSeconds();
+};
diff --git a/ClearScript/V8/ClearScriptV8/HostException.h b/ClearScript/V8/ClearScriptV8/HostException.h
index a4a84a40b..05532a4c6 100644
--- a/ClearScript/V8/ClearScriptV8/HostException.h
+++ b/ClearScript/V8/ClearScriptV8/HostException.h
@@ -70,7 +70,7 @@ class HostException
public:
HostException(StdString&& message, V8Value&& exception):
- m_Message(std::move(message)),
+ m_Message(std::move(message)),
m_Exception(std::move(exception))
{
}
diff --git a/ClearScript/V8/ClearScriptV8/HostObjectHelpers.cpp b/ClearScript/V8/ClearScriptV8/HostObjectHelpers.cpp
index 27701f71d..048691615 100644
--- a/ClearScript/V8/ClearScriptV8/HostObjectHelpers.cpp
+++ b/ClearScript/V8/ClearScriptV8/HostObjectHelpers.cpp
@@ -67,9 +67,9 @@ using namespace Microsoft::ClearScript::V8;
// local helper functions
//-----------------------------------------------------------------------------
-static void DECLSPEC_NORETURN ThrowHostException(Exception^ gcException)
+static void DECLSPEC_NORETURN ThrowHostException(void* pvSource, Exception^ gcException)
{
- throw HostException(StdString(gcException->Message), V8ContextProxyImpl::ImportValue(gcException));
+ throw HostException(StdString(gcException->GetBaseException()->Message), V8ContextProxyImpl::ImportValue(V8ProxyHelpers::MarshalExceptionToScript(pvSource, gcException)));
}
//-----------------------------------------------------------------------------
@@ -98,7 +98,7 @@ V8Value HostObjectHelpers::GetProperty(void* pvObject, const StdString& name)
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -112,7 +112,7 @@ V8Value HostObjectHelpers::GetProperty(void* pvObject, const StdString& name, bo
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -126,7 +126,7 @@ void HostObjectHelpers::SetProperty(void* pvObject, const StdString& name, const
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -140,7 +140,7 @@ bool HostObjectHelpers::DeleteProperty(void* pvObject, const StdString& name)
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -161,7 +161,7 @@ void HostObjectHelpers::GetPropertyNames(void* pvObject, std::vector&
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -175,7 +175,7 @@ V8Value HostObjectHelpers::GetProperty(void* pvObject, int index)
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -189,7 +189,7 @@ void HostObjectHelpers::SetProperty(void* pvObject, int index, const V8Value& va
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -203,7 +203,7 @@ bool HostObjectHelpers::DeleteProperty(void* pvObject, int index)
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -224,7 +224,7 @@ void HostObjectHelpers::GetPropertyIndices(void* pvObject, std::vector& ind
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -246,7 +246,7 @@ V8Value HostObjectHelpers::Invoke(void* pvObject, const std::vector& ar
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -268,7 +268,7 @@ V8Value HostObjectHelpers::InvokeMethod(void* pvObject, const StdString& name, c
}
catch (Exception^ gcException)
{
- ThrowHostException(gcException);
+ ThrowHostException(pvObject, gcException);
}
}
@@ -316,6 +316,27 @@ bool HostObjectHelpers::RemoveV8ObjectCacheEntry(void* pvCache, void* pvObject)
//-----------------------------------------------------------------------------
+void* HostObjectHelpers::CreateDebugAgent(const StdString& name, const StdString& version, int port, DebugCallback&& callback)
+{
+ return V8ProxyHelpers::CreateDebugAgent(name.ToManagedString(), version.ToManagedString(), port, gcnew V8DebugListenerImpl(std::move(callback)));
+}
+
+//-----------------------------------------------------------------------------
+
+void HostObjectHelpers::SendDebugMessage(void* pvAgent, const StdString& content)
+{
+ return V8ProxyHelpers::SendDebugMessage(pvAgent, content.ToManagedString());
+}
+
+//-----------------------------------------------------------------------------
+
+void HostObjectHelpers::DestroyDebugAgent(void* pvAgent)
+{
+ V8ProxyHelpers::DestroyDebugAgent(pvAgent);
+}
+
+//-----------------------------------------------------------------------------
+
bool HostObjectHelpers::TryParseInt32(const StdString& text, int& result)
{
return Int32::TryParse(text.ToManagedString(), NumberStyles::Integer, CultureInfo::InvariantCulture, result);
diff --git a/ClearScript/V8/ClearScriptV8/HostObjectHelpers.h b/ClearScript/V8/ClearScriptV8/HostObjectHelpers.h
index f616c6083..0fc456f7b 100644
--- a/ClearScript/V8/ClearScriptV8/HostObjectHelpers.h
+++ b/ClearScript/V8/ClearScriptV8/HostObjectHelpers.h
@@ -94,5 +94,10 @@ class HostObjectHelpers
static void GetAllCachedV8Objects(void* pvCache, std::vector& v8ObjectPtrs);
static bool RemoveV8ObjectCacheEntry(void* pvCache, void* pvObject);
+ typedef std::function DebugCallback;
+ static void* CreateDebugAgent(const StdString& name, const StdString& version, int port, DebugCallback&& callback);
+ static void SendDebugMessage(void* pvAgent, const StdString& content);
+ static void DestroyDebugAgent(void* pvAgent);
+
static bool TryParseInt32(const StdString& text, int& result);
};
diff --git a/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp b/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp
index 727ed3683..54e493ee4 100644
--- a/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp
@@ -165,7 +165,8 @@ static void* UnwrapHostObject(const FunctionCallbackInfo& args)
V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name, bool enableDebugging, bool disableGlobalMembers, int debugPort):
m_Name(name),
- m_spIsolateImpl(pIsolateImpl)
+ m_spIsolateImpl(pIsolateImpl),
+ m_AllowHostObjectFunctionCall(false)
{
VerifyNotOutOfMemory();
@@ -193,10 +194,11 @@ V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name,
// Such a change will require a corresponding change in the V8ScriptEngine constructor.
m_hHostObjectCookieName = CreatePersistent(CreateString(StdString(L"{c2cf47d3-916b-4a3f-be2a-6ff567425808}")));
- m_hInnerExceptionName = CreatePersistent(CreateString(StdString(L"inner")));
+ m_hHostExceptionName = CreatePersistent(CreateString(StdString(L"hostException")));
m_hHostObjectTemplate = CreatePersistent(CreateFunctionTemplate());
m_hHostObjectTemplate->SetClassName(CreateString(StdString(L"HostObject")));
+ m_hHostObjectTemplate->SetCallHandler(HostObjectFunctionCallHandler, Wrap());
m_hHostObjectTemplate->InstanceTemplate()->SetInternalFieldCount(1);
m_hHostObjectTemplate->InstanceTemplate()->SetNamedPropertyHandler(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyNames, Wrap());
@@ -295,21 +297,18 @@ void V8ContextImpl::SetGlobalProperty(const StdString& name, const V8Value& valu
{
if (!hOldValue.IsEmpty() && hOldValue->IsObject())
{
- for (auto it = m_GlobalMembersStack.begin(); it != m_GlobalMembersStack.end();)
+ for (auto it = m_GlobalMembersStack.begin(); it != m_GlobalMembersStack.end(); it++)
{
- if ((*it)->Equals(hOldValue))
+ if (it->first == name)
{
- it->Dispose();
- it = m_GlobalMembersStack.erase(it);
- }
- else
- {
- it++;
+ it->second.Dispose();
+ m_GlobalMembersStack.erase(it);
+ break;
}
}
}
- m_GlobalMembersStack.push_back(CreatePersistent(hValue->ToObject()));
+ m_GlobalMembersStack.emplace_back(name, CreatePersistent(hValue->ToObject()));
}
END_CONTEXT_SCOPE
@@ -582,11 +581,11 @@ V8ContextImpl::~V8ContextImpl()
for (auto it = m_GlobalMembersStack.rbegin(); it != m_GlobalMembersStack.rend(); it++)
{
- Dispose(*it);
+ Dispose(it->second);
}
Dispose(m_hHostObjectTemplate);
- Dispose(m_hInnerExceptionName);
+ Dispose(m_hHostExceptionName);
Dispose(m_hHostObjectCookieName);
// As of V8 3.16.0, the global property getter for a disposed context
@@ -600,7 +599,7 @@ V8ContextImpl::~V8ContextImpl()
}
Dispose(m_hContext);
- V8::ContextDisposedNotification();
+ ContextDisposedNotification();
END_ISOLATE_SCOPE
}
@@ -692,14 +691,14 @@ void V8ContextImpl::GetGlobalProperty(Local hName, const PropertyCallbac
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if ((stack.size() > 0) && !hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->HasOwnProperty(hName))
+ if (it->second->HasOwnProperty(hName))
{
- CALLBACK_RETURN((*it)->Get(hName));
+ CALLBACK_RETURN(it->second->Get(hName));
}
}
}
@@ -716,14 +715,14 @@ void V8ContextImpl::SetGlobalProperty(Local hName, Local hValue,
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if ((stack.size() > 0) && !hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->HasOwnProperty(hName))
+ if (it->second->HasOwnProperty(hName))
{
- (*it)->Set(hName, hValue);
+ it->second->Set(hName, hValue);
CALLBACK_RETURN(hValue);
}
}
@@ -741,14 +740,14 @@ void V8ContextImpl::QueryGlobalProperty(Local hName, const PropertyCallb
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if ((stack.size() > 0) && !hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->HasOwnProperty(hName))
+ if (it->second->HasOwnProperty(hName))
{
- CALLBACK_RETURN((*it)->GetPropertyAttributes(hName));
+ CALLBACK_RETURN(it->second->GetPropertyAttributes(hName));
}
}
}
@@ -765,22 +764,22 @@ void V8ContextImpl::DeleteGlobalProperty(Local hName, const PropertyCall
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->HasOwnProperty(hName))
+ if (it->second->HasOwnProperty(hName))
{
// WORKAROUND: Object::Delete() crashes if a custom property deleter calls
// ThrowException(). Interestingly, there is no crash if the same deleter is
// invoked directly from script via the delete operator.
- if ((*it)->HasOwnProperty(pContextImpl->m_hHostObjectCookieName))
+ if (it->second->HasOwnProperty(pContextImpl->m_hHostObjectCookieName))
{
try
{
- CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::GetHostObject(*it), StdString(hName)));
+ CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::GetHostObject(it->second), StdString(hName)));
}
catch (const HostException&)
{
@@ -788,7 +787,7 @@ void V8ContextImpl::DeleteGlobalProperty(Local hName, const PropertyCall
}
}
- CALLBACK_RETURN((*it)->Delete(hName));
+ CALLBACK_RETURN(it->second->Delete(hName));
}
}
}
@@ -807,20 +806,20 @@ void V8ContextImpl::GetGlobalPropertyNames(const PropertyCallbackInfo& in
{
try
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
std::vector names;
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
std::vector tempNames;
- if ((*it)->HasOwnProperty(pContextImpl->m_hHostObjectCookieName))
+ if (it->second->HasOwnProperty(pContextImpl->m_hHostObjectCookieName))
{
- HostObjectHelpers::GetPropertyNames(::GetHostObject(*it), tempNames);
+ HostObjectHelpers::GetPropertyNames(::GetHostObject(it->second), tempNames);
}
else
{
- pContextImpl->GetV8ObjectPropertyNames(*it, tempNames);
+ pContextImpl->GetV8ObjectPropertyNames(it->second, tempNames);
}
names.insert(names.end(), tempNames.begin(), tempNames.end());
@@ -856,14 +855,15 @@ void V8ContextImpl::GetGlobalProperty(unsigned __int32 index, const PropertyCall
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
+ auto hName = pContextImpl->CreateInteger(index)->ToString();
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->Has(index))
+ if (it->second->HasOwnProperty(hName))
{
- CALLBACK_RETURN((*it)->Get(index));
+ CALLBACK_RETURN(it->second->Get(index));
}
}
}
@@ -880,14 +880,15 @@ void V8ContextImpl::SetGlobalProperty(unsigned __int32 index, Local hValu
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
auto hName = pContextImpl->CreateInteger(index)->ToString();
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->HasOwnProperty(hName) && (*it)->Set(index, hValue))
+ if (it->second->HasOwnProperty(hName))
{
+ it->second->Set(index, hValue);
CALLBACK_RETURN(hValue);
}
}
@@ -905,14 +906,16 @@ void V8ContextImpl::QueryGlobalProperty(unsigned __int32 index, const PropertyCa
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
+ auto hIndex = pContextImpl->CreateInteger(index);
+ auto hName = hIndex->ToString();
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->Has(index))
+ if (it->second->HasOwnProperty(hName))
{
- CALLBACK_RETURN((*it)->GetPropertyAttributes(pContextImpl->CreateInteger(index)));
+ CALLBACK_RETURN(it->second->GetPropertyAttributes(hIndex));
}
}
}
@@ -929,15 +932,15 @@ void V8ContextImpl::DeleteGlobalProperty(unsigned __int32 index, const PropertyC
auto pContextImpl = static_cast(hGlobal->GetAlignedPointerFromInternalField(0));
if (pContextImpl != nullptr)
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
auto hName = pContextImpl->CreateInteger(index)->ToString();
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
- if ((*it)->HasOwnProperty(hName))
+ if (it->second->HasOwnProperty(hName))
{
- CALLBACK_RETURN((*it)->Delete(index));
+ CALLBACK_RETURN(it->second->Delete(index));
}
}
}
@@ -956,20 +959,20 @@ void V8ContextImpl::GetGlobalPropertyIndices(const PropertyCallbackInfo&
{
try
{
- const std::vector>& stack = pContextImpl->m_GlobalMembersStack;
+ const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
std::vector indices;
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
std::vector tempIndices;
- if ((*it)->HasOwnProperty(pContextImpl->m_hHostObjectCookieName))
+ if (it->second->HasOwnProperty(pContextImpl->m_hHostObjectCookieName))
{
- HostObjectHelpers::GetPropertyIndices(::GetHostObject(*it), tempIndices);
+ HostObjectHelpers::GetPropertyIndices(::GetHostObject(it->second), tempIndices);
}
else
{
- pContextImpl->GetV8ObjectPropertyIndices(*it, tempIndices);
+ pContextImpl->GetV8ObjectPropertyIndices(it->second, tempIndices);
}
indices.insert(indices.end(), tempIndices.begin(), tempIndices.end());
@@ -997,6 +1000,15 @@ void V8ContextImpl::GetGlobalPropertyIndices(const PropertyCallbackInfo&
//-----------------------------------------------------------------------------
+void V8ContextImpl::HostObjectFunctionCallHandler(const FunctionCallbackInfo& info)
+{
+ auto pContextImpl = ::UnwrapContextImpl(info);
+ if (!pContextImpl->m_AllowHostObjectFunctionCall)
+ pContextImpl->ThrowException(Exception::Error(pContextImpl->CreateString(StdString(L"This function is for ClearScript internal use only"))));
+}
+
+//-----------------------------------------------------------------------------
+
void V8ContextImpl::GetHostObjectProperty(Local hName, const PropertyCallbackInfo& info)
{
auto pContextImpl = ::UnwrapContextImpl(info);
@@ -1327,10 +1339,14 @@ Handle V8ContextImpl::ImportValue(const V8Value& value)
return CreateLocal(::ObjectHandleFromPtr(pvV8Object));
}
+ Local hObject;
+ BEGIN_PULSE_VALUE_SCOPE(&m_AllowHostObjectFunctionCall, true)
+ hObject = m_hHostObjectTemplate->InstanceTemplate()->NewInstance();
+ END_PULSE_VALUE_SCOPE
+
// WARNING: Instantiation may fail during script interruption. Check NewInstance()
// result to avoid access violations and V8 fatal errors in ::SetObjectHolder().
- auto hObject = m_hHostObjectTemplate->InstanceTemplate()->NewInstance();
if (!hObject.IsEmpty())
{
::SetHostObjectHolder(hObject, pHolder = pHolder->Clone());
@@ -1442,12 +1458,14 @@ void V8ContextImpl::Verify(const TryCatch& tryCatch)
StdString message;
bool stackOverflow;
+ bool allowGenericError;
StdString value(hException);
if (value.GetLength() > 0)
{
message = std::move(value);
stackOverflow = (_wcsicmp(message.ToCString(), L"RangeError: Maximum call stack size exceeded") == 0);
+ allowGenericError = false;
}
else
{
@@ -1456,6 +1474,7 @@ void V8ContextImpl::Verify(const TryCatch& tryCatch)
message = L"Unknown error; potential stack overflow detected";
stackOverflow = true;
+ allowGenericError = true;
}
#ifdef _DEBUG
@@ -1469,13 +1488,14 @@ void V8ContextImpl::Verify(const TryCatch& tryCatch)
// from robust. These sanity checks are intended to mitigate this fragility.
_ASSERTE(hException->IsObject());
- _ASSERTE(StdString(hException->ToObject()->GetConstructorName()) == L"RangeError");
+ StdString constructorName(hException->ToObject()->GetConstructorName());
+ _ASSERTE((constructorName == L"RangeError") || (allowGenericError && (constructorName == L"Error")));
}
#endif // _DEBUG
StdString stackTrace;
- V8Value innerException(V8Value::Undefined);
+ V8Value hostException(V8Value::Undefined);
if (stackOverflow)
{
@@ -1598,11 +1618,11 @@ void V8ContextImpl::Verify(const TryCatch& tryCatch)
if (hException->IsObject())
{
- innerException = ExportValue(hException->ToObject()->Get(m_hInnerExceptionName));
+ hostException = ExportValue(hException->ToObject()->Get(m_hHostExceptionName));
}
}
- throw V8Exception(V8Exception::Type_General, m_Name, std::move(message), std::move(stackTrace), std::move(innerException));
+ throw V8Exception(V8Exception::Type_General, m_Name, std::move(message), std::move(stackTrace), std::move(hostException));
}
}
@@ -1622,10 +1642,10 @@ void V8ContextImpl::ThrowScriptException(const HostException& exception)
{
auto hException = Exception::Error(CreateString(exception.GetMessage()))->ToObject();
- auto hInnerException = ImportValue(exception.GetException());
- if (!hInnerException.IsEmpty() && hInnerException->IsObject())
+ auto hHostException = ImportValue(exception.GetException());
+ if (!hHostException.IsEmpty() && hHostException->IsObject())
{
- hException->Set(m_hInnerExceptionName, hInnerException);
+ hException->Set(m_hHostExceptionName, hHostException);
}
ThrowException(hException);
diff --git a/ClearScript/V8/ClearScriptV8/V8ContextImpl.h b/ClearScript/V8/ClearScriptV8/V8ContextImpl.h
index 04f8fc742..29e8e07fc 100644
--- a/ClearScript/V8/ClearScriptV8/V8ContextImpl.h
+++ b/ClearScript/V8/ClearScriptV8/V8ContextImpl.h
@@ -257,6 +257,21 @@ class V8ContextImpl: public V8Context
return m_spIsolateImpl->TerminateExecution();
}
+ int ContextDisposedNotification()
+ {
+ return m_spIsolateImpl->ContextDisposedNotification();
+ }
+
+ bool IdleNotification(int idleTimeInMilliseconds)
+ {
+ return m_spIsolateImpl->IdleNotification(idleTimeInMilliseconds);
+ }
+
+ void LowMemoryNotification()
+ {
+ m_spIsolateImpl->LowMemoryNotification();
+ }
+
template
T Verify(const TryCatch& tryCatch, T result)
{
@@ -282,6 +297,8 @@ class V8ContextImpl: public V8Context
static void DeleteGlobalProperty(unsigned __int32 index, const PropertyCallbackInfo& info);
static void GetGlobalPropertyIndices(const PropertyCallbackInfo& info);
+ static void HostObjectFunctionCallHandler(const FunctionCallbackInfo& info);
+
static void GetHostObjectProperty(Local hName, const PropertyCallbackInfo& info);
static void SetHostObjectProperty(Local hName, Local hValue, const PropertyCallbackInfo& info);
static void QueryHostObjectProperty(Local hName, const PropertyCallbackInfo& info);
@@ -309,10 +326,11 @@ class V8ContextImpl: public V8Context
SharedPtr m_spIsolateImpl;
Persistent m_hContext;
Persistent m_hGlobal;
- std::vector> m_GlobalMembersStack;
+ std::vector>> m_GlobalMembersStack;
Persistent m_hHostObjectCookieName;
- Persistent m_hInnerExceptionName;
+ Persistent m_hHostExceptionName;
Persistent m_hHostObjectTemplate;
SharedPtr m_spWeakBinding;
void* m_pvV8ObjectCache;
+ bool m_AllowHostObjectFunctionCall;
};
diff --git a/ClearScript/V8/ClearScriptV8/V8DebugListenerImpl.cpp b/ClearScript/V8/ClearScriptV8/V8DebugListenerImpl.cpp
new file mode 100644
index 000000000..75ecca44d
--- /dev/null
+++ b/ClearScript/V8/ClearScriptV8/V8DebugListenerImpl.cpp
@@ -0,0 +1,136 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+#include "ClearScriptV8Managed.h"
+
+namespace Microsoft {
+namespace ClearScript {
+namespace V8 {
+
+ //-------------------------------------------------------------------------
+ // V8DebugListenerImpl implementation
+ //-------------------------------------------------------------------------
+
+ V8DebugListenerImpl::V8DebugListenerImpl(HostObjectHelpers::DebugCallback&& callback):
+ m_gcLock(gcnew Object),
+ m_pspCallback(new SharedPtr(new HostObjectHelpers::DebugCallback(std::move(callback))))
+ {
+ }
+
+ //-------------------------------------------------------------------------
+
+ void V8DebugListenerImpl::OnMessageReceived(String^ gcCommand)
+ {
+ SharedPtr spCallback;
+ if (TryGetCallback(spCallback))
+ {
+ (*spCallback)(StdString(gcCommand));
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ V8DebugListenerImpl::~V8DebugListenerImpl()
+ {
+ SharedPtr spCallback;
+
+ BEGIN_LOCK_SCOPE(m_gcLock)
+
+ if (m_pspCallback != nullptr)
+ {
+ // hold callback for destruction outside lock scope
+ spCallback = *m_pspCallback;
+ delete m_pspCallback;
+ m_pspCallback = nullptr;
+ }
+
+ END_LOCK_SCOPE
+ }
+
+ //-------------------------------------------------------------------------
+
+ V8DebugListenerImpl::!V8DebugListenerImpl()
+ {
+ if (m_pspCallback != nullptr)
+ {
+ delete m_pspCallback;
+ m_pspCallback = nullptr;
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ bool V8DebugListenerImpl::TryGetCallback(SharedPtr& spCallback)
+ {
+ BEGIN_LOCK_SCOPE(m_gcLock)
+
+ if (m_pspCallback == nullptr)
+ {
+ return false;
+ }
+
+ spCallback = *m_pspCallback;
+ return true;
+
+ END_LOCK_SCOPE
+ }
+
+}}}
diff --git a/ClearScript/V8/ClearScriptV8/V8DebugListenerImpl.h b/ClearScript/V8/ClearScriptV8/V8DebugListenerImpl.h
new file mode 100644
index 000000000..7d6d3ebd3
--- /dev/null
+++ b/ClearScript/V8/ClearScriptV8/V8DebugListenerImpl.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+#pragma once
+
+namespace Microsoft {
+namespace ClearScript {
+namespace V8 {
+
+ //-------------------------------------------------------------------------
+ // V8DebugListenerImpl
+ //-------------------------------------------------------------------------
+
+ private ref class V8DebugListenerImpl : IV8DebugListener
+ {
+ public:
+
+ V8DebugListenerImpl(HostObjectHelpers::DebugCallback&& callback);
+
+ virtual void OnMessageReceived(String^ gcCommand);
+
+ ~V8DebugListenerImpl();
+ !V8DebugListenerImpl();
+
+ private:
+
+ bool TryGetCallback(SharedPtr& spCallback);
+
+ Object^ m_gcLock;
+ SharedPtr* m_pspCallback;
+ };
+
+}}}
diff --git a/ClearScript/V8/ClearScriptV8/V8Exception.cpp b/ClearScript/V8/ClearScriptV8/V8Exception.cpp
index a7f6110dd..643af1ebd 100644
--- a/ClearScript/V8/ClearScriptV8/V8Exception.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8Exception.cpp
@@ -73,7 +73,7 @@ void DECLSPEC_NORETURN V8Exception::ThrowScriptEngineException() const
auto gcEngineName = m_EngineName.ToManagedString();
auto gcMessage = m_Message.ToManagedString();
auto gcStackTrace = m_StackTrace.ToManagedString();
- auto gcInnerException = dynamic_cast(V8ContextProxyImpl::ExportValue(m_InnerException));
+ auto gcInnerException = V8ProxyHelpers::MarshalExceptionToHost(V8ContextProxyImpl::ExportValue(m_InnerException));
switch (m_Type)
{
diff --git a/ClearScript/V8/ClearScriptV8/V8Exception.h b/ClearScript/V8/ClearScriptV8/V8Exception.h
index 78426ad72..1011c8b3e 100644
--- a/ClearScript/V8/ClearScriptV8/V8Exception.h
+++ b/ClearScript/V8/ClearScriptV8/V8Exception.h
@@ -78,17 +78,17 @@ class V8Exception
V8Exception(Type type, const StdString& engineName, StdString&& message):
m_Type(type),
- m_EngineName(engineName),
- m_Message(std::move(message)),
+ m_EngineName(engineName),
+ m_Message(std::move(message)),
m_InnerException(V8Value::Undefined)
{
}
V8Exception(Type type, const StdString& engineName, StdString&& message, StdString&& stackTrace, V8Value&& innerException):
m_Type(type),
- m_EngineName(engineName),
- m_Message(std::move(message)),
- m_StackTrace(std::move(stackTrace)),
+ m_EngineName(engineName),
+ m_Message(std::move(message)),
+ m_StackTrace(std::move(stackTrace)),
m_InnerException(std::move(innerException))
{
}
diff --git a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp
index db8d229cd..3b1194ee5 100644
--- a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp
@@ -61,6 +61,73 @@
#include "ClearScriptV8Native.h"
+//-----------------------------------------------------------------------------
+// V8Platform
+//-----------------------------------------------------------------------------
+
+class V8Platform: public Platform
+{
+public:
+
+ static void EnsureInstalled();
+
+ virtual void CallOnBackgroundThread(Task* pTask, ExpectedRuntime runtime) override;
+ virtual void CallOnForegroundThread(Isolate* pIsolate, Task* pTask) override;
+ virtual double MonotonicallyIncreasingTime() override;
+
+private:
+
+ V8Platform();
+
+ static V8Platform ms_Instance;
+ static std::once_flag ms_InstallationFlag;
+};
+
+//-----------------------------------------------------------------------------
+
+void V8Platform::EnsureInstalled()
+{
+ std::call_once(ms_InstallationFlag, []
+ {
+ V8::InitializePlatform(&ms_Instance);
+ ASSERT_EVAL(V8::Initialize());
+ });
+}
+
+//-----------------------------------------------------------------------------
+
+void V8Platform::CallOnBackgroundThread(Task* pTask, ExpectedRuntime /*runtime*/)
+{
+ std::shared_ptr spTask(pTask);
+ Concurrency::create_task([spTask] { spTask->Run(); });
+}
+
+//-----------------------------------------------------------------------------
+
+void V8Platform::CallOnForegroundThread(Isolate* /*pIsolate*/, Task* /*pTask*/)
+{
+ // unexpected call to unsupported method
+ std::terminate();
+}
+
+//-----------------------------------------------------------------------------
+
+double V8Platform::MonotonicallyIncreasingTime()
+{
+ return HighResolutionClock::GetRelativeSeconds();
+}
+
+//-----------------------------------------------------------------------------
+
+V8Platform::V8Platform()
+{
+}
+
+//-----------------------------------------------------------------------------
+
+V8Platform V8Platform::ms_Instance;
+std::once_flag V8Platform::ms_InstallationFlag;
+
//-----------------------------------------------------------------------------
// V8ArrayBufferAllocator
//-----------------------------------------------------------------------------
@@ -71,9 +138,9 @@ class V8ArrayBufferAllocator: public ArrayBuffer::Allocator
static void EnsureInstalled();
- void* Allocate(size_t size);
- void* AllocateUninitialized(size_t size);
- void Free(void* pvData, size_t size);
+ virtual void* Allocate(size_t size) override;
+ virtual void* AllocateUninitialized(size_t size) override;
+ virtual void Free(void* pvData, size_t size) override;
private:
@@ -97,21 +164,21 @@ void V8ArrayBufferAllocator::EnsureInstalled()
void* V8ArrayBufferAllocator::Allocate(size_t size)
{
- return calloc(1, size);
+ return ::calloc(1, size);
}
//-----------------------------------------------------------------------------
void* V8ArrayBufferAllocator::AllocateUninitialized(size_t size)
{
- return malloc(size);
+ return ::malloc(size);
}
//-----------------------------------------------------------------------------
void V8ArrayBufferAllocator::Free(void* pvData, size_t /*size*/)
{
- free(pvData);
+ ::free(pvData);
}
//-----------------------------------------------------------------------------
@@ -147,10 +214,6 @@ std::once_flag V8ArrayBufferAllocator::ms_InstallationFlag;
//-----------------------------------------------------------------------------
-DEFINE_CONCURRENT_CALLBACK_MANAGER(DebugMessageDispatcher, void())
-
-//-----------------------------------------------------------------------------
-
static const size_t s_StackBreathingRoom = static_cast(16 * 1024);
static size_t* const s_pMinStackLimit = reinterpret_cast(sizeof(size_t));
@@ -158,7 +221,6 @@ static size_t* const s_pMinStackLimit = reinterpret_cast(sizeof(size_t)
V8IsolateImpl::V8IsolateImpl(const StdString& name, const V8IsolateConstraints* pConstraints, bool enableDebugging, int debugPort):
m_Name(name),
- m_pIsolate(Isolate::New()),
m_DebuggingEnabled(false),
m_DebugMessageDispatchCount(0),
m_MaxHeapSize(0),
@@ -168,8 +230,19 @@ V8IsolateImpl::V8IsolateImpl(const StdString& name, const V8IsolateConstraints*
m_pStackLimit(nullptr),
m_IsOutOfMemory(false)
{
+ V8Platform::EnsureInstalled();
V8ArrayBufferAllocator::EnsureInstalled();
+ Isolate::CreateParams params;
+ if (pConstraints != nullptr)
+ {
+ params.constraints.set_max_semi_space_size(pConstraints->GetMaxNewSpaceSize());
+ params.constraints.set_max_old_space_size(pConstraints->GetMaxOldSpaceSize());
+ params.constraints.set_max_executable_size(pConstraints->GetMaxExecutableSize());
+ }
+
+ m_pIsolate = Isolate::New(params);
+
BEGIN_ADDREF_SCOPE
m_pIsolate->SetData(0, this);
@@ -177,14 +250,6 @@ V8IsolateImpl::V8IsolateImpl(const StdString& name, const V8IsolateConstraints*
BEGIN_ISOLATE_ENTRY_SCOPE
V8::SetCaptureStackTraceForUncaughtExceptions(true, 64, StackTrace::kDetailed);
- if (pConstraints != nullptr)
- {
- ResourceConstraints constraints;
- constraints.set_max_new_space_size(pConstraints->GetMaxNewSpaceSize());
- constraints.set_max_old_space_size(pConstraints->GetMaxOldSpaceSize());
- constraints.set_max_executable_size(pConstraints->GetMaxExecutableSize());
- ASSERT_EVAL(SetResourceConstraints(m_pIsolate, &constraints));
- }
END_ISOLATE_ENTRY_SCOPE
@@ -237,28 +302,24 @@ void V8IsolateImpl::EnableDebugging(int debugPort)
if (!m_DebuggingEnabled)
{
+ StdString version(String::NewFromUtf8(m_pIsolate, V8::GetVersion()));
if (debugPort < 1)
{
debugPort = 9222;
}
auto wrIsolate = CreateWeakRef();
- m_pDebugMessageDispatcher = CALLBACK_MANAGER(DebugMessageDispatcher)::Alloc([wrIsolate]
+ m_pvDebugAgent = HostObjectHelpers::CreateDebugAgent(m_Name, version, debugPort, [wrIsolate] (const StdString& command)
{
- Concurrency::create_task([wrIsolate]
+ auto spIsolate = wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
{
- auto spIsolate = wrIsolate.GetTarget();
- if (!spIsolate.IsEmpty())
- {
- auto pIsolateImpl = static_cast(spIsolate.GetRawPtr());
- pIsolateImpl->DispatchDebugMessages();
- }
- });
+ auto pIsolateImpl = static_cast(spIsolate.GetRawPtr());
+ pIsolateImpl->SendDebugCommand(command);
+ }
});
- _ASSERTE(m_pDebugMessageDispatcher);
- Debug::SetDebugMessageDispatchHandler(m_pDebugMessageDispatcher);
- ASSERT_EVAL(Debug::EnableAgent(*String::Utf8Value(CreateString(m_Name)), debugPort));
+ Debug::SetMessageHandler(OnDebugMessageShared);
m_DebuggingEnabled = true;
m_DebugPort = debugPort;
@@ -274,13 +335,8 @@ void V8IsolateImpl::DisableDebugging()
if (m_DebuggingEnabled)
{
- Debug::DisableAgent();
- Debug::SetDebugMessageDispatchHandler(nullptr);
-
- if (m_pDebugMessageDispatcher != nullptr)
- {
- ASSERT_EVAL(CALLBACK_MANAGER(DebugMessageDispatcher)::Free(m_pDebugMessageDispatcher));
- }
+ Debug::SetMessageHandler(nullptr);
+ HostObjectHelpers::DestroyDebugAgent(m_pvDebugAgent);
m_DebuggingEnabled = false;
m_DebugMessageDispatchCount = 0;
@@ -370,11 +426,11 @@ void V8IsolateImpl::CollectGarbage(bool exhaustive)
if (exhaustive)
{
- V8::LowMemoryNotification();
+ LowMemoryNotification();
}
else
{
- while (!V8::IdleNotification());
+ while (!IdleNotification(100));
}
END_ISOLATE_SCOPE
@@ -447,6 +503,13 @@ V8IsolateImpl::~V8IsolateImpl()
//-----------------------------------------------------------------------------
+void V8IsolateImpl::OnInterruptShared(Isolate* pIsolate, void* /*pvData*/)
+{
+ static_cast(pIsolate->GetData(0))->OnInterrupt();
+}
+
+//-----------------------------------------------------------------------------
+
void V8IsolateImpl::OnInterrupt()
{
std::function callback;
@@ -465,6 +528,41 @@ void V8IsolateImpl::OnInterrupt()
//-----------------------------------------------------------------------------
+void V8IsolateImpl::SendDebugCommand(const StdString& command)
+{
+ Debug::SendCommand(m_pIsolate, command.ToCString(), command.GetLength());
+
+ auto wrIsolate = CreateWeakRef();
+ Concurrency::create_task([wrIsolate]
+ {
+ auto spIsolate = wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
+ {
+ auto pIsolateImpl = static_cast(spIsolate.GetRawPtr());
+ pIsolateImpl->DispatchDebugMessages();
+ }
+ });
+}
+
+//-----------------------------------------------------------------------------
+
+void V8IsolateImpl::OnDebugMessageShared(const Debug::Message& message)
+{
+ static_cast(message.GetIsolate()->GetData(0))->OnDebugMessage(message);
+}
+
+//-----------------------------------------------------------------------------
+
+void V8IsolateImpl::OnDebugMessage(const Debug::Message& message)
+{
+ if (m_pvDebugAgent)
+ {
+ HostObjectHelpers::SendDebugMessage(m_pvDebugAgent, StdString(message.GetJSON()));
+ }
+}
+
+//-----------------------------------------------------------------------------
+
void V8IsolateImpl::DispatchDebugMessages()
{
if (++m_DebugMessageDispatchCount == 1)
@@ -546,9 +644,7 @@ void V8IsolateImpl::EnterExecutionScope(size_t* pStackMarker)
}
// set and record stack address limit
- ResourceConstraints constraints;
- constraints.set_stack_limit(reinterpret_cast(pStackLimit));
- ASSERT_EVAL(SetResourceConstraints(m_pIsolate, &constraints));
+ m_pIsolate->SetStackLimit(reinterpret_cast(pStackLimit));
m_pStackLimit = pStackLimit;
// enter outermost stack usage monitoring scope
@@ -586,9 +682,7 @@ void V8IsolateImpl::ExitExecutionScope()
if (m_pStackLimit != nullptr)
{
// V8 has no API for removing a stack address limit
- ResourceConstraints constraints;
- constraints.set_stack_limit(reinterpret_cast(s_pMinStackLimit));
- ASSERT_EVAL(SetResourceConstraints(m_pIsolate, &constraints));
+ m_pIsolate->SetStackLimit(reinterpret_cast(s_pMinStackLimit));
m_pStackLimit = nullptr;
}
}
@@ -653,7 +747,7 @@ void V8IsolateImpl::CheckHeapSize(size_t maxHeapSize)
if (heapInfo.GetTotalHeapSize() > maxHeapSize)
{
// yes; collect garbage
- V8::LowMemoryNotification();
+ LowMemoryNotification();
// is the total heap size still over the limit?
GetHeapInfo(heapInfo);
diff --git a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h
index 83be49edf..0f54b38ed 100644
--- a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h
+++ b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h
@@ -245,16 +245,27 @@ class V8IsolateImpl: public V8Isolate
V8::TerminateExecution(m_pIsolate);
}
+ int ContextDisposedNotification()
+ {
+ return m_pIsolate->ContextDisposedNotification();
+ }
+
+ bool IdleNotification(int idleTimeInMilliseconds)
+ {
+ return m_pIsolate->IdleNotification(idleTimeInMilliseconds);
+ }
+
+ void LowMemoryNotification()
+ {
+ m_pIsolate->LowMemoryNotification();
+ }
+
void RequestInterrupt(std::function&& callback)
{
BEGIN_MUTEX_SCOPE(m_InterruptMutex)
m_InterruptCallback = std::move(callback);
- m_pIsolate->RequestInterrupt([] (Isolate* pIsolate, void* /*pvData*/)
- {
- static_cast(pIsolate->GetData(0))->OnInterrupt();
-
- }, nullptr);
+ m_pIsolate->RequestInterrupt(OnInterruptShared, nullptr);
END_MUTEX_SCOPE
}
@@ -304,8 +315,12 @@ class V8IsolateImpl: public V8Isolate
private:
+ static void OnInterruptShared(Isolate* pIsolate, void* pvData);
void OnInterrupt();
+ void SendDebugCommand(const StdString& command);
+ static void OnDebugMessageShared(const Debug::Message& message);
+ void OnDebugMessage(const Debug::Message& message);
void DispatchDebugMessages();
void ProcessDebugMessages();
@@ -324,7 +339,7 @@ class V8IsolateImpl: public V8Isolate
bool m_DebuggingEnabled;
int m_DebugPort;
- Debug::DebugMessageDispatchHandler m_pDebugMessageDispatcher;
+ void* m_pvDebugAgent;
std::atomic m_DebugMessageDispatchCount;
std::atomic m_MaxHeapSize;
diff --git a/ClearScript/V8/ClearScriptV8/V8Platform.h b/ClearScript/V8/ClearScriptV8/V8Platform.h
index 8a48bb5f5..674a32838 100644
--- a/ClearScript/V8/ClearScriptV8/V8Platform.h
+++ b/ClearScript/V8/ClearScriptV8/V8Platform.h
@@ -68,6 +68,7 @@
#pragma warning(push, 3)
#include "v8.h"
+#include "v8-platform.h"
#include "v8-debug.h"
using namespace v8;
@@ -107,29 +108,29 @@ class V8FastPersistent
return V8FastPersistent(GetPtrAndClear(hTemp));
}
- template
- bool operator==(const Handle& hValue)
- {
- return AsPersistent() == hValue;
- }
+ template
+ bool operator==(const Handle& hValue)
+ {
+ return AsPersistent() == hValue;
+ }
- template
- bool operator==(const V8FastPersistent& hValue)
- {
- return AsPersistent() == hValue.AsPersistent();
- }
+ template
+ bool operator==(const V8FastPersistent& hValue)
+ {
+ return AsPersistent() == hValue.AsPersistent();
+ }
- template
- bool operator!=(const Handle& hValue)
- {
- return AsPersistent() != hValue;
- }
+ template
+ bool operator!=(const Handle& hValue)
+ {
+ return AsPersistent() != hValue;
+ }
- template
- bool operator!=(const V8FastPersistent& hValue)
- {
- return AsPersistent() != hValue.AsPersistent();
- }
+ template
+ bool operator!=(const V8FastPersistent& hValue)
+ {
+ return AsPersistent() != hValue.AsPersistent();
+ }
bool IsEmpty() const
{
@@ -278,29 +279,29 @@ class V8SafePersistent
return V8SafePersistent(new Persistent(pIsolate, hValue.GetImpl()));
}
- template
- bool operator==(const Handle& hValue)
- {
- return GetImpl() == hValue;
- }
-
- template
- bool operator==(const V8SafePersistent& hValue)
- {
- return GetImpl() == hValue.GetImpl();
- }
-
- template
- bool operator!=(const Handle& hValue)
- {
- return GetImpl() != hValue;
- }
-
- template
- bool operator!=(const V8SafePersistent& hValue)
- {
- return GetImpl() != hValue.GetImpl();
- }
+ template
+ bool operator==(const Handle& hValue)
+ {
+ return GetImpl() == hValue;
+ }
+
+ template
+ bool operator==(const V8SafePersistent& hValue)
+ {
+ return GetImpl() == hValue.GetImpl();
+ }
+
+ template
+ bool operator!=(const Handle& hValue)
+ {
+ return GetImpl() != hValue;
+ }
+
+ template
+ bool operator!=(const V8SafePersistent& hValue)
+ {
+ return GetImpl() != hValue.GetImpl();
+ }
bool IsEmpty() const
{
diff --git a/ClearScript/V8/ClearScriptV8/V8WeakContextBinding.h b/ClearScript/V8/ClearScriptV8/V8WeakContextBinding.h
index 37241251f..523cc0458 100644
--- a/ClearScript/V8/ClearScriptV8/V8WeakContextBinding.h
+++ b/ClearScript/V8/ClearScriptV8/V8WeakContextBinding.h
@@ -111,7 +111,6 @@ class V8WeakContextBinding: public SharedPtrTarget
throw V8Exception(V8Exception::Type_General, m_ContextName, StdString(L"The V8 script engine has been destroyed"));
}
-
bool TryGetContextImpl(SharedPtr& spContextImpl) const
{
auto spContext = m_wrContext.GetTarget();
diff --git a/ClearScript/V8/IV8DebugListener.cs b/ClearScript/V8/IV8DebugListener.cs
new file mode 100644
index 000000000..46e8cd3da
--- /dev/null
+++ b/ClearScript/V8/IV8DebugListener.cs
@@ -0,0 +1,70 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+using System;
+
+namespace Microsoft.ClearScript.V8
+{
+ internal interface IV8DebugListener: IDisposable
+ {
+ void OnMessageReceived(string command);
+ }
+}
diff --git a/ClearScript/V8/V8/LICENSE.v8 b/ClearScript/V8/V8/LICENSE.v8
new file mode 100644
index 000000000..933718a9e
--- /dev/null
+++ b/ClearScript/V8/V8/LICENSE.v8
@@ -0,0 +1,26 @@
+Copyright 2006-2011, the V8 project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/ClearScript/V8/V8/V8Patch.txt b/ClearScript/V8/V8/V8Patch.txt
index 4b8c5773e..46337def7 100644
--- a/ClearScript/V8/V8/V8Patch.txt
+++ b/ClearScript/V8/V8/V8Patch.txt
@@ -1,7 +1,59 @@
-Index: tools/gyp/v8.gyp
-===================================================================
---- tools/gyp/v8.gyp (revision 24646)
-+++ tools/gyp/v8.gyp (working copy)
+diff --git a/src/api.cc b/src/api.cc
+index 239c7ac..be3cfc8 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -5171,10 +5171,6 @@ void v8::V8::SetReturnAddressLocationResolver(
+
+ void v8::V8::SetArrayBufferAllocator(
+ ArrayBuffer::Allocator* allocator) {
+- if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
+- "v8::V8::SetArrayBufferAllocator",
+- "ArrayBufferAllocator might only be set once"))
+- return;
+ i::V8::SetArrayBufferAllocator(allocator);
+ }
+
+diff --git a/src/objects.cc b/src/objects.cc
+index a4c3bea..e78888a 100644
+--- a/src/objects.cc
++++ b/src/objects.cc
+@@ -6229,7 +6229,7 @@ MaybeHandle JSObject::DefineAccessor(Handle object,
+ if (is_observed) {
+ if (is_element) {
+ Maybe maybe = HasOwnElement(object, index);
+- // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
++ // Workaround for a GCC 4.4.3 bug which leads to "'preexists' may be used
+ // uninitialized in this function".
+ if (!maybe.has_value) {
+ DCHECK(false);
+diff --git a/src/v8.cc b/src/v8.cc
+index 62c3da4..ab97c36 100644
+--- a/src/v8.cc
++++ b/src/v8.cc
+@@ -100,7 +100,6 @@ void V8::InitializeOncePerProcess() {
+
+
+ void V8::InitializePlatform(v8::Platform* platform) {
+- CHECK(!platform_);
+ CHECK(platform);
+ platform_ = platform;
+ }
+diff --git a/src/v8.h b/src/v8.h
+index 13c33e1..c89fc1d 100644
+--- a/src/v8.h
++++ b/src/v8.h
+@@ -74,7 +74,6 @@ class V8 : public AllStatic {
+ }
+
+ static void SetArrayBufferAllocator(v8::ArrayBuffer::Allocator *allocator) {
+- CHECK_EQ(NULL, array_buffer_allocator_);
+ array_buffer_allocator_ = allocator;
+ }
+
+diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
+index 5874865..52f6039 100644
+--- a/tools/gyp/v8.gyp
++++ b/tools/gyp/v8.gyp
@@ -35,6 +35,7 @@
'targets': [
{
diff --git a/ClearScript/V8/V8DebugAgent.cs b/ClearScript/V8/V8DebugAgent.cs
new file mode 100644
index 000000000..3fc28ef35
--- /dev/null
+++ b/ClearScript/V8/V8DebugAgent.cs
@@ -0,0 +1,376 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Microsoft Public License (MS-PL)
+//
+// This license governs use of the accompanying software. If you use the
+// software, you accept this license. If you do not accept the license, do not
+// use the software.
+//
+// 1. Definitions
+//
+// The terms "reproduce," "reproduction," "derivative works," and
+// "distribution" have the same meaning here as under U.S. copyright law. A
+// "contribution" is the original software, or any additions or changes to
+// the software. A "contributor" is any person that distributes its
+// contribution under this license. "Licensed patents" are a contributor's
+// patent claims that read directly on its contribution.
+//
+// 2. Grant of Rights
+//
+// (A) Copyright Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free copyright license
+// to reproduce its contribution, prepare derivative works of its
+// contribution, and distribute its contribution or any derivative works
+// that you create.
+//
+// (B) Patent Grant- Subject to the terms of this license, including the
+// license conditions and limitations in section 3, each contributor
+// grants you a non-exclusive, worldwide, royalty-free license under its
+// licensed patents to make, have made, use, sell, offer for sale,
+// import, and/or otherwise dispose of its contribution in the software
+// or derivative works of the contribution in the software.
+//
+// 3. Conditions and Limitations
+//
+// (A) No Trademark License- This license does not grant you rights to use
+// any contributors' name, logo, or trademarks.
+//
+// (B) If you bring a patent claim against any contributor over patents that
+// you claim are infringed by the software, your patent license from such
+// contributor to the software ends automatically.
+//
+// (C) If you distribute any portion of the software, you must retain all
+// copyright, patent, trademark, and attribution notices that are present
+// in the software.
+//
+// (D) If you distribute any portion of the software in source code form, you
+// may do so only under this license by including a complete copy of this
+// license with your distribution. If you distribute any portion of the
+// software in compiled or object code form, you may only do so under a
+// license that complies with this license.
+//
+// (E) The software is licensed "as-is." You bear the risk of using it. The
+// contributors give no express warranties, guarantees or conditions. You
+// may have additional consumer rights under your local laws which this
+// license cannot change. To the extent permitted under your local laws,
+// the contributors exclude the implied warranties of merchantability,
+// fitness for a particular purpose and non-infringement.
+//
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using Microsoft.ClearScript.Util;
+
+namespace Microsoft.ClearScript.V8
+{
+ internal sealed class V8DebugAgent : IDisposable
+ {
+ #region data
+
+ private readonly string name;
+ private readonly string version;
+ private readonly IV8DebugListener listener;
+
+ private TcpListener tcpListener;
+ private TcpClient tcpClient;
+
+ private readonly ConcurrentQueue queue = new ConcurrentQueue();
+ private readonly AutoResetEvent queueEvent = new AutoResetEvent(false);
+ private RegisteredWaitHandle queueWaitHandle;
+
+ private DisposedFlag disposedFlag = new DisposedFlag();
+
+ #endregion
+
+ #region constructors
+
+ public V8DebugAgent(string name, string version, int port, IV8DebugListener listener)
+ {
+ this.name = name;
+ this.version = version;
+ this.listener = listener;
+
+ RegisterWaitForQueueEvent();
+
+ MiscHelpers.Try(() =>
+ {
+ tcpListener = new TcpListener(IPAddress.Loopback, port);
+ tcpListener.Start();
+ tcpListener.BeginAcceptTcpClient(OnClientAccepted, null);
+ });
+ }
+
+ #endregion
+
+ #region session management
+
+ private void OnClientAccepted(IAsyncResult result)
+ {
+ if (!disposedFlag.IsSet())
+ {
+ TcpClient tempTcpClient;
+ if (MiscHelpers.Try(out tempTcpClient, () => tcpListener.EndAcceptTcpClient(result)))
+ {
+ if (Interlocked.CompareExchange(ref tcpClient, tempTcpClient, null) == null)
+ {
+ ConnectClient();
+ }
+ else
+ {
+ RejectClient(tempTcpClient);
+ }
+
+ MiscHelpers.Try(() => tcpListener.BeginAcceptTcpClient(OnClientAccepted, null));
+ }
+ }
+ }
+
+ private void ConnectClient()
+ {
+ SendStringAsync(tcpClient, "Type:connect\r\nV8-Version:" + version + "\r\nProtocol-Version:1\r\nEmbedding-Host:" + name + "\r\nContent-Length:0\r\n\r\n", OnConnectionMessageSent);
+ }
+
+ private void OnConnectionMessageSent(bool succeeded)
+ {
+ if (succeeded)
+ {
+ ReceiveMessage();
+ }
+ else
+ {
+ DisconnectClient("Could not send connection message");
+ }
+ }
+
+ private static void RejectClient(TcpClient tcpClient)
+ {
+ SendStringAsync(tcpClient, "Remote debugging session already active\r\n", succeeded => MiscHelpers.Try(tcpClient.Close));
+ }
+
+ private void DisconnectClient(string errorMessage)
+ {
+ var tempTcpClient = Interlocked.Exchange(ref tcpClient, null);
+ if (tempTcpClient != null)
+ {
+ if (!string.IsNullOrWhiteSpace(errorMessage))
+ {
+ Trace("Disconnecting debugger: " + errorMessage);
+ }
+
+ MiscHelpers.Try(tempTcpClient.Close);
+ }
+ }
+
+ #endregion
+
+ #region inbound message processing
+
+ private void ReceiveMessage()
+ {
+ ReceiveLineAsync(line => OnHeaderLineReceived(line, -1));
+ }
+
+ private void OnHeaderLineReceived(string line, int contentLength)
+ {
+ if (line != null)
+ {
+ if (!string.IsNullOrWhiteSpace(line))
+ {
+ var segments = line.Split(':');
+ if ((segments.Length == 2) && (segments[0] == "Content-Length"))
+ {
+ int length;
+ if (int.TryParse(segments[1], out length))
+ {
+ contentLength = length;
+ }
+ }
+
+ ReceiveLineAsync(nextLine => OnHeaderLineReceived(nextLine, contentLength));
+ }
+ else if (contentLength > 0)
+ {
+ ReceiveStringAsync(contentLength, OnMessageReceived);
+ }
+ else if (contentLength == 0)
+ {
+ OnMessageReceived(string.Empty);
+ }
+ else
+ {
+ OnMessageReceivedInternal(null, "Message content length not specified");
+ }
+ }
+ else
+ {
+ OnMessageReceivedInternal(null, "Could not receive message header");
+ }
+ }
+
+ void OnMessageReceived(string content)
+ {
+ OnMessageReceivedInternal(content, "Could not receive message content");
+ }
+
+ void OnMessageReceivedInternal(string content, string errorMessage)
+ {
+ bool disconnect;
+ if (content != null)
+ {
+ disconnect = content.Contains("\"type\":\"request\",\"command\":\"disconnect\"}");
+ }
+ else
+ {
+ content = "{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}";
+ disconnect = true;
+ }
+
+ listener.OnMessageReceived(content);
+
+ if (disconnect)
+ {
+ DisconnectClient(errorMessage);
+ }
+ else
+ {
+ ReceiveMessage();
+ }
+ }
+
+ #endregion
+
+ #region outbound message queue
+
+ public void SendMessage(string content)
+ {
+ if (!disposedFlag.IsSet())
+ {
+ queue.Enqueue(content);
+ MiscHelpers.Try(() => queueEvent.Set());
+ }
+ }
+
+ private void RegisterWaitForQueueEvent()
+ {
+ var oldQueueWaitHandle = Interlocked.Exchange(ref queueWaitHandle, ThreadPool.RegisterWaitForSingleObject(queueEvent, OnQueueEvent, null, Timeout.Infinite, true));
+ if (oldQueueWaitHandle != null)
+ {
+ oldQueueWaitHandle.Unregister(null);
+ }
+ }
+
+ private void OnQueueEvent(object state, bool timedOut)
+ {
+ string content;
+ while (queue.TryDequeue(out content))
+ {
+ var tempTcpClient = tcpClient;
+ if (tempTcpClient != null)
+ {
+ var contentBytes = Encoding.UTF8.GetBytes(content);
+ var headerBytes = Encoding.UTF8.GetBytes(MiscHelpers.FormatInvariant("Content-Length:{0}\r\n\r\n", contentBytes.Length));
+ tempTcpClient.Client.SendBytesAsync(headerBytes.Concat(contentBytes).ToArray(), OnMessageSent);
+ return;
+ }
+ }
+
+ if (!disposedFlag.IsSet())
+ {
+ RegisterWaitForQueueEvent();
+ }
+ }
+
+ private void OnMessageSent(bool succeeded)
+ {
+ if (succeeded)
+ {
+ OnQueueEvent(null, false);
+ }
+ else
+ {
+ DisconnectClient("Could not send message");
+ }
+ }
+
+ #endregion
+
+ #region protocol helpers
+
+ private static void SendStringAsync(TcpClient tcpClient, string content, Action callback)
+ {
+ tcpClient.Client.SendBytesAsync(Encoding.UTF8.GetBytes(content), callback);
+ }
+
+ private void ReceiveStringAsync(int sizeInBytes, Action callback)
+ {
+ tcpClient.Client.ReceiveBytesAsync(sizeInBytes, bytes => callback((bytes != null) ? Encoding.UTF8.GetString(bytes) : null));
+ }
+
+ private void ReceiveLineAsync(Action