Skip to content

Commit 6df5f19

Browse files
Version 7.4.4: Added ConcurrentPropertyBag (GitHub Issue #531); [V8] added V8ScriptEngineFlags.UseSynchronizationContexts (GitHub Discussion #509); added ScriptEngine.CustomAttributeLoader (GitHub Discussion #540); fixed property accessor recursion bug (GitHub Issue #541); added ScriptEngine.HostData and CustomAttributeLoader.Default; updated API documentation. Tested with V8 11.8.172.15.
1 parent cb50bb0 commit 6df5f19

File tree

835 files changed

+2256
-1457
lines changed

Some content is hidden

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

835 files changed

+2256
-1457
lines changed

ClearScript/CanonicalRefTable.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ private static ICanonicalRefMap GetMap(object obj)
4040
type == typeof(TimeSpan) ||
4141
type == typeof(Guid) ||
4242
#if NET471_OR_GREATER || NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
43-
type.GetOrLoadCustomAttributes<System.Runtime.CompilerServices.IsReadOnlyAttribute>(false).Any() ||
43+
type.GetOrLoadCustomAttributes<System.Runtime.CompilerServices.IsReadOnlyAttribute>(null, false).Any() ||
4444
#endif
45-
type.GetOrLoadCustomAttributes<ImmutableValueAttribute>(false).Any())
45+
type.GetOrLoadCustomAttributes<ImmutableValueAttribute>(null, false).Any())
4646
{
4747
map = (ICanonicalRefMap)typeof(CanonicalRefMap<>).MakeGenericType(type).CreateInstance();
4848
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Reflection;
7+
using System.Runtime.CompilerServices;
8+
using Microsoft.ClearScript.Util;
9+
10+
namespace Microsoft.ClearScript
11+
{
12+
internal sealed class CustomAttributeCache
13+
{
14+
private readonly ConditionalWeakTable<ICustomAttributeProvider, Entry> table = new ConditionalWeakTable<ICustomAttributeProvider, Entry>();
15+
16+
public T[] GetOrLoad<T>(CustomAttributeLoader loader, ICustomAttributeProvider resource, bool inherit) where T : Attribute
17+
{
18+
lock (table)
19+
{
20+
return GetOrLoad<T>(loader, table.GetOrCreateValue(resource), resource, inherit);
21+
}
22+
}
23+
24+
private T[] GetOrLoad<T>(CustomAttributeLoader loader, Entry entry, ICustomAttributeProvider resource, bool inherit) where T : Attribute
25+
{
26+
if (entry.TryGet<T>(out var attrs))
27+
{
28+
return attrs;
29+
}
30+
31+
attrs = Load<T>(GetIsBypass(entry, resource) ? CustomAttributeLoader.Default : loader, resource, inherit);
32+
entry.Add(attrs);
33+
34+
return attrs;
35+
}
36+
37+
private static T[] Load<T>(CustomAttributeLoader loader, ICustomAttributeProvider resource, bool inherit) where T : Attribute
38+
{
39+
return loader.LoadCustomAttributes<T>(resource, inherit) ?? ArrayHelpers.GetEmptyArray<T>();
40+
}
41+
42+
private bool GetIsBypass(ICustomAttributeProvider resource)
43+
{
44+
// ReSharper disable once InconsistentlySynchronizedField
45+
return GetIsBypass(table.GetOrCreateValue(resource), resource);
46+
}
47+
48+
private bool GetIsBypass(Entry entry, ICustomAttributeProvider resource)
49+
{
50+
if (!entry.IsBypass.HasValue)
51+
{
52+
entry.IsBypass = GetIsBypassInternal(resource);
53+
}
54+
55+
return entry.IsBypass.Value;
56+
}
57+
58+
private bool GetIsBypassInternal(ICustomAttributeProvider resource)
59+
{
60+
if (Load<BypassCustomAttributeLoaderAttribute>(CustomAttributeLoader.Default, resource, false).Length > 0)
61+
{
62+
return true;
63+
}
64+
65+
var parent = GetParent(resource);
66+
if (parent != null)
67+
{
68+
return GetIsBypass(parent);
69+
}
70+
71+
return false;
72+
}
73+
74+
private static ICustomAttributeProvider GetParent(ICustomAttributeProvider resource)
75+
{
76+
if (resource is ParameterInfo parameter)
77+
{
78+
return parameter.Member;
79+
}
80+
81+
if (resource is Type type)
82+
{
83+
return (type.DeclaringType as ICustomAttributeProvider) ?? type.Module;
84+
}
85+
86+
if (resource is MemberInfo member)
87+
{
88+
return member.DeclaringType;
89+
}
90+
91+
if (resource is Module module)
92+
{
93+
return module.Assembly;
94+
}
95+
96+
return null;
97+
}
98+
99+
#region Nested type: Entry
100+
101+
// ReSharper disable ClassNeverInstantiated.Local
102+
103+
private sealed class Entry
104+
{
105+
private readonly Dictionary<Type, object> map = new Dictionary<Type, object>();
106+
107+
public bool? IsBypass { get; set; }
108+
109+
public void Add<T>(T[] attrs)
110+
{
111+
map.Add(typeof(T), attrs);
112+
}
113+
114+
public bool TryGet<T>(out T[] attrs)
115+
{
116+
if (map.TryGetValue(typeof(T), out var attrsObject))
117+
{
118+
attrs = attrsObject as T[];
119+
return true;
120+
}
121+
122+
attrs = null;
123+
return false;
124+
}
125+
}
126+
127+
// ReSharper restore ClassNeverInstantiated.Local
128+
129+
#endregion
130+
}
131+
132+
[AttributeUsage(AttributeTargets.All, Inherited = false)]
133+
internal sealed class BypassCustomAttributeLoaderAttribute : Attribute
134+
{
135+
}
136+
}

ClearScript/CustomAttributeLoader.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Microsoft.ClearScript
1212
/// </summary>
1313
public class CustomAttributeLoader
1414
{
15+
private readonly CustomAttributeCache cache = new CustomAttributeCache();
16+
1517
// ReSharper disable EmptyConstructor
1618

1719
/// <summary>
@@ -22,6 +24,11 @@ public CustomAttributeLoader()
2224
// the help file builder (SHFB) insists on an empty constructor here
2325
}
2426

27+
/// <summary>
28+
/// Gets the default custom attribute loader.
29+
/// </summary>
30+
public static CustomAttributeLoader Default { get; } = new CustomAttributeLoader();
31+
2532
// ReSharper restore EmptyConstructor
2633

2734
/// <summary>
@@ -60,5 +67,10 @@ public virtual T[] LoadCustomAttributes<T>(ICustomAttributeProvider resource, bo
6067

6168
return resource.GetCustomAttributes(typeof(T), inherit).OfType<T>().ToArray();
6269
}
70+
71+
internal T[] GetOrLoad<T>(ICustomAttributeProvider resource, bool inherit) where T : Attribute
72+
{
73+
return cache.GetOrLoad<T>(this, resource, inherit);
74+
}
6375
}
6476
}

ClearScript/CustomAttributes.NetFramework.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

ClearScript/CustomAttributes.NetStandard.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

ClearScript/CustomAttributes.cs

Lines changed: 7 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,154 +1,23 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.Reflection;
76
using Microsoft.ClearScript.Util;
87

98
namespace Microsoft.ClearScript
109
{
11-
internal static partial class CustomAttributes
10+
internal static class CustomAttributes
1211
{
13-
private static readonly object cacheLock = new object();
14-
15-
public static T[] GetOrLoad<T>(ICustomAttributeProvider resource, bool inherit) where T : Attribute
16-
{
17-
lock (cacheLock)
18-
{
19-
return GetOrLoad<T>(cache.GetOrCreateValue(resource), resource, inherit);
20-
}
21-
}
22-
23-
public static bool Has<T>(ICustomAttributeProvider resource, bool inherit) where T : Attribute
24-
{
25-
lock (cacheLock)
26-
{
27-
return Has<T>(cache.GetOrCreateValue(resource), resource, inherit);
28-
}
29-
}
30-
31-
private static T[] GetOrLoad<T>(CacheEntry entry, ICustomAttributeProvider resource, bool inherit) where T : Attribute
32-
{
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)
12+
public static T[] GetOrLoad<T>(IHostContext context, ICustomAttributeProvider resource, bool inherit) where T : Attribute
6713
{
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;
14+
var loader = context?.CustomAttributeLoader ?? HostSettings.CustomAttributeLoader;
15+
return loader.GetOrLoad<T>(resource, inherit);
11516
}
11617

117-
#region Nested type: CacheEntry
118-
119-
// ReSharper disable ClassNeverInstantiated.Local
120-
121-
private sealed class CacheEntry
18+
public static bool Has<T>(IHostContext context, ICustomAttributeProvider resource, bool inherit) where T : Attribute
12219
{
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-
}
20+
return GetOrLoad<T>(context, resource, inherit).Length > 0;
14321
}
144-
145-
// ReSharper restore ClassNeverInstantiated.Local
146-
147-
#endregion
148-
}
149-
150-
[AttributeUsage(AttributeTargets.All, Inherited = false)]
151-
internal sealed class BypassCustomAttributeLoaderAttribute : Attribute
152-
{
15322
}
15423
}

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.4.3"
9-
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,4,3
10-
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.4.3"
8+
#define CLEARSCRIPT_VERSION_STRING "7.4.4"
9+
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,4,4
10+
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.4.4"
1111
#define CLEARSCRIPT_FILE_FLAGS 0L

0 commit comments

Comments
 (0)