Skip to content

Commit

Permalink
Version 7.4.2: Enhanced support for parameterless value type construc…
Browse files Browse the repository at this point in the history
…tors (mentioned in GitHub Issue #444); fixed COM-related memory leak on .NET Framework (GitHub Issue #510); enabled multidimensional array manipulation via VBScript indexing syntax (GitHub Issue #511); improved stability on Apple Silicon devices. Tested with V8 11.4.183.17.
  • Loading branch information
ClearScriptLib committed Jun 1, 2023
1 parent d9a58a6 commit a02a01f
Show file tree
Hide file tree
Showing 32 changed files with 686 additions and 185 deletions.
6 changes: 3 additions & 3 deletions ClearScript/Exports/VersionSymbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#pragma once

#define CLEARSCRIPT_VERSION_STRING "7.4.1"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,4,1
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.4.1"
#define CLEARSCRIPT_VERSION_STRING "7.4.2"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,4,2
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.4.2"
#define CLEARSCRIPT_FILE_FLAGS 0L
50 changes: 50 additions & 0 deletions ClearScript/HostItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,30 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
return GetHostProperty(signature, defaultProperty, invokeFlags, args);
}

if (Target.Type.IsArray && (Target.Type.GetArrayRank() == args.Length))
{
// special case to enable VBScript "x(a, b, ...)" syntax when x is a multidimensional array

var indices = new long[args.Length];
var failed = false;

for (var position = 0; position < args.Length; position++)
{
if (!MiscHelpers.TryGetNumericIndex(args[position], out long index))
{
failed = true;
break;
}

indices[position] = index;
}

if (!failed)
{
return ((Array)Target.InvokeTarget).GetValue(indices);
}
}

if (TargetDynamicMetaObject != null)
{
if (TargetDynamicMetaObject.TryGetIndex(args, out var result))
Expand Down Expand Up @@ -1641,6 +1665,32 @@ private object SetHostProperty(string name, BindingFlags invokeFlags, object[] a
throw new InvalidOperationException("Invalid argument count");
}

if (Target.Type.IsArray && (Target.Type.GetArrayRank() == (args.Length - 1)))
{
// special case to enable VBScript "x(a, b, ...) = value" syntax when x is a multidimensional array

var indices = new long[args.Length - 1];
var failed = false;

for (var position = 0; position < (args.Length - 1); position++)
{
if (!MiscHelpers.TryGetNumericIndex(args[position], out long index))
{
failed = true;
break;
}

indices[position] = index;
}

if (!failed)
{
var value = args[args.Length - 1];
((Array)Target.InvokeTarget).SetValue(value, indices);
return value;
}
}

if (TargetDynamicMetaObject != null)
{
if (TargetDynamicMetaObject.TrySetIndex(args.Take(args.Length - 1).ToArray(), args[args.Length - 1], out result))
Expand Down
10 changes: 5 additions & 5 deletions ClearScript/Properties/AssemblyInfo.Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
[assembly: InternalsVisibleTo("ClearScriptTest")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]

namespace Microsoft.ClearScript.Properties
{
internal static class ClearScriptVersion
{
public const string Triad = "7.4.1";
public const string Informational = "7.4.1";
public const string Triad = "7.4.2";
public const string Informational = "7.4.2";
}
}
6 changes: 3 additions & 3 deletions ClearScript/Properties/AssemblyInfo.V8.ICUData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
[assembly: InternalsVisibleTo("ClearScript.V8")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]
6 changes: 3 additions & 3 deletions ClearScript/Properties/AssemblyInfo.V8.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
[assembly: InternalsVisibleTo("ClearScriptTest")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]
6 changes: 3 additions & 3 deletions ClearScript/Properties/AssemblyInfo.Windows.Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
[assembly: InternalsVisibleTo("ClearScriptTest")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]
6 changes: 3 additions & 3 deletions ClearScript/Properties/AssemblyInfo.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
[assembly: InternalsVisibleTo("ClearScriptTest")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]
23 changes: 15 additions & 8 deletions ClearScript/Util/COM/TypeInfoHelpers.NetFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,31 @@
// Licensed under the MIT license.

using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace Microsoft.ClearScript.Util.COM
{
internal static partial class TypeInfoHelpers
{
private static readonly ConcurrentDictionary<Guid, Type> managedTypeMap = new ConcurrentDictionary<Guid, Type>();

public static Type GetManagedType(this ITypeInfo typeInfo)
{
var pTypeInfo = Marshal.GetComInterfaceForObject(typeInfo, typeof(ITypeInfo));
try
{
return Marshal.GetTypeForITypeInfo(pTypeInfo);
}
finally
var guid = typeInfo.GetGuid();
return (guid == Guid.Empty) ? null : managedTypeMap.GetOrAdd(guid, _ =>
{
Marshal.Release(pTypeInfo);
}
var pTypeInfo = Marshal.GetComInterfaceForObject(typeInfo, typeof(ITypeInfo));
try
{
return Marshal.GetTypeForITypeInfo(pTypeInfo);
}
finally
{
Marshal.Release(pTypeInfo);
}
});
}
}
}
28 changes: 22 additions & 6 deletions ClearScript/Util/TypeHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ public static object CreateInstance(this Type type, BindingFlags flags, params o

public static object CreateInstance(this Type type, IHostInvokeContext invokeContext, HostTarget target, object[] args, object[] bindArgs)
{
if (type.IsCOMObject || (type.IsValueType && (args.Length < 1)))
if (type.IsCOMObject)
{
return type.CreateInstance(args);
}
Expand All @@ -500,7 +500,13 @@ public static object CreateInstance(this Type type, IHostInvokeContext invokeCon
return InvokeHelpers.InvokeConstructor(invokeContext, boundConstructor, args);
}

var candidates = type.GetConstructors(flags).Where(testConstructor => testConstructor.IsAccessible(invokeContext.AccessContext) && !testConstructor.IsBlockedFromScript(invokeContext.DefaultAccess)).ToArray();
var constructors = type.GetConstructors(flags);
if (type.IsValueType && (args.Length < 1) && !constructors.Any(testConstructor => testConstructor.GetParameters().Length < 1))
{
return type.CreateInstance();
}

var candidates = constructors.Where(testConstructor => testConstructor.IsAccessible(invokeContext.AccessContext) && !testConstructor.IsBlockedFromScript(invokeContext.DefaultAccess)).ToArray();
if (candidates.Length < 1)
{
throw new MissingMethodException(MiscHelpers.FormatInvariant("Type '{0}' has no constructor that matches the specified arguments", type.GetFullFriendlyName()));
Expand Down Expand Up @@ -1271,14 +1277,16 @@ public int CompareTo(BindArgCost other)

private sealed class BindCandidate<T> : IComparable<BindCandidate<T>> where T : MemberInfo
{
private readonly int defaultArgCount;
private readonly bool paramArray;
private readonly List<BindArgCost> argCosts;

public T Candidate { get; }

private BindCandidate(T candidate, bool paramArray, List<BindArgCost> argCosts)
private BindCandidate(T candidate, int defaultArgCount, bool paramArray, List<BindArgCost> argCosts)
{
Candidate = candidate;
this.defaultArgCount = defaultArgCount;
this.paramArray = paramArray;
this.argCosts = argCosts;
}
Expand All @@ -1297,6 +1305,12 @@ public int CompareTo(BindCandidate<T> other)
}
}

result = defaultArgCount.CompareTo(other.defaultArgCount);
if (result != 0)
{
return result;
}

result = paramArray.CompareTo(other.paramArray);
if (result != 0)
{
Expand All @@ -1316,6 +1330,7 @@ public int CompareTo(BindCandidate<T> other)

public static BindCandidate<T> TryCreateInstance(T candidate, ParameterInfo[] parameters, object[] args, Type[] argTypes)
{
var defaultArgCount = 0;
var paramArray = false;
var argCosts = new List<BindArgCost>();

Expand Down Expand Up @@ -1343,6 +1358,7 @@ public static BindCandidate<T> TryCreateInstance(T candidate, ParameterInfo[] pa
return null;
}

defaultArgCount += 1;
continue;
}

Expand All @@ -1359,13 +1375,13 @@ public static BindCandidate<T> TryCreateInstance(T candidate, ParameterInfo[] pa
{
if (argIndex >= args.Length)
{
return new BindCandidate<T>(candidate, true, argCosts);
return new BindCandidate<T>(candidate, defaultArgCount, true, argCosts);
}

if ((argIndex == (args.Length - 1)) && paramType.IsBindableFromArg(args[argIndex], argTypes[argIndex], out cost))
{
argCosts.Add(cost);
return new BindCandidate<T>(candidate, true, argCosts);
return new BindCandidate<T>(candidate, defaultArgCount, true, argCosts);
}

paramType = paramType.GetElementType();
Expand All @@ -1385,7 +1401,7 @@ public static BindCandidate<T> TryCreateInstance(T candidate, ParameterInfo[] pa
return null;
}

return new BindCandidate<T>(candidate, paramArray, argCosts);
return new BindCandidate<T>(candidate, defaultArgCount, paramArray, argCosts);
}
}

Expand Down
6 changes: 3 additions & 3 deletions ClearScriptBenchmarks/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]
6 changes: 3 additions & 3 deletions ClearScriptConsole/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]

[assembly: ComVisible(false)]
[assembly: AssemblyVersion("7.4.1")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
[assembly: AssemblyVersion("7.4.2")]
[assembly: AssemblyFileVersion("7.4.2")]
[assembly: AssemblyInformationalVersion("7.4.2")]
34 changes: 34 additions & 0 deletions ClearScriptTest/BugFixTest.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,40 @@ public void BugFix_DefaultArgs_Indexer_VBScript()
Assert.AreEqual(Math.Sqrt(Math.PI * Math.E), engine.Evaluate("test.Item.get(789, \"bar\")"));
}

[TestMethod, TestCategory("BugFix")]
public void BugFix_MultidimensionalArray_VBScript()
{
engine.Dispose();
engine = new VBScriptEngine();
engine.AddHostObject("host", new HostFunctions());

engine.Script.x = new int[2];
engine.Script.y = new int[3, 4];

Assert.AreEqual(0, engine.Evaluate("x(1)"));
engine.Execute("x(1) = 123");
Assert.AreEqual(123, engine.Evaluate("x(1)"));

Assert.AreEqual(0, engine.Evaluate("y(2, 3)"));
engine.Execute("y(2, 3) = 456");
Assert.AreEqual(456, engine.Evaluate("y(2, 3)"));

engine.Execute(@"
x = host.newVar(x)
x(1) = 0
y = host.newVar(y)
y(2, 3) = 0
");

Assert.AreEqual(0, engine.Evaluate("x(1)"));
engine.Execute("x(1) = 123");
Assert.AreEqual(123, engine.Evaluate("x(1)"));

Assert.AreEqual(0, engine.Evaluate("y(2, 3)"));
engine.Execute("y(2, 3) = 456");
Assert.AreEqual(456, engine.Evaluate("y(2, 3)"));
}

// ReSharper restore InconsistentNaming

#endregion
Expand Down
Loading

0 comments on commit a02a01f

Please sign in to comment.