diff --git a/ClearScript.NoV8.sln.DotSettings b/ClearScript.NoV8.sln.DotSettings
index 035259696..2ca2f1521 100644
--- a/ClearScript.NoV8.sln.DotSettings
+++ b/ClearScript.NoV8.sln.DotSettings
@@ -123,6 +123,7 @@
True
True
True
+ True
True
True
True
@@ -162,6 +163,7 @@
True
True
True
+ True
True
True
True
diff --git a/ClearScript.sln.DotSettings b/ClearScript.sln.DotSettings
index 035259696..2ca2f1521 100644
--- a/ClearScript.sln.DotSettings
+++ b/ClearScript.sln.DotSettings
@@ -123,6 +123,7 @@
True
True
True
+ True
True
True
True
@@ -162,6 +163,7 @@
True
True
True
+ True
True
True
True
diff --git a/ClearScript/ByRefArg.cs b/ClearScript/ByRefArg.cs
index 145dc3b5e..06218382f 100644
--- a/ClearScript/ByRefArg.cs
+++ b/ClearScript/ByRefArg.cs
@@ -58,9 +58,9 @@ public override object DynamicInvokeTarget
get { return target.DynamicInvokeTarget; }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get { return target.Flags; }
+ return target.GetFlags(context);
}
public override string[] GetAuxMethodNames(IHostInvokeContext context, BindingFlags bindFlags)
diff --git a/ClearScript/ClearScript.csproj b/ClearScript/ClearScript.csproj
index 1a6d2ea07..e8cd1103f 100644
--- a/ClearScript/ClearScript.csproj
+++ b/ClearScript/ClearScript.csproj
@@ -126,6 +126,7 @@
+
diff --git a/ClearScript/DocumentInfo.cs b/ClearScript/DocumentInfo.cs
index b0c3fb82d..89a9397db 100644
--- a/ClearScript/DocumentInfo.cs
+++ b/ClearScript/DocumentInfo.cs
@@ -136,7 +136,7 @@ internal UniqueDocumentInfo MakeUnique(IUniqueNameManager manager, DocumentFlags
}
var uniqueName = manager.GetUniqueName(Name, Category.DefaultName);
- if (Flags.GetValueOrDefault().HasFlag(DocumentFlags.IsTransient))
+ if (info.Flags.GetValueOrDefault().HasFlag(DocumentFlags.IsTransient))
{
uniqueName += " [temp]";
}
diff --git a/ClearScript/DocumentSettings.cs b/ClearScript/DocumentSettings.cs
index ac515bb98..c84f0030d 100644
--- a/ClearScript/DocumentSettings.cs
+++ b/ClearScript/DocumentSettings.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.ClearScript.JavaScript;
@@ -190,14 +189,13 @@ internal async Task LoadDocumentAsync(DocumentInfo? sourceInfo, string
private Document FindSystemDocument(string identifier, DocumentCategory category)
{
- try
+ Document document;
+ if (systemDocumentMap.TryGetValue(Tuple.Create(identifier, category ?? DocumentCategory.Script), out document))
{
- return systemDocumentMap[Tuple.Create(identifier, category ?? DocumentCategory.Script)];
- }
- catch (KeyNotFoundException)
- {
- return null;
+ return document;
}
+
+ return null;
}
}
}
diff --git a/ClearScript/Exports/VersionSymbols.h b/ClearScript/Exports/VersionSymbols.h
index 7ccda4bdb..b5c149b28 100644
--- a/ClearScript/Exports/VersionSymbols.h
+++ b/ClearScript/Exports/VersionSymbols.h
@@ -5,5 +5,5 @@
#pragma once
-#define CLEARSCRIPT_VERSION_STRING "6.0.0.0"
-#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 6,0,0,0
+#define CLEARSCRIPT_VERSION_STRING "6.0.1.0"
+#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 6,0,1,0
diff --git a/ClearScript/HostFunctions.cs b/ClearScript/HostFunctions.cs
index 7792e26ae..1e9a3980d 100644
--- a/ClearScript/HostFunctions.cs
+++ b/ClearScript/HostFunctions.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using System;
-using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
@@ -1647,13 +1646,20 @@ public object newComObj(string progID, string serverName = null)
}
///
- /// Imports enumerations from a type library.
+ /// Imports enumerations defined within or referenced from a COM/ActiveX type library.
///
- /// The imported type whose parent library is to be searched for enumerations.
+ /// The imported type whose parent library is to be searched for relevant enumerations.
/// An instance of the representative type.
- /// A collection of imported enumerations.
- public IPropertyBag typeLibEnums(T obj) where T : class
+ /// An optional host type collection with which to merge the imported enumerations.
+ /// A host type collection: if it is not null, a new host type collection otherwise.
+ public HostTypeCollection typeLibEnums(T obj, HostTypeCollection collection = null) where T : class
{
+ MiscHelpers.VerifyNonNullArgument(obj, "obj");
+ if (collection == null)
+ {
+ collection = new HostTypeCollection();
+ }
+
var type = typeof(T);
if (type.IsUnknownCOMObject())
{
@@ -1663,31 +1669,18 @@ public IPropertyBag typeLibEnums(T obj) where T : class
var typeInfo = dispatch.GetTypeInfo();
if (typeInfo != null)
{
- return typeInfo.GetTypeLibEnums();
+ typeInfo.GetContainingTypeLib().GetReferencedEnums().ForEach(collection.AddEnumTypeInfo);
+ return collection;
}
}
-
- throw new ArgumentException("Object type is not imported", "obj");
- }
-
- if (!type.IsImport)
- {
- throw new ArgumentException("Object type is not imported", "obj");
}
-
- var typeCollection = new HostTypeCollection();
-
- var assembly = type.Assembly;
- Debug.Assert(assembly.GetCustomAttribute(typeof(ImportedFromTypeLibAttribute)) != null);
- foreach (var assemblyType in assembly.GetTypes())
+ else if (type.IsImport && (type.Assembly.GetCustomAttribute(typeof(ImportedFromTypeLibAttribute)) != null))
{
- if (assemblyType.IsPublic && assemblyType.IsEnum)
- {
- typeCollection.AddType(assemblyType);
- }
+ type.Assembly.GetReferencedEnums().ForEach(collection.AddType);
+ return collection;
}
- return typeCollection;
+ throw new ArgumentException("Object type is not imported", "obj");
}
// ReSharper restore InconsistentNaming
diff --git a/ClearScript/HostIndexedProperty.cs b/ClearScript/HostIndexedProperty.cs
index e770a231e..23875584a 100644
--- a/ClearScript/HostIndexedProperty.cs
+++ b/ClearScript/HostIndexedProperty.cs
@@ -51,9 +51,9 @@ public override object DynamicInvokeTarget
get { return null; }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get { return HostTargetFlags.None; }
+ return HostTargetFlags.None;
}
public override string[] GetAuxMethodNames(IHostInvokeContext context, BindingFlags bindFlags)
diff --git a/ClearScript/HostItem.InvokeMethod.cs b/ClearScript/HostItem.InvokeMethod.cs
index 4046a2786..05ede7128 100644
--- a/ClearScript/HostItem.InvokeMethod.cs
+++ b/ClearScript/HostItem.InvokeMethod.cs
@@ -53,7 +53,7 @@ private object InvokeMethod(string name, object[] args, object[] bindArgs)
private object InvokeMethod(string name, Type[] typeArgs, object[] args, object[] bindArgs)
{
var bindResult = BindMethod(name, typeArgs, args, bindArgs);
- if ((bindResult is MethodBindFailure) && target.Flags.HasFlag(HostTargetFlags.AllowExtensionMethods))
+ if ((bindResult is MethodBindFailure) && target.GetFlags(this).HasFlag(HostTargetFlags.AllowExtensionMethods))
{
var targetArg = target.Target.ToEnumerable();
var extensionArgs = targetArg.Concat(args).ToArray();
@@ -108,17 +108,17 @@ private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args,
// WARNING: BindSignature holds on to the specified typeArgs; subsequent modification
// will result in bugs that are difficult to diagnose. Create a copy if necessary.
- var signature = new BindSignature(accessContext, bindFlags, target, name, typeArgs, bindArgs);
+ var signature = new BindSignature(AccessContext, bindFlags, target, name, typeArgs, bindArgs);
MethodBindResult result;
object rawResult;
if (engine.TryGetCachedBindResult(signature, out rawResult))
{
- result = MethodBindResult.Create(name, rawResult, target, args);
+ result = MethodBindResult.Create(name, bindFlags, rawResult, target, args);
}
else
{
- result = BindMethodInternal(accessContext, bindFlags, target, name, typeArgs, args, bindArgs);
+ result = BindMethodInternal(AccessContext, bindFlags, target, name, typeArgs, args, bindArgs);
if (!result.IsPreferredMethod(this, name))
{
if (result is MethodBindSuccess)
@@ -128,7 +128,7 @@ private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args,
foreach (var altName in GetAltMethodNames(name, bindFlags))
{
- var altResult = BindMethodInternal(accessContext, bindFlags, target, altName, typeArgs, args, bindArgs);
+ var altResult = BindMethodInternal(AccessContext, bindFlags, target, altName, typeArgs, args, bindArgs);
if (altResult.IsUnblockedMethod(this))
{
result = altResult;
@@ -163,7 +163,7 @@ private static MethodBindResult BindMethodInternal(Type bindContext, BindingFlag
object rawResult;
if (coreBindCache.TryGetValue(signature, out rawResult))
{
- result = MethodBindResult.Create(name, rawResult, target, args);
+ result = MethodBindResult.Create(name, bindFlags, rawResult, target, args);
}
else
{
@@ -185,7 +185,7 @@ private static MethodBindResult BindMethodCore(Type bindContext, BindingFlags bi
// perform default binding
var rawResult = BindMethodRaw(bindFlags, binder, target, bindArgs);
- var result = MethodBindResult.Create(name, rawResult, target, args);
+ var result = MethodBindResult.Create(name, bindFlags, rawResult, target, args);
if ((result is MethodBindFailure) && !(target is HostType) && target.Type.IsInterface)
{
// binding through interface failed; try base interfaces
@@ -194,7 +194,7 @@ private static MethodBindResult BindMethodCore(Type bindContext, BindingFlags bi
var baseInterfaceTarget = HostObject.Wrap(target.InvokeTarget, interfaceType);
rawResult = BindMethodRaw(bindFlags, binder, baseInterfaceTarget, bindArgs);
- var baseInterfaceResult = MethodBindResult.Create(name, rawResult, target, args);
+ var baseInterfaceResult = MethodBindResult.Create(name, bindFlags, rawResult, target, args);
if (baseInterfaceResult is MethodBindSuccess)
{
return baseInterfaceResult;
@@ -205,7 +205,7 @@ private static MethodBindResult BindMethodCore(Type bindContext, BindingFlags bi
var objectTarget = HostObject.Wrap(target.InvokeTarget, typeof(object));
rawResult = BindMethodRaw(bindFlags, binder, objectTarget, bindArgs);
- var objectResult = MethodBindResult.Create(name, rawResult, target, args);
+ var objectResult = MethodBindResult.Create(name, bindFlags, rawResult, target, args);
if (objectResult is MethodBindSuccess)
{
return objectResult;
@@ -259,7 +259,7 @@ private IEnumerable GetAltMethodNames(string name, BindingFlags bindFlag
private IEnumerable GetAltMethodNamesInternal(string name, BindingFlags bindFlags)
{
- foreach (var method in target.Type.GetScriptableMethods(name, bindFlags, accessContext, defaultAccess))
+ foreach (var method in target.Type.GetScriptableMethods(name, bindFlags, AccessContext, DefaultAccess))
{
var methodName = method.GetShortName();
if (methodName != name)
@@ -326,7 +326,7 @@ private MethodBindResult BindMethodUsingReflection(BindingFlags bindFlags, HostT
{
object state;
var rawResult = Type.DefaultBinder.BindToMethod(bindFlags, candidates, ref args, null, null, null, out state);
- return MethodBindResult.Create(name, rawResult, hostTarget, args);
+ return MethodBindResult.Create(name, bindFlags, rawResult, hostTarget, args);
}
catch (MissingMethodException)
{
@@ -368,7 +368,7 @@ private IEnumerable GetReflectionCandidates(BindingFlags bindFlags,
private IEnumerable GetReflectionCandidates(BindingFlags bindFlags, Type type, string name, Type[] typeArgs)
{
- foreach (var method in type.GetScriptableMethods(name, bindFlags, accessContext, defaultAccess))
+ foreach (var method in type.GetScriptableMethods(name, bindFlags, AccessContext, DefaultAccess))
{
MethodInfo tempMethod = null;
@@ -420,12 +420,12 @@ internal static long GetCoreBindCount()
private abstract class MethodBindResult
{
- public static MethodBindResult Create(string name, object rawResult, HostTarget hostTarget, object[] args)
+ public static MethodBindResult Create(string name, BindingFlags bindFlags, object rawResult, HostTarget hostTarget, object[] args)
{
var method = rawResult as MethodInfo;
if (method != null)
{
- if ((method.IsStatic) && !hostTarget.Flags.HasFlag(HostTargetFlags.AllowStaticMembers))
+ if (method.IsStatic && !bindFlags.HasFlag(BindingFlags.Static))
{
return new MethodBindFailure(() => new InvalidOperationException(MiscHelpers.FormatInvariant("Cannot access static method '{0}' in non-static context", method.Name)));
}
diff --git a/ClearScript/HostItem.cs b/ClearScript/HostItem.cs
index 9fb987e3c..6c3209773 100644
--- a/ClearScript/HostItem.cs
+++ b/ClearScript/HostItem.cs
@@ -25,9 +25,6 @@ internal partial class HostItem : DynamicObject, IReflect, IDynamic, IEnumVARIAN
private readonly ScriptEngine engine;
private readonly HostTarget target;
private readonly HostItemFlags flags;
-
- private Type accessContext;
- private ScriptAccess defaultAccess;
private HostTargetMemberData targetMemberData;
internal static bool EnableVTablePatching;
@@ -141,7 +138,7 @@ public Invocability Invocability
{
if (TargetInvocability == null)
{
- TargetInvocability = target.GetInvocability(GetCommonBindFlags(), accessContext, defaultAccess, flags.HasFlag(HostItemFlags.HideDynamicMembers));
+ TargetInvocability = target.GetInvocability(GetCommonBindFlags(), AccessContext, DefaultAccess, flags.HasFlag(HostItemFlags.HideDynamicMembers));
}
return TargetInvocability.GetValueOrDefault();
@@ -404,6 +401,48 @@ private Invocability? TargetInvocability
set { targetMemberData.TargetInvocability = value; }
}
+ private Type CurrentAccessContext
+ {
+ get { return (flags.HasFlag(HostItemFlags.PrivateAccess) || (target.Type.IsAnonymous() && !engine.EnforceAnonymousTypeAccess)) ? target.Type : engine.AccessContext; }
+ }
+
+ private ScriptAccess CurrentDefaultAccess
+ {
+ get { return engine.DefaultAccess; }
+ }
+
+ private HostTargetFlags CurrentTargetFlags
+ {
+ get { return target.GetFlags(this); }
+ }
+
+ private Type CachedAccessContext
+ {
+ get
+ {
+ var targetMemberDataWithContext = targetMemberData as HostTargetMemberDataWithContext;
+ return (targetMemberDataWithContext != null) ? targetMemberDataWithContext.AccessContext : CurrentAccessContext;
+ }
+ }
+
+ private ScriptAccess CachedDefaultAccess
+ {
+ get
+ {
+ var targetMemberDataWithContext = targetMemberData as HostTargetMemberDataWithContext;
+ return (targetMemberDataWithContext) != null ? targetMemberDataWithContext.DefaultAccess : CurrentDefaultAccess;
+ }
+ }
+
+ private HostTargetFlags CachedTargetFlags
+ {
+ get
+ {
+ var targetMemberDataWithContext = targetMemberData as HostTargetMemberDataWithContext;
+ return (targetMemberDataWithContext) != null ? targetMemberDataWithContext.TargetFlags : CurrentTargetFlags;
+ }
+ }
+
#endregion
#region initialization
@@ -531,14 +570,8 @@ private bool BindSpecialTarget(out T specialTarget) where T : class
private void BindTargetMemberData()
{
- var newAccessContext = flags.HasFlag(HostItemFlags.PrivateAccess) || (target.Type.IsAnonymous() && !engine.EnforceAnonymousTypeAccess) ? target.Type : engine.AccessContext;
- var newDefaultAccess = engine.DefaultAccess;
-
- if ((targetMemberData == null) || (accessContext != newAccessContext) || (defaultAccess != newDefaultAccess))
+ if ((targetMemberData == null) || (AccessContext != CurrentAccessContext) || (DefaultAccess != CurrentDefaultAccess) || (TargetFlags != CurrentTargetFlags))
{
- accessContext = newAccessContext;
- defaultAccess = newDefaultAccess;
-
if (target is HostMethod)
{
// host methods can share their (dummy) member data
@@ -566,13 +599,13 @@ private void BindTargetMemberData()
if ((TargetDynamic == null) && (TargetPropertyBag == null) && (TargetList == null) && (TargetDynamicMetaObject == null))
{
// host objects without dynamic members can share their member data
- targetMemberData = engine.GetSharedHostObjectMemberData(hostObject, accessContext, defaultAccess);
+ targetMemberData = engine.GetSharedHostObjectMemberData(hostObject, CurrentAccessContext, CurrentDefaultAccess, CurrentTargetFlags);
return;
}
}
// all other targets use unique member data
- targetMemberData = new HostTargetMemberData();
+ targetMemberData = new HostTargetMemberDataWithContext(CurrentAccessContext, CurrentDefaultAccess, CurrentTargetFlags);
}
}
@@ -635,7 +668,7 @@ private string[] GetLocalEventNames()
{
if (TypeEventNames == null)
{
- var localEvents = target.Type.GetScriptableEvents(GetCommonBindFlags(), accessContext, defaultAccess);
+ var localEvents = target.Type.GetScriptableEvents(GetCommonBindFlags(), AccessContext, DefaultAccess);
TypeEventNames = localEvents.Select(eventInfo => eventInfo.GetScriptName()).ToArray();
}
@@ -646,7 +679,7 @@ private string[] GetLocalFieldNames()
{
if (TypeFieldNames == null)
{
- var localFields = target.Type.GetScriptableFields(GetCommonBindFlags(), accessContext, defaultAccess);
+ var localFields = target.Type.GetScriptableFields(GetCommonBindFlags(), AccessContext, DefaultAccess);
TypeFieldNames = localFields.Select(field => field.GetScriptName()).ToArray();
}
@@ -657,7 +690,7 @@ private string[] GetLocalMethodNames()
{
if (TypeMethodNames == null)
{
- var localMethods = target.Type.GetScriptableMethods(GetMethodBindFlags(), accessContext, defaultAccess);
+ var localMethods = target.Type.GetScriptableMethods(GetMethodBindFlags(), AccessContext, DefaultAccess);
TypeMethodNames = localMethods.Select(method => method.GetScriptName()).ToArray();
}
@@ -668,7 +701,7 @@ private string[] GetLocalPropertyNames()
{
if (TypePropertyNames == null)
{
- var localProperties = target.Type.GetScriptableProperties(GetCommonBindFlags(), accessContext, defaultAccess);
+ var localProperties = target.Type.GetScriptableProperties(GetCommonBindFlags(), AccessContext, DefaultAccess);
TypePropertyNames = localProperties.Select(property => property.GetScriptName()).ToArray();
}
@@ -689,11 +722,11 @@ private string[] GetAllMethodNames(out string[] ownMethodNames)
{
ownMethodNames = null;
- var names = target.GetAuxMethodNames(this, GetMethodBindFlags()).AsEnumerable();
+ var names = target.GetAuxMethodNames(this, GetMethodBindFlags()).AsEnumerable() ?? Enumerable.Empty();
if ((TargetDynamic == null) && (TargetPropertyBag == null))
{
names = names.Concat(GetLocalMethodNames());
- if (target.Flags.HasFlag(HostTargetFlags.AllowExtensionMethods))
+ if (TargetFlags.HasFlag(HostTargetFlags.AllowExtensionMethods))
{
var extensionMethodSummary = engine.ExtensionMethodSummary;
ExtensionMethodSummary = extensionMethodSummary;
@@ -718,7 +751,7 @@ private string[] GetAllMethodNames(out string[] ownMethodNames)
private string[] GetAllPropertyNames()
{
- var names = target.GetAuxPropertyNames(this, GetCommonBindFlags()).AsEnumerable();
+ var names = target.GetAuxPropertyNames(this, GetCommonBindFlags()).AsEnumerable() ?? Enumerable.Empty();
if (TargetDynamic != null)
{
names = names.Concat(TargetDynamic.GetPropertyNames());
@@ -771,7 +804,7 @@ private void UpdateFieldNames(out bool updated)
private void UpdateMethodNames(out bool updated)
{
if ((AllMethodNames == null) ||
- (target.Flags.HasFlag(HostTargetFlags.AllowExtensionMethods) && (ExtensionMethodSummary != engine.ExtensionMethodSummary)))
+ (TargetFlags.HasFlag(HostTargetFlags.AllowExtensionMethods) && (ExtensionMethodSummary != engine.ExtensionMethodSummary)))
{
string[] ownMethodNames;
AllMethodNames = GetAllMethodNames(out ownMethodNames);
@@ -847,12 +880,12 @@ private BindingFlags GetCommonBindFlags()
{
var bindFlags = BindingFlags.Public | BindingFlags.NonPublic;
- if (target.Flags.HasFlag(HostTargetFlags.AllowStaticMembers))
+ if (TargetFlags.HasFlag(HostTargetFlags.AllowStaticMembers))
{
- bindFlags |= BindingFlags.Static;
+ bindFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
}
- if (target.Flags.HasFlag(HostTargetFlags.AllowInstanceMembers))
+ if (TargetFlags.HasFlag(HostTargetFlags.AllowInstanceMembers))
{
bindFlags |= BindingFlags.Instance;
}
@@ -890,16 +923,16 @@ private void AdjustInvokeFlags(ref BindingFlags invokeFlags)
invokeFlags |= onFlags;
invokeFlags &= ~offFlags;
- if (target.Flags.HasFlag(HostTargetFlags.AllowStaticMembers))
+ if (TargetFlags.HasFlag(HostTargetFlags.AllowStaticMembers))
{
- invokeFlags |= BindingFlags.Static;
+ invokeFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
}
else
{
invokeFlags &= ~BindingFlags.Static;
}
- if (target.Flags.HasFlag(HostTargetFlags.AllowInstanceMembers))
+ if (TargetFlags.HasFlag(HostTargetFlags.AllowInstanceMembers))
{
invokeFlags |= BindingFlags.Instance;
}
@@ -1237,7 +1270,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[]
return DelegateFactory.CreateDelegate(engine, args[0], specificType);
}
- return specificType.CreateInstance(accessContext, defaultAccess, args);
+ return specificType.CreateInstance(AccessContext, DefaultAccess, args);
}
}
@@ -1257,7 +1290,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[]
return DelegateFactory.CreateDelegate(engine, args[0], type);
}
- return type.CreateInstance(accessContext, defaultAccess, args);
+ return type.CreateInstance(AccessContext, DefaultAccess, args);
}
if (TargetDynamicMetaObject != null)
@@ -1399,7 +1432,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
if (name == SpecialMemberNames.Default)
{
- var defaultProperty = target.Type.GetScriptableDefaultProperty(invokeFlags, bindArgs, accessContext, defaultAccess);
+ var defaultProperty = target.Type.GetScriptableDefaultProperty(invokeFlags, bindArgs, AccessContext, DefaultAccess);
if (defaultProperty != null)
{
return GetHostProperty(defaultProperty, invokeFlags, args, culture);
@@ -1495,7 +1528,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
}
}
- var property = target.Type.GetScriptableProperty(name, invokeFlags, bindArgs, accessContext, defaultAccess);
+ var property = target.Type.GetScriptableProperty(name, invokeFlags, bindArgs, AccessContext, DefaultAccess);
if (property != null)
{
return GetHostProperty(property, invokeFlags, args, culture);
@@ -1506,7 +1539,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
throw new MissingMemberException(MiscHelpers.FormatInvariant("Object has no suitable property named '{0}'", name));
}
- var eventInfo = target.Type.GetScriptableEvent(name, invokeFlags, accessContext, defaultAccess);
+ var eventInfo = target.Type.GetScriptableEvent(name, invokeFlags, AccessContext, DefaultAccess);
if (eventInfo != null)
{
var type = typeof(EventSource<>).MakeSpecificType(eventInfo.EventHandlerType);
@@ -1514,7 +1547,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
return type.CreateInstance(BindingFlags.NonPublic, engine, target.InvokeTarget, eventInfo);
}
- var field = target.Type.GetScriptableField(name, invokeFlags, accessContext, defaultAccess);
+ var field = target.Type.GetScriptableField(name, invokeFlags, AccessContext, DefaultAccess);
if (field != null)
{
var result = field.GetValue(target.InvokeTarget);
@@ -1524,7 +1557,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
if (includeBoundMembers)
{
- if (target.Type.GetScriptableProperties(name, invokeFlags, accessContext, defaultAccess).Any())
+ if (target.Type.GetScriptableProperties(name, invokeFlags, AccessContext, DefaultAccess).Any())
{
if (HostIndexedPropertyMap == null)
{
@@ -1572,7 +1605,7 @@ private object GetHostProperty(PropertyInfo property, BindingFlags invokeFlags,
}
var getMethod = property.GetMethod;
- if ((getMethod == null) || !getMethod.IsAccessible(accessContext) || getMethod.IsBlockedFromScript(defaultAccess, false))
+ if ((getMethod == null) || !getMethod.IsAccessible(AccessContext) || getMethod.IsBlockedFromScript(DefaultAccess, false))
{
throw new UnauthorizedAccessException("Property get method is unavailable or inaccessible");
}
@@ -1592,7 +1625,7 @@ private object SetHostProperty(string name, BindingFlags invokeFlags, object[] a
object result;
- var defaultProperty = target.Type.GetScriptableDefaultProperty(invokeFlags, bindArgs.Take(bindArgs.Length - 1).ToArray(), accessContext, defaultAccess);
+ var defaultProperty = target.Type.GetScriptableDefaultProperty(invokeFlags, bindArgs.Take(bindArgs.Length - 1).ToArray(), AccessContext, DefaultAccess);
if (defaultProperty != null)
{
return SetHostProperty(defaultProperty, invokeFlags, args, culture);
@@ -1645,18 +1678,18 @@ private object SetHostProperty(string name, BindingFlags invokeFlags, object[] a
throw new InvalidOperationException("Invalid argument count");
}
- var property = target.Type.GetScriptableProperty(name, invokeFlags, bindArgs.Take(bindArgs.Length - 1).ToArray(), accessContext, defaultAccess);
+ var property = target.Type.GetScriptableProperty(name, invokeFlags, bindArgs.Take(bindArgs.Length - 1).ToArray(), AccessContext, DefaultAccess);
if (property != null)
{
return SetHostProperty(property, invokeFlags, args, culture);
}
- var field = target.Type.GetScriptableField(name, invokeFlags, accessContext, defaultAccess);
+ var field = target.Type.GetScriptableField(name, invokeFlags, AccessContext, DefaultAccess);
if (field != null)
{
if (args.Length == 1)
{
- if (field.IsLiteral || field.IsInitOnly || field.IsReadOnlyForScript(defaultAccess))
+ if (field.IsLiteral || field.IsInitOnly || field.IsReadOnlyForScript(DefaultAccess))
{
throw new UnauthorizedAccessException("Field is read-only");
}
@@ -1679,13 +1712,13 @@ private object SetHostProperty(string name, BindingFlags invokeFlags, object[] a
private object SetHostProperty(PropertyInfo property, BindingFlags invokeFlags, object[] args, CultureInfo culture)
{
- if (property.IsReadOnlyForScript(defaultAccess))
+ if (property.IsReadOnlyForScript(DefaultAccess))
{
throw new UnauthorizedAccessException("Property is read-only");
}
var setMethod = property.SetMethod;
- if ((setMethod == null) || !setMethod.IsAccessible(accessContext) || setMethod.IsBlockedFromScript(defaultAccess, false))
+ if ((setMethod == null) || !setMethod.IsAccessible(AccessContext) || setMethod.IsBlockedFromScript(DefaultAccess, false))
{
throw new UnauthorizedAccessException("Property set method is unavailable or inaccessible");
}
@@ -2206,11 +2239,6 @@ public ScriptEngine Engine
get { return engine; }
}
- public Type AccessContext
- {
- get { return accessContext; }
- }
-
public object Unwrap()
{
return target.Target;
@@ -2220,9 +2248,19 @@ public object Unwrap()
#region IHostInvokeContext implementation
+ public Type AccessContext
+ {
+ get { return CachedAccessContext; }
+ }
+
public ScriptAccess DefaultAccess
{
- get { return defaultAccess; }
+ get { return CachedDefaultAccess; }
+ }
+
+ public HostTargetFlags TargetFlags
+ {
+ get { return CachedTargetFlags; }
}
#endregion
diff --git a/ClearScript/HostItemFlags.cs b/ClearScript/HostItemFlags.cs
index 9dd5005e8..79ff4e1c2 100644
--- a/ClearScript/HostItemFlags.cs
+++ b/ClearScript/HostItemFlags.cs
@@ -38,7 +38,8 @@ public enum HostItemFlags
/// Specifies that the script engine is to be given direct access to the exposed object if
/// possible. This option, when supported, suppresses marshaling and hands off the object
/// for script access without the host's involvement. It is currently supported only for
- /// COM objects exposed in Windows Script engines.
+ /// COM and COM-visible
+ /// objects exposed in Windows Script engines.
///
DirectAccess = 0x00000008
}
diff --git a/ClearScript/HostMethod.cs b/ClearScript/HostMethod.cs
index ee265f6a4..d9f212743 100644
--- a/ClearScript/HostMethod.cs
+++ b/ClearScript/HostMethod.cs
@@ -49,9 +49,9 @@ public override object DynamicInvokeTarget
get { return null; }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get { return HostTargetFlags.None; }
+ return HostTargetFlags.None;
}
public override bool TryInvoke(IHostInvokeContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result)
diff --git a/ClearScript/HostObject.cs b/ClearScript/HostObject.cs
index 8e0b0b585..d0e9fb527 100644
--- a/ClearScript/HostObject.cs
+++ b/ClearScript/HostObject.cs
@@ -139,9 +139,15 @@ public override object DynamicInvokeTarget
get { return target; }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get { return HostTargetFlags.AllowInstanceMembers | HostTargetFlags.AllowExtensionMethods; }
+ var flags = HostTargetFlags.AllowInstanceMembers | HostTargetFlags.AllowExtensionMethods;
+ if (context.Engine.ExposeHostObjectStaticMembers)
+ {
+ flags |= HostTargetFlags.AllowStaticMembers;
+ }
+
+ return flags;
}
public override Invocability GetInvocability(BindingFlags bindFlags, Type accessContext, ScriptAccess defaultAccess, bool ignoreDynamic)
diff --git a/ClearScript/HostTarget.cs b/ClearScript/HostTarget.cs
index ceeb39c29..351106211 100644
--- a/ClearScript/HostTarget.cs
+++ b/ClearScript/HostTarget.cs
@@ -17,7 +17,7 @@ internal abstract class HostTarget
public abstract object DynamicInvokeTarget { get; }
- public abstract HostTargetFlags Flags { get; }
+ public abstract HostTargetFlags GetFlags(IHostInvokeContext context);
public virtual string[] GetAuxMethodNames(IHostInvokeContext context, BindingFlags bindFlags)
{
diff --git a/ClearScript/HostTargetMemberData.cs b/ClearScript/HostTargetMemberData.cs
index 4655f4be2..7c47c2cad 100644
--- a/ClearScript/HostTargetMemberData.cs
+++ b/ClearScript/HostTargetMemberData.cs
@@ -28,15 +28,17 @@ internal class HostTargetMemberData
public Invocability? TargetInvocability;
}
- internal sealed class SharedHostObjectMemberData : HostTargetMemberData
+ internal class HostTargetMemberDataWithContext : HostTargetMemberData
{
public readonly Type AccessContext;
public readonly ScriptAccess DefaultAccess;
+ public readonly HostTargetFlags TargetFlags;
- public SharedHostObjectMemberData(Type accessContext, ScriptAccess defaultAccess)
+ public HostTargetMemberDataWithContext(Type accessContext, ScriptAccess defaultAccess, HostTargetFlags targetFlags)
{
AccessContext = accessContext;
DefaultAccess = defaultAccess;
+ TargetFlags = targetFlags;
}
}
}
diff --git a/ClearScript/HostType.cs b/ClearScript/HostType.cs
index 74569b6bd..5c991e49b 100644
--- a/ClearScript/HostType.cs
+++ b/ClearScript/HostType.cs
@@ -156,13 +156,10 @@ public override object DynamicInvokeTarget
get { return GetSpecificType(); }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get
- {
- var type = GetSpecificTypeNoThrow();
- return (type != null) ? HostTargetFlags.AllowStaticMembers : HostTargetFlags.None;
- }
+ var type = GetSpecificTypeNoThrow();
+ return (type != null) ? HostTargetFlags.AllowStaticMembers : HostTargetFlags.None;
}
public override string[] GetAuxPropertyNames(IHostInvokeContext context, BindingFlags bindFlags)
diff --git a/ClearScript/HostTypeCollection.cs b/ClearScript/HostTypeCollection.cs
index 47314be56..98a3183a4 100644
--- a/ClearScript/HostTypeCollection.cs
+++ b/ClearScript/HostTypeCollection.cs
@@ -5,7 +5,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
using Microsoft.ClearScript.Util;
+using Microsoft.ClearScript.Util.COM;
+using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND;
namespace Microsoft.ClearScript
{
@@ -185,12 +189,105 @@ public PropertyBag GetNamespaceNode(string name)
return namespaceNode;
}
+ internal void AddEnumTypeInfo(ITypeInfo typeInfo)
+ {
+ AddEnumTypeInfoInternal(typeInfo);
+ }
+
+ private PropertyBag AddEnumTypeInfoInternal(ITypeInfo typeInfo)
+ {
+ using (var attrScope = typeInfo.CreateAttrScope())
+ {
+ if (attrScope.Value.typekind == TYPEKIND.TKIND_ALIAS)
+ {
+ ITypeInfo refTypeInfo;
+ typeInfo.GetRefTypeInfo(unchecked((int)attrScope.Value.tdescAlias.lpValue.ToInt64()), out refTypeInfo);
+
+ var node = AddEnumTypeInfoInternal(refTypeInfo);
+ if (node != null)
+ {
+ var locator = typeInfo.GetManagedName();
+
+ var segments = locator.Split('.');
+ if (segments.Length > 0)
+ {
+ var namespaceNode = GetOrCreateNamespaceNode(locator);
+ if (namespaceNode != null)
+ {
+ namespaceNode.SetPropertyNoCheck(segments.Last(), node);
+ return node;
+ }
+ }
+ }
+ }
+ else if (attrScope.Value.typekind == TYPEKIND.TKIND_ENUM)
+ {
+ var node = GetOrCreateEnumTypeInfoNode(typeInfo);
+ if (node != null)
+ {
+ var count = attrScope.Value.cVars;
+ for (var index = 0; index < count; index++)
+ {
+ using (var varDescScope = typeInfo.CreateVarDescScope(index))
+ {
+ if (varDescScope.Value.varkind == VARKIND.VAR_CONST)
+ {
+ var name = typeInfo.GetMemberName(varDescScope.Value.memid);
+ node.SetPropertyNoCheck(name, Marshal.GetObjectForNativeVariant(varDescScope.Value.desc.lpvarValue));
+ }
+ }
+ }
+
+ return node;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private PropertyBag GetOrCreateEnumTypeInfoNode(ITypeInfo typeInfo)
+ {
+ var locator = typeInfo.GetManagedName();
+
+ var segments = locator.Split('.');
+ if (segments.Length < 1)
+ {
+ return null;
+ }
+
+ PropertyBag enumTypeInfoNode = this;
+ foreach (var segment in segments)
+ {
+ PropertyBag innerNode;
+
+ object node;
+ if (!enumTypeInfoNode.TryGetValue(segment, out node))
+ {
+ innerNode = new PropertyBag(true);
+ enumTypeInfoNode.SetPropertyNoCheck(segment, innerNode);
+ }
+ else
+ {
+ innerNode = node as PropertyBag;
+ if (innerNode == null)
+ {
+ throw new OperationCanceledException(MiscHelpers.FormatInvariant("Enumeration conflicts with '{0}' at '{1}'", node.GetFriendlyName(), locator));
+ }
+ }
+
+ enumTypeInfoNode = innerNode;
+ }
+
+ return enumTypeInfoNode;
+ }
+
private void AddType(HostType hostType)
{
MiscHelpers.VerifyNonNullArgument(hostType, "hostType");
foreach (var type in hostType.Types)
{
- var namespaceNode = GetNamespaceNode(type);
+ var namespaceNode = GetOrCreateNamespaceNode(type);
if (namespaceNode != null)
{
AddTypeToNamespaceNode(namespaceNode, type);
@@ -198,10 +295,13 @@ private void AddType(HostType hostType)
}
}
- private PropertyBag GetNamespaceNode(Type type)
+ private PropertyBag GetOrCreateNamespaceNode(Type type)
{
- var locator = type.GetLocator();
+ return GetOrCreateNamespaceNode(type.GetLocator());
+ }
+ private PropertyBag GetOrCreateNamespaceNode(string locator)
+ {
var segments = locator.Split('.');
if (segments.Length < 1)
{
diff --git a/ClearScript/HostVariable.cs b/ClearScript/HostVariable.cs
index 2b6c14374..a671d4b1b 100644
--- a/ClearScript/HostVariable.cs
+++ b/ClearScript/HostVariable.cs
@@ -89,9 +89,15 @@ public override object DynamicInvokeTarget
get { return value; }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get { return HostTargetFlags.AllowInstanceMembers | HostTargetFlags.AllowExtensionMethods; }
+ var flags = HostTargetFlags.AllowInstanceMembers | HostTargetFlags.AllowExtensionMethods;
+ if (context.Engine.ExposeHostObjectStaticMembers)
+ {
+ flags |= HostTargetFlags.AllowStaticMembers;
+ }
+
+ return flags;
}
public override bool TryInvokeAuxMember(IHostInvokeContext context, string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result)
diff --git a/ClearScript/Properties/AssemblyInfo.cs b/ClearScript/Properties/AssemblyInfo.cs
index d86a9a822..d818e8cc9 100644
--- a/ClearScript/Properties/AssemblyInfo.cs
+++ b/ClearScript/Properties/AssemblyInfo.cs
@@ -17,14 +17,14 @@
[assembly: InternalsVisibleTo("ClearScriptTest")]
[assembly: ComVisible(false)]
-[assembly: AssemblyVersion("6.0.0.0")]
-[assembly: AssemblyFileVersion("6.0.0.0")]
+[assembly: AssemblyVersion("6.0.1.0")]
+[assembly: AssemblyFileVersion("6.0.1.0")]
namespace Microsoft.ClearScript.Properties
{
internal static class ClearScriptVersion
{
- public const string Value = "6.0.0.0";
- public const string Triad = "6.0.0";
+ public const string Value = "6.0.1.0";
+ public const string Triad = "6.0.1";
}
}
diff --git a/ClearScript/ScriptEngine.cs b/ClearScript/ScriptEngine.cs
index af6fbd6ab..693118388 100644
--- a/ClearScript/ScriptEngine.cs
+++ b/ClearScript/ScriptEngine.cs
@@ -22,6 +22,8 @@ public abstract class ScriptEngine : IDisposable
private Type accessContext;
private ScriptAccess defaultAccess;
private bool enforceAnonymousTypeAccess;
+ private bool exposeHostObjectStaticMembers;
+ private object undefinedImportValue = Undefined.Value;
private DocumentSettings documentSettings;
private readonly DocumentSettings defaultDocumentSettings = new DocumentSettings();
@@ -148,6 +150,19 @@ public bool EnforceAnonymousTypeAccess
}
}
+ ///
+ /// Controls whether host objects provide access to the static members of their exposed types to script code.
+ ///
+ public bool ExposeHostObjectStaticMembers
+ {
+ get { return exposeHostObjectStaticMembers; }
+ set
+ {
+ exposeHostObjectStaticMembers = value;
+ OnAccessSettingsChanged();
+ }
+ }
+
///
/// Enables or disables script code formatting.
///
@@ -237,6 +252,21 @@ public bool EnforceAnonymousTypeAccess
///
public bool EnableAutoHostVariables { get; set; }
+ ///
+ /// Gets or sets the engine's undefined import value.
+ ///
+ ///
+ /// Some script languages support one or more special non-null values that represent
+ /// nonexistent, missing, unknown, or undefined data. When such a value is marshaled to the
+ /// host, the script engine maps it to the value of this property. The default value is
+ /// .
+ ///
+ public object UndefinedImportValue
+ {
+ get { return undefinedImportValue; }
+ set { undefinedImportValue = value; }
+ }
+
///
/// Gets or sets a callback that can be used to halt script execution.
///
@@ -969,7 +999,8 @@ public void Execute(string documentName, string code)
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with the specified name. Discarding this document removes it from view but
- /// has no effect on the script engine.
+ /// has no effect on the script engine. Only Windows Script engines honor
+ /// .
///
///
public void Execute(string documentName, bool discard, string code)
@@ -1124,7 +1155,8 @@ public object Evaluate(string documentName, string code)
///
/// If a debugger is attached, it will present the specified script code to the user as a
/// document with the specified name. Discarding this document removes it from view but
- /// has no effect on the script engine.
+ /// has no effect on the script engine. Only Windows Script engines honor
+ /// .
///
///
/// The following table summarizes the types of result values that script code can return.
@@ -1786,7 +1818,7 @@ private HostItem GetOrCreateHostItemForHostType(HostType hostType, HostItemFlags
private readonly ConditionalWeakTable> sharedHostObjectMemberDataCache = new ConditionalWeakTable>();
- internal HostTargetMemberData GetSharedHostObjectMemberData(HostObject target, Type targetAccessContext, ScriptAccess targetDefaultAccess)
+ internal HostTargetMemberData GetSharedHostObjectMemberData(HostObject target, Type targetAccessContext, ScriptAccess targetDefaultAccess, HostTargetFlags targetFlags)
{
var cacheEntry = sharedHostObjectMemberDataCache.GetOrCreateValue(target.Type);
@@ -1795,14 +1827,14 @@ internal HostTargetMemberData GetSharedHostObjectMemberData(HostObject target, T
foreach (var weakRef in cacheEntry)
{
- var memberData = weakRef.Target as SharedHostObjectMemberData;
+ var memberData = weakRef.Target as HostTargetMemberDataWithContext;
if (memberData == null)
{
staleWeakRefCount++;
}
else
{
- if ((memberData.AccessContext == targetAccessContext) && (memberData.DefaultAccess == targetDefaultAccess))
+ if ((memberData.AccessContext == targetAccessContext) && (memberData.DefaultAccess == targetDefaultAccess) && (memberData.TargetFlags == targetFlags))
{
return memberData;
}
@@ -1826,7 +1858,7 @@ internal HostTargetMemberData GetSharedHostObjectMemberData(HostObject target, T
}
}
- var newMemberData = new SharedHostObjectMemberData(targetAccessContext, targetDefaultAccess);
+ var newMemberData = new HostTargetMemberDataWithContext(targetAccessContext, targetDefaultAccess, targetFlags);
cacheEntry.Add(new WeakReference(newMemberData));
return newMemberData;
}
diff --git a/ClearScript/ScriptMethod.cs b/ClearScript/ScriptMethod.cs
index a04700caa..e99669c0c 100644
--- a/ClearScript/ScriptMethod.cs
+++ b/ClearScript/ScriptMethod.cs
@@ -55,9 +55,9 @@ public override object DynamicInvokeTarget
get { return null; }
}
- public override HostTargetFlags Flags
+ public override HostTargetFlags GetFlags(IHostInvokeContext context)
{
- get { return HostTargetFlags.None; }
+ return HostTargetFlags.None;
}
public override bool TryInvoke(IHostInvokeContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result)
diff --git a/ClearScript/Undefined.cs b/ClearScript/Undefined.cs
index 369d67a00..bad72d77e 100644
--- a/ClearScript/Undefined.cs
+++ b/ClearScript/Undefined.cs
@@ -7,13 +7,16 @@ namespace Microsoft.ClearScript
/// Represents an undefined value.
///
///
- /// Most script languages support one or more special values that represent nonexistent,
- /// missing, unknown, or undefined data. The ClearScript library maps some such values to
- /// null, and others to instances of this class.
+ /// Some script languages support one or more special non-null values that represent
+ /// nonexistent, missing, unknown, or undefined data. The ClearScript library maps such values
+ /// to instances of this class.
///
public class Undefined
{
- internal static readonly Undefined Value = new Undefined();
+ ///
+ /// The sole instance of the class.
+ ///
+ public static readonly Undefined Value = new Undefined();
private Undefined()
{
diff --git a/ClearScript/Util/AssemblyHelpers.cs b/ClearScript/Util/AssemblyHelpers.cs
index c5c0ee967..880a48424 100644
--- a/ClearScript/Util/AssemblyHelpers.cs
+++ b/ClearScript/Util/AssemblyHelpers.cs
@@ -47,6 +47,19 @@ public static string GetFullAssemblyName(string name)
{
return assemblyName.FullName;
}
+
+ IEnumerable subDirPaths;
+ if (MiscHelpers.Try(out subDirPaths, () => Directory.EnumerateDirectories(dirPath, "*", SearchOption.AllDirectories)))
+ {
+ foreach (var subDirPath in subDirPaths)
+ {
+ path = Path.Combine(subDirPath, fileName);
+ if (File.Exists(path) && MiscHelpers.Try(out assemblyName, () => AssemblyName.GetAssemblyName(path)))
+ {
+ return assemblyName.FullName;
+ }
+ }
+ }
}
return name;
@@ -94,5 +107,146 @@ public static bool IsFriendOf(this Assembly thisAssembly, Assembly thatAssembly)
return false;
}
+
+ public static IEnumerable GetReferencedEnums(this Assembly assembly)
+ {
+ var processedTypes = new HashSet();
+ return assembly.GetAllTypes().SelectMany(type => GetReferencedEnums(assembly, type, processedTypes));
+ }
+
+ private static IEnumerable GetReferencedEnums(Assembly assembly, Type type, HashSet processedTypes)
+ {
+ if ((type == null) || !type.IsVisible || type.ContainsGenericParameters || processedTypes.Contains(type))
+ {
+ yield break;
+ }
+
+ processedTypes.Add(type);
+
+ if (type.IsEnum)
+ {
+ yield return type;
+ yield break;
+ }
+
+ foreach (var enumType in GetReferencedEnums(assembly, type.GetElementType(), processedTypes))
+ {
+ yield return enumType;
+ }
+
+ foreach (var enumType in type.GetGenericArguments().SelectMany(argType => GetReferencedEnums(assembly, argType, processedTypes)))
+ {
+ yield return enumType;
+ }
+
+ foreach (var enumType in GetReferencedEnums(assembly, type.BaseType, processedTypes))
+ {
+ yield return enumType;
+ }
+
+ foreach (var enumType in type.GetInterfaces().SelectMany(interfaceType => GetReferencedEnums(assembly, interfaceType, processedTypes)))
+ {
+ yield return enumType;
+ }
+
+ if (type.Assembly == assembly)
+ {
+ foreach (var enumType in type.GetMembers().SelectMany(member => GetReferencedEnums(assembly, member, processedTypes)))
+ {
+ yield return enumType;
+ }
+ }
+ }
+
+ private static IEnumerable GetReferencedEnums(Assembly assembly, MemberInfo member, HashSet processedTypes)
+ {
+ if (member == null)
+ {
+ return Enumerable.Empty();
+ }
+
+ if (member.MemberType == MemberTypes.Field)
+ {
+ return GetReferencedEnums(assembly, (FieldInfo)member, processedTypes);
+ }
+
+ if (member.MemberType == MemberTypes.Property)
+ {
+ return GetReferencedEnums(assembly, (PropertyInfo)member, processedTypes);
+ }
+
+ if (member.MemberType == MemberTypes.Method)
+ {
+ return GetReferencedEnums(assembly, (MethodInfo)member, processedTypes);
+ }
+
+ if (member.MemberType == MemberTypes.NestedType)
+ {
+ return GetReferencedEnums(assembly, (Type)member, processedTypes);
+ }
+
+ return Enumerable.Empty();
+ }
+
+ private static IEnumerable GetReferencedEnums(Assembly assembly, FieldInfo field, HashSet processedTypes)
+ {
+ if (field == null)
+ {
+ return Enumerable.Empty();
+ }
+
+ return GetReferencedEnums(assembly, field.FieldType, processedTypes);
+ }
+
+ private static IEnumerable GetReferencedEnums(Assembly assembly, PropertyInfo property, HashSet processedTypes)
+ {
+ if (property == null)
+ {
+ yield break;
+ }
+
+ foreach (var enumType in GetReferencedEnums(assembly, property.PropertyType, processedTypes))
+ {
+ yield return enumType;
+ }
+
+ foreach (var enumType in GetReferencedEnums(assembly, property.GetMethod, processedTypes))
+ {
+ yield return enumType;
+ }
+
+ foreach (var enumType in GetReferencedEnums(assembly, property.SetMethod, processedTypes))
+ {
+ yield return enumType;
+ }
+ }
+
+ private static IEnumerable GetReferencedEnums(Assembly assembly, MethodInfo method, HashSet processedTypes)
+ {
+ if (method == null)
+ {
+ yield break;
+ }
+
+ foreach (var enumType in GetReferencedEnums(assembly, method.ReturnParameter, processedTypes))
+ {
+ yield return enumType;
+ }
+
+ foreach (var enumType in method.GetParameters().SelectMany(param => GetReferencedEnums(assembly, param, processedTypes)))
+ {
+ yield return enumType;
+ }
+ }
+
+ private static IEnumerable GetReferencedEnums(Assembly assembly, ParameterInfo param, HashSet processedTypes)
+ {
+ if (param == null)
+ {
+ return Enumerable.Empty();
+ }
+
+ return GetReferencedEnums(assembly, param.ParameterType, processedTypes);
+ }
}
}
diff --git a/ClearScript/Util/AssemblyTable.NetFramework.cs b/ClearScript/Util/AssemblyTable.NetFramework.cs
index b0fb0ca11..e1e50bacb 100644
--- a/ClearScript/Util/AssemblyTable.NetFramework.cs
+++ b/ClearScript/Util/AssemblyTable.NetFramework.cs
@@ -36,66 +36,49 @@ static AssemblyTableImpl()
public static string GetFullAssemblyNameImpl(string name)
{
string fullName;
- return ((table != null) && table.TryGetValue(name, out fullName)) ? fullName : name;
+ return ((table != null) && table.TryGetValue(name, out fullName)) ? fullName : AssemblyHelpers.GetFullAssemblyName(name);
}
private static void LoadAssemblyTable()
{
- // ReSharper disable EmptyGeneralCatchClause
-
- string filePath = null;
- try
+ if (!ReadAssemblyTable() && BuildAssemblyTable())
{
- var dirPath = Path.Combine(MiscHelpers.GetLocalDataRootPath(), GetRuntimeVersionDirectoryName());
- Directory.CreateDirectory(dirPath);
-
- filePath = Path.Combine(dirPath, "AssemblyTable.bin");
- if (File.Exists(filePath))
- {
- try
- {
- using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- var formatter = new BinaryFormatter();
- table = (ConcurrentDictionary)formatter.Deserialize(stream);
- }
- }
- catch (Exception)
- {
- }
- }
+ WriteAssemblyTable();
}
- catch (Exception)
+ }
+
+ private static bool ReadAssemblyTable()
+ {
+ bool usingAppPath;
+ if (ReadAssemblyTable(MiscHelpers.GetLocalDataRootPath(out usingAppPath)))
{
+ return true;
}
- if (table == null)
+ return !usingAppPath && ReadAssemblyTable(MiscHelpers.GetLocalDataRootPath(AppDomain.CurrentDomain.BaseDirectory));
+ }
+
+ private static bool ReadAssemblyTable(string rootPath)
+ {
+ var succeeded = MiscHelpers.Try(() =>
{
- BuildAssemblyTable();
- if ((table != null) && (filePath != null))
+ var filePath = GetFilePath(rootPath);
+ if (File.Exists(filePath))
{
- try
- {
- using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
- {
- var formatter = new BinaryFormatter();
- formatter.Serialize(stream, table);
- }
- }
- catch (Exception)
+ using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
+ var formatter = new BinaryFormatter();
+ table = (ConcurrentDictionary)formatter.Deserialize(stream);
}
}
- }
+ });
- // ReSharper restore EmptyGeneralCatchClause
+ return succeeded && (table != null);
}
- private static void BuildAssemblyTable()
+ private static bool BuildAssemblyTable()
{
- // ReSharper disable EmptyGeneralCatchClause
-
- try
+ var succeeded = MiscHelpers.Try(() =>
{
var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\.NETFramework");
if (key != null)
@@ -105,22 +88,47 @@ private static void BuildAssemblyTable()
table = new ConcurrentDictionary();
foreach (var filePath in Directory.EnumerateFiles(dirPath, "*.dll", SearchOption.AllDirectories))
{
- try
+ var path = filePath;
+ MiscHelpers.Try(() =>
{
- var assemblyName = Assembly.ReflectionOnlyLoadFrom(filePath).GetName();
+ var assemblyName = Assembly.ReflectionOnlyLoadFrom(path).GetName();
table.TryAdd(assemblyName.Name, assemblyName.FullName);
- }
- catch (Exception)
- {
- }
+ });
}
}
- }
- catch (Exception)
+ });
+
+ return succeeded && (table != null);
+ }
+
+ private static void WriteAssemblyTable()
+ {
+ bool usingAppPath;
+ if (!WriteAssemblyTable(MiscHelpers.GetLocalDataRootPath(out usingAppPath)) && !usingAppPath)
{
+ WriteAssemblyTable(MiscHelpers.GetLocalDataRootPath(AppDomain.CurrentDomain.BaseDirectory));
}
+ }
+
+ private static bool WriteAssemblyTable(string rootPath)
+ {
+ return MiscHelpers.Try(() =>
+ {
+ var filePath = GetFilePath(rootPath);
+ using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
+ {
+ var formatter = new BinaryFormatter();
+ formatter.Serialize(stream, table);
+ }
+ });
+ }
+
+ private static string GetFilePath(string rootPath)
+ {
+ var dirPath = Path.Combine(rootPath, GetRuntimeVersionDirectoryName());
+ Directory.CreateDirectory(dirPath);
- // ReSharper restore EmptyGeneralCatchClause
+ return Path.Combine(dirPath, "AssemblyTable.bin");
}
private static string GetRuntimeVersionDirectoryName()
diff --git a/ClearScript/Util/COM/StructHelpers.cs b/ClearScript/Util/COM/StructHelpers.cs
new file mode 100644
index 000000000..bfbf9e4ef
--- /dev/null
+++ b/ClearScript/Util/COM/StructHelpers.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.ClearScript.Util.COM
+{
+ internal static class StructHelpers
+ {
+ public delegate void GetStruct(out IntPtr pStruct);
+
+ public delegate void ReleaseStruct(IntPtr pStruct);
+
+ public static IScope CreateScope(GetStruct get, ReleaseStruct release)
+ {
+ IntPtr pStruct;
+ get(out pStruct);
+ return Scope.Create(() => (T)Marshal.PtrToStructure(pStruct, typeof(T)), value => release(pStruct));
+ }
+
+ public static IEnumerable GetStructsFromArray(IntPtr pStructs, int count)
+ {
+ var size = Marshal.SizeOf(typeof(T));
+ for (var pStruct = pStructs; count > 0; count--)
+ {
+ yield return (T)Marshal.PtrToStructure(pStruct, typeof(T));
+ pStruct += size;
+ }
+ }
+ }
+}
diff --git a/ClearScript/Util/COM/TypeInfoHelpers.cs b/ClearScript/Util/COM/TypeInfoHelpers.cs
index 7713282cb..a1aa505d9 100644
--- a/ClearScript/Util/COM/TypeInfoHelpers.cs
+++ b/ClearScript/Util/COM/TypeInfoHelpers.cs
@@ -17,6 +17,9 @@ namespace Microsoft.ClearScript.Util.COM
{
internal static partial class TypeInfoHelpers
{
+ // GUID_ManagedName (um\cor.h)
+ private static readonly Guid managedNameGuid = new Guid("{0f21f359-ab84-41e8-9a78-36d110e6d2f9}");
+
public static ITypeLib GetContainingTypeLib(this ITypeInfo typeInfo)
{
int index;
@@ -35,6 +38,35 @@ public static string GetName(this ITypeInfo typeInfo)
return typeInfo.GetMemberName(-1);
}
+ public static string GetManagedName(this ITypeInfo typeInfo)
+ {
+ 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 typeInfo.GetContainingTypeLib().GetManagedName() + "." + Marshal.GetTypeInfoName(typeInfo);
+ }
+
public static string GetMemberName(this ITypeInfo typeInfo, int memid)
{
string name;
@@ -47,140 +79,118 @@ public static string GetMemberName(this ITypeInfo typeInfo, int memid)
public static Guid GetGuid(this ITypeInfo typeInfo)
{
- return typeInfo.GetTypeAttr().guid;
+ using (var attrScope = typeInfo.CreateAttrScope())
+ {
+ return attrScope.Value.guid;
+ }
+ }
+
+ public static Guid GetOrCreateGuid(this ITypeInfo typeInfo)
+ {
+ var guid = typeInfo.GetGuid();
+ if (guid != Guid.Empty)
+ {
+ return guid;
+ }
+
+ var guidBytes = typeInfo.GetContainingTypeLib().GetGuid().ToByteArray();
+
+ var nameBytes = BitConverter.GetBytes(typeInfo.GetName().GetDigestAsUInt64());
+ for (var index = 0; index < guidBytes.Length; index++)
+ {
+ guidBytes[index] ^= nameBytes[index % nameBytes.Length];
+ }
+
+ return new Guid(guidBytes);
}
public static TYPEFLAGS GetFlags(this ITypeInfo typeInfo)
{
- return typeInfo.GetTypeAttr().wTypeFlags;
+ using (var attrScope = typeInfo.CreateAttrScope())
+ {
+ return attrScope.Value.wTypeFlags;
+ }
}
public static TYPEKIND GetKind(this ITypeInfo typeInfo)
{
- return typeInfo.GetTypeAttr().typekind;
+ using (var attrScope = typeInfo.CreateAttrScope())
+ {
+ return attrScope.Value.typekind;
+ }
}
public static IEnumerable GetDispatchMembers(this ITypeInfo typeInfo)
{
- var funcCount = typeInfo.GetTypeAttr().cFuncs;
- var isEnumerable = false;
-
- var names = new string[1];
- for (var index = 0; index < funcCount; index++)
+ using (var attrScope = typeInfo.CreateAttrScope())
{
- IntPtr pDesc;
- typeInfo.GetFuncDesc(index, out pDesc);
- try
+ var count = attrScope.Value.cFuncs;
+ var isEnumerable = false;
+
+ var names = new string[1];
+ for (var index = 0; index < count; index++)
{
- var desc = (FUNCDESC)Marshal.PtrToStructure(pDesc, typeof(FUNCDESC));
- if (desc.memid == SpecialDispIDs.NewEnum)
+ using (var funcDescScope = typeInfo.CreateFuncDescScope(index))
{
- isEnumerable = true;
- }
+ if (funcDescScope.Value.memid == SpecialDispIDs.NewEnum)
+ {
+ isEnumerable = true;
+ }
- if ((desc.wFuncFlags & (short)FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0)
- {
- continue;
- }
+ if ((funcDescScope.Value.wFuncFlags & (short)FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0)
+ {
+ continue;
+ }
- int nameCount;
- typeInfo.GetNames(desc.memid, names, 1, out nameCount);
- if (nameCount > 0)
- {
- yield return new DispatchMember(names[0], desc.memid, desc.invkind);
- }
- }
- finally
- {
- typeInfo.ReleaseFuncDesc(pDesc);
- }
+ int nameCount;
+ typeInfo.GetNames(funcDescScope.Value.memid, names, 1, out nameCount);
+ if (nameCount > 0)
+ {
+ yield return new DispatchMember(names[0], funcDescScope.Value.memid, funcDescScope.Value.invkind);
+ }
- if (isEnumerable)
- {
- yield return new DispatchMember("GetEnumerator", SpecialDispIDs.GetEnumerator, INVOKEKIND.INVOKE_FUNC);
+ if (isEnumerable)
+ {
+ yield return new DispatchMember("GetEnumerator", SpecialDispIDs.GetEnumerator, INVOKEKIND.INVOKE_FUNC);
+ }
+ }
}
}
}
- public static IPropertyBag GetTypeLibEnums(this ITypeInfo typeInfo)
+ public static bool IsEnum(this ITypeInfo typeInfo)
{
- var typeLib = typeInfo.GetContainingTypeLib();
- var typeLibName = typeLib.GetName();
-
- var rootNode = new PropertyBag(true);
-
- var typeInfoCount = typeLib.GetTypeInfoCount();
- for (var typeInfoIndex = 0; typeInfoIndex < typeInfoCount; typeInfoIndex++)
+ using (var attrScope = typeInfo.CreateAttrScope())
{
- typeLib.GetTypeInfo(typeInfoIndex, out typeInfo);
- var typeInfoName = typeInfo.GetName();
-
- var typeAttr = typeInfo.GetTypeAttr();
- if (typeAttr.typekind == TYPEKIND.TKIND_ALIAS)
+ if (attrScope.Value.typekind == TYPEKIND.TKIND_ENUM)
{
- ITypeInfo refTypeInfo;
- typeInfo.GetRefTypeInfo(unchecked((int)(long)typeAttr.tdescAlias.lpValue), out refTypeInfo);
-
- typeInfo = refTypeInfo;
- typeAttr = typeInfo.GetTypeAttr();
+ return true;
}
- if (typeAttr.typekind == TYPEKIND.TKIND_ENUM)
+ if (attrScope.Value.typekind == TYPEKIND.TKIND_ALIAS)
{
- var varCount = typeAttr.cVars;
- for (var varIndex = 0; varIndex < varCount; varIndex++)
- {
- IntPtr pVarDesc;
- typeInfo.GetVarDesc(varIndex, out pVarDesc);
- try
- {
- var varDesc = (VARDESC)Marshal.PtrToStructure(pVarDesc, typeof(VARDESC));
- if (varDesc.varkind == VARKIND.VAR_CONST)
- {
- var varName = typeInfo.GetMemberName(varDesc.memid);
-
- object typeLibNodeObj;
- if (!rootNode.TryGetValue(typeLibName, out typeLibNodeObj) || !(typeLibNodeObj is PropertyBag))
- {
- typeLibNodeObj = new PropertyBag(true);
- rootNode.SetPropertyNoCheck(typeLibName, typeLibNodeObj);
- }
-
- object typeInfoNodeObj;
- var typeLibNode = (PropertyBag)typeLibNodeObj;
- if (!typeLibNode.TryGetValue(typeInfoName, out typeInfoNodeObj) || !(typeInfoNodeObj is PropertyBag))
- {
- typeInfoNodeObj = new PropertyBag(true);
- typeLibNode.SetPropertyNoCheck(typeInfoName, typeInfoNodeObj);
- }
-
- var typeInfoNode = (PropertyBag)typeInfoNodeObj;
- typeInfoNode.SetPropertyNoCheck(varName, Marshal.GetObjectForNativeVariant(varDesc.desc.lpvarValue));
- }
- }
- finally
- {
- typeInfo.ReleaseVarDesc(pVarDesc);
- }
- }
+ ITypeInfo refTypeInfo;
+ typeInfo.GetRefTypeInfo(unchecked((int)attrScope.Value.tdescAlias.lpValue.ToInt64()), out refTypeInfo);
+ return refTypeInfo.IsEnum();
}
+
+ return false;
}
+ }
- return rootNode;
+ public static IScope CreateAttrScope(this ITypeInfo typeInfo)
+ {
+ return StructHelpers.CreateScope(typeInfo.GetTypeAttr, typeInfo.ReleaseTypeAttr);
}
- private static TYPEATTR GetTypeAttr(this ITypeInfo typeInfo)
+ public static IScope CreateVarDescScope(this ITypeInfo typeInfo, int index)
{
- IntPtr pTypeAttr;
- typeInfo.GetTypeAttr(out pTypeAttr);
- try
- {
- return (TYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(TYPEATTR));
- }
- finally
- {
- typeInfo.ReleaseTypeAttr(pTypeAttr);
- }
+ return StructHelpers.CreateScope((out IntPtr pVarDesc) => typeInfo.GetVarDesc(index, out pVarDesc), typeInfo.ReleaseVarDesc);
+ }
+
+ public static IScope CreateFuncDescScope(this ITypeInfo typeInfo, int index)
+ {
+ return StructHelpers.CreateScope((out IntPtr pFuncDesc) => typeInfo.GetFuncDesc(index, out pFuncDesc), typeInfo.ReleaseFuncDesc);
}
}
}
diff --git a/ClearScript/Util/COM/TypeLibHelpers.cs b/ClearScript/Util/COM/TypeLibHelpers.cs
index ec2767caf..eeb47e3b6 100644
--- a/ClearScript/Util/COM/TypeLibHelpers.cs
+++ b/ClearScript/Util/COM/TypeLibHelpers.cs
@@ -1,12 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
+using ELEMDESC = System.Runtime.InteropServices.ComTypes.ELEMDESC;
+using FUNCDESC = System.Runtime.InteropServices.ComTypes.FUNCDESC;
+using TYPEDESC = System.Runtime.InteropServices.ComTypes.TYPEDESC;
+using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR;
+using VARDESC = System.Runtime.InteropServices.ComTypes.VARDESC;
namespace Microsoft.ClearScript.Util.COM
{
internal static class TypeLibHelpers
{
+ // GUID_ManagedName (um\cor.h)
+ private static readonly Guid managedNameGuid = new Guid("{0f21f359-ab84-41e8-9a78-36d110e6d2f9}");
+
public static string GetName(this ITypeLib typeLib)
{
return typeLib.GetMemberName(-1);
@@ -21,5 +33,186 @@ public static string GetMemberName(this ITypeLib typeLib, int index)
typeLib.GetDocumentation(index, out name, out docString, out helpContext, out helpFile);
return name;
}
+
+ public static string GetManagedName(this 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 typeLib.GetName();
+ }
+
+ public static Guid GetGuid(this ITypeLib typeLib)
+ {
+ using (var attrScope = typeLib.CreateAttrScope())
+ {
+ return attrScope.Value.guid;
+ }
+ }
+
+ public static IScope CreateAttrScope(this ITypeLib typeLib)
+ {
+ return StructHelpers.CreateScope(typeLib.GetLibAttr, typeLib.ReleaseTLibAttr);
+ }
+
+ public static IEnumerable GetReferencedEnums(this ITypeLib typeLib)
+ {
+ var processedTypeInfo = new Dictionary();
+
+ var count = typeLib.GetTypeInfoCount();
+ for (var index = 0; index < count; index++)
+ {
+ ITypeInfo typeInfo;
+ typeLib.GetTypeInfo(index, out typeInfo);
+
+ foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, processedTypeInfo))
+ {
+ yield return enumTypeInfo;
+ }
+ }
+ }
+
+ private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, Dictionary processedTypeInfo)
+ {
+ if (typeInfo == null)
+ {
+ yield break;
+ }
+
+ var guid = typeInfo.GetOrCreateGuid();
+
+ if (processedTypeInfo.ContainsKey(guid))
+ {
+ yield break;
+ }
+
+ processedTypeInfo.Add(guid, typeInfo);
+
+ if (typeInfo.IsEnum())
+ {
+ yield return typeInfo;
+ yield break;
+ }
+
+ if (typeInfo.GetContainingTypeLib().GetGuid() != typeLib.GetGuid())
+ {
+ yield break;
+ }
+
+ using (var typeAttrScope = typeInfo.CreateAttrScope())
+ {
+ for (var funcIndex = 0; funcIndex < typeAttrScope.Value.cFuncs; funcIndex++)
+ {
+ using (var funcDescScope = typeInfo.CreateFuncDescScope(funcIndex))
+ {
+ foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, funcDescScope.Value, processedTypeInfo))
+ {
+ yield return enumTypeInfo;
+ }
+ }
+ }
+
+ for (var varIndex = 0; varIndex < typeAttrScope.Value.cVars; varIndex++)
+ {
+ using (var varDescScope = typeInfo.CreateVarDescScope(varIndex))
+ {
+ foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, varDescScope.Value, processedTypeInfo))
+ {
+ yield return enumTypeInfo;
+ }
+ }
+ }
+
+ for (var implTypeIndex = 0; implTypeIndex < typeAttrScope.Value.cImplTypes; implTypeIndex++)
+ {
+ int href;
+ typeInfo.GetRefTypeOfImplType(implTypeIndex, out href);
+
+ ITypeInfo refTypeInfo;
+ typeInfo.GetRefTypeInfo(href, out refTypeInfo);
+
+ var refGuid = refTypeInfo.GetGuid();
+ if ((refGuid == typeof(IDispatch).GUID) || (refGuid == typeof(IDispatchEx).GUID))
+ {
+ continue;
+ }
+
+ foreach (var enumTypeInfo in GetReferencedEnums(typeLib, refTypeInfo, processedTypeInfo))
+ {
+ yield return enumTypeInfo;
+ }
+ }
+ }
+ }
+
+ private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, FUNCDESC funcDesc, Dictionary processedTypeInfo)
+ {
+ foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, funcDesc.elemdescFunc, processedTypeInfo))
+ {
+ yield return enumTypeInfo;
+ }
+
+ foreach (var elemDesc in StructHelpers.GetStructsFromArray(funcDesc.lprgelemdescParam, funcDesc.cParams))
+ {
+ foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, elemDesc, processedTypeInfo))
+ {
+ yield return enumTypeInfo;
+ }
+ }
+ }
+
+ private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, VARDESC varDesc, Dictionary processedTypeInfo)
+ {
+ return GetReferencedEnums(typeLib, typeInfo, varDesc.elemdescVar, processedTypeInfo);
+ }
+
+ private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, ELEMDESC elemDesc, Dictionary processedTypeInfo)
+ {
+ return GetReferencedEnums(typeLib, typeInfo, elemDesc.tdesc, processedTypeInfo);
+ }
+
+ private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, TYPEDESC typeDesc, Dictionary processedTypeInfo)
+ {
+ if ((typeDesc.vt == (short)VarEnum.VT_PTR) || (typeDesc.vt == (short)VarEnum.VT_CARRAY))
+ {
+ return GetReferencedEnums(typeLib, typeInfo, (TYPEDESC)Marshal.PtrToStructure(typeDesc.lpValue, typeof(TYPEDESC)), processedTypeInfo);
+ }
+
+ if (typeDesc.vt == (short)VarEnum.VT_USERDEFINED)
+ {
+ ITypeInfo refTypeInfo;
+ typeInfo.GetRefTypeInfo(unchecked((int)typeDesc.lpValue.ToInt64()), out refTypeInfo);
+ return GetReferencedEnums(typeLib, refTypeInfo, processedTypeInfo);
+ }
+
+ return Enumerable.Empty();
+ }
}
}
diff --git a/ClearScript/Util/IHostInvokeContext.cs b/ClearScript/Util/IHostInvokeContext.cs
index 3f7097dbe..7bb205e9a 100644
--- a/ClearScript/Util/IHostInvokeContext.cs
+++ b/ClearScript/Util/IHostInvokeContext.cs
@@ -10,5 +10,6 @@ internal interface IHostInvokeContext
ScriptEngine Engine { get; }
Type AccessContext { get; }
ScriptAccess DefaultAccess { get; }
+ HostTargetFlags TargetFlags { get; }
}
}
diff --git a/NetCore/ClearScript/Util/IJW/IJWHostLibrary.cs b/ClearScript/Util/IJW/IJWHostLibrary.cs
similarity index 79%
rename from NetCore/ClearScript/Util/IJW/IJWHostLibrary.cs
rename to ClearScript/Util/IJW/IJWHostLibrary.cs
index 09dfdf334..84e4206bf 100644
--- a/NetCore/ClearScript/Util/IJW/IJWHostLibrary.cs
+++ b/ClearScript/Util/IJW/IJWHostLibrary.cs
@@ -10,7 +10,20 @@ internal static class IJWHostLibrary
{
public static IntPtr Load()
{
- var dirPath = Path.Combine(MiscHelpers.GetLocalDataRootPath(), "IJW");
+ IntPtr hLibrary;
+
+ var usingAppPath = false;
+ if (!MiscHelpers.Try(out hLibrary, () => Load(MiscHelpers.GetLocalDataRootPath(out usingAppPath))) && !usingAppPath)
+ {
+ hLibrary = Load(MiscHelpers.GetLocalDataRootPath(AppDomain.CurrentDomain.BaseDirectory));
+ }
+
+ return hLibrary;
+ }
+
+ private static IntPtr Load(string rootPath)
+ {
+ var dirPath = Path.Combine(rootPath, "IJW");
var filePath = Path.Combine(dirPath, "ijwhost.dll");
if (!File.Exists(filePath))
diff --git a/ClearScript/Util/MemberHelpers.cs b/ClearScript/Util/MemberHelpers.cs
index d93624ce7..a7faab5a1 100644
--- a/ClearScript/Util/MemberHelpers.cs
+++ b/ClearScript/Util/MemberHelpers.cs
@@ -305,12 +305,7 @@ public static string GetShortName(this MemberInfo member)
return (index >= 0) ? name.Substring(index + 1) : name;
}
- private static bool IsExplicitImplementation(this MemberInfo member)
- {
- return member.Name.IndexOf('.') >= 0;
- }
-
- private static T GetAttribute(this MemberInfo member, bool inherit) where T : Attribute
+ public static T GetAttribute(this MemberInfo member, bool inherit) where T : Attribute
{
try
{
@@ -329,5 +324,10 @@ private static T GetAttribute(this MemberInfo member, bool inherit) where T :
throw;
}
}
+
+ private static bool IsExplicitImplementation(this MemberInfo member)
+ {
+ return member.Name.IndexOf('.') >= 0;
+ }
}
}
diff --git a/ClearScript/Util/MiscHelpers.cs b/ClearScript/Util/MiscHelpers.cs
index 14a474142..f1a8bf2f1 100644
--- a/ClearScript/Util/MiscHelpers.cs
+++ b/ClearScript/Util/MiscHelpers.cs
@@ -514,9 +514,33 @@ public static void AssertUnreachable()
Debug.Assert(false, "Entered code block presumed unreachable.");
}
- public static string GetLocalDataRootPath()
+ public static string GetLocalDataRootPath(out bool usingAppPath)
{
- return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "ClearScript", ClearScriptVersion.Triad, Environment.Is64BitProcess ? "x64" : "x86");
+ var basePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ if (string.IsNullOrWhiteSpace(basePath))
+ {
+ basePath = AppDomain.CurrentDomain.BaseDirectory;
+ usingAppPath = true;
+ }
+ else
+ {
+ usingAppPath = false;
+ }
+
+ return GetLocalDataRootPath(basePath);
+ }
+
+ public static string GetLocalDataRootPath(string basePath)
+ {
+ var path = Path.Combine(basePath, "Microsoft", "ClearScript", ClearScriptVersion.Triad, Environment.Is64BitProcess ? "x64" : "x86");
+
+ string fullPath;
+ if (Try(out fullPath, () => Path.GetFullPath(path)))
+ {
+ return fullPath;
+ }
+
+ return path;
}
#endregion
diff --git a/ClearScript/Util/ObjectHelpers.cs b/ClearScript/Util/ObjectHelpers.cs
index b37efc952..e8ec61104 100644
--- a/ClearScript/Util/ObjectHelpers.cs
+++ b/ClearScript/Util/ObjectHelpers.cs
@@ -11,15 +11,11 @@
using Microsoft.Win32;
using TYPEFLAGS = System.Runtime.InteropServices.ComTypes.TYPEFLAGS;
using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND;
-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();
@@ -176,7 +172,7 @@ private static Type GetTypeForTypeInfo(ITypeInfo typeInfo)
var assembly = LoadPrimaryInteropAssembly(typeLib);
if (assembly != null)
{
- var name = GetManagedTypeInfoName(typeInfo, typeLib);
+ var name = typeInfo.GetManagedName();
var guid = typeInfo.GetGuid();
var type = assembly.GetType(name, false, true);
@@ -185,7 +181,7 @@ private static Type GetTypeForTypeInfo(ITypeInfo typeInfo)
return type;
}
- var types = assembly.GetTypes();
+ var types = assembly.GetAllTypes().ToArray();
if ((index >= 0) && (index < types.Length))
{
type = types[index];
@@ -225,23 +221,15 @@ private static Assembly LoadPrimaryInteropAssembly(ITypeLib typeLib)
try
{
- IntPtr pLibAttr;
- typeLib.GetLibAttr(out pLibAttr);
- try
+ using (var attrScope = typeLib.CreateAttrScope())
{
- var typeLibAttr = (TYPELIBATTR)Marshal.PtrToStructure(pLibAttr, typeof(TYPELIBATTR));
-
string name;
string codeBase;
- if (GetPrimaryInteropAssembly(typeLibAttr.guid, typeLibAttr.wMajorVerNum, typeLibAttr.wMinorVerNum, out name, out codeBase))
+ if (GetPrimaryInteropAssembly(attrScope.Value.guid, attrScope.Value.wMajorVerNum, attrScope.Value.wMinorVerNum, out name, out codeBase))
{
return Assembly.Load(new AssemblyName(name) { CodeBase = codeBase });
}
}
- finally
- {
- typeLib.ReleaseTLibAttr(pLibAttr);
- }
}
catch (Exception)
{
@@ -283,70 +271,6 @@ private static bool GetPrimaryInteropAssembly(Guid libid, int major, int minor,
return name != null;
}
- 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 typeLib.GetName();
- }
-
#region Nested type: IProvideClassInfo
[ComImport]
diff --git a/ClearScript/Util/Test/AccessContextTestObject.cs b/ClearScript/Util/Test/AccessContextTestObject.cs
index 9340016e9..8c767c165 100644
--- a/ClearScript/Util/Test/AccessContextTestObject.cs
+++ b/ClearScript/Util/Test/AccessContextTestObject.cs
@@ -11,11 +11,11 @@ internal class AccessContextTestBase
// ReSharper disable EventNeverSubscribedTo.Local
// ReSharper disable UnusedType.Local
- public AccessContextTestBase() { }
- internal AccessContextTestBase(int arg) { }
- protected AccessContextTestBase(string arg) { }
- protected internal AccessContextTestBase(DateTime arg) { }
- private AccessContextTestBase(TimeSpan arg) { }
+ public AccessContextTestBase() {}
+ internal AccessContextTestBase(int arg) {}
+ protected AccessContextTestBase(string arg) {}
+ protected internal AccessContextTestBase(DateTime arg) {}
+ private AccessContextTestBase(TimeSpan arg) {}
public event EventHandler PublicEvent;
internal event EventHandler InternalEvent;
@@ -29,11 +29,11 @@ private AccessContextTestBase(TimeSpan arg) { }
protected internal string ProtectedInternalField;
private string privateField;
- public void PublicMethod() { }
- internal void InternalMethod() { }
- protected void ProtectedMethod() { }
- protected internal void ProtectedInternalMethod() { }
- private void PrivateMethod() { }
+ public void PublicMethod() {}
+ internal void InternalMethod() {}
+ protected void ProtectedMethod() {}
+ protected internal void ProtectedInternalMethod() {}
+ private void PrivateMethod() {}
public string PublicProperty { get; set; }
internal string InternalProperty { get; set; }
@@ -41,11 +41,11 @@ private void PrivateMethod() { }
protected internal string ProtectedInternalProperty { get; set; }
private string PrivateProperty { get; set; }
- public class PublicNestedType { }
- internal sealed class InternalNestedType { }
- protected class ProtectedNestedType { }
- protected internal sealed class ProtectedInternalNestedType { }
- private sealed class PrivateNestedType { }
+ public class PublicNestedType {}
+ internal sealed class InternalNestedType {}
+ protected class ProtectedNestedType {}
+ protected internal sealed class ProtectedInternalNestedType {}
+ private sealed class PrivateNestedType {}
// ReSharper restore UnusedType.Local
// ReSharper restore EventNeverSubscribedTo.Local
diff --git a/ClearScript/Util/TypeHelpers.NetCore.cs b/ClearScript/Util/TypeHelpers.NetCore.cs
index 48511a434..6bb7920fb 100644
--- a/ClearScript/Util/TypeHelpers.NetCore.cs
+++ b/ClearScript/Util/TypeHelpers.NetCore.cs
@@ -3,7 +3,6 @@
using System;
using System.Reflection;
-using System.Runtime.InteropServices.ComTypes;
namespace Microsoft.ClearScript.Util
{
@@ -40,14 +39,9 @@ private static string GetFullTypeName(string name, string assemblyName, bool use
return fullTypeName;
}
- public static IntPtr GetITypeInfo(this Type type)
+ public static IntPtr GetTypeInfo(this Type type)
{
return IntPtr.Zero;
}
-
- public static Type GetManagedType(this ITypeInfo typeInfo)
- {
- return null;
- }
}
}
diff --git a/ClearScript/Util/TypeHelpers.NetFramework.cs b/ClearScript/Util/TypeHelpers.NetFramework.cs
index 05de7540b..3636ada08 100644
--- a/ClearScript/Util/TypeHelpers.NetFramework.cs
+++ b/ClearScript/Util/TypeHelpers.NetFramework.cs
@@ -25,7 +25,7 @@ private static string GetFullTypeName(string name, string assemblyName, bool use
return fullTypeName;
}
- public static IntPtr GetITypeInfo(this Type type)
+ public static IntPtr GetTypeInfo(this Type type)
{
return Marshal.GetITypeInfoForType(type);
}
diff --git a/ClearScript/Util/TypeHelpers.cs b/ClearScript/Util/TypeHelpers.cs
index 0553cd83d..4d5e48eb4 100644
--- a/ClearScript/Util/TypeHelpers.cs
+++ b/ClearScript/Util/TypeHelpers.cs
@@ -324,6 +324,23 @@ public static bool IsFriendOf(this Type type, Type thatType)
return type.Assembly.IsFriendOf(thatType.Assembly);
}
+ public static bool IsCOMVisible(this Type type)
+ {
+ var attribute = type.GetAttribute(false);
+ if (attribute != null)
+ {
+ return attribute.Value;
+ }
+
+ attribute = type.Assembly.GetAttribute(false);
+ if (attribute != null)
+ {
+ return attribute.Value;
+ }
+
+ return false;
+ }
+
public static string GetRootName(this Type type)
{
return StripGenericSuffix(type.Name);
diff --git a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj
index 29794eb04..d579065c3 100644
--- a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj
+++ b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj
@@ -293,7 +293,7 @@
-
+
Document
copy "%(FullPath)" "$(OutDir)"
copy "%(FullPath)" "$(OutDir)"
@@ -302,7 +302,7 @@
$(OutDir)%(Filename)%(Extension)
$(OutDir)%(Filename)%(Extension)
-
+
Document
copy "%(FullPath)" "$(OutDir)"
copy "%(FullPath)" "$(OutDir)"
diff --git a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters
index d1ea11a2f..62774b1c4 100644
--- a/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters
+++ b/ClearScript/V8/ClearScriptV8/32/ClearScriptV8-32.vcxproj.filters
@@ -210,7 +210,7 @@
-
-
+
+
\ 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 a9a94ec09..e4d415881 100644
--- a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj
+++ b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj
@@ -88,11 +88,13 @@
true
true
false
+ -d2FH4- %(AdditionalOptions)
DebugFull
true
$(SolutionDir)ClearScript\V8\V8\lib\v8-x64.dll.lib
+ -d2:-FH4- %(AdditionalOptions)
$(SolutionDir)\ClearScript\Exports
@@ -119,6 +121,7 @@
true
Speed
true
+ -d2FH4- %(AdditionalOptions)
DebugFull
@@ -127,6 +130,7 @@
UseLinkTimeCodeGeneration
true
true
+ -d2:-FH4- %(AdditionalOptions)
$(SolutionDir)\ClearScript\Exports
@@ -294,7 +298,7 @@
-
+
Document
copy "%(FullPath)" "$(OutDir)"
copy "%(FullPath)" "$(OutDir)"
@@ -303,7 +307,7 @@
$(OutDir)%(Filename)%(Extension)
$(OutDir)%(Filename)%(Extension)
-
+
Document
copy "%(FullPath)" "$(OutDir)"
copy "%(FullPath)" "$(OutDir)"
diff --git a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters
index bac751a9b..27d121740 100644
--- a/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters
+++ b/ClearScript/V8/ClearScriptV8/64/ClearScriptV8-64.vcxproj.filters
@@ -210,7 +210,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h b/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h
index 2881d31b6..b2f62ffc8 100644
--- a/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h
+++ b/ClearScript/V8/ClearScriptV8/ClearScriptV8Native.h
@@ -31,4 +31,3 @@
#include "V8ObjectHolderImpl.h"
#include "V8ScriptHolderImpl.h"
#include "HighResolutionClock.h"
-#include "CallbackManager.h"
\ No newline at end of file
diff --git a/ClearScript/V8/ClearScriptV8/CommonPlatform.h b/ClearScript/V8/ClearScriptV8/CommonPlatform.h
index d58751bdd..d4874a93f 100644
--- a/ClearScript/V8/ClearScriptV8/CommonPlatform.h
+++ b/ClearScript/V8/ClearScriptV8/CommonPlatform.h
@@ -8,6 +8,7 @@
//-----------------------------------------------------------------------------
#include
+#include
#include
#include
#include
diff --git a/ClearScript/V8/ClearScriptV8/SharedPtr.h b/ClearScript/V8/ClearScriptV8/SharedPtr.h
index 42ab88b4c..03890cbad 100644
--- a/ClearScript/V8/ClearScriptV8/SharedPtr.h
+++ b/ClearScript/V8/ClearScriptV8/SharedPtr.h
@@ -95,6 +95,9 @@ class SharedPtrTraits final
template
class SharedPtr final
{
+ template
+ friend class SharedPtr;
+
public:
SharedPtr()
@@ -179,14 +182,56 @@ class SharedPtr final
return m_pTarget;
}
- operator T*() const
+ T& operator*() const
{
- return m_pTarget;
+ _ASSERTE(m_pTarget != nullptr);
+ return *m_pTarget;
}
- T* GetRawPtr() const
+ template
+ TOther& DerefAs() const
{
- return m_pTarget;
+ _ASSERTE(m_pTarget != nullptr);
+ return *static_cast(m_pTarget);
+ }
+
+ bool operator==(nullptr_t) const
+ {
+ return IsEmpty();
+ }
+
+ bool operator==(T* pThat) const
+ {
+ return m_pTarget == pThat;
+ }
+
+ template
+ bool operator==(const SharedPtr& that) const
+ {
+ return m_pTarget == that.m_pTarget;
+ }
+
+ bool operator!=(nullptr_t) const
+ {
+ return !operator==(nullptr);
+ }
+
+ bool operator!=(T* pThat) const
+ {
+ return !operator==(pThat);
+ }
+
+ template
+ bool operator!=(const SharedPtr& that) const
+ {
+ return !operator==(that);
+ }
+
+ template
+ SharedPtr CastTo() const
+ {
+ AddRef();
+ return SharedPtr(static_cast(m_pTarget), m_pRefCount);
}
bool IsEmpty() const
@@ -257,7 +302,7 @@ class SharedPtr final
MoveInitialize(that);
}
- void AddRef()
+ void AddRef() const
{
if (m_pTarget != nullptr)
{
diff --git a/ClearScript/V8/ClearScriptV8/V8Context.cpp b/ClearScript/V8/ClearScriptV8/V8Context.cpp
index ee9ea78ae..d12e02826 100644
--- a/ClearScript/V8/ClearScriptV8/V8Context.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8Context.cpp
@@ -9,7 +9,7 @@
V8Context* V8Context::Create(const SharedPtr& spIsolate, const StdString& name, const Options& options)
{
- return new V8ContextImpl(static_cast(spIsolate.GetRawPtr()), name, options);
+ return new V8ContextImpl(spIsolate.CastTo(), name, options);
}
//-----------------------------------------------------------------------------
diff --git a/ClearScript/V8/ClearScriptV8/V8Context.h b/ClearScript/V8/ClearScriptV8/V8Context.h
index 64a4cc1fa..8b0feed96 100644
--- a/ClearScript/V8/ClearScriptV8/V8Context.h
+++ b/ClearScript/V8/ClearScriptV8/V8Context.h
@@ -51,8 +51,8 @@ class V8Context: public WeakRefTarget, public IV8Entity
virtual V8ScriptHolder* Compile(const V8DocumentInfo& documentInfo, StdString&& code) = 0;
virtual V8ScriptHolder* Compile(const V8DocumentInfo& documentInfo, StdString&& code, V8CacheType cacheType, std::vector& cacheBytes) = 0;
virtual V8ScriptHolder* Compile(const V8DocumentInfo& documentInfo, StdString&& code, V8CacheType cacheType, const std::vector& cacheBytes, bool& cacheAccepted) = 0;
- virtual bool CanExecute(V8ScriptHolder* pHolder) = 0;
- virtual V8Value Execute(V8ScriptHolder* pHolder, bool evaluate) = 0;
+ virtual bool CanExecute(const SharedPtr& spHolder) = 0;
+ virtual V8Value Execute(const SharedPtr& spHolder, bool evaluate) = 0;
virtual void Interrupt() = 0;
virtual void GetIsolateHeapStatistics(v8::HeapStatistics& heapStatistics) = 0;
diff --git a/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp b/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp
index a673dccac..bd4dd220a 100644
--- a/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8ContextImpl.cpp
@@ -120,7 +120,7 @@ static V8ContextImpl* GetContextImplFromData(const TInfo& info)
#define BEGIN_ISOLATE_SCOPE \
{ \
__pragma(warning(disable:4456)) /* declaration hides previous local declaration */ \
- V8IsolateImpl::Scope t_IsolateScope(m_spIsolateImpl); \
+ V8IsolateImpl::Scope t_IsolateScope(*m_spIsolateImpl); \
__pragma(warning(default:4456))
#define END_ISOLATE_SCOPE \
@@ -169,8 +169,8 @@ static V8ContextImpl* GetContextImplFromData(const TInfo& info)
#define BEGIN_EXECUTION_SCOPE \
{ \
__pragma(warning(disable:4456)) /* declaration hides previous local declaration */ \
- V8IsolateImpl::ExecutionScope t_ExecutionScope(m_spIsolateImpl); \
- V8IsolateImpl::TryCatch t_TryCatch(m_spIsolateImpl); \
+ V8IsolateImpl::ExecutionScope t_ExecutionScope(*m_spIsolateImpl); \
+ V8IsolateImpl::TryCatch t_TryCatch(*m_spIsolateImpl); \
__pragma(warning(default:4456))
#define END_EXECUTION_SCOPE \
@@ -184,7 +184,7 @@ static V8ContextImpl* GetContextImplFromData(const TInfo& info)
#define BEGIN_DOCUMENT_SCOPE(DOCUMENT_INFO) \
{ \
__pragma(warning(disable:4456)) /* declaration hides previous local declaration */ \
- V8IsolateImpl::DocumentScope t_DocumentScope(m_spIsolateImpl, DOCUMENT_INFO); \
+ V8IsolateImpl::DocumentScope t_DocumentScope(*m_spIsolateImpl, DOCUMENT_INFO); \
__pragma(warning(default:4456))
#define END_DOCUMENT_SCOPE \
@@ -214,15 +214,15 @@ static const size_t s_MaxModuleCacheSize = 1024;
//-----------------------------------------------------------------------------
V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name):
- V8ContextImpl(pIsolateImpl, name, Options())
+ V8ContextImpl(SharedPtr(pIsolateImpl), name, Options())
{
}
//-----------------------------------------------------------------------------
-V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name, const Options& options):
+V8ContextImpl::V8ContextImpl(SharedPtr&& spIsolateImpl, const StdString& name, const Options& options):
m_Name(name),
- m_spIsolateImpl(pIsolateImpl),
+ m_spIsolateImpl(std::move(spIsolateImpl)),
m_DateTimeConversionEnabled(options.EnableDateTimeConversion),
m_pvV8ObjectCache(nullptr),
m_AllowHostObjectConstructorCall(false)
@@ -539,7 +539,7 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
auto codeDigest = code.GetDigest();
v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(code)), CreateScriptOrigin(documentInfo));
- std::unique_ptr spScriptHolder;
+ std::unique_ptr upScriptHolder;
if (documentInfo.IsModule())
{
@@ -555,7 +555,7 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
CacheModule(documentInfo, codeDigest, hModule);
}
- spScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hModule)), documentInfo, codeDigest, std::move(code)));
+ upScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hModule)), documentInfo, codeDigest, std::move(code)));
}
else
{
@@ -571,10 +571,10 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
CacheScript(documentInfo, codeDigest, hScript);
}
- spScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hScript)), documentInfo, codeDigest));
+ upScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hScript)), documentInfo, codeDigest));
}
- return spScriptHolder.release();
+ return upScriptHolder.release();
FROM_MAYBE_CATCH
@@ -603,8 +603,8 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
auto codeDigest = code.GetDigest();
v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(code)), CreateScriptOrigin(documentInfo));
- std::unique_ptr spScriptHolder;
- UniqueDeletePtr spCachedData;
+ std::unique_ptr upScriptHolder;
+ UniqueDeletePtr upCachedData;
if (documentInfo.IsModule())
{
@@ -620,8 +620,8 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
CacheModule(documentInfo, codeDigest, hModule);
}
- spScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hModule)), documentInfo, codeDigest, std::move(code)));
- spCachedData.reset(v8::ScriptCompiler::CreateCodeCache(hModule->GetUnboundModuleScript()));
+ upScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hModule)), documentInfo, codeDigest, std::move(code)));
+ upCachedData.reset(v8::ScriptCompiler::CreateCodeCache(hModule->GetUnboundModuleScript()));
}
else
{
@@ -637,23 +637,23 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
CacheScript(documentInfo, codeDigest, hScript);
}
- spScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hScript)), documentInfo, codeDigest));
- spCachedData.reset(v8::ScriptCompiler::CreateCodeCache(hScript));
+ upScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hScript)), documentInfo, codeDigest));
+ upCachedData.reset(v8::ScriptCompiler::CreateCodeCache(hScript));
}
cacheBytes.clear();
- if (spCachedData && (spCachedData->length > 0) && (spCachedData->data != nullptr))
+ if (upCachedData && (upCachedData->length > 0) && (upCachedData->data != nullptr))
{
- cacheBytes.resize(spCachedData->length);
- memcpy_s(&cacheBytes[0], cacheBytes.size(), spCachedData->data, spCachedData->length);
+ cacheBytes.resize(upCachedData->length);
+ memcpy_s(&cacheBytes[0], cacheBytes.size(), upCachedData->data, upCachedData->length);
if (documentInfo.IsModule())
{
- spScriptHolder->SetCacheBytes(cacheBytes);
+ upScriptHolder->SetCacheBytes(cacheBytes);
}
}
- return spScriptHolder.release();
+ return upScriptHolder.release();
FROM_MAYBE_CATCH
@@ -683,7 +683,7 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
auto codeDigest = code.GetDigest();
auto pCachedData = new v8::ScriptCompiler::CachedData(&cacheBytes[0], static_cast(cacheBytes.size()), v8::ScriptCompiler::CachedData::BufferNotOwned);
v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(code)), CreateScriptOrigin(documentInfo), pCachedData);
- std::unique_ptr spScriptHolder;
+ std::unique_ptr upScriptHolder;
if (documentInfo.IsModule())
{
@@ -699,7 +699,7 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
CacheModule(documentInfo, codeDigest, hModule);
}
- spScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hModule)), documentInfo, codeDigest, std::move(code)));
+ upScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hModule)), documentInfo, codeDigest, std::move(code)));
}
else
{
@@ -715,16 +715,16 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
CacheScript(documentInfo, codeDigest, hScript);
}
- spScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hScript)), documentInfo, codeDigest));
+ upScriptHolder.reset(new V8ScriptHolderImpl(GetWeakBinding(), ::PtrFromHandle(CreatePersistent(hScript)), documentInfo, codeDigest));
}
cacheAccepted = !pCachedData->rejected;
if (cacheAccepted && documentInfo.IsModule())
{
- spScriptHolder->SetCacheBytes(cacheBytes);
+ upScriptHolder->SetCacheBytes(cacheBytes);
}
- return spScriptHolder.release();
+ return upScriptHolder.release();
FROM_MAYBE_CATCH
@@ -738,38 +738,38 @@ V8ScriptHolder* V8ContextImpl::Compile(const V8DocumentInfo& documentInfo, StdSt
//-----------------------------------------------------------------------------
-bool V8ContextImpl::CanExecute(V8ScriptHolder* pHolder)
+bool V8ContextImpl::CanExecute(const SharedPtr& spHolder)
{
- return pHolder->IsSameIsolate(m_spIsolateImpl.GetRawPtr());
+ return spHolder->IsSameIsolate(m_spIsolateImpl);
}
//-----------------------------------------------------------------------------
-V8Value V8ContextImpl::Execute(V8ScriptHolder* pHolder, bool evaluate)
+V8Value V8ContextImpl::Execute(const SharedPtr& spHolder, bool evaluate)
{
BEGIN_CONTEXT_SCOPE
- BEGIN_DOCUMENT_SCOPE(pHolder->GetDocumentInfo())
+ BEGIN_DOCUMENT_SCOPE(spHolder->GetDocumentInfo())
BEGIN_EXECUTION_SCOPE
FROM_MAYBE_TRY
v8::Local hResult;
- if (pHolder->GetDocumentInfo().IsModule())
+ if (spHolder->GetDocumentInfo().IsModule())
{
- auto codeDigest = pHolder->GetCode().GetDigest();
- auto hModule = GetCachedModule(pHolder->GetDocumentInfo(), codeDigest);
+ auto codeDigest = spHolder->GetCode().GetDigest();
+ auto hModule = GetCachedModule(spHolder->GetDocumentInfo(), codeDigest);
if (hModule.IsEmpty())
{
- if (pHolder->GetCacheBytes().size() > 0)
+ if (spHolder->GetCacheBytes().size() > 0)
{
- auto pCachedData = new v8::ScriptCompiler::CachedData(&pHolder->GetCacheBytes()[0], static_cast(pHolder->GetCacheBytes().size()), v8::ScriptCompiler::CachedData::BufferNotOwned);
- v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(pHolder->GetCode())), CreateScriptOrigin(pHolder->GetDocumentInfo()), pCachedData);
+ auto pCachedData = new v8::ScriptCompiler::CachedData(&spHolder->GetCacheBytes()[0], static_cast(spHolder->GetCacheBytes().size()), v8::ScriptCompiler::CachedData::BufferNotOwned);
+ v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(spHolder->GetCode())), CreateScriptOrigin(spHolder->GetDocumentInfo()), pCachedData);
hModule = VERIFY_MAYBE(CompileModule(&source));
_ASSERTE(!pCachedData->rejected);
}
else
{
- v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(pHolder->GetCode())), CreateScriptOrigin(pHolder->GetDocumentInfo()));
+ v8::ScriptCompiler::Source source(FROM_MAYBE(CreateString(spHolder->GetCode())), CreateScriptOrigin(spHolder->GetDocumentInfo()));
hModule = VERIFY_MAYBE(CompileModule(&source));
}
@@ -778,7 +778,7 @@ V8Value V8ContextImpl::Execute(V8ScriptHolder* pHolder, bool evaluate)
throw V8Exception(V8Exception::Type::General, m_Name, StdString(L"Module compilation failed; no additional information was provided by the V8 runtime"), false /*executionStarted*/);
}
- CacheModule(pHolder->GetDocumentInfo(), codeDigest, hModule);
+ CacheModule(spHolder->GetDocumentInfo(), codeDigest, hModule);
}
if (hModule->GetStatus() < v8::Module::kInstantiated)
@@ -797,7 +797,7 @@ V8Value V8ContextImpl::Execute(V8ScriptHolder* pHolder, bool evaluate)
}
else
{
- auto hScript = ::HandleFromPtr(pHolder->GetScript());
+ auto hScript = ::HandleFromPtr(spHolder->GetScript());
hResult = VERIFY_MAYBE(hScript->BindToCurrentContext()->Run(m_hContext));
}
@@ -922,7 +922,7 @@ void V8ContextImpl::Flush()
void V8ContextImpl::Destroy()
{
- m_spIsolateImpl->CallWithLockNoWait([this] (V8IsolateImpl* /*pIsolateImpl*/)
+ m_spIsolateImpl->CallWithLockNoWait(true /*allowNesting*/, [this] (V8IsolateImpl* /*pIsolateImpl*/)
{
delete this;
});
@@ -1259,13 +1259,13 @@ void V8ContextImpl::InitializeImportMeta(v8::Local /*hContext*/, v8
v8::MaybeLocal V8ContextImpl::ImportModule(v8::Local /*hReferrer*/, v8::Local hSpecifier)
{
- V8IsolateImpl::TryCatch outerTryCatch(m_spIsolateImpl);
+ V8IsolateImpl::TryCatch outerTryCatch(*m_spIsolateImpl);
FROM_MAYBE_TRY
auto hResolver = FROM_MAYBE(v8::Promise::Resolver::New(m_hContext));
- V8IsolateImpl::TryCatch innerTryCatch(m_spIsolateImpl);
+ V8IsolateImpl::TryCatch innerTryCatch(*m_spIsolateImpl);
FROM_MAYBE_TRY
@@ -1302,7 +1302,7 @@ v8::MaybeLocal V8ContextImpl::ImportModule(v8::Local V8ContextImpl::ResolveModule(v8::Local hSpecifier, v8::Local /*hReferrer*/)
{
- V8IsolateImpl::TryCatch tryCatch(m_spIsolateImpl);
+ V8IsolateImpl::TryCatch tryCatch(*m_spIsolateImpl);
FROM_MAYBE_TRY
diff --git a/ClearScript/V8/ClearScriptV8/V8ContextImpl.h b/ClearScript/V8/ClearScriptV8/V8ContextImpl.h
index dc7fbb77f..1c8b26707 100644
--- a/ClearScript/V8/ClearScriptV8/V8ContextImpl.h
+++ b/ClearScript/V8/ClearScriptV8/V8ContextImpl.h
@@ -20,7 +20,7 @@ class V8ContextImpl final: public V8Context
public:
V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name);
- V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name, const Options& options);
+ V8ContextImpl(SharedPtr&& spIsolateImpl, const StdString& name, const Options& options);
static size_t GetInstanceCount();
const StdString& GetName() const { return m_Name; }
@@ -45,8 +45,8 @@ class V8ContextImpl final: public V8Context
virtual V8ScriptHolder* Compile(const V8DocumentInfo& documentInfo, StdString&& code) override;
virtual V8ScriptHolder* Compile(const V8DocumentInfo& documentInfo, StdString&& code, V8CacheType cacheType, std::vector& cacheBytes) override;
virtual V8ScriptHolder* Compile(const V8DocumentInfo& documentInfo, StdString&& code, V8CacheType cacheType, const std::vector& cacheBytes, bool& cacheAccepted) override;
- virtual bool CanExecute(V8ScriptHolder* pHolder) override;
- virtual V8Value Execute(V8ScriptHolder* pHolder, bool evaluate) override;
+ virtual bool CanExecute(const SharedPtr& spHolder) override;
+ virtual V8Value Execute(const SharedPtr& spHolder, bool evaluate) override;
virtual void Interrupt() override;
virtual void GetIsolateHeapStatistics(v8::HeapStatistics& heapStatistics) override;
diff --git a/ClearScript/V8/ClearScriptV8/V8ContextProxyImpl.cpp b/ClearScript/V8/ClearScriptV8/V8ContextProxyImpl.cpp
index 6c53ffb94..99fc98126 100644
--- a/ClearScript/V8/ClearScriptV8/V8ContextProxyImpl.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8ContextProxyImpl.cpp
@@ -299,9 +299,25 @@ namespace V8 {
auto statistics = GetContext()->GetIsolateStatistics();
auto gcStatistics = gcnew V8Runtime::Statistics;
+
gcStatistics->ScriptCount = statistics.ScriptCount;
gcStatistics->ScriptCacheSize = statistics.ScriptCacheSize;
gcStatistics->ModuleCount = statistics.ModuleCount;
+
+ auto size = static_cast(statistics.PostedTaskCounts.size());
+ gcStatistics->PostedTaskCounts = gcnew array(size);
+ for (auto index = 0; index < size; index++)
+ {
+ gcStatistics->PostedTaskCounts[index] = statistics.PostedTaskCounts[index];
+ }
+
+ size = static_cast(statistics.InvokedTaskCounts.size());
+ gcStatistics->InvokedTaskCounts = gcnew array(size);
+ for (auto index = 0; index < size; index++)
+ {
+ gcStatistics->InvokedTaskCounts[index] = statistics.InvokedTaskCounts[index];
+ }
+
return gcStatistics;
}
diff --git a/ClearScript/V8/ClearScriptV8/V8Isolate.h b/ClearScript/V8/ClearScriptV8/V8Isolate.h
index 9582e12d5..7df84bebb 100644
--- a/ClearScript/V8/ClearScriptV8/V8Isolate.h
+++ b/ClearScript/V8/ClearScriptV8/V8Isolate.h
@@ -11,6 +11,17 @@ class V8Isolate: public WeakRefTarget, public IV8Entity
{
public:
+ enum class TaskKind: uint16_t
+ {
+ Worker,
+ DelayedWorker,
+ Foreground,
+ DelayedForeground,
+ NonNestableForeground,
+ NonNestableDelayedForeground,
+ Count
+ };
+
struct Options final
{
bool EnableDebugging = false;
@@ -21,9 +32,23 @@ class V8Isolate: public WeakRefTarget, public IV8Entity
struct Statistics final
{
+ using TaskCounts = std::array(TaskKind::Count)>;
+
+ void BumpPostedTaskCount(TaskKind kind)
+ {
+ ++PostedTaskCounts[static_cast(kind)];
+ }
+
+ void BumpInvokedTaskCount(TaskKind kind)
+ {
+ ++InvokedTaskCounts[static_cast(kind)];
+ }
+
size_t ScriptCount = 0;
size_t ScriptCacheSize = 0;
size_t ModuleCount = 0;
+ TaskCounts PostedTaskCounts = {};
+ TaskCounts InvokedTaskCounts = {};
};
static V8Isolate* Create(const StdString& name, const v8::ResourceConstraints* pConstraints, const Options& options);
diff --git a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp
index 396351287..01b93e824 100644
--- a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp
+++ b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.cpp
@@ -7,7 +7,7 @@
// V8Platform
//-----------------------------------------------------------------------------
-class V8Platform final: public v8::SafePlatform
+class V8Platform final: public v8::Platform
{
public:
@@ -15,11 +15,9 @@ class V8Platform final: public v8::SafePlatform
static void EnsureInstalled();
virtual int NumberOfWorkerThreads() override;
- virtual v8::TaskRunner* CreateForegroundTaskRunner(v8::Isolate* pIsolate) override;
- virtual void CallOnWorkerThread(std::unique_ptr spTask) override;
- virtual void CallDelayedOnWorkerThread(std::unique_ptr spTask, double delayInSeconds) override;
- virtual void CallOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask) override;
- virtual void CallDelayedOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask, double delayInSeconds) override;
+ virtual std::shared_ptr GetForegroundTaskRunner(v8::Isolate* pIsolate) override;
+ virtual void CallOnWorkerThread(std::unique_ptr upTask) override;
+ virtual void CallDelayedOnWorkerThread(std::unique_ptr upTask, double delayInSeconds) override;
virtual double MonotonicallyIncreasingTime() override;
virtual double CurrentClockTimeMillis() override;
virtual v8::TracingController* GetTracingController() override;
@@ -46,7 +44,7 @@ void V8Platform::EnsureInstalled()
{
ms_InstallationFlag.CallOnce([]
{
- v8::SafePlatform::Initialize(ms_Instance);
+ v8::V8::InitializePlatform(&ms_Instance);
ASSERT_EVAL(v8::V8::Initialize());
});
}
@@ -60,53 +58,39 @@ int V8Platform::NumberOfWorkerThreads()
//-----------------------------------------------------------------------------
-v8::TaskRunner* V8Platform::CreateForegroundTaskRunner(v8::Isolate* pIsolate)
+std::shared_ptr V8Platform::GetForegroundTaskRunner(v8::Isolate* pIsolate)
{
- return V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->CreateForegroundTaskRunner();
+ return V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->GetForegroundTaskRunner();
}
//-----------------------------------------------------------------------------
-void V8Platform::CallOnWorkerThread(std::unique_ptr spTask)
+void V8Platform::CallOnWorkerThread(std::unique_ptr upTask)
{
auto pIsolate = v8::Isolate::GetCurrent();
if (pIsolate == nullptr)
{
- spTask->Run();
+ upTask->Run();
}
else
{
- V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->RunTaskAsync(spTask.release());
+ V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->RunTaskAsync(std::move(upTask));
}
}
//-----------------------------------------------------------------------------
-void V8Platform::CallDelayedOnWorkerThread(std::unique_ptr spTask, double delayInSeconds)
+void V8Platform::CallDelayedOnWorkerThread(std::unique_ptr upTask, double delayInSeconds)
{
auto pIsolate = v8::Isolate::GetCurrent();
if (pIsolate != nullptr)
{
- V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->RunTaskDelayed(spTask.release(), delayInSeconds);
+ V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->RunTaskDelayed(std::move(upTask), delayInSeconds);
}
}
//-----------------------------------------------------------------------------
-void V8Platform::CallOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask)
-{
- V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->RunTaskWithLockAsync(pTask);
-}
-
-//-----------------------------------------------------------------------------
-
-void V8Platform::CallDelayedOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask, double delayInSeconds)
-{
- V8IsolateImpl::GetInstanceFromIsolate(pIsolate)->RunTaskWithLockDelayed(pTask, delayInSeconds);
-}
-
-//-----------------------------------------------------------------------------
-
double V8Platform::MonotonicallyIncreasingTime()
{
return HighResolutionClock::GetRelativeSeconds();
@@ -149,10 +133,14 @@ class V8ForegroundTaskRunner final: public v8::TaskRunner
V8ForegroundTaskRunner(V8IsolateImpl* pIsolateImpl);
- virtual void PostTask(std::unique_ptr spTask) override;
- virtual void PostDelayedTask(std::unique_ptr spTask, double delayInSeconds) override;
- virtual void PostIdleTask(std::unique_ptr spTask) override;
+ virtual void PostTask(std::unique_ptr upTask) override;
+ virtual void PostNonNestableTask(std::unique_ptr upTask) override;
+ virtual void PostDelayedTask(std::unique_ptr upTask, double delayInSeconds) override;
+ virtual void PostNonNestableDelayedTask(std::unique_ptr upTask, double delayInSeconds) override;
+ virtual void PostIdleTask(std::unique_ptr upTask) override;
virtual bool IdleTasksEnabled() override;
+ virtual bool NonNestableTasksEnabled() const override;
+ virtual bool NonNestableDelayedTasksEnabled() const override;
private:
@@ -170,33 +158,55 @@ V8ForegroundTaskRunner::V8ForegroundTaskRunner(V8IsolateImpl* pIsolateImpl):
//-----------------------------------------------------------------------------
-void V8ForegroundTaskRunner::PostTask(std::unique_ptr spTask)
+void V8ForegroundTaskRunner::PostTask(std::unique_ptr upTask)
{
auto spIsolate = m_wrIsolate.GetTarget();
if (spIsolate.IsEmpty())
{
- spTask->Run();
+ upTask->Run();
}
else
{
- m_pIsolateImpl->RunTaskWithLockAsync(spTask.release());
+ m_pIsolateImpl->RunTaskWithLockAsync(true /*allowNesting*/, std::move(upTask));
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void V8ForegroundTaskRunner::PostNonNestableTask(std::unique_ptr upTask)
+{
+ auto spIsolate = m_wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
+ {
+ m_pIsolateImpl->RunTaskWithLockAsync(false /*allowNesting*/, std::move(upTask));
}
}
//-----------------------------------------------------------------------------
-void V8ForegroundTaskRunner::PostDelayedTask(std::unique_ptr spTask, double delayInSeconds)
+void V8ForegroundTaskRunner::PostDelayedTask(std::unique_ptr upTask, double delayInSeconds)
{
auto spIsolate = m_wrIsolate.GetTarget();
if (!spIsolate.IsEmpty())
{
- m_pIsolateImpl->RunTaskWithLockDelayed(spTask.release(), delayInSeconds);
+ m_pIsolateImpl->RunTaskWithLockDelayed(true /*allowNesting*/, std::move(upTask), delayInSeconds);
}
}
//-----------------------------------------------------------------------------
-void V8ForegroundTaskRunner::PostIdleTask(std::unique_ptr spTask)
+void V8ForegroundTaskRunner::PostNonNestableDelayedTask(std::unique_ptr upTask, double delayInSeconds)
+{
+ auto spIsolate = m_wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
+ {
+ m_pIsolateImpl->RunTaskWithLockDelayed(false /*allowNesting*/, std::move(upTask), delayInSeconds);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void V8ForegroundTaskRunner::PostIdleTask(std::unique_ptr upTask)
{
// unexpected call to unsupported method
std::terminate();
@@ -209,6 +219,20 @@ bool V8ForegroundTaskRunner::IdleTasksEnabled()
return false;
}
+//-----------------------------------------------------------------------------
+
+bool V8ForegroundTaskRunner::NonNestableTasksEnabled() const
+{
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool V8ForegroundTaskRunner::NonNestableDelayedTasksEnabled() const
+{
+ return true;
+}
+
//-----------------------------------------------------------------------------
// V8ArrayBufferAllocator
//-----------------------------------------------------------------------------
@@ -275,7 +299,7 @@ V8ArrayBufferAllocator V8ArrayBufferAllocator::ms_Instance;
#define BEGIN_ISOLATE_NATIVE_SCOPE \
{ \
__pragma(warning(disable:4456)) /* declaration hides previous local declaration */ \
- NativeScope t_IsolateNativeScope(this); \
+ NativeScope t_IsolateNativeScope(*this); \
__pragma(warning(default:4456))
#define END_ISOLATE_NATIVE_SCOPE \
@@ -285,7 +309,7 @@ V8ArrayBufferAllocator V8ArrayBufferAllocator::ms_Instance;
#define BEGIN_ISOLATE_SCOPE \
{ \
__pragma(warning(disable:4456)) /* declaration hides previous local declaration */ \
- Scope t_IsolateScope(this); \
+ Scope t_IsolateScope(*this); \
__pragma(warning(default:4456))
#define END_ISOLATE_SCOPE \
@@ -304,6 +328,7 @@ static const size_t s_MaxScriptCacheSize = 256;
V8IsolateImpl::V8IsolateImpl(const StdString& name, const v8::ResourceConstraints* pConstraints, const Options& options):
m_Name(name),
+ m_CallWithLockLevel(0),
m_DebuggingEnabled(false),
m_AwaitingDebugger(false),
m_InMessageLoop(false),
@@ -331,19 +356,19 @@ V8IsolateImpl::V8IsolateImpl(const StdString& name, const v8::ResourceConstraint
params.constraints.set_max_old_space_size(pConstraints->max_old_space_size());
}
- m_spIsolate.reset(v8::Isolate::Allocate());
- m_spIsolate->SetData(0, this);
+ m_upIsolate.reset(v8::Isolate::Allocate());
+ m_upIsolate->SetData(0, this);
BEGIN_ADDREF_SCOPE
- v8::Isolate::Initialize(m_spIsolate.get(), params);
+ v8::Isolate::Initialize(m_upIsolate.get(), params);
- m_spIsolate->AddBeforeCallEnteredCallback(OnBeforeCallEntered);
- m_spIsolate->SetPromiseHook(PromiseHook);
+ m_upIsolate->AddBeforeCallEnteredCallback(OnBeforeCallEntered);
+ m_upIsolate->SetPromiseHook(PromiseHook);
BEGIN_ISOLATE_SCOPE
- m_spIsolate->SetCaptureStackTraceForUncaughtExceptions(true, 64, v8::StackTrace::kDetailed);
+ m_upIsolate->SetCaptureStackTraceForUncaughtExceptions(true, 64, v8::StackTrace::kDetailed);
m_hHostObjectHolderKey = CreatePersistent(CreatePrivate());
@@ -352,10 +377,10 @@ V8IsolateImpl::V8IsolateImpl(const StdString& name, const v8::ResourceConstraint
EnableDebugging(options.DebugPort, options.EnableRemoteDebugging);
}
- m_spIsolate->SetHostInitializeImportMetaObjectCallback(ImportMetaInitializeCallback);
+ m_upIsolate->SetHostInitializeImportMetaObjectCallback(ImportMetaInitializeCallback);
if (options.EnableDynamicModuleImports)
{
- m_spIsolate->SetHostImportModuleDynamicallyCallback(ModuleImportCallback);
+ m_upIsolate->SetHostImportModuleDynamicallyCallback(ModuleImportCallback);
}
END_ISOLATE_SCOPE
@@ -369,6 +394,7 @@ V8IsolateImpl::V8IsolateImpl(const StdString& name, const v8::ResourceConstraint
V8IsolateImpl* V8IsolateImpl::GetInstanceFromIsolate(v8::Isolate* pIsolate)
{
+ _ASSERTE(pIsolate);
return static_cast(pIsolate->GetData(0));
}
@@ -397,12 +423,12 @@ void V8IsolateImpl::AddContext(V8ContextImpl* pContextImpl, const V8Context::Opt
if (options.EnableDynamicModuleImports)
{
- m_spIsolate->SetHostImportModuleDynamicallyCallback(ModuleImportCallback);
+ m_upIsolate->SetHostImportModuleDynamicallyCallback(ModuleImportCallback);
}
- if (m_spInspector)
+ if (m_upInspector)
{
- m_spInspector->contextCreated(v8_inspector::V8ContextInfo(pContextImpl->GetContext(), s_ContextGroupId, pContextImpl->GetName().GetStringView()));
+ m_upInspector->contextCreated(v8_inspector::V8ContextInfo(pContextImpl->GetContext(), s_ContextGroupId, pContextImpl->GetName().GetStringView()));
}
}
@@ -412,9 +438,9 @@ void V8IsolateImpl::RemoveContext(V8ContextImpl* pContextImpl)
{
_ASSERTE(IsCurrent() && IsLocked());
- if (m_spInspector)
+ if (m_upInspector)
{
- m_spInspector->contextDestroyed(pContextImpl->GetContext());
+ m_upInspector->contextDestroyed(pContextImpl->GetContext());
}
m_ContextEntries.remove_if([pContextImpl] (const ContextEntry& contextEntry)
@@ -477,7 +503,7 @@ void V8IsolateImpl::EnableDebugging(int port, bool remote)
}
});
- m_spInspector.reset(v8_inspector::V8Inspector::createPtr(m_spIsolate.get(), this));
+ m_upInspector = v8_inspector::V8Inspector::create(m_upIsolate.get(), this);
m_DebuggingEnabled = true;
m_DebugPort = port;
@@ -492,8 +518,8 @@ void V8IsolateImpl::DisableDebugging()
if (m_DebuggingEnabled)
{
- m_spInspectorSession.reset();
- m_spInspector.reset();
+ m_upInspectorSession.reset();
+ m_upInspector.reset();
HostObjectHelpers::DestroyDebugAgent(m_pvDebugAgent);
m_DebuggingEnabled = false;
@@ -551,16 +577,16 @@ void V8IsolateImpl::AwaitDebuggerAndPause()
if (m_DebuggingEnabled)
{
- if (!m_spInspectorSession && !RunMessageLoop(true))
+ if (!m_upInspectorSession && !RunMessageLoop(true))
{
throw V8Exception(V8Exception::Type::Interrupt, m_Name, StdString(L"Script execution interrupted by host while awaiting debugger connection"), false);
}
- _ASSERTE(m_spInspectorSession);
- if (m_spInspectorSession)
+ _ASSERTE(m_upInspectorSession);
+ if (m_upInspectorSession)
{
StdString breakReason(L"Break on debugger connection");
- m_spInspectorSession->schedulePauseOnNextStatement(breakReason.GetStringView(), breakReason.GetStringView());
+ m_upInspectorSession->schedulePauseOnNextStatement(breakReason.GetStringView(), breakReason.GetStringView());
}
}
@@ -609,7 +635,7 @@ void V8IsolateImpl::GetHeapStatistics(v8::HeapStatistics& heapStatistics)
{
BEGIN_ISOLATE_SCOPE
- m_spIsolate->GetHeapStatistics(&heapStatistics);
+ m_upIsolate->GetHeapStatistics(&heapStatistics);
END_ISOLATE_SCOPE
}
@@ -619,9 +645,11 @@ void V8IsolateImpl::GetHeapStatistics(v8::HeapStatistics& heapStatistics)
V8Isolate::Statistics V8IsolateImpl::GetStatistics()
{
BEGIN_ISOLATE_SCOPE
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
return m_Statistics;
+ END_MUTEX_SCOPE
END_ISOLATE_SCOPE
}
@@ -650,9 +678,9 @@ bool V8IsolateImpl::BeginCpuProfile(const StdString& name, v8::CpuProfilingMode
{
BEGIN_ISOLATE_SCOPE
- if (!m_spCpuProfiler)
+ if (!m_upCpuProfiler)
{
- m_spCpuProfiler.reset(v8::CpuProfiler::New(m_spIsolate.get()));
+ m_upCpuProfiler.reset(v8::CpuProfiler::New(m_upIsolate.get()));
}
v8::Local hName;
@@ -661,7 +689,7 @@ bool V8IsolateImpl::BeginCpuProfile(const StdString& name, v8::CpuProfilingMode
return false;
}
- m_spCpuProfiler->StartProfiling(hName, mode, recordSamples);
+ m_upCpuProfiler->StartProfiling(hName, mode, recordSamples);
return true;
END_ISOLATE_SCOPE
@@ -673,7 +701,7 @@ bool V8IsolateImpl::EndCpuProfile(const StdString& name, CpuProfileCallbackT* pC
{
BEGIN_ISOLATE_SCOPE
- if (!m_spCpuProfiler)
+ if (!m_upCpuProfiler)
{
return false;
}
@@ -684,15 +712,15 @@ bool V8IsolateImpl::EndCpuProfile(const StdString& name, CpuProfileCallbackT* pC
return false;
}
- UniqueDeletePtr spProfile(m_spCpuProfiler->StopProfiling(hName));
- if (!spProfile)
+ UniqueDeletePtr upProfile(m_upCpuProfiler->StopProfiling(hName));
+ if (!upProfile)
{
return false;
}
if (pCallback)
{
- pCallback(*spProfile, pvArg);
+ pCallback(*upProfile, pvArg);
}
return true;
@@ -706,7 +734,7 @@ void V8IsolateImpl::CollectCpuProfileSample()
{
BEGIN_ISOLATE_SCOPE
- v8::CpuProfiler::CollectSample(m_spIsolate.get());
+ v8::CpuProfiler::CollectSample(m_upIsolate.get());
END_ISOLATE_SCOPE
}
@@ -726,14 +754,14 @@ void V8IsolateImpl::SetCpuProfileSampleInterval(uint32_t value)
if (value != m_CpuProfileSampleInterval)
{
- m_CpuProfileSampleInterval = std::min(std::max(value, 250U), static_cast(INT_MAX));
+ m_CpuProfileSampleInterval = std::min(std::max(value, 125U), static_cast(INT_MAX));
- if (!m_spCpuProfiler)
+ if (!m_upCpuProfiler)
{
- m_spCpuProfiler.reset(v8::CpuProfiler::New(m_spIsolate.get()));
+ m_upCpuProfiler.reset(v8::CpuProfiler::New(m_upIsolate.get()));
}
- m_spCpuProfiler->SetSamplingInterval(static_cast(m_CpuProfileSampleInterval));
+ m_upCpuProfiler->SetSamplingInterval(static_cast(m_CpuProfileSampleInterval));
}
END_ISOLATE_SCOPE
@@ -787,21 +815,21 @@ double V8IsolateImpl::currentTimeMS()
//-----------------------------------------------------------------------------
-void V8IsolateImpl::sendResponse(int /*callId*/, std::unique_ptr spMessage)
+void V8IsolateImpl::sendResponse(int /*callId*/, std::unique_ptr upMessage)
{
_ASSERTE(IsCurrent() && IsLocked());
if (m_pvDebugAgent)
{
- HostObjectHelpers::SendDebugMessage(m_pvDebugAgent, StdString(spMessage->string()));
+ HostObjectHelpers::SendDebugMessage(m_pvDebugAgent, StdString(upMessage->string()));
}
}
//-----------------------------------------------------------------------------
-void V8IsolateImpl::sendNotification(std::unique_ptr spMessage)
+void V8IsolateImpl::sendNotification(std::unique_ptr upMessage)
{
- sendResponse(0, std::move(spMessage));
+ sendResponse(0, std::move(upMessage));
}
//-----------------------------------------------------------------------------
@@ -825,7 +853,7 @@ void* V8IsolateImpl::AddRefV8Object(void* pvObject)
void V8IsolateImpl::ReleaseV8Object(void* pvObject)
{
- CallWithLockNoWait([pvObject] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockNoWait(true /*allowNesting*/, [pvObject] (V8IsolateImpl* pIsolateImpl)
{
pIsolateImpl->Dispose(::HandleFromPtr(pvObject));
});
@@ -846,7 +874,7 @@ void* V8IsolateImpl::AddRefV8Script(void* pvScript)
void V8IsolateImpl::ReleaseV8Script(void* pvScript)
{
- CallWithLockNoWait([pvScript] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockNoWait(true /*allowNesting*/, [pvScript] (V8IsolateImpl* pIsolateImpl)
{
pIsolateImpl->Dispose(::HandleFromPtr(pvScript));
});
@@ -854,84 +882,82 @@ void V8IsolateImpl::ReleaseV8Script(void* pvScript)
//-----------------------------------------------------------------------------
-void V8IsolateImpl::RunTaskAsync(v8::Task* pTask)
+void V8IsolateImpl::RunTaskAsync(std::unique_ptr upTask)
{
- if (m_Released)
- {
- pTask->Run();
- delete pTask;
- }
- else
+ if (upTask)
{
- std::shared_ptr spTask(pTask);
- std::weak_ptr wpTask(spTask);
+ if (m_Released)
+ {
+ upTask->Run();
+ }
+ else
+ {
+ std::shared_ptr spTask(std::move(upTask));
+ std::weak_ptr wpTask(spTask);
- BEGIN_MUTEX_SCOPE(m_DataMutex)
- m_AsyncTasks.push_back(std::move(spTask));
- END_MUTEX_SCOPE
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
+ m_AsyncTasks.push_back(std::move(spTask));
+ m_Statistics.BumpPostedTaskCount(TaskKind::Worker);
+ END_MUTEX_SCOPE
- auto wrIsolate = CreateWeakRef();
- HostObjectHelpers::QueueNativeCallback([this, wrIsolate, wpTask] ()
- {
- auto spIsolate = wrIsolate.GetTarget();
- if (!spIsolate.IsEmpty())
+ auto wrIsolate = CreateWeakRef();
+ HostObjectHelpers::QueueNativeCallback([this, wrIsolate, wpTask] ()
{
- auto spTask = wpTask.lock();
- if (spTask)
+ auto spIsolate = wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
{
- spTask->Run();
+ auto spTask = wpTask.lock();
+ if (spTask)
+ {
+ spTask->Run();
- BEGIN_MUTEX_SCOPE(m_DataMutex)
- auto it = std::remove(m_AsyncTasks.begin(), m_AsyncTasks.end(), spTask);
- m_AsyncTasks.erase(it, m_AsyncTasks.end());
- END_MUTEX_SCOPE
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
+ auto it = std::remove(m_AsyncTasks.begin(), m_AsyncTasks.end(), spTask);
+ m_AsyncTasks.erase(it, m_AsyncTasks.end());
+ m_Statistics.BumpInvokedTaskCount(TaskKind::Worker);
+ END_MUTEX_SCOPE
+ }
}
- }
- });
+ });
+ }
}
}
//-----------------------------------------------------------------------------
-void V8IsolateImpl::RunTaskDelayed(v8::Task* pTask, double delayInSeconds)
+void V8IsolateImpl::RunTaskDelayed(std::unique_ptr upTask, double delayInSeconds)
{
- if (m_Released)
- {
- delete pTask;
- }
- else
+ if (upTask && !m_Released)
{
- std::shared_ptr spTask(pTask);
+ std::shared_ptr spTask(std::move(upTask));
auto wrIsolate = CreateWeakRef();
SharedPtr spTimer(new Timer(static_cast(delayInSeconds * 1000), -1, [this, wrIsolate, spTask] (Timer* pTimer) mutable
{
- if (spTask)
+ auto spIsolate = wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
{
- auto spIsolate = wrIsolate.GetTarget();
- if (!spIsolate.IsEmpty())
- {
- spTask->Run();
+ spTask->Run();
- // Release the timer's strong task reference. Doing so avoids a deadlock when
- // spIsolate's implicit destruction below triggers immediate isolate teardown.
+ // Release the timer's strong task reference. Doing so avoids a deadlock when
+ // spIsolate's implicit destruction below triggers immediate isolate teardown.
- spTask.reset();
+ spTask.reset();
- // the timer has fired; discard it
+ // the timer has fired; discard it
- BEGIN_MUTEX_SCOPE(m_DataMutex)
- auto it = std::remove(m_TaskTimers.begin(), m_TaskTimers.end(), pTimer);
- m_TaskTimers.erase(it, m_TaskTimers.end());
- END_MUTEX_SCOPE
- }
- else
- {
- // Release the timer's strong task reference. Doing so avoids a deadlock if the
- // isolate is awaiting task completion on the managed finalization thread.
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
+ auto it = std::remove(m_TaskTimers.begin(), m_TaskTimers.end(), SharedPtr(pTimer));
+ m_TaskTimers.erase(it, m_TaskTimers.end());
+ m_Statistics.BumpInvokedTaskCount(TaskKind::DelayedWorker);
+ END_MUTEX_SCOPE
+ }
+ else
+ {
+ // Release the timer's strong task reference. Doing so avoids a deadlock if the
+ // isolate is awaiting task completion on the managed finalization thread.
- spTask.reset();
- }
+ spTask.reset();
}
}));
@@ -939,6 +965,7 @@ void V8IsolateImpl::RunTaskDelayed(v8::Task* pTask, double delayInSeconds)
BEGIN_MUTEX_SCOPE(m_DataMutex)
m_TaskTimers.push_back(spTimer);
+ m_Statistics.BumpPostedTaskCount(TaskKind::DelayedWorker);
END_MUTEX_SCOPE
// Release the local task reference explicitly. Doing so avoids a deadlock if the callback is
@@ -954,67 +981,77 @@ void V8IsolateImpl::RunTaskDelayed(v8::Task* pTask, double delayInSeconds)
//-----------------------------------------------------------------------------
-void V8IsolateImpl::RunTaskWithLockAsync(v8::Task* pTask)
+void V8IsolateImpl::RunTaskWithLockAsync(bool allowNesting, std::unique_ptr upTask)
{
- if (m_Released)
+ if (upTask)
{
- pTask->Run();
- delete pTask;
- }
- else
- {
- std::shared_ptr spTask(pTask);
- CallWithLockAsync([spTask] (V8IsolateImpl* /*pIsolateImpl*/)
+ if (m_Released)
{
- spTask->Run();
- });
+ if (allowNesting)
+ {
+ upTask->Run();
+ }
+ }
+ else
+ {
+ std::shared_ptr spTask(std::move(upTask));
+ CallWithLockAsync(allowNesting, [allowNesting, spTask] (V8IsolateImpl* pIsolateImpl)
+ {
+ spTask->Run();
+
+ BEGIN_MUTEX_SCOPE(pIsolateImpl->m_DataMutex)
+ pIsolateImpl->m_Statistics.BumpInvokedTaskCount(allowNesting ? TaskKind::Foreground : TaskKind::NonNestableForeground);
+ END_MUTEX_SCOPE
+ });
+
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
+ m_Statistics.BumpPostedTaskCount(allowNesting ? TaskKind::Foreground : TaskKind::NonNestableForeground);
+ END_MUTEX_SCOPE
+ }
}
}
//-----------------------------------------------------------------------------
-void V8IsolateImpl::RunTaskWithLockDelayed(v8::Task* pTask, double delayInSeconds)
+void V8IsolateImpl::RunTaskWithLockDelayed(bool allowNesting, std::unique_ptr upTask, double delayInSeconds)
{
- if (m_Released)
+ if (upTask && !m_Released)
{
- delete pTask;
- }
- else
- {
- std::shared_ptr spTask(pTask);
+ std::shared_ptr spTask(std::move(upTask));
auto wrIsolate = CreateWeakRef();
- SharedPtr spTimer(new Timer(static_cast(delayInSeconds * 1000), -1, [this, wrIsolate, spTask] (Timer* pTimer) mutable
+ SharedPtr spTimer(new Timer(static_cast(delayInSeconds * 1000), -1, [this, wrIsolate, allowNesting, spTask] (Timer* pTimer) mutable
{
- if (spTask)
+ auto spIsolate = wrIsolate.GetTarget();
+ if (!spIsolate.IsEmpty())
{
- auto spIsolate = wrIsolate.GetTarget();
- if (!spIsolate.IsEmpty())
+ CallWithLockNoWait(allowNesting, [allowNesting, spTask] (V8IsolateImpl* pIsolateImpl)
{
- CallWithLockNoWait([spTask] (V8IsolateImpl* /*pIsolateImpl*/)
- {
- spTask->Run();
- });
+ spTask->Run();
- // Release the timer's strong task reference. Doing so avoids a deadlock when
- // spIsolate's implicit destruction below triggers immediate isolate teardown.
+ BEGIN_MUTEX_SCOPE(pIsolateImpl->m_DataMutex)
+ pIsolateImpl->m_Statistics.BumpInvokedTaskCount(allowNesting ? TaskKind::DelayedForeground : TaskKind::NonNestableDelayedForeground);
+ END_MUTEX_SCOPE
+ });
- spTask.reset();
+ // Release the timer's strong task reference. Doing so avoids a deadlock when
+ // spIsolate's implicit destruction below triggers immediate isolate teardown.
- // the timer has fired; discard it
+ spTask.reset();
- BEGIN_MUTEX_SCOPE(m_DataMutex)
- auto it = std::remove(m_TaskTimers.begin(), m_TaskTimers.end(), pTimer);
- m_TaskTimers.erase(it, m_TaskTimers.end());
- END_MUTEX_SCOPE
- }
- else
- {
- // Release the timer's strong task reference. Doing so avoids a deadlock if the
- // isolate is awaiting task completion on the managed finalization thread.
+ // the timer has fired; discard it
- spTask.reset();
- }
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
+ auto it = std::remove(m_TaskTimers.begin(), m_TaskTimers.end(), pTimer);
+ m_TaskTimers.erase(it, m_TaskTimers.end());
+ END_MUTEX_SCOPE
+ }
+ else
+ {
+ // Release the timer's strong task reference. Doing so avoids a deadlock if the
+ // isolate is awaiting task completion on the managed finalization thread.
+
+ spTask.reset();
}
}));
@@ -1022,6 +1059,7 @@ void V8IsolateImpl::RunTaskWithLockDelayed(v8::Task* pTask, double delayInSecond
BEGIN_MUTEX_SCOPE(m_DataMutex)
m_TaskTimers.push_back(spTimer);
+ m_Statistics.BumpPostedTaskCount(allowNesting ? TaskKind::DelayedForeground : TaskKind::NonNestableDelayedForeground);
END_MUTEX_SCOPE
// Release the local task reference explicitly. Doing so avoids a deadlock if the callback is
@@ -1037,28 +1075,46 @@ void V8IsolateImpl::RunTaskWithLockDelayed(v8::Task* pTask, double delayInSecond
//-----------------------------------------------------------------------------
-v8::TaskRunner* V8IsolateImpl::CreateForegroundTaskRunner()
+std::shared_ptr V8IsolateImpl::GetForegroundTaskRunner()
{
- return new V8ForegroundTaskRunner(this);
+ BEGIN_MUTEX_SCOPE(m_DataMutex)
+
+ if (!m_spForegroundTaskRunner)
+ {
+ m_spForegroundTaskRunner = std::make_shared(this);
+ }
+
+ return m_spForegroundTaskRunner;
+
+ END_MUTEX_SCOPE
}
//-----------------------------------------------------------------------------
-void V8IsolateImpl::CallWithLockNoWait(std::function&& callback)
+void V8IsolateImpl::CallWithLockNoWait(bool allowNesting, CallWithLockCallback&& callback)
{
- if (m_Mutex.TryLock())
+ if (callback)
{
- // the callback may release this instance; hold it for destruction outside isolate scope
- SharedPtr spThis(this);
+ if (m_Mutex.TryLock())
+ {
+ // the callback may release this instance; hold it for destruction outside isolate scope
+ SharedPtr spThis(this);
- MutexLock lock(m_Mutex, false);
- BEGIN_ISOLATE_NATIVE_SCOPE
- callback(this);
- END_ISOLATE_NATIVE_SCOPE
- }
- else
- {
- CallWithLockAsync(std::move(callback));
+ MutexLock lock(m_Mutex, false);
+ if (allowNesting || (m_CallWithLockLevel < 1))
+ {
+ BEGIN_ISOLATE_NATIVE_SCOPE
+ BEGIN_PULSE_VALUE_SCOPE(&m_CallWithLockLevel, m_CallWithLockLevel + 1)
+
+ callback(this);
+ return;
+
+ END_PULSE_VALUE_SCOPE
+ END_ISOLATE_NATIVE_SCOPE
+ }
+ }
+
+ CallWithLockAsync(allowNesting, std::move(callback));
}
}
@@ -1222,10 +1278,10 @@ V8IsolateImpl::~V8IsolateImpl()
}
Dispose(m_hHostObjectHolderKey);
- m_spIsolate->SetHostImportModuleDynamicallyCallback(nullptr);
- m_spIsolate->SetHostInitializeImportMetaObjectCallback(nullptr);
- m_spIsolate->SetPromiseHook(nullptr);
- m_spIsolate->RemoveBeforeCallEnteredCallback(OnBeforeCallEntered);
+ m_upIsolate->SetHostImportModuleDynamicallyCallback(nullptr);
+ m_upIsolate->SetHostInitializeImportMetaObjectCallback(nullptr);
+ m_upIsolate->SetPromiseHook(nullptr);
+ m_upIsolate->RemoveBeforeCallEnteredCallback(OnBeforeCallEntered);
}
//-----------------------------------------------------------------------------
@@ -1269,13 +1325,13 @@ bool V8IsolateImpl::RunMessageLoop(bool awaitingDebugger)
//-----------------------------------------------------------------------------
-void V8IsolateImpl::CallWithLockAsync(std::function&& callback)
+void V8IsolateImpl::CallWithLockAsync(bool allowNesting, CallWithLockCallback&& callback)
{
if (callback)
{
BEGIN_MUTEX_SCOPE(m_DataMutex)
- m_CallWithLockQueue.push(std::move(callback));
+ m_CallWithLockQueue.push(std::make_pair(allowNesting, std::move(callback)));
if (m_InMessageLoop)
{
@@ -1328,70 +1384,89 @@ void V8IsolateImpl::ProcessCallWithLockQueue(v8::Isolate* /*pIsolate*/, void* pv
void V8IsolateImpl::ProcessCallWithLockQueue()
{
- std::queue> callWithLockQueue;
-
- while (true)
- {
- BEGIN_MUTEX_SCOPE(m_DataMutex)
- std::swap(callWithLockQueue, m_CallWithLockQueue);
- END_MUTEX_SCOPE
-
- if (callWithLockQueue.size() > 0)
- {
- ProcessCallWithLockQueue(callWithLockQueue);
- continue;
- }
-
- break;
- }
+ std::unique_lock lock(m_DataMutex.GetImpl());
+ ProcessCallWithLockQueue(lock);
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::ProcessCallWithLockQueue(std::unique_lock& lock)
{
+ _ASSERTE(lock.mutex() == &m_DataMutex.GetImpl());
_ASSERTE(lock.owns_lock());
- std::queue> callWithLockQueue(std::move(m_CallWithLockQueue));
+ CallWithLockQueue callWithLockQueue(PopCallWithLockQueue(lock));
while (callWithLockQueue.size() > 0)
{
lock.unlock();
ProcessCallWithLockQueue(callWithLockQueue);
lock.lock();
- callWithLockQueue = std::move(m_CallWithLockQueue);
+ callWithLockQueue = PopCallWithLockQueue(lock);
}
}
-
//-----------------------------------------------------------------------------
-void V8IsolateImpl::ProcessCallWithLockQueue(std::queue>& callWithLockQueue)
+void V8IsolateImpl::ProcessCallWithLockQueue(CallWithLockQueue& callWithLockQueue)
{
_ASSERTE(IsCurrent() && IsLocked());
- while (callWithLockQueue.size() > 0)
- {
- try
- {
- callWithLockQueue.front()(this);
- }
- catch (...)
+ BEGIN_PULSE_VALUE_SCOPE(&m_CallWithLockLevel, m_CallWithLockLevel + 1)
+
+ while (callWithLockQueue.size() > 0)
{
+ try
+ {
+ callWithLockQueue.front().second(this);
+ }
+ catch (...)
+ {
+ }
+
+ callWithLockQueue.pop();
}
- callWithLockQueue.pop();
+ END_PULSE_VALUE_SCOPE
+}
+
+//-----------------------------------------------------------------------------
+
+V8IsolateImpl::CallWithLockQueue V8IsolateImpl::PopCallWithLockQueue(const std::unique_lock& lock)
+{
+ _ASSERTE(IsCurrent() && IsLocked());
+ _ASSERTE(lock.mutex() == &m_DataMutex.GetImpl());
+ _ASSERTE(lock.owns_lock());
+ IGNORE_UNUSED(lock);
+
+ if (m_CallWithLockLevel < 1)
+ {
+ return std::move(m_CallWithLockQueue);
}
+
+ CallWithLockQueue nestableCallWithLockQueue;
+ CallWithLockQueue nonNestableCallWithLockQueue;
+
+ while (m_CallWithLockQueue.size() > 0)
+ {
+ auto& callWithLockEntry = m_CallWithLockQueue.front();
+ auto& callWithLockQueue = callWithLockEntry.first ? nestableCallWithLockQueue : nonNestableCallWithLockQueue;
+ callWithLockQueue.push(std::move(callWithLockEntry));
+ m_CallWithLockQueue.pop();
+ }
+
+ m_CallWithLockQueue = std::move(nonNestableCallWithLockQueue);
+ return nestableCallWithLockQueue;
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::ConnectDebugClient()
{
- CallWithLockNoWait([] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockNoWait(true /*allowNesting*/, [] (V8IsolateImpl* pIsolateImpl)
{
- if (pIsolateImpl->m_spInspector && !pIsolateImpl->m_spInspectorSession)
+ if (pIsolateImpl->m_upInspector && !pIsolateImpl->m_upInspectorSession)
{
- pIsolateImpl->m_spInspectorSession = pIsolateImpl->m_spInspector->connect(s_ContextGroupId, pIsolateImpl, v8_inspector::StringView());
+ pIsolateImpl->m_upInspectorSession = pIsolateImpl->m_upInspector->connect(s_ContextGroupId, pIsolateImpl, v8_inspector::StringView());
}
});
}
@@ -1400,11 +1475,11 @@ void V8IsolateImpl::ConnectDebugClient()
void V8IsolateImpl::SendDebugCommand(const StdString& command)
{
- CallWithLockNoWait([command] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockNoWait(true /*allowNesting*/, [command] (V8IsolateImpl* pIsolateImpl)
{
- if (pIsolateImpl->m_spInspectorSession)
+ if (pIsolateImpl->m_upInspectorSession)
{
- pIsolateImpl->m_spInspectorSession->dispatchProtocolMessage(command.GetStringView());
+ pIsolateImpl->m_upInspectorSession->dispatchProtocolMessage(command.GetStringView());
}
});
}
@@ -1413,9 +1488,9 @@ void V8IsolateImpl::SendDebugCommand(const StdString& command)
void V8IsolateImpl::DisconnectDebugClient()
{
- CallWithLockNoWait([] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockNoWait(true /*allowNesting*/, [] (V8IsolateImpl* pIsolateImpl)
{
- pIsolateImpl->m_spInspectorSession.reset();
+ pIsolateImpl->m_upInspectorSession.reset();
});
}
@@ -1475,7 +1550,7 @@ V8IsolateImpl::ExecutionScope* V8IsolateImpl::EnterExecutionScope(ExecutionScope
}
// set and record stack address limit
- m_spIsolate->SetStackLimit(reinterpret_cast(pStackLimit));
+ m_upIsolate->SetStackLimit(reinterpret_cast(pStackLimit));
m_pStackLimit = pStackLimit;
// enter outermost stack usage monitoring scope
@@ -1526,7 +1601,7 @@ void V8IsolateImpl::ExitExecutionScope(ExecutionScope* pPreviousExecutionScope)
if (m_pStackLimit != nullptr)
{
// V8 has no API for removing a stack address limit
- m_spIsolate->SetStackLimit(reinterpret_cast(s_pMinStackLimit));
+ m_upIsolate->SetStackLimit(reinterpret_cast(s_pMinStackLimit));
m_pStackLimit = nullptr;
}
}
@@ -1552,7 +1627,7 @@ void V8IsolateImpl::SetUpHeapWatchTimer(size_t maxHeapSize)
// create heap watch timer
auto wrIsolate = CreateWeakRef();
- m_spHeapWatchTimer = new Timer(static_cast(std::max(GetHeapSizeSampleInterval(), 250.0)), -1, [this, wrIsolate, maxHeapSize] (Timer* pTimer)
+ m_spHeapWatchTimer = new Timer(static_cast(std::max(GetHeapSizeSampleInterval(), 125.0)), -1, [this, wrIsolate, maxHeapSize] (Timer* pTimer)
{
// heap watch callback; is the isolate still alive?
auto spIsolate = wrIsolate.GetTarget();
@@ -1560,7 +1635,7 @@ void V8IsolateImpl::SetUpHeapWatchTimer(size_t maxHeapSize)
{
// yes; request callback on execution thread
auto wrTimer = pTimer->CreateWeakRef();
- CallWithLockAsync([wrTimer, maxHeapSize] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockAsync(true /*allowNesting*/, [wrTimer, maxHeapSize] (V8IsolateImpl* pIsolateImpl)
{
// execution thread callback; is the timer still alive?
auto spTimer = wrTimer.GetTarget();
@@ -1663,12 +1738,12 @@ void V8IsolateImpl::FlushContextAsync(ContextEntry& contextEntry)
if (contextEntry.FlushPending.compare_exchange_strong(expected, true))
{
auto wrContext = contextEntry.pContextImpl->CreateWeakRef();
- CallWithLockAsync([wrContext] (V8IsolateImpl* pIsolateImpl)
+ CallWithLockAsync(true /*allowNesting*/, [wrContext] (V8IsolateImpl* pIsolateImpl)
{
auto spContext = wrContext.GetTarget();
if (!spContext.IsEmpty())
{
- pIsolateImpl->FlushContext(static_cast(spContext.GetRawPtr()));
+ pIsolateImpl->FlushContext(spContext.DerefAs());
}
});
}
@@ -1676,18 +1751,18 @@ void V8IsolateImpl::FlushContextAsync(ContextEntry& contextEntry)
//-----------------------------------------------------------------------------
-void V8IsolateImpl::FlushContext(V8ContextImpl* pContextImpl)
+void V8IsolateImpl::FlushContext(V8ContextImpl& contextImpl)
{
_ASSERTE(IsCurrent() && IsLocked());
for (auto& contextEntry : m_ContextEntries)
{
- if (contextEntry.pContextImpl == pContextImpl)
+ if (contextEntry.pContextImpl == &contextImpl)
{
contextEntry.FlushPending = false;
break;
}
}
- pContextImpl->Flush();
+ contextImpl.Flush();
}
diff --git a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h
index e0d99913c..72b674723 100644
--- a/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h
+++ b/ClearScript/V8/ClearScriptV8/V8IsolateImpl.h
@@ -24,23 +24,23 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
public:
- explicit NativeScope(V8IsolateImpl* pIsolateImpl):
- m_pIsolateImpl(pIsolateImpl),
- m_LockScope(m_pIsolateImpl->m_spIsolate.get()),
- m_IsolateScope(m_pIsolateImpl->m_spIsolate.get()),
- m_HandleScope(m_pIsolateImpl->m_spIsolate.get())
+ explicit NativeScope(V8IsolateImpl& isolateImpl):
+ m_IsolateImpl(isolateImpl),
+ m_LockScope(m_IsolateImpl.m_upIsolate.get()),
+ m_IsolateScope(m_IsolateImpl.m_upIsolate.get()),
+ m_HandleScope(m_IsolateImpl.m_upIsolate.get())
{
- m_pIsolateImpl->ProcessCallWithLockQueue();
+ m_IsolateImpl.ProcessCallWithLockQueue();
}
~NativeScope()
{
- m_pIsolateImpl->ProcessCallWithLockQueue();
+ m_IsolateImpl.ProcessCallWithLockQueue();
}
private:
- V8IsolateImpl* m_pIsolateImpl;
+ V8IsolateImpl& m_IsolateImpl;
v8::Locker m_LockScope;
v8::Isolate::Scope m_IsolateScope;
v8::HandleScope m_HandleScope;
@@ -48,6 +48,8 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
public:
+ using CallWithLockCallback = std::function;
+
class Scope final
{
PROHIBIT_COPY(Scope)
@@ -55,9 +57,9 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
public:
- explicit Scope(V8IsolateImpl* pIsolateImpl):
- m_MutexLock(pIsolateImpl->m_Mutex),
- m_NativeScope(pIsolateImpl)
+ explicit Scope(V8IsolateImpl& isolateImpl):
+ m_MutexLock(isolateImpl.m_Mutex),
+ m_NativeScope(isolateImpl)
{
}
@@ -74,11 +76,11 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
public:
- explicit ExecutionScope(V8IsolateImpl* pIsolateImpl):
- m_pIsolateImpl(pIsolateImpl),
+ explicit ExecutionScope(V8IsolateImpl& isolateImpl):
+ m_IsolateImpl(isolateImpl),
m_ExecutionStarted(false)
{
- m_pPreviousExecutionScope = m_pIsolateImpl->EnterExecutionScope(this, reinterpret_cast(&pIsolateImpl));
+ m_pPreviousExecutionScope = m_IsolateImpl.EnterExecutionScope(this, reinterpret_cast(this));
}
void OnExecutionStarted()
@@ -93,12 +95,12 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
~ExecutionScope()
{
- m_pIsolateImpl->ExitExecutionScope(m_pPreviousExecutionScope);
+ m_IsolateImpl.ExitExecutionScope(m_pPreviousExecutionScope);
}
private:
- V8IsolateImpl* m_pIsolateImpl;
+ V8IsolateImpl& m_IsolateImpl;
ExecutionScope* m_pPreviousExecutionScope;
bool m_ExecutionStarted;
};
@@ -110,21 +112,21 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
public:
- DocumentScope(V8IsolateImpl* pIsolateImpl, const V8DocumentInfo& documentInfo):
- m_pIsolateImpl(pIsolateImpl)
+ DocumentScope(V8IsolateImpl& isolateImpl, const V8DocumentInfo& documentInfo):
+ m_IsolateImpl(isolateImpl)
{
- m_pPreviousDocumentInfo = m_pIsolateImpl->m_pDocumentInfo;
- m_pIsolateImpl->m_pDocumentInfo = &documentInfo;
+ m_pPreviousDocumentInfo = m_IsolateImpl.m_pDocumentInfo;
+ m_IsolateImpl.m_pDocumentInfo = &documentInfo;
}
~DocumentScope()
{
- m_pIsolateImpl->m_pDocumentInfo = m_pPreviousDocumentInfo;
+ m_IsolateImpl.m_pDocumentInfo = m_pPreviousDocumentInfo;
}
private:
- V8IsolateImpl* m_pIsolateImpl;
+ V8IsolateImpl& m_IsolateImpl;
const V8DocumentInfo* m_pPreviousDocumentInfo;
};
@@ -135,8 +137,8 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
public:
- explicit TryCatch(V8IsolateImpl* pIsolateImpl):
- v8::TryCatch(pIsolateImpl->m_spIsolate.get())
+ explicit TryCatch(V8IsolateImpl& isolateImpl):
+ v8::TryCatch(isolateImpl.m_upIsolate.get())
{
}
};
@@ -152,102 +154,102 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
v8::Local CreateContext(v8::ExtensionConfiguration* pExtensionConfiguation = nullptr, v8::Local hGlobalTemplate = v8::Local(), v8::Local hGlobalObject = v8::Local())
{
- return v8::Context::New(m_spIsolate.get(), pExtensionConfiguation, hGlobalTemplate, hGlobalObject);
+ return v8::Context::New(m_upIsolate.get(), pExtensionConfiguation, hGlobalTemplate, hGlobalObject);
}
v8::Local GetUndefined()
{
- return v8::Undefined(m_spIsolate.get());
+ return v8::Undefined(m_upIsolate.get());
}
v8::Local GetNull()
{
- return v8::Null(m_spIsolate.get());
+ return v8::Null(m_upIsolate.get());
}
v8::Local GetTrue()
{
- return v8::True(m_spIsolate.get());
+ return v8::True(m_upIsolate.get());
}
v8::Local GetFalse()
{
- return v8::False(m_spIsolate.get());
+ return v8::False(m_upIsolate.get());
}
bool BooleanValue(v8::Local hValue)
{
- return hValue->BooleanValue(m_spIsolate.get());
+ return hValue->BooleanValue(m_upIsolate.get());
}
v8::Local GetIteratorSymbol()
{
- return v8::Symbol::GetIterator(m_spIsolate.get());
+ return v8::Symbol::GetIterator(m_upIsolate.get());
}
v8::Local CreateObject()
{
- return v8::Object::New(m_spIsolate.get());
+ return v8::Object::New(m_upIsolate.get());
}
v8::Local CreateNumber(double value)
{
- return v8::Number::New(m_spIsolate.get(), value);
+ return v8::Number::New(m_upIsolate.get(), value);
}
v8::Local CreateInteger(int32_t value)
{
- return v8::Int32::New(m_spIsolate.get(), value);
+ return v8::Int32::New(m_upIsolate.get(), value);
}
v8::Local CreateInteger(uint32_t value)
{
- return v8::Uint32::NewFromUnsigned(m_spIsolate.get(), value);
+ return v8::Uint32::NewFromUnsigned(m_upIsolate.get(), value);
}
v8::MaybeLocal CreateString(const StdString& value, v8::NewStringType type = v8::NewStringType::kNormal)
{
- return value.ToV8String(m_spIsolate.get(), type);
+ return value.ToV8String(m_upIsolate.get(), type);
}
StdString CreateStdString(v8::Local hValue)
{
- return StdString(m_spIsolate.get(), hValue);
+ return StdString(m_upIsolate.get(), hValue);
}
v8::Local CreateSymbol(v8::Local hName = v8::Local())
{
- return v8::Symbol::New(m_spIsolate.get(), hName);
+ return v8::Symbol::New(m_upIsolate.get(), hName);
}
v8::Local CreatePrivate(v8::Local hName = v8::Local())
{
- return v8::Private::New(m_spIsolate.get(), hName);
+ return v8::Private::New(m_upIsolate.get(), hName);
}
v8::Local CreateArray(int length = 0)
{
- return v8::Array::New(m_spIsolate.get(), length);
+ return v8::Array::New(m_upIsolate.get(), length);
}
v8::Local CreateExternal(void* pvValue)
{
- return v8::External::New(m_spIsolate.get(), pvValue);
+ return v8::External::New(m_upIsolate.get(), pvValue);
}
v8::Local CreateObjectTemplate()
{
- return v8::ObjectTemplate::New(m_spIsolate.get());
+ return v8::ObjectTemplate::New(m_upIsolate.get());
}
v8::Local CreateFunctionTemplate(v8::FunctionCallback callback = 0, v8::Local data = v8::Local(), v8::Local signature = v8::Local(), int length = 0)
{
- return v8::FunctionTemplate::New(m_spIsolate.get(), callback, data, signature, length);
+ return v8::FunctionTemplate::New(m_upIsolate.get(), callback, data, signature, length);
}
v8::MaybeLocal CompileUnboundScript(v8::ScriptCompiler::Source* pSource, v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileOptions, v8::ScriptCompiler::NoCacheReason noCacheReason = v8::ScriptCompiler::kNoCacheNoReason)
{
- auto result = v8::ScriptCompiler::CompileUnboundScript(m_spIsolate.get(), pSource, options, noCacheReason);
+ auto result = v8::ScriptCompiler::CompileUnboundScript(m_upIsolate.get(), pSource, options, noCacheReason);
if (!result.IsEmpty())
{
@@ -259,7 +261,7 @@ class V8IsolateImpl final: public V8Isolate, public v8_inspector::V8InspectorCli
v8::MaybeLocal