Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5fe5403

Browse files
Version 7.3.5: Added support for script object identity comparison (GitHub Issue #422); overhauled scriptable enumerators to fix GitHub Issue #423; eliminated default V8 platform to fix process exit deadlock on Windows 7 (GitHub Issue #424); addressed performance regression reported in GitHub Issue #433; added a pair of ToRestrictedHostObject overloads (GitHub Issue #437); fixed a specific property accessor scriptability scenario (GitHub Issue #439); updated API documentation. Tested with V8 10.7.193.22.
1 parent 02b7203 commit 5fe5403

File tree

699 files changed

+3174
-972
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

699 files changed

+3174
-972
lines changed
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
using System.Reflection;
5+
using System.Runtime.CompilerServices;
46
using Microsoft.ClearScript.Util;
57

68
namespace Microsoft.ClearScript
79
{
810
internal static partial class CustomAttributes
911
{
12+
private static ConditionalWeakTable<ICustomAttributeProvider, CacheEntry> cache = new ConditionalWeakTable<ICustomAttributeProvider, CacheEntry>();
13+
1014
public static void ClearCache()
1115
{
12-
keyCache.Values.ForEach(key => attributeCache.Remove(key));
16+
lock (cacheLock)
17+
{
18+
cache = new ConditionalWeakTable<ICustomAttributeProvider, CacheEntry>();
19+
}
1320
}
1421
}
1522
}
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
using System.Reflection;
5+
using System.Runtime.CompilerServices;
6+
47
namespace Microsoft.ClearScript
58
{
69
internal static partial class CustomAttributes
710
{
11+
private static readonly ConditionalWeakTable<ICustomAttributeProvider, CacheEntry> cache = new ConditionalWeakTable<ICustomAttributeProvider, CacheEntry>();
12+
813
public static void ClearCache()
914
{
10-
attributeCache.Clear();
15+
lock (cacheLock)
16+
{
17+
cache.Clear();
18+
}
1119
}
1220
}
1321
}

ClearScript/CustomAttributes.cs

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,153 @@
22
// Licensed under the MIT license.
33

44
using System;
5-
using System.Collections.Concurrent;
5+
using System.Collections.Generic;
66
using System.Reflection;
7-
using System.Runtime.CompilerServices;
87
using Microsoft.ClearScript.Util;
98

109
namespace Microsoft.ClearScript
1110
{
1211
internal static partial class CustomAttributes
1312
{
14-
private static readonly ConcurrentDictionary<(ICustomAttributeProvider, Type), object> keyCache = new ConcurrentDictionary<(ICustomAttributeProvider, Type), object>();
15-
private static readonly ConditionalWeakTable<object, object> attributeCache = new ConditionalWeakTable<object, object>();
13+
private static readonly object cacheLock = new object();
1614

1715
public static T[] GetOrLoad<T>(ICustomAttributeProvider resource, bool inherit) where T : Attribute
1816
{
19-
return (T[])attributeCache.GetValue(GetKey<T>(resource), _ => HostSettings.CustomAttributeLoader.LoadCustomAttributes<T>(resource, inherit) ?? ArrayHelpers.GetEmptyArray<T>());
17+
lock (cacheLock)
18+
{
19+
return GetOrLoad<T>(cache.GetOrCreateValue(resource), resource, inherit);
20+
}
2021
}
2122

2223
public static bool Has<T>(ICustomAttributeProvider resource, bool inherit) where T : Attribute
2324
{
24-
return GetOrLoad<T>(resource, inherit).Length > 0;
25+
lock (cacheLock)
26+
{
27+
return Has<T>(cache.GetOrCreateValue(resource), resource, inherit);
28+
}
2529
}
2630

27-
private static object GetKey<T>(ICustomAttributeProvider resource) where T : Attribute
31+
private static T[] GetOrLoad<T>(CacheEntry entry, ICustomAttributeProvider resource, bool inherit) where T : Attribute
2832
{
29-
return keyCache.GetOrAdd((resource, typeof(T)), _ => new object());
33+
if (entry.TryGet<T>(out var attrs))
34+
{
35+
return attrs;
36+
}
37+
38+
attrs = GetOrLoad<T>(GetIsBypass(entry, resource), resource, inherit);
39+
entry.Add(attrs);
40+
41+
return attrs;
42+
}
43+
44+
private static bool Has<T>(CacheEntry entry, ICustomAttributeProvider resource, bool inherit) where T : Attribute
45+
{
46+
return GetOrLoad<T>(entry, resource, inherit).Length > 0;
47+
}
48+
49+
private static T[] GetOrLoad<T>(bool isBypass, ICustomAttributeProvider resource, bool inherit) where T : Attribute
50+
{
51+
var loader = isBypass ? HostSettings.DefaultCustomAttributeLoader : HostSettings.CustomAttributeLoader;
52+
return loader.LoadCustomAttributes<T>(resource, inherit) ?? ArrayHelpers.GetEmptyArray<T>();
53+
}
54+
55+
private static bool Has<T>(bool isBypass, ICustomAttributeProvider resource, bool inherit) where T : Attribute
56+
{
57+
return GetOrLoad<T>(isBypass, resource, inherit).Length > 0;
58+
}
59+
60+
private static bool GetIsBypass(ICustomAttributeProvider resource)
61+
{
62+
// ReSharper disable once InconsistentlySynchronizedField
63+
return GetIsBypass(cache.GetOrCreateValue(resource), resource);
64+
}
65+
66+
private static bool GetIsBypass(CacheEntry entry, ICustomAttributeProvider resource)
67+
{
68+
if (!entry.IsBypass.HasValue)
69+
{
70+
entry.IsBypass = GetIsBypassInternal(resource);
71+
}
72+
73+
return entry.IsBypass.Value;
74+
}
75+
76+
private static bool GetIsBypassInternal(ICustomAttributeProvider resource)
77+
{
78+
if (Has<BypassCustomAttributeLoaderAttribute>(true, resource, false))
79+
{
80+
return true;
81+
}
82+
83+
var parent = GetParent(resource);
84+
if (parent != null)
85+
{
86+
return GetIsBypass(parent);
87+
}
88+
89+
return false;
90+
}
91+
92+
private static ICustomAttributeProvider GetParent(ICustomAttributeProvider resource)
93+
{
94+
if (resource is ParameterInfo parameter)
95+
{
96+
return parameter.Member;
97+
}
98+
99+
if (resource is Type type)
100+
{
101+
return (type.DeclaringType as ICustomAttributeProvider) ?? type.Module;
102+
}
103+
104+
if (resource is MemberInfo member)
105+
{
106+
return member.DeclaringType;
107+
}
108+
109+
if (resource is Module module)
110+
{
111+
return module.Assembly;
112+
}
113+
114+
return null;
115+
}
116+
117+
#region Nested type: CacheEntry
118+
119+
// ReSharper disable ClassNeverInstantiated.Local
120+
121+
private sealed class CacheEntry
122+
{
123+
private readonly Dictionary<Type, object> map = new Dictionary<Type, object>();
124+
125+
public bool? IsBypass { get; set; }
126+
127+
public void Add<T>(T[] attrs)
128+
{
129+
map.Add(typeof(T), attrs);
130+
}
131+
132+
public bool TryGet<T>(out T[] attrs)
133+
{
134+
if (map.TryGetValue(typeof(T), out var attrsObject))
135+
{
136+
attrs = attrsObject as T[];
137+
return true;
138+
}
139+
140+
attrs = null;
141+
return false;
142+
}
30143
}
144+
145+
// ReSharper restore ClassNeverInstantiated.Local
146+
147+
#endregion
148+
}
149+
150+
[AttributeUsage(AttributeTargets.All, Inherited = false)]
151+
internal sealed class BypassCustomAttributeLoaderAttribute : Attribute
152+
{
31153
}
32154
}

ClearScript/Exports/VersionSymbols.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#pragma once
77

8-
#define CLEARSCRIPT_VERSION_STRING "7.3.4"
9-
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,3,4
10-
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.3.4"
8+
#define CLEARSCRIPT_VERSION_STRING "7.3.5"
9+
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,3,5
10+
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.3.5"
1111
#define CLEARSCRIPT_FILE_FLAGS 0L

ClearScript/Extensions.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,46 @@ public static object ToRestrictedHostObject<T>(this T target, ScriptEngine engin
6262
MiscHelpers.VerifyNonNullArgument(engine, nameof(engine));
6363
return HostItem.Wrap(engine, target, typeof(T));
6464
}
65+
66+
/// <summary>
67+
/// Converts an object to a host object with a type restriction specified as a
68+
/// <see cref="Type"/> instance, for use with script code currently running on the calling
69+
/// thread.
70+
/// </summary>
71+
/// <param name="target">The object to convert to a host object for use with script code.</param>
72+
/// <param name="type">The type whose members are to be made accessible from script code.</param>
73+
/// <returns>A host object with the specified type restriction.</returns>
74+
public static object ToRestrictedHostObject(this object target, Type type)
75+
{
76+
return target.ToRestrictedHostObject(type, ScriptEngine.Current);
77+
}
78+
79+
/// <summary>
80+
/// Converts an object to a host object with a type restriction specified as a
81+
/// <see cref="Type"/> instance, for use with script code running in the specified script
82+
/// engine.
83+
/// </summary>
84+
/// <param name="target">The object to convert to a host object for use with script code.</param>
85+
/// <param name="type">The type whose members are to be made accessible from script code.</param>
86+
/// <param name="engine">The script engine in which the host object will be used.</param>
87+
/// <returns>A host object with the specified type restriction.</returns>
88+
public static object ToRestrictedHostObject(this object target, Type type, ScriptEngine engine)
89+
{
90+
MiscHelpers.VerifyNonNullArgument(target, nameof(target));
91+
MiscHelpers.VerifyNonNullArgument(type, nameof(type));
92+
MiscHelpers.VerifyNonNullArgument(engine, nameof(engine));
93+
94+
if (!MiscHelpers.Try(out var holder, () => typeof(Holder<>).MakeGenericType(type).CreateInstance()))
95+
{
96+
throw new ArgumentException("The specified type is invalid", nameof(type));
97+
}
98+
99+
if (!MiscHelpers.Try(() => ((IHolder)holder).Value = target))
100+
{
101+
throw new ArgumentException("The target object is incompatible with the specified type", nameof(target));
102+
}
103+
104+
return HostItem.Wrap(engine, target, type);
105+
}
65106
}
66107
}

ClearScript/HostItem.NetFramework.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemF
2626

2727
private object CreateAsyncEnumerator<T>(IEnumerable<T> enumerable)
2828
{
29-
return HostObject.Wrap(enumerable.GetEnumerator().ToAsyncEnumerator(Engine), typeof(IAsyncEnumeratorPromise<T>));
29+
return HostObject.Wrap(enumerable.GetEnumerator().ToScriptableAsyncEnumerator(Engine), typeof(IScriptableAsyncEnumerator<T>));
3030
}
3131

3232
private object CreateAsyncEnumerator()
@@ -35,16 +35,16 @@ private object CreateAsyncEnumerator()
3535
{
3636
if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IEnumerable<>), out var typeArgs))
3737
{
38-
var enumerableHelpersHostItem = Wrap(Engine, typeof(EnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess);
39-
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetAsyncEnumerator", this, Engine)))
38+
var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess);
39+
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine)))
4040
{
4141
return enumerator;
4242
}
4343
}
4444
else if (BindSpecialTarget(out IEnumerable _))
4545
{
46-
var enumerableHelpersHostItem = Wrap(Engine, EnumerableHelpers.HostType, HostItemFlags.PrivateAccess);
47-
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetAsyncEnumerator", this, Engine)))
46+
var helpersHostItem = Wrap(Engine, ScriptableEnumerableHelpers.HostType, HostItemFlags.PrivateAccess);
47+
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine)))
4848
{
4949
return enumerator;
5050
}

ClearScript/HostItem.NetStandard.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemF
3636

3737
private object CreateAsyncEnumerator<T>(IEnumerable<T> enumerable)
3838
{
39-
return HostObject.Wrap(enumerable.GetEnumerator().ToAsyncEnumerator(Engine), typeof(IAsyncEnumeratorPromise<T>));
39+
return HostObject.Wrap(enumerable.GetEnumerator().ToScriptableAsyncEnumerator(Engine), typeof(IScriptableAsyncEnumerator<T>));
4040
}
4141

4242
private object CreateAsyncEnumerator()
@@ -45,24 +45,24 @@ private object CreateAsyncEnumerator()
4545
{
4646
if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IAsyncEnumerable<>), out var typeArgs))
4747
{
48-
var enumerableHelpersHostItem = Wrap(Engine, typeof(EnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess);
49-
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetAsyncEnumerator", this, Engine)))
48+
var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess);
49+
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine)))
5050
{
5151
return enumerator;
5252
}
5353
}
5454
else if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IEnumerable<>), out typeArgs))
5555
{
56-
var enumerableHelpersHostItem = Wrap(Engine, typeof(EnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess);
57-
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetAsyncEnumerator", this, Engine)))
56+
var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess);
57+
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine)))
5858
{
5959
return enumerator;
6060
}
6161
}
6262
else if (BindSpecialTarget(out IEnumerable _))
6363
{
64-
var enumerableHelpersHostItem = Wrap(Engine, EnumerableHelpers.HostType, HostItemFlags.PrivateAccess);
65-
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetAsyncEnumerator", this, Engine)))
64+
var helpersHostItem = Wrap(Engine, ScriptableEnumerableHelpers.HostType, HostItemFlags.PrivateAccess);
65+
if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine)))
6666
{
6767
return enumerator;
6868
}

0 commit comments

Comments
 (0)