Version 5.4.4: Added fast data transfer between host arrays and JavaScript typed arrays (and other ArrayBuffer views) (Issue #83); IEnumerable instances now support ES6 iteration and for...of when exposed in V8ScriptEngine; added fully dynamic treatment for exposed IDispatchEx instances (Issue #96); fixed host member enumeration and deletion on JScript with Standards Mode (Issue #94); improved numeric argument conversion and matching (Issue #95); fixed nested termination behavior on V8; added tests for bug fixes and new APIs. Tested with V8 4.7.80.25.

This commit is contained in:
ClearScript 2015-12-07 06:57:35 -05:00
Родитель ba8bf459e4
Коммит 4d6048f4be
71 изменённых файлов: 5909 добавлений и 510 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -27,6 +27,7 @@ obj/
_ReSharper*/
[Tt]est[Rr]esult*
*.sdf
*.opendb
*.opensdf
*.shfbproj_*
ClearScript/V8/V8/build/

Просмотреть файл

@ -1,5 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp40</s:String>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecpp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Eh/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToConditionalTernaryExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToNullCoalescingExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ImpureMethodCallOnReadonlyValueField/@EntryIndexedValue">DO_NOT_SHOW</s:String>

Просмотреть файл

@ -1,5 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp40</s:String>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecpp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Eh/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToConditionalTernaryExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToNullCoalescingExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ImpureMethodCallOnReadonlyValueField/@EntryIndexedValue">DO_NOT_SHOW</s:String>

Просмотреть файл

@ -69,6 +69,10 @@
<Compile Include="BindSignature.cs" />
<Compile Include="IScriptEngineException.cs" />
<Compile Include="DefaultScriptUsageAttribute.cs" />
<Compile Include="JavaScript\IArrayBuffer.cs" />
<Compile Include="JavaScript\IArrayBufferView.cs" />
<Compile Include="JavaScript\IDataView.cs" />
<Compile Include="JavaScript\ITypedArray.cs" />
<Compile Include="NoDefaultScriptAccessAttribute.cs" />
<Compile Include="NoScriptAccessAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
@ -97,7 +101,11 @@
<Compile Include="Util\Scope.cs" />
<Compile Include="Util\SocketHelpers.cs" />
<Compile Include="Util\SpecialDispIDs.cs" />
<Compile Include="Util\UnmanagedMemoryHelpers.cs" />
<Compile Include="Util\VTablePatcher.cs" />
<Compile Include="V8\IV8DebugListener.cs" />
<Compile Include="V8\V8ArrayBufferOrViewInfo.cs" />
<Compile Include="V8\V8ArrayBufferOrViewKind.cs" />
<Compile Include="V8\V8DebugAgent.cs" />
<Compile Include="V8\V8RuntimeHeapInfo.cs" />
<Compile Include="V8\V8Script.cs" />

Просмотреть файл

@ -63,5 +63,5 @@
#pragma once
#define CLEARSCRIPT_VERSION_STRING "5.4.3.0"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,4,3,0
#define CLEARSCRIPT_VERSION_STRING "5.4.4.0"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,4,4,0

Просмотреть файл

@ -343,7 +343,11 @@ namespace Microsoft.ClearScript
if (arg != null)
{
flags |= CSharpArgumentInfoFlags.UseCompileTimeType;
if (arg is IOutArg)
if (arg is int)
{
flags |= CSharpArgumentInfoFlags.Constant;
}
else if (arg is IOutArg)
{
flags |= CSharpArgumentInfoFlags.IsOut;
}

Просмотреть файл

@ -75,7 +75,7 @@ using Microsoft.ClearScript.Util;
namespace Microsoft.ClearScript
{
internal partial class HostItem : DynamicObject, IExpando, IDynamic, IEnumVARIANT, ICustomQueryInterface, IScriptMarshalWrapper, IHostInvokeContext
internal partial class HostItem : DynamicObject, IReflect, IDynamic, IEnumVARIANT, ICustomQueryInterface, IScriptMarshalWrapper, IHostInvokeContext
{
#region data
@ -87,6 +87,9 @@ namespace Microsoft.ClearScript
private ScriptAccess defaultAccess;
private HostTargetMemberData targetMemberData;
internal static bool EnableVTablePatching;
[ThreadStatic] private static bool bypassVTablePatching;
#endregion
#region constructors
@ -97,11 +100,7 @@ namespace Microsoft.ClearScript
this.target = target;
this.flags = flags;
if ((target is HostObject) || (target is IHostVariable) || (target is IByRefArg))
{
BindSpecialTarget();
}
BindSpecialTarget();
BindTargetMemberData();
var scriptableObject = target.Target as IScriptableObject;
@ -262,7 +261,7 @@ namespace Microsoft.ClearScript
#region interface accessors
private IExpando ThisExpando
private IReflect ThisReflect
{
get { return this; }
}
@ -431,34 +430,37 @@ namespace Microsoft.ClearScript
private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags)
{
return new HostItem(engine, target, flags);
return TargetSupportsExpandoMembers(target, flags) ? new ExpandoHostItem(engine, target, flags) : new HostItem(engine, target, flags);
}
private void BindSpecialTarget()
{
if (BindSpecialTarget(Collateral.TargetDynamic))
if (TargetSupportsSpecialTargets(target))
{
TargetPropertyBag = null;
TargetList = null;
TargetDynamicMetaObject = null;
}
else if (BindSpecialTarget(Collateral.TargetPropertyBag))
{
TargetList = null;
TargetDynamicMetaObject = null;
}
else
{
IDynamicMetaObjectProvider dynamicMetaObjectProvider;
if (!flags.HasFlag(HostItemFlags.HideDynamicMembers) && BindSpecialTarget(out dynamicMetaObjectProvider))
if (BindSpecialTarget(Collateral.TargetDynamic))
{
TargetDynamicMetaObject = dynamicMetaObjectProvider.GetMetaObject(Expression.Constant(target.InvokeTarget));
TargetPropertyBag = null;
TargetList = null;
TargetDynamicMetaObject = null;
}
else if (BindSpecialTarget(Collateral.TargetPropertyBag))
{
TargetList = null;
TargetDynamicMetaObject = null;
}
else
{
TargetDynamicMetaObject = null;
BindSpecialTarget(Collateral.TargetList);
IDynamicMetaObjectProvider dynamicMetaObjectProvider;
if (!flags.HasFlag(HostItemFlags.HideDynamicMembers) && BindSpecialTarget(out dynamicMetaObjectProvider))
{
TargetDynamicMetaObject = dynamicMetaObjectProvider.GetMetaObject(Expression.Constant(target.InvokeTarget));
TargetList = null;
}
else
{
TargetDynamicMetaObject = null;
BindSpecialTarget(Collateral.TargetList);
}
}
}
}
@ -478,6 +480,18 @@ namespace Microsoft.ClearScript
private bool BindSpecialTarget<T>(out T specialTarget) where T : class
{
// provide fully dynamic behavior for exposed IDispatchEx implementations
if (typeof(T) == typeof(IDynamic))
{
var dispatchEx = target.InvokeTarget as IDispatchEx;
if ((dispatchEx != null) && dispatchEx.GetType().IsCOMObject)
{
specialTarget = (T)(object)(new DynamicDispatchExWrapper(dispatchEx));
return true;
}
}
// The check here is required because the item may be bound to a specific target base
// class or interface - one that must not trigger special treatment.
@ -531,6 +545,57 @@ namespace Microsoft.ClearScript
}
}
private static bool TargetSupportsSpecialTargets(HostTarget target)
{
return (target is HostObject) || (target is IHostVariable) || (target is IByRefArg);
}
private static bool TargetSupportsExpandoMembers(HostTarget target, HostItemFlags flags)
{
if (!TargetSupportsSpecialTargets(target))
{
return false;
}
if (typeof(IDynamic).IsAssignableFrom(target.Type))
{
return true;
}
if (target is IHostVariable)
{
if (target.Type.IsImport)
{
return true;
}
}
else
{
var dispatchEx = target.InvokeTarget as IDispatchEx;
if ((dispatchEx != null) && dispatchEx.GetType().IsCOMObject)
{
return true;
}
}
if (typeof(IPropertyBag).IsAssignableFrom(target.Type))
{
return true;
}
if (!flags.HasFlag(HostItemFlags.HideDynamicMembers) && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(target.Type))
{
return true;
}
return false;
}
private bool CanAddExpandoMembers()
{
return (TargetDynamic != null) || ((TargetPropertyBag != null) && !TargetPropertyBag.IsReadOnly) || (TargetDynamicMetaObject != null);
}
#endregion
#region member data maintenance
@ -892,7 +957,7 @@ namespace Microsoft.ClearScript
{
if (invokeFlags.HasFlag(BindingFlags.GetField) && (args.Length < 1))
{
return TargetDynamic.GetProperty(name);
return TargetDynamic.GetProperty(name, args);
}
throw;
@ -901,16 +966,15 @@ namespace Microsoft.ClearScript
if (invokeFlags.HasFlag(BindingFlags.GetField))
{
return TargetDynamic.GetProperty(name);
return TargetDynamic.GetProperty(name, args);
}
if (invokeFlags.HasFlag(BindingFlags.SetField))
{
if (args.Length == 1)
if (args.Length > 0)
{
var value = args[0];
TargetDynamic.SetProperty(name, value);
return value;
TargetDynamic.SetProperty(name, args);
return args[args.Length - 1];
}
throw new InvalidOperationException("Invalid argument count");
@ -933,6 +997,11 @@ namespace Microsoft.ClearScript
throw new NotSupportedException("Object does not support invocation");
}
if (name == SpecialMemberNames.NewEnum)
{
return HostObject.Wrap(TargetPropertyBag.GetEnumerator(), typeof(IEnumerator));
}
object value;
if (!TargetPropertyBag.TryGetValue(name, out value))
{
@ -1121,11 +1190,18 @@ namespace Microsoft.ClearScript
IEnumerable enumerable;
if (BindSpecialTarget(out enumerable))
{
return HostObject.Wrap(enumerable.GetEnumerator(), typeof(IEnumerator));
var enumerationHelpersHostItem = Wrap(engine, EnumerationHelpers.HostType, HostItemFlags.PrivateAccess);
try
{
return ((IDynamic)enumerationHelpersHostItem).InvokeMethod("GetEnumerator", new object[] { this });
}
catch (MissingMemberException)
{
}
}
}
throw new NotSupportedException("Object is not a collection");
throw new NotSupportedException("Object is not enumerable");
}
if ((TargetDynamicMetaObject != null) && (TargetDynamicMetaObject.GetDynamicMemberNames().Contains(name)))
@ -1136,7 +1212,7 @@ namespace Microsoft.ClearScript
}
}
if (ThisExpando.GetMethods(GetMethodBindFlags()).Any(method => method.Name == name))
if (ThisReflect.GetMethods(GetMethodBindFlags()).Any(method => method.Name == name))
{
// The target appears to have a method with the right name, but it could be an
// extension method that fails to bind. If that happens, we should attempt the
@ -1286,7 +1362,7 @@ namespace Microsoft.ClearScript
return hostIndexedProperty;
}
var method = ThisExpando.GetMethods(GetMethodBindFlags()).FirstOrDefault(testMethod => testMethod.Name == name);
var method = ThisReflect.GetMethods(GetMethodBindFlags()).FirstOrDefault(testMethod => testMethod.Name == name);
if (method != null)
{
if (HostMethodMap == null)
@ -1443,13 +1519,13 @@ namespace Microsoft.ClearScript
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = ThisDynamic.GetProperty(binder.Name).ToDynamicResult(engine);
result = ThisDynamic.GetProperty(binder.Name, MiscHelpers.GetEmptyArray<object>()).ToDynamicResult(engine);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
ThisDynamic.SetProperty(binder.Name, value);
ThisDynamic.SetProperty(binder.Name, new[] { value });
return true;
}
@ -1461,12 +1537,16 @@ namespace Microsoft.ClearScript
if (MiscHelpers.TryGetIndex(indices[0], out index))
{
result = ThisDynamic.GetProperty(index).ToDynamicResult(engine);
}
else
{
result = ThisDynamic.GetProperty(indices[0].ToString()).ToDynamicResult(engine);
return true;
}
result = ThisDynamic.GetProperty(indices[0].ToString(), MiscHelpers.GetEmptyArray<object>()).ToDynamicResult(engine);
return true;
}
if (indices.Length > 1)
{
result = ThisDynamic.GetProperty(SpecialMemberNames.Default, indices);
return true;
}
@ -1481,15 +1561,18 @@ namespace Microsoft.ClearScript
if (MiscHelpers.TryGetIndex(indices[0], out index))
{
ThisDynamic.SetProperty(index, value);
}
else
{
ThisDynamic.SetProperty(indices[0].ToString(), value);
return true;
}
ThisDynamic.SetProperty(indices[0].ToString(), new[] { value });
return true;
}
if (indices.Length > 1)
{
ThisDynamic.SetProperty(SpecialMemberNames.Default, indices.Concat(new[] { value }).ToArray());
}
throw new InvalidOperationException("Invalid argument or index count");
}
@ -1526,7 +1609,7 @@ namespace Microsoft.ClearScript
FieldInfo IReflect.GetField(string name, BindingFlags bindFlags)
{
var fields = ThisExpando.GetFields(bindFlags).Where(field => field.Name == name).ToArray();
var fields = ThisReflect.GetFields(bindFlags).Where(field => field.Name == name).ToArray();
if (fields.Length < 1)
{
return null;
@ -1561,17 +1644,17 @@ namespace Microsoft.ClearScript
MemberInfo[] IReflect.GetMember(string name, BindingFlags bindFlags)
{
return ThisExpando.GetMembers(bindFlags).Where(member => member.Name == name).ToArray();
return ThisReflect.GetMembers(bindFlags).Where(member => member.Name == name).ToArray();
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindFlags)
{
return ThisExpando.GetFields(bindFlags).Cast<MemberInfo>().Concat(ThisExpando.GetMethods(bindFlags)).Concat(ThisExpando.GetProperties(bindFlags)).ToArray();
return ThisReflect.GetFields(bindFlags).Cast<MemberInfo>().Concat(ThisReflect.GetMethods(bindFlags)).Concat(ThisReflect.GetProperties(bindFlags)).ToArray();
}
MethodInfo IReflect.GetMethod(string name, BindingFlags bindFlags)
{
var methods = ThisExpando.GetMethods(bindFlags).Where(method => method.Name == name).ToArray();
var methods = ThisReflect.GetMethods(bindFlags).Where(method => method.Name == name).ToArray();
if (methods.Length < 1)
{
return null;
@ -1635,7 +1718,7 @@ namespace Microsoft.ClearScript
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindFlags)
{
var properties = ThisExpando.GetProperties(bindFlags).Where(property => property.Name == name).ToArray();
var properties = ThisReflect.GetProperties(bindFlags).Where(property => property.Name == name).ToArray();
if (properties.Length < 1)
{
return null;
@ -1661,99 +1744,21 @@ namespace Microsoft.ClearScript
#endregion
#region IExpando implementation
FieldInfo IExpando.AddField(string name)
{
return HostInvoke(() =>
{
if ((TargetDynamic != null) || ((TargetPropertyBag != null) && !TargetPropertyBag.IsReadOnly) || (TargetDynamicMetaObject != null))
{
AddExpandoMemberName(name);
return MemberMap.GetField(name);
}
throw new NotSupportedException("Object does not support dynamic fields");
});
}
PropertyInfo IExpando.AddProperty(string name)
{
return HostInvoke(() =>
{
if ((TargetDynamic != null) || ((TargetPropertyBag != null) && !TargetPropertyBag.IsReadOnly) || (TargetDynamicMetaObject != null))
{
AddExpandoMemberName(name);
return MemberMap.GetProperty(name);
}
throw new NotSupportedException("Object does not support dynamic properties");
});
}
MethodInfo IExpando.AddMethod(string name, Delegate method)
{
throw new NotImplementedException();
}
void IExpando.RemoveMember(MemberInfo member)
{
HostInvoke(() =>
{
if (TargetDynamic != null)
{
int index;
if (int.TryParse(member.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
{
if (TargetDynamic.DeleteProperty(index))
{
RemoveExpandoMemberName(index.ToString(CultureInfo.InvariantCulture));
}
}
else if (TargetDynamic.DeleteProperty(member.Name))
{
RemoveExpandoMemberName(member.Name);
}
}
else if (TargetPropertyBag != null)
{
if (TargetPropertyBag.Remove(member.Name))
{
RemoveExpandoMemberName(member.Name);
}
}
else if (TargetDynamicMetaObject != null)
{
bool result;
if (TargetDynamicMetaObject.TryDeleteMember(member.Name, out result) && result)
{
RemoveExpandoMemberName(member.Name);
}
}
else
{
throw new NotSupportedException("Object does not support dynamic members");
}
});
}
#endregion
#region IDynamic implementation
object IDynamic.GetProperty(string name)
object IDynamic.GetProperty(string name, object[] args)
{
return InvokeReflectMember(name, BindingFlags.GetProperty, MiscHelpers.GetEmptyArray<object>(), CultureInfo.InvariantCulture, null);
return InvokeReflectMember(name, BindingFlags.GetProperty, args, CultureInfo.InvariantCulture, null);
}
object IDynamic.GetProperty(string name, out bool isCacheable)
object IDynamic.GetProperty(string name, object[] args, out bool isCacheable)
{
return InvokeReflectMember(name, BindingFlags.GetProperty, MiscHelpers.GetEmptyArray<object>(), CultureInfo.InvariantCulture, null, out isCacheable);
return InvokeReflectMember(name, BindingFlags.GetProperty, args, CultureInfo.InvariantCulture, null, out isCacheable);
}
void IDynamic.SetProperty(string name, object value)
void IDynamic.SetProperty(string name, object[] args)
{
ThisExpando.InvokeMember(name, BindingFlags.SetProperty, null, ThisExpando, new[] { value }, null, CultureInfo.InvariantCulture, null);
ThisReflect.InvokeMember(name, BindingFlags.SetProperty, null, ThisReflect, args, null, CultureInfo.InvariantCulture, null);
}
bool IDynamic.DeleteProperty(string name)
@ -1809,12 +1814,12 @@ namespace Microsoft.ClearScript
object IDynamic.GetProperty(int index)
{
return ThisDynamic.GetProperty(index.ToString(CultureInfo.InvariantCulture));
return ThisDynamic.GetProperty(index.ToString(CultureInfo.InvariantCulture), MiscHelpers.GetEmptyArray<object>());
}
void IDynamic.SetProperty(int index, object value)
{
ThisDynamic.SetProperty(index.ToString(CultureInfo.InvariantCulture), value);
ThisDynamic.SetProperty(index.ToString(CultureInfo.InvariantCulture), new[] { value });
}
bool IDynamic.DeleteProperty(int index)
@ -1863,12 +1868,12 @@ namespace Microsoft.ClearScript
object IDynamic.Invoke(object[] args, bool asConstructor)
{
return ThisExpando.InvokeMember(SpecialMemberNames.Default, asConstructor ? BindingFlags.CreateInstance : ((args.Length < 1) ? BindingFlags.InvokeMethod : BindingFlags.InvokeMethod | BindingFlags.GetProperty), null, ThisExpando, args, null, CultureInfo.InvariantCulture, null);
return ThisReflect.InvokeMember(SpecialMemberNames.Default, asConstructor ? BindingFlags.CreateInstance : ((args.Length < 1) ? BindingFlags.InvokeMethod : BindingFlags.InvokeMethod | BindingFlags.GetProperty), null, ThisReflect, args, null, CultureInfo.InvariantCulture, null);
}
object IDynamic.InvokeMethod(string name, object[] args)
{
return ThisExpando.InvokeMember(name, BindingFlags.InvokeMethod, null, ThisExpando, args, null, CultureInfo.InvariantCulture, null);
return ThisReflect.InvokeMember(name, BindingFlags.InvokeMethod, null, ThisReflect, args, null, CultureInfo.InvariantCulture, null);
}
#endregion
@ -1885,7 +1890,7 @@ namespace Microsoft.ClearScript
var maxCount = Math.Min(count, elements.Length);
while ((index < maxCount) && TargetEnumerator.MoveNext())
{
elements[index++] = engine.MarshalToScript(TargetEnumerator.Current);
elements[index++] = ThisDynamic.GetProperty("Current", MiscHelpers.GetEmptyArray<object>());
}
}
@ -1932,15 +1937,35 @@ namespace Microsoft.ClearScript
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr pInterface)
{
pInterface = IntPtr.Zero;
if (iid == typeof(IEnumVARIANT).GUID)
{
if ((target is HostObject) || (target is IHostVariable) || (target is IByRefArg))
{
pInterface = IntPtr.Zero;
return BindSpecialTarget(Collateral.TargetEnumerator) ? CustomQueryInterfaceResult.NotHandled : CustomQueryInterfaceResult.Failed;
}
}
else if (iid == typeof(IDispatchEx).GUID)
{
if (EnableVTablePatching && !bypassVTablePatching)
{
var pUnknown = Marshal.GetIUnknownForObject(this);
bypassVTablePatching = true;
pInterface = RawCOMHelpers.QueryInterfaceNoThrow<IDispatchEx>(pUnknown);
bypassVTablePatching = false;
Marshal.Release(pUnknown);
if (pInterface != IntPtr.Zero)
{
VTablePatcher.GetInstance().PatchDispatchEx(pInterface);
return CustomQueryInterfaceResult.Handled;
}
}
}
pInterface = IntPtr.Zero;
return CustomQueryInterfaceResult.NotHandled;
}
@ -1968,5 +1993,122 @@ namespace Microsoft.ClearScript
}
#endregion
#region Nested type: ExpandoHostItem
private class ExpandoHostItem : HostItem, IExpando
{
#region constructors
public ExpandoHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags)
: base(engine, target, flags)
{
}
#endregion
#region IExpando implementation
FieldInfo IExpando.AddField(string name)
{
return HostInvoke(() =>
{
if (CanAddExpandoMembers())
{
AddExpandoMemberName(name);
return MemberMap.GetField(name);
}
throw new NotSupportedException("Object does not support dynamic fields");
});
}
PropertyInfo IExpando.AddProperty(string name)
{
return HostInvoke(() =>
{
if (CanAddExpandoMembers())
{
AddExpandoMemberName(name);
return MemberMap.GetProperty(name);
}
throw new NotSupportedException("Object does not support dynamic properties");
});
}
MethodInfo IExpando.AddMethod(string name, Delegate method)
{
throw new NotImplementedException();
}
void IExpando.RemoveMember(MemberInfo member)
{
HostInvoke(() =>
{
if (TargetDynamic != null)
{
int index;
if (int.TryParse(member.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
{
if (TargetDynamic.DeleteProperty(index))
{
RemoveExpandoMemberName(index.ToString(CultureInfo.InvariantCulture));
}
}
else if (TargetDynamic.DeleteProperty(member.Name))
{
RemoveExpandoMemberName(member.Name);
}
}
else if (TargetPropertyBag != null)
{
if (TargetPropertyBag.Remove(member.Name))
{
RemoveExpandoMemberName(member.Name);
}
}
else if (TargetDynamicMetaObject != null)
{
bool result;
if (TargetDynamicMetaObject.TryDeleteMember(member.Name, out result) && result)
{
RemoveExpandoMemberName(member.Name);
}
}
else
{
throw new NotSupportedException("Object does not support dynamic members");
}
});
}
#endregion
}
#endregion
#region Nested type: EnumerationHelpers
private static class EnumerationHelpers
{
// ReSharper disable UnusedMember.Local
public static readonly HostType HostType = HostType.Wrap(typeof(EnumerationHelpers));
public static IEnumerator<T> GetEnumerator<T>(IEnumerable<T> source)
{
return source.GetEnumerator();
}
public static IEnumerator GetEnumerator(IEnumerable source)
{
return source.GetEnumerator();
}
// ReSharper restore UnusedMember.Local
}
#endregion
}
}

Просмотреть файл

@ -92,7 +92,7 @@ namespace Microsoft.ClearScript
#endregion
#region Nested type : CollateralObject<T>
#region Nested type: CollateralObject<T>
public class CollateralObject<T> : CollateralObject<HostItem, T> where T : class
{
@ -100,7 +100,7 @@ namespace Microsoft.ClearScript
#endregion
#region Nested type : ListDataFields
#region Nested type: ListDataFields
public class ListDataFields
{

Просмотреть файл

@ -0,0 +1,101 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
namespace Microsoft.ClearScript.JavaScript
{
/// <summary>
/// Represents a JavaScript
/// <see href="https://msdn.microsoft.com/en-us/library/br212474(v=vs.94).aspx">ArrayBuffer</see>.
/// </summary>
public interface IArrayBuffer
{
/// <summary>
/// Gets the size of the <c>ArrayBuffer</c> in bytes.
/// </summary>
ulong Size { get; }
/// <summary>
/// Creates a byte array containing a copy of the <c>ArrayBuffer</c>'s contents.
/// </summary>
/// <returns>A new byte array containing a copy of the <c>ArrayBuffer</c>'s contents.</returns>
byte[] GetBytes();
/// <summary>
/// Copies bytes from the <c>ArrayBuffer</c> into the specified byte array.
/// </summary>
/// <param name="offset">The offset within the <c>ArrayBuffer</c> of the first byte to copy.</param>
/// <param name="count">The maximum number of bytes to copy.</param>
/// <param name="destination">The byte array into which to copy the bytes.</param>
/// <param name="destinationIndex">The index within <paramref name="destination"/> at which to store the first copied byte.</param>
/// <returns>The number of bytes copied.</returns>
ulong ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex);
/// <summary>
/// Copies bytes from the specified byte array into the <c>ArrayBuffer</c>.
/// </summary>
/// <param name="source">The byte array from which to copy the bytes.</param>
/// <param name="sourceIndex">The index within <paramref name="source"/> of the first byte to copy.</param>
/// <param name="count">The maximum number of bytes to copy.</param>
/// <param name="offset">The offset within the <c>ArrayBuffer</c> at which to store the first copied byte.</param>
/// <returns>The number of bytes copied.</returns>
ulong WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset);
}
}

Просмотреть файл

@ -0,0 +1,112 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
namespace Microsoft.ClearScript.JavaScript
{
/// <summary>
/// Defines properties and methods common to all
/// <see href="https://msdn.microsoft.com/en-us/library/br212474(v=vs.94).aspx">ArrayBuffer</see>
/// views.
/// </summary>
public interface IArrayBufferView
{
/// <summary>
/// Gets view's underlying <c>ArrayBuffer</c>.
/// </summary>
IArrayBuffer ArrayBuffer { get; }
/// <summary>
/// Gets the view's offset within the underlying <c>ArrayBuffer</c>.
/// </summary>
ulong Offset { get; }
/// <summary>
/// Gets the view's size in bytes.
/// </summary>
ulong Size { get; }
/// <summary>
/// Creates a byte array containing a copy of the view's contents.
/// </summary>
/// <returns>A new byte array containing a copy of the view's contents.</returns>
byte[] GetBytes();
/// <summary>
/// Copies bytes from the view into the specified byte array.
/// </summary>
/// <param name="offset">The offset within the view of the first byte to copy.</param>
/// <param name="count">The maximum number of bytes to copy.</param>
/// <param name="destination">The byte array into which to copy the bytes.</param>
/// <param name="destinationIndex">The index within <paramref name="destination"/> at which to store the first copied byte.</param>
/// <returns>The number of bytes copied.</returns>
ulong ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex);
/// <summary>
/// Copies bytes from the specified byte array into the view.
/// </summary>
/// <param name="source">The byte array from which to copy the bytes.</param>
/// <param name="sourceIndex">The index within <paramref name="source"/> of the first byte to copy.</param>
/// <param name="count">The maximum number of bytes to copy.</param>
/// <param name="offset">The offset within the view at which to store the first copied byte.</param>
/// <returns>The number of bytes copied.</returns>
ulong WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset);
}
}

Просмотреть файл

@ -0,0 +1,71 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
namespace Microsoft.ClearScript.JavaScript
{
/// <summary>
/// Represents a JavaScript
/// <see href="https://msdn.microsoft.com/en-us/library/br212463(v=vs.94).aspx">DataView</see>.
/// </summary>
public interface IDataView : IArrayBufferView
{
}
}

Просмотреть файл

@ -0,0 +1,155 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
namespace Microsoft.ClearScript.JavaScript
{
/// <summary>
/// Defines properties and methods common to all JavaScript
/// <see href="https://msdn.microsoft.com/en-us/library/br212485(v=vs.94).aspx">typed arrays</see>.
/// </summary>
public interface ITypedArray : IArrayBufferView
{
/// <summary>
/// Gets the typed array's length.
/// </summary>
ulong Length { get; }
}
/// <summary>
/// Represents a JavaScript <see href="https://msdn.microsoft.com/en-us/library/br212485(v=vs.94).aspx">typed array</see>.
/// </summary>
/// <typeparam name="T">The typed array's element type.</typeparam>
/// <remarks>
/// The following table lists the specific interfaces implemented by JavaScript typed arrays:
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Typed&#xA0;Array</term>
/// <term>Interface(s)&#xA0;(C#)</term>
/// </listheader>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212477(v=vs.94).aspx">Uint8Array</see></term>
/// <term><c>ITypedArray&#x3C;byte&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/dn641188(v=vs.94).aspx">Uint8ClampedArray</see></term>
/// <term><c>ITypedArray&#x3C;byte&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212462(v=vs.94).aspx">Int8Array</see></term>
/// <term><c>ITypedArray&#x3C;sbyte&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212484(v=vs.94).aspx">Uint16Array</see></term>
/// <term><c>ITypedArray&#x3C;ushort&#x3E;</c> and <c>ITypedArray&#x3C;char&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212480(v=vs.94).aspx">Int16Array</see></term>
/// <term><c>ITypedArray&#x3C;short&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br230737(v=vs.94).aspx">Uint32Array</see></term>
/// <term><c>ITypedArray&#x3C;uint&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212468(v=vs.94).aspx">Int32Array</see></term>
/// <term><c>ITypedArray&#x3C;int&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212916(v=vs.94).aspx">Float32Array</see></term>
/// <term><c>ITypedArray&#x3C;float&#x3E;</c></term>
/// </item>
/// <item>
/// <term><see href="https://msdn.microsoft.com/en-us/library/br212931(v=vs.94).aspx">Float64Array</see></term>
/// <term><c>ITypedArray&#x3C;double&#x3E;</c></term>
/// </item>
/// </list>
/// </para>
/// </remarks>
public interface ITypedArray<T> : ITypedArray
{
/// <summary>
/// Creates an array containing a copy of the typed array's contents.
/// </summary>
/// <returns>A new array containing a copy of the typed array's contents.</returns>
T[] ToArray();
/// <summary>
/// Copies elements from the typed array into the specified array.
/// </summary>
/// <param name="index">The index within the typed array of the first element to copy.</param>
/// <param name="length">The maximum number of elements to copy.</param>
/// <param name="destination">The array into which to copy the elements.</param>
/// <param name="destinationIndex">The index within <paramref name="destination"/> at which to store the first copied element.</param>
/// <returns>The number of elements copied.</returns>
ulong Read(ulong index, ulong length, T[] destination, ulong destinationIndex);
/// <summary>
/// Copies elements from the specified array into the typed array.
/// </summary>
/// <param name="source">The array from which to copy the elements.</param>
/// <param name="sourceIndex">The index within <paramref name="source"/> of the first element to copy.</param>
/// <param name="length">The maximum number of elements to copy.</param>
/// <param name="index">The index within the typed array at which to store the first copied element.</param>
/// <returns>The number of elements copied.</returns>
ulong Write(T[] source, ulong sourceIndex, ulong length, ulong index);
}
}

Просмотреть файл

@ -75,5 +75,5 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("ClearScriptTest")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.3.0")]
[assembly: AssemblyFileVersion("5.4.3.0")]
[assembly: AssemblyVersion("5.4.4.0")]
[assembly: AssemblyFileVersion("5.4.4.0")]

Просмотреть файл

@ -335,7 +335,7 @@ namespace Microsoft.ClearScript
return GetProperty(index);
}
return GetProperty(name);
return GetProperty(name, args);
}
if (invokeFlags.HasFlag(BindingFlags.SetField))
@ -354,7 +354,7 @@ namespace Microsoft.ClearScript
return value;
}
SetProperty(name, value);
SetProperty(name, args);
return value;
}
@ -394,18 +394,18 @@ namespace Microsoft.ClearScript
#region IDynamic implementation
public object GetProperty(string name, out bool isCacheable)
public object GetProperty(string name, object[] args, out bool isCacheable)
{
isCacheable = false;
return GetProperty(name);
return GetProperty(name, args);
}
#endregion
#region IDynamic implementation (abstract)
public abstract object GetProperty(string name);
public abstract void SetProperty(string name, object value);
public abstract object GetProperty(string name, object[] args);
public abstract void SetProperty(string name, object[] args);
public abstract bool DeleteProperty(string name);
public abstract string[] GetPropertyNames();
public abstract object GetProperty(int index);

Просмотреть файл

@ -218,7 +218,8 @@ namespace Microsoft.ClearScript.Util
[In] [Optional] [MarshalAs(UnmanagedType.Interface)] IServiceProvider svpCaller
);
void DeleteMemberByName(
[PreserveSig]
int DeleteMemberByName(
[In] [MarshalAs(UnmanagedType.BStr)] string name,
[In] DispatchNameFlags flags
);
@ -233,12 +234,14 @@ namespace Microsoft.ClearScript.Util
[Out] out DispatchPropFlags flags
);
void GetMemberName(
[PreserveSig]
int GetMemberName(
[In] int dispid,
[Out] [MarshalAs(UnmanagedType.BStr)] out string name
);
void GetNextDispID(
[PreserveSig]
int GetNextDispID(
[In] DispatchEnumFlags flags,
[In] int dispidCurrent,
[Out] out int dispidNext

Просмотреть файл

@ -60,6 +60,9 @@
//
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using DISPPARAMS = System.Runtime.InteropServices.ComTypes.DISPPARAMS;
using EXCEPINFO = System.Runtime.InteropServices.ComTypes.EXCEPINFO;
@ -112,7 +115,28 @@ namespace Microsoft.ClearScript.Util
}
}
public static object Invoke(this IDispatchEx dispatchEx, object[] args)
public static bool DeleteProperty(this IDispatchEx dispatchEx, string name, bool ignoreCase)
{
return dispatchEx.DeleteMemberByName(name, ignoreCase ? DispatchNameFlags.CaseInsensitive : DispatchNameFlags.CaseSensitive) == RawCOMHelpers.HResult.S_OK;
}
public static IEnumerable<string> GetPropertyNames(this IDispatchEx dispatchEx)
{
int dispid;
var result = dispatchEx.GetNextDispID(DispatchEnumFlags.All, SpecialDispIDs.StartEnum, out dispid);
while (result == RawCOMHelpers.HResult.S_OK)
{
string name;
if (dispatchEx.GetMemberName(dispid, out name) == RawCOMHelpers.HResult.S_OK)
{
yield return name;
}
result = dispatchEx.GetNextDispID(DispatchEnumFlags.All, dispid, out dispid);
}
}
public static object Invoke(this IDispatchEx dispatchEx, object[] args, bool asConstructor)
{
using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
{
@ -120,7 +144,7 @@ namespace Microsoft.ClearScript.Util
{
EXCEPINFO excepInfo;
var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero };
dispatchEx.InvokeEx(SpecialDispIDs.Default, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo);
dispatchEx.InvokeEx(SpecialDispIDs.Default, 0, asConstructor ? DispatchFlags.Construct : DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo);
return Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr);
}
}
@ -143,4 +167,71 @@ namespace Microsoft.ClearScript.Util
}
}
}
internal class DynamicDispatchExWrapper : IDynamic
{
private readonly IDispatchEx dispatchEx;
public DynamicDispatchExWrapper(IDispatchEx dispatchEx)
{
this.dispatchEx = dispatchEx;
}
public object GetProperty(string name, object[] args)
{
bool isCacheable;
return GetProperty(name, args, out isCacheable);
}
public object GetProperty(string name, object[] args, out bool isCacheable)
{
isCacheable = false;
return dispatchEx.GetProperty(name, false, args);
}
public void SetProperty(string name, object[] args)
{
dispatchEx.SetProperty(name, false, args);
}
public bool DeleteProperty(string name)
{
return dispatchEx.DeleteProperty(name, false);
}
public string[] GetPropertyNames()
{
return dispatchEx.GetPropertyNames().ExcludeIndices().ToArray();
}
public object GetProperty(int index)
{
return dispatchEx.GetProperty(index.ToString(CultureInfo.InvariantCulture), false, MiscHelpers.GetEmptyArray<object>());
}
public void SetProperty(int index, object value)
{
dispatchEx.SetProperty(index.ToString(CultureInfo.InvariantCulture), false, new[] { value });
}
public bool DeleteProperty(int index)
{
return dispatchEx.DeleteProperty(index.ToString(CultureInfo.InvariantCulture), false);
}
public int[] GetPropertyIndices()
{
return dispatchEx.GetPropertyNames().GetIndices().ToArray();
}
public object Invoke(object[] args, bool asConstructor)
{
return dispatchEx.Invoke(args, asConstructor);
}
public object InvokeMethod(string name, object[] args)
{
return dispatchEx.InvokeMethod(name, false, args);
}
}
}

Просмотреть файл

@ -223,7 +223,7 @@ namespace Microsoft.ClearScript.Util
var pArgRef = GetAddrInternal(args.Length - 1 - index);
NativeMethods.VariantInit(pArgRef);
Marshal.WriteInt16(pArgRef, 0, 0x400C /*VT_BYREF | VT_VARIANT*/);
Marshal.WriteInt16(pArgRef, 0, 0x400C /*VT_BYREF|VT_VARIANT*/);
Marshal.WriteIntPtr(pArgRef, sizeof(ushort) * 4, pArg);
}
}

Просмотреть файл

@ -123,44 +123,55 @@ namespace Microsoft.ClearScript.Util
}
else
{
var invokeBinder = binder as InvokeBinder;
if (invokeBinder != null)
var createInstanceBinder = binder as CreateInstanceBinder;
if (createInstanceBinder != null)
{
if (TryInvoke(reflect, args, out result))
if (TryCreateInstance(reflect, args, out result))
{
return true;
}
}
else
{
var invokeMemberBinder = binder as InvokeMemberBinder;
if (invokeMemberBinder != null)
var invokeBinder = binder as InvokeBinder;
if (invokeBinder != null)
{
if (TryInvokeMethod(reflect, invokeMemberBinder.Name, invokeMemberBinder.IgnoreCase, args, out result))
if (TryInvoke(reflect, args, out result))
{
return true;
}
}
else if ((args != null) && (args.Length > 0))
else
{
var getIndexBinder = binder as GetIndexBinder;
if (getIndexBinder != null)
var invokeMemberBinder = binder as InvokeMemberBinder;
if (invokeMemberBinder != null)
{
if (TryGetProperty(reflect, args[0].ToString(), false, args.Skip(1).ToArray(), out result))
if (TryInvokeMethod(reflect, invokeMemberBinder.Name, invokeMemberBinder.IgnoreCase, args, out result))
{
return true;
}
}
else
else if ((args != null) && (args.Length > 0))
{
var setIndexBinder = binder as SetIndexBinder;
if (setIndexBinder != null)
var getIndexBinder = binder as GetIndexBinder;
if (getIndexBinder != null)
{
if (TrySetProperty(reflect, args[0].ToString(), false, args.Skip(1).ToArray(), out result))
if (TryGetProperty(reflect, args[0].ToString(), false, args.Skip(1).ToArray(), out result))
{
return true;
}
}
else
{
var setIndexBinder = binder as SetIndexBinder;
if (setIndexBinder != null)
{
if (TrySetProperty(reflect, args[0].ToString(), false, args.Skip(1).ToArray(), out result))
{
return true;
}
}
}
}
}
}
@ -314,6 +325,39 @@ namespace Microsoft.ClearScript.Util
return false;
}
private static bool TryCreateInstance(IReflect target, object[] args, out object result)
{
// ReSharper disable SuspiciousTypeConversion.Global
var dispatchEx = target as IDispatchEx;
if (dispatchEx != null)
{
// Standard IExpando-over-IDispatchEx support appears to leak the variants it
// creates for the invocation arguments. This issue has been reported. In the
// meantime we'll bypass this facility and interface with IDispatchEx directly.
result = dispatchEx.Invoke(args, true);
return true;
}
// ReSharper restore SuspiciousTypeConversion.Global
try
{
result = target.InvokeMember(SpecialMemberNames.Default, BindingFlags.CreateInstance, null, target, args, null, CultureInfo.InvariantCulture, null);
return true;
}
catch (TargetInvocationException)
{
throw;
}
catch (Exception)
{
result = null;
return false;
}
}
private static bool TryInvoke(IReflect target, object[] args, out object result)
{
// ReSharper disable SuspiciousTypeConversion.Global
@ -325,14 +369,26 @@ namespace Microsoft.ClearScript.Util
// creates for the invocation arguments. This issue has been reported. In the
// meantime we'll bypass this facility and interface with IDispatchEx directly.
result = dispatchEx.Invoke(args);
result = dispatchEx.Invoke(args, false);
return true;
}
// ReSharper restore SuspiciousTypeConversion.Global
result = null;
return false;
try
{
result = target.InvokeMember(SpecialMemberNames.Default, BindingFlags.InvokeMethod, null, target, args, null, CultureInfo.InvariantCulture, null);
return true;
}
catch (TargetInvocationException)
{
throw;
}
catch (Exception)
{
result = null;
return false;
}
}
private static bool TryInvokeMethod(IReflect target, string name, bool ignoreCase, object[] args, out object result)

Просмотреть файл

@ -63,9 +63,9 @@ namespace Microsoft.ClearScript.Util
{
internal interface IDynamic
{
object GetProperty(string name);
object GetProperty(string name, out bool isCacheable);
void SetProperty(string name, object value);
object GetProperty(string name, object[] args);
object GetProperty(string name, object[] args, out bool isCacheable);
void SetProperty(string name, object[] args);
bool DeleteProperty(string name);
string[] GetPropertyNames();

Просмотреть файл

@ -83,17 +83,18 @@ namespace Microsoft.ClearScript.Util
{
if ((index != (args.Length - 1)) || !param.ParameterType.IsInstanceOfType(args[index]))
{
var tailArgs = Array.CreateInstance(param.ParameterType.GetElementType(), args.Length - index);
var tailArgType = param.ParameterType.GetElementType();
var tailArgs = Array.CreateInstance(tailArgType, args.Length - index);
for (var innerIndex = index; innerIndex < args.Length; innerIndex++)
{
var byRefArg = args[innerIndex] as IByRefArg;
if (byRefArg == null)
{
tailArgs.SetValue(args[innerIndex], innerIndex - index);
tailArgs.SetValue(GetCompatibleArg(param.Name, tailArgType, args[innerIndex]), innerIndex - index);
}
else
{
tailArgs.SetValue(byRefArg.Value, innerIndex - index);
tailArgs.SetValue(GetCompatibleArg(param.Name, tailArgType, byRefArg.Value), innerIndex - index);
byRefArgInfo.Add(new ByRefArgItem(byRefArg, tailArgs, innerIndex - index));
}
}
@ -109,11 +110,11 @@ namespace Microsoft.ClearScript.Util
var byRefArg = args[index] as IByRefArg;
if (byRefArg == null)
{
argList.Add(args[index]);
argList.Add(GetCompatibleArg(param, args[index]));
}
else
{
argList.Add(byRefArg.Value);
argList.Add(GetCompatibleArg(param, byRefArg.Value));
byRefArgInfo.Add(new ByRefArgItem(byRefArg, null, index));
}
}
@ -232,6 +233,21 @@ namespace Microsoft.ClearScript.Util
return false;
}
private static object GetCompatibleArg(ParameterInfo param, object value)
{
return GetCompatibleArg(param.Name, param.ParameterType, value);
}
private static object GetCompatibleArg(string paramName, Type type, object value)
{
if (!type.IsAssignableFrom(ref value))
{
throw new ArgumentException(MiscHelpers.FormatInvariant("Invalid argument specified for parameter '{0}'", paramName));
}
return value;
}
#region Nested type: ByRefArgItem
private class ByRefArgItem

Просмотреть файл

@ -355,11 +355,28 @@ namespace Microsoft.ClearScript.Util
public static T Exchange<T>(ref T target, T value)
{
T oldValue = target;
var oldValue = target;
target = value;
return oldValue;
}
public static bool IsX86InstructionSet()
{
SystemInfo info;
try
{
NativeMethods.GetNativeSystemInfo(out info);
}
catch (EntryPointNotFoundException)
{
NativeMethods.GetSystemInfo(out info);
}
return
((info.ProcessorArchitecture == 0 /*PROCESSOR_ARCHITECTURE_INTEL*/) ||
(info.ProcessorArchitecture == 9 /*PROCESSOR_ARCHITECTURE_AMD64*/));
}
#region Nested type: EmptyArray<T>
private static class EmptyArray<T>

Просмотреть файл

@ -64,6 +64,22 @@ using System.Runtime.InteropServices;
namespace Microsoft.ClearScript.Util
{
[StructLayout(LayoutKind.Sequential)]
internal struct SystemInfo
{
public ushort ProcessorArchitecture;
public ushort Reserved;
public uint PageSize;
public IntPtr MinimumApplicationAddress;
public IntPtr MaximumApplicationAddress;
public IntPtr ActiveProcessorMask;
public uint NumberOfProcessors;
public uint ProcessorType;
public uint AllocationGranularity;
public ushort ProcessorLevel;
public ushort ProcessorRevision;
}
internal static class NativeMethods
{
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
@ -99,5 +115,38 @@ namespace Microsoft.ClearScript.Util
public static extern uint VariantClear(
[In] IntPtr pVariant
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr HeapCreate(
[In] uint options,
[In] UIntPtr initialSize,
[In] UIntPtr maximumSize
);
[DllImport("kernel32.dll", SetLastError = false)]
public static extern IntPtr HeapAlloc(
[In] IntPtr hHeap,
[In] uint flags,
[In] UIntPtr size
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool HeapDestroy(
[In] IntPtr hHeap
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool VirtualProtect(
[In] IntPtr pBlock,
[In] UIntPtr size,
[In] uint newProtect,
[Out] out uint oldProtect
);
[DllImport("kernel32.dll", SetLastError = false)]
public static extern void GetSystemInfo(out SystemInfo info);
[DllImport("kernel32.dll")]
public static extern void GetNativeSystemInfo(out SystemInfo info);
}
}

Просмотреть файл

@ -65,6 +65,8 @@ using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
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
@ -77,14 +79,18 @@ namespace Microsoft.ClearScript.Util
public static Type GetTypeOrTypeInfo(this object value)
{
var type = value.GetType();
IDispatch dispatch = null;
Type typeInfo = null;
TYPEKIND typeInfoKind = 0;
TYPEFLAGS typeInfoFlags = 0;
if (type.IsUnknownCOMObject())
{
// This appears to be a generic COM object with no specific type information.
// Attempt to acquire COM type information via IDispatch or IProvideClassInfo.
var dispatch = value as IDispatch;
dispatch = value as IDispatch;
if (dispatch != null)
{
uint count;
@ -94,6 +100,8 @@ namespace Microsoft.ClearScript.Util
if (RawCOMHelpers.HResult.Succeeded(dispatch.GetTypeInfo(0, 0, out tempTypeInfo)))
{
typeInfo = GetTypeForTypeInfo(tempTypeInfo);
typeInfoKind = GetTypeInfoKind(tempTypeInfo);
typeInfoFlags = GetTypeInfoFlags(tempTypeInfo);
}
}
}
@ -107,6 +115,8 @@ namespace Microsoft.ClearScript.Util
if (RawCOMHelpers.HResult.Succeeded(provideClassInfo.GetClassInfo(out tempTypeInfo)))
{
typeInfo = GetTypeForTypeInfo(tempTypeInfo);
typeInfoKind = GetTypeInfoKind(tempTypeInfo);
typeInfoFlags = GetTypeInfoFlags(tempTypeInfo);
}
}
}
@ -114,6 +124,14 @@ namespace Microsoft.ClearScript.Util
if (typeInfo != null)
{
// If the COM type is a dispatch-only interface, use it. Such interfaces typically
// aren't exposed via QueryInterface(), so there's no way to validate them anyway.
if ((dispatch != null) && (typeInfoKind == TYPEKIND.TKIND_DISPATCH) && typeInfoFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FDISPATCHABLE) && !typeInfoFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FDUAL))
{
return typeInfo;
}
// COM type information acquired in this manner may not actually be valid for the
// original object. In some cases the original object implements a base interface.
@ -209,7 +227,7 @@ namespace Microsoft.ClearScript.Util
var name = GetManagedTypeInfoName(typeInfo, typeLib);
var guid = GetTypeInfoGuid(typeInfo);
var type = assembly.GetType(name, false /*throwOnError*/);
var type = assembly.GetType(name, false /*throwOnError*/, true /*ignoreCase*/);
if ((type != null) && (type.GUID == guid))
{
return type;
@ -225,14 +243,14 @@ namespace Microsoft.ClearScript.Util
}
}
type = types.FirstOrDefault(testType => (testType.GUID == guid) && (testType.FullName == name));
type = types.FirstOrDefault(testType => (testType.GUID == guid) && (testType.FullName.Equals(name, StringComparison.OrdinalIgnoreCase)));
if (type != null)
{
return type;
}
}
var pTypeInfo = RawCOMHelpers.QueryInterface<ITypeInfo>(Marshal.GetIUnknownForObject(typeInfo));
var pTypeInfo = Marshal.GetComInterfaceForObject(typeInfo, typeof(ITypeInfo));
try
{
return Marshal.GetTypeForITypeInfo(pTypeInfo);
@ -363,6 +381,36 @@ namespace Microsoft.ClearScript.Util
}
}
private static TYPEKIND GetTypeInfoKind(ITypeInfo typeInfo)
{
IntPtr pAttr;
typeInfo.GetTypeAttr(out pAttr);
try
{
var attr = (TYPEATTR)Marshal.PtrToStructure(pAttr, typeof(TYPEATTR));
return attr.typekind;
}
finally
{
typeInfo.ReleaseTypeAttr(pAttr);
}
}
private static TYPEFLAGS GetTypeInfoFlags(ITypeInfo typeInfo)
{
IntPtr pAttr;
typeInfo.GetTypeAttr(out pAttr);
try
{
var attr = (TYPEATTR)Marshal.PtrToStructure(pAttr, typeof(TYPEATTR));
return attr.wTypeFlags;
}
finally
{
typeInfo.ReleaseTypeAttr(pAttr);
}
}
#region Nested type: IProvideClassInfo
[ComImport]

Просмотреть файл

@ -65,6 +65,7 @@ namespace Microsoft.ClearScript.Util
{
public const int Default = 0;
public const int Unknown = -1;
public const int StartEnum = Unknown;
public const int PropertyPut = -3;
public const int NewEnum = -4;
public const int This = -613;

Просмотреть файл

@ -81,20 +81,6 @@ namespace Microsoft.ClearScript.Util
"__DynamicallyInvokableAttribute"
};
private static readonly Dictionary<TypeCode, TypeCode[]> implicitNumericConversions = new Dictionary<TypeCode, TypeCode[]>
{
{ TypeCode.SByte, new[] { TypeCode.Int16, TypeCode.Int32, TypeCode.Int64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.Byte, new[] { TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.Int16, new[] { TypeCode.Int32, TypeCode.Int64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.UInt16, new[] { TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.Int32, new[] { TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.UInt32, new[] { TypeCode.Int64, TypeCode.UInt64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.Int64, new[] { TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.UInt64, new[] { TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.Char, new[] { TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal } },
{ TypeCode.Single, new[] { TypeCode.Double } },
};
private static readonly HashSet<Type> nullableNumericTypes = new HashSet<Type>
{
typeof(char?),
@ -142,31 +128,40 @@ namespace Microsoft.ClearScript.Util
return false;
}
public static bool IsIntegral(this Type type)
{
return
(type == typeof(sbyte)) ||
(type == typeof(byte)) ||
(type == typeof(short)) ||
(type == typeof(ushort)) ||
(type == typeof(char)) ||
(type == typeof(int)) ||
(type == typeof(uint)) ||
(type == typeof(long)) ||
(type == typeof(ulong));
}
public static bool IsFloatingPoint(this Type type)
{
return
(type == typeof(float)) ||
(type == typeof(double));
}
public static bool IsNumeric(this Type type, out bool isIntegral)
{
isIntegral = type.IsIntegral();
return
isIntegral ||
type.IsFloatingPoint() ||
type == typeof(decimal);
}
public static bool IsNumeric(this Type type)
{
if (type.IsEnum)
{
return false;
}
switch (Type.GetTypeCode(type))
{
case TypeCode.Char:
case TypeCode.SByte:
case TypeCode.Byte:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
bool isIntegral;
return type.IsNumeric(out isIntegral);
}
public static bool IsNullable(this Type type)
@ -227,15 +222,23 @@ namespace Microsoft.ClearScript.Util
return false;
}
TypeCode[] typeCodes;
if (implicitNumericConversions.TryGetValue(Type.GetTypeCode(valueType), out typeCodes))
bool typeIsIntegral;
if (type.IsNumeric(out typeIsIntegral))
{
var typeCode = Type.GetTypeCode(type);
if (typeCodes.Contains(Type.GetTypeCode(type)))
if (typeIsIntegral)
{
value = Convert.ChangeType(value, typeCode);
return true;
if (!valueType.IsIntegral())
{
return false;
}
}
else if (!valueType.IsNumeric())
{
return false;
}
value = Convert.ChangeType(value, type);
return true;
}
return false;
@ -451,7 +454,7 @@ namespace Microsoft.ClearScript.Util
// ReSharper disable RedundantEnumerableCastCall
// the OfType<>() call is not redundant; it filters out null elements
// the OfType<Type>() call is not redundant; it filters out null elements
var counts = Enumerable.Range(1, maxTypeArgCount);
var templates = counts.Select(count => ImportType(typeName, assemblyName, useAssemblyName, count)).OfType<Type>().ToArray();

Просмотреть файл

@ -0,0 +1,655 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Microsoft.ClearScript.Util
{
internal static class UnmanagedMemoryHelpers
{
private delegate ulong ReadArrayFromUnmanagedMemoryHandler(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex);
private delegate ulong WriteArrayToUnmanagedMemoryHandler(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination);
private static readonly Dictionary<Type, ReadArrayFromUnmanagedMemoryHandler> readArrayFromUnmanagedMemoryHandlerMap = new Dictionary<Type, ReadArrayFromUnmanagedMemoryHandler>
{
{ typeof(byte), ReadByteArrayFromUnmanagedMemory },
{ typeof(sbyte), ReadSByteArrayFromUnmanagedMemory },
{ typeof(ushort), ReadUInt16ArrayFromUnmanagedMemory },
{ typeof(char), ReadCharArrayFromUnmanagedMemory },
{ typeof(short), ReadInt16ArrayFromUnmanagedMemory },
{ typeof(uint), ReadUInt32ArrayFromUnmanagedMemory },
{ typeof(int), ReadInt32ArrayFromUnmanagedMemory },
{ typeof(float), ReadSingleArrayFromUnmanagedMemory },
{ typeof(double), ReadDoubleArrayFromUnmanagedMemory }
};
private static readonly Dictionary<Type, WriteArrayToUnmanagedMemoryHandler> writeArrayToUnmanagedMemoryHandlerMap = new Dictionary<Type, WriteArrayToUnmanagedMemoryHandler>
{
{ typeof(byte), WriteByteArrayToUnmanagedMemory },
{ typeof(sbyte), WriteSByteArrayToUnmanagedMemory },
{ typeof(ushort), WriteUInt16ArrayToUnmanagedMemory },
{ typeof(char), WriteCharArrayToUnmanagedMemory },
{ typeof(short), WriteInt16ArrayToUnmanagedMemory },
{ typeof(uint), WriteUInt32ArrayToUnmanagedMemory },
{ typeof(int), WriteInt32ArrayToUnmanagedMemory },
{ typeof(float), WriteSingleArrayToUnmanagedMemory },
{ typeof(double), WriteDoubleArrayToUnmanagedMemory }
};
public static ulong Copy<T>(IntPtr pSource, ulong length, T[] destination, ulong destinationIndex)
{
return Copy(typeof(T), pSource, length, destination, destinationIndex);
}
public static ulong Copy<T>(T[] source, ulong sourceIndex, ulong length, IntPtr pDestination)
{
return Copy(typeof(T), source, sourceIndex, length, pDestination);
}
private static ulong Copy(Type type, IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
ReadArrayFromUnmanagedMemoryHandler handler;
if (readArrayFromUnmanagedMemoryHandlerMap.TryGetValue(type, out handler))
{
return handler(pSource, length, destinationArray, destinationIndex);
}
throw new NotSupportedException("Unsupported unmanaged data transfer operation");
}
private static ulong Copy(Type type, Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
WriteArrayToUnmanagedMemoryHandler handler;
if (writeArrayToUnmanagedMemoryHandlerMap.TryGetValue(type, out handler))
{
return handler(sourceArray, sourceIndex, length, pDestination);
}
throw new NotSupportedException("Unsupported unmanaged data transfer operation");
}
private static unsafe ulong ReadByteArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (byte[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (byte* pDest = destination)
{
var pSrc = (byte*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
}
return length;
}
private static unsafe ulong ReadSByteArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (sbyte[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
fixed (sbyte* pDest = destination)
{
var pSrc = (sbyte*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
return length;
}
private static unsafe ulong ReadUInt16ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (ushort[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
fixed (ushort* pDest = destination)
{
var pSrc = (ushort*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
return length;
}
private static unsafe ulong ReadCharArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (char[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (char* pDest = destination)
{
var pSrc = (char*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
}
return length;
}
private static unsafe ulong ReadInt16ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (short[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (short* pDest = destination)
{
var pSrc = (short*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
}
return length;
}
private static unsafe ulong ReadUInt32ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (uint[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
fixed (uint* pDest = destination)
{
var pSrc = (uint*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
return length;
}
private static unsafe ulong ReadInt32ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (int[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (int* pDest = destination)
{
var pSrc = (int*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
}
return length;
}
private static unsafe ulong ReadSingleArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (float[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (float* pDest = destination)
{
var pSrc = (float*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
}
return length;
}
private static unsafe ulong ReadDoubleArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex)
{
var destinationLength = (ulong)destinationArray.LongLength;
if (destinationIndex >= destinationLength)
{
throw new ArgumentOutOfRangeException("destinationIndex");
}
var destination = (double[])destinationArray;
length = Math.Min(length, destinationLength - destinationIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (double* pDest = destination)
{
var pSrc = (double*)pSource;
for (var index = 0UL; index < length; index++)
{
pDest[destinationIndex + index] = pSrc[index];
}
}
}
return length;
}
private static unsafe ulong WriteByteArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (byte[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (byte* pSrc = source)
{
var pDest = (byte*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
}
return length;
}
private static unsafe ulong WriteSByteArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (sbyte[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
fixed (sbyte* pSrc = source)
{
var pDest = (sbyte*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
return length;
}
private static unsafe ulong WriteUInt16ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (ushort[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
fixed (ushort* pSrc = source)
{
var pDest = (ushort*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
return length;
}
private static unsafe ulong WriteCharArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (char[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (char* pSrc = source)
{
var pDest = (char*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
}
return length;
}
private static unsafe ulong WriteInt16ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (short[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (short* pSrc = source)
{
var pDest = (short*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
}
return length;
}
private static unsafe ulong WriteUInt32ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (uint[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
fixed (uint* pSrc = source)
{
var pDest = (uint*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
return length;
}
private static unsafe ulong WriteInt32ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (int[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (int* pSrc = source)
{
var pDest = (int*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
}
return length;
}
private static unsafe ulong WriteSingleArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (float[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (float* pSrc = source)
{
var pDest = (float*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
}
return length;
}
private static unsafe ulong WriteDoubleArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination)
{
var sourceLength = (ulong)sourceArray.LongLength;
if (sourceIndex >= sourceLength)
{
throw new ArgumentOutOfRangeException("sourceIndex");
}
var source = (double[])sourceArray;
length = Math.Min(length, sourceLength - sourceIndex);
try
{
VerifyMarshalCopyEnabled();
Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length));
}
catch (OverflowException)
{
fixed (double* pSrc = source)
{
var pDest = (double*)pDestination;
for (var index = 0UL; index < length; index++)
{
pDest[index] = pSrc[sourceIndex + index];
}
}
}
return length;
}
#region unit test support
internal static bool DisableMarshalCopy;
private static void VerifyMarshalCopyEnabled()
{
if (DisableMarshalCopy)
{
throw new OverflowException();
}
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,256 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Microsoft.ClearScript.Util
{
internal abstract class VTablePatcher
{
private static readonly object dataLock = new object();
private static readonly HashSet<IntPtr> patchedVTables = new HashSet<IntPtr>();
private static IntPtr hHeap;
public static VTablePatcher GetInstance()
{
return Environment.Is64BitProcess ? VTablePatcher64.Instance : VTablePatcher32.Instance;
}
public abstract void PatchDispatchEx(IntPtr pDispatchEx);
private static void ApplyVTablePatches(IntPtr pInterface, params VTablePatch[] patches)
{
lock (dataLock)
{
var pVTable = Marshal.ReadIntPtr(pInterface);
if (!patchedVTables.Contains(pVTable))
{
patchedVTables.Add(pVTable);
EnsureHeap();
foreach (var patch in patches)
{
var pSlot = pVTable + patch.SlotIndex * IntPtr.Size;
var pTarget = Marshal.ReadIntPtr(pSlot);
uint oldProtect;
if (NativeMethods.VirtualProtect(pSlot, (UIntPtr)IntPtr.Size, 0x04 /*PAGE_READWRITE*/, out oldProtect))
{
var thunkSize = patch.ThunkBytes.Length;
var pThunk = NativeMethods.HeapAlloc(hHeap, 0, (UIntPtr)thunkSize);
for (var index = 0; index < thunkSize; index++)
{
Marshal.WriteByte(pThunk + index, patch.ThunkBytes[index]);
}
Marshal.WriteIntPtr(pThunk + patch.TargetOffset, pTarget);
Marshal.WriteIntPtr(pSlot, pThunk);
NativeMethods.VirtualProtect(pSlot, (UIntPtr)IntPtr.Size, oldProtect, out oldProtect);
}
}
}
}
}
private static void EnsureHeap()
{
if (hHeap == IntPtr.Zero)
{
hHeap = NativeMethods.HeapCreate(0x00040005 /*HEAP_CREATE_ENABLE_EXECUTE|HEAP_GENERATE_EXCEPTIONS|HEAP_NO_SERIALIZE*/, UIntPtr.Zero, UIntPtr.Zero);
if (hHeap == IntPtr.Zero)
{
throw new Win32Exception();
}
}
}
#region Nested type: VTablePatcher32
private sealed class VTablePatcher32 : VTablePatcher
{
public static readonly VTablePatcher Instance = new VTablePatcher32();
private VTablePatcher32()
{
}
public override void PatchDispatchEx(IntPtr pDispatchEx)
{
// JScript in Standards Mode extends the IDispatchEx contract slightly in order to
// pass extra data to the host. This confuses the CLR's IDispatchEx implementation.
// The vtable patches below sanitize the arguments before passing them through.
ApplyVTablePatches(
pDispatchEx,
new VTablePatch
{
SlotIndex = 7, // IDispatchEx::GetDispID()
ThunkBytes = new byte[] { //-------------------------
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x81, 0x65, 0x10, 0xFF, 0xFF, 0xFF, 0x0F, // and dword ptr [grfdex],0FFFFFFFh
0xB8, 0x0D, 0xF0, 0xAD, 0xBA, // mov eax,0BAADF00Dh <- Target
0x5D, // pop ebp
0xFF, 0xE0 // jmp eax
},
TargetOffset = 11
},
new VTablePatch
{
SlotIndex = 9, // IDispatchEx::DeleteMemberByName()
ThunkBytes = new byte[] { // ---------------------------------
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x8B, 0x45, 0x10, // mov eax,dword ptr [grfdex]
0x25, 0xFF, 0xFF, 0xFF, 0x0F, // and eax,0FFFFFFFh
0x89, 0x45, 0x10, // mov dword ptr [grfdex],eax
0xB8, 0x0D, 0xF0, 0xAD, 0xBA, // mov eax,0BAADF00Dh <- Target
0x5D, // pop ebp
0xFF, 0xE0 // jmp eax
},
TargetOffset = 15
},
new VTablePatch
{
SlotIndex = 13, // IDispatchEx::GetNextDispID()
ThunkBytes = new byte[] { // ----------------------------
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x81, 0x65, 0x0C, 0xFF, 0xFF, 0xFF, 0x0F, // and dword ptr [grfdex],0FFFFFFFh
0xB8, 0x0D, 0xF0, 0xAD, 0xBA, // mov eax,0BAADF00Dh <- Target
0x5D, // pop ebp
0xFF, 0xE0 // jmp eax
},
TargetOffset = 11
}
);
}
}
#endregion
#region Nested type: VTablePatcher64
private sealed class VTablePatcher64 : VTablePatcher
{
public static readonly VTablePatcher Instance = new VTablePatcher64();
private VTablePatcher64()
{
}
public override void PatchDispatchEx(IntPtr pDispatchEx)
{
// JScript in Standards Mode extends the IDispatchEx contract slightly in order to
// pass extra data to the host. This confuses the CLR's IDispatchEx implementation.
// The vtable patches below sanitize the arguments before passing them through.
ApplyVTablePatches(
pDispatchEx,
new VTablePatch
{
SlotIndex = 7, // IDispatchEx::GetDispID()
ThunkBytes = new byte[] { //-------------------------
0x41, 0x81, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, // and r8d,0FFFFFFFh
0x48, 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, 0x0D, 0xF0, 0xAD, 0xBA, // mov rax,0BAADF00DBAADF00Dh <- Target
0x48, 0xFF, 0xE0 // jmp rax
},
TargetOffset = 9
},
new VTablePatch {
SlotIndex = 9, // IDispatchEx::DeleteMemberByName()
ThunkBytes = new byte[] { // ---------------------------------
0x41, 0x81, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, // and r8d,0FFFFFFFh
0x48, 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, 0x0D, 0xF0, 0xAD, 0xBA, // mov rax,0BAADF00DBAADF00Dh <- Target
0x48, 0xFF, 0xE0 // jmp rax
},
TargetOffset = 9
},
new VTablePatch {
SlotIndex = 13, // IDispatchEx::GetNextDispID()
ThunkBytes = new byte[] { // ----------------------------
0x81, 0xE2, 0xFF, 0xFF, 0xFF, 0x0F, // and edx,0FFFFFFFh
0x48, 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, 0x0D, 0xF0, 0xAD, 0xBA, // mov rax,0BAADF00DBAADF00Dh <- Target
0x48, 0xFF, 0xE0 // jmp rax
},
TargetOffset = 8
}
);
}
}
#endregion
#region Nested type: VTablePatch
private class VTablePatch
{
public int SlotIndex;
public byte[] ThunkBytes;
public int TargetOffset;
}
#endregion
}
}

Просмотреть файл

@ -66,6 +66,7 @@
//-----------------------------------------------------------------------------
#include <algorithm>
#include <cstdint>
#include <functional>
#include <queue>
#include <string>

Просмотреть файл

@ -288,6 +288,41 @@ bool HostObjectHelpers::IsDelegate(void* pvObject)
//-----------------------------------------------------------------------------
V8Value HostObjectHelpers::GetEnumerator(void* pvObject)
{
try
{
return V8ContextProxyImpl::ImportValue(V8ProxyHelpers::GetEnumeratorForHostObject(pvObject));
}
catch (Exception^ gcException)
{
ThrowHostException(pvObject, gcException);
}
}
//-----------------------------------------------------------------------------
bool HostObjectHelpers::AdvanceEnumerator(void* pvEnumerator, V8Value& value)
{
try
{
Object^ gcValue;
if (V8ProxyHelpers::AdvanceEnumerator(pvEnumerator, gcValue))
{
value = V8ContextProxyImpl::ImportValue(gcValue);
return true;
}
return false;
}
catch (Exception^ gcException)
{
ThrowHostException(pvEnumerator, gcException);
}
}
//-----------------------------------------------------------------------------
void* HostObjectHelpers::CreateV8ObjectCache()
{
return V8ProxyHelpers::CreateV8ObjectCache();

Просмотреть файл

@ -89,6 +89,9 @@ public:
static V8Value InvokeMethod(void* pvObject, const StdString& name, const std::vector<V8Value>& args);
static bool IsDelegate(void* pvObject);
static V8Value GetEnumerator(void* pvObject);
static bool AdvanceEnumerator(void* pvEnumerator, V8Value& value);
static void* CreateV8ObjectCache();
static void CacheV8Object(void* pvCache, void* pvObject, void* pvV8Object);
static void* GetCachedV8Object(void* pvCache, void* pvObject);

Просмотреть файл

@ -87,6 +87,7 @@ using namespace System;
using namespace System::Globalization;
using namespace System::Runtime::InteropServices;
using namespace System::Threading;
using namespace Microsoft::ClearScript::JavaScript;
using namespace Microsoft::ClearScript::Util;
//-----------------------------------------------------------------------------
@ -104,7 +105,7 @@ using namespace Microsoft::ClearScript::Util;
//-----------------------------------------------------------------------------
#define ENSURE_INTERNAL_CLASS(NAME) \
public ref class NAME##Hook \
public ref class NAME##Anchor \
{ \
private: \
static String^ m_gcName = NAME::typeid->Name; \

Просмотреть файл

@ -70,11 +70,11 @@ class Timer: public WeakRefTarget<Timer>
public:
Timer(unsigned int delay, bool repeating, std::function<void(Timer*)>&& func):
m_spTimer(std::make_shared<Concurrency::timer<int>>(delay, 0, nullptr, repeating)),
m_spTimer(new Concurrency::timer<int>(delay, 0, nullptr, repeating)),
m_Func(std::move(func))
{
auto wrTimer = CreateWeakRef();
m_spCall = std::make_shared<Concurrency::call<int>>([wrTimer] (int)
m_spCall = new Concurrency::call<int>([wrTimer] (int)
{
Concurrency::create_task([wrTimer]
{
@ -86,7 +86,7 @@ public:
});
});
m_spTimer->link_target(m_spCall.get());
m_spTimer->link_target(m_spCall);
}
void Start()
@ -111,7 +111,7 @@ private:
m_Func(this);
}
std::shared_ptr<Concurrency::timer<int>> m_spTimer;
std::shared_ptr<Concurrency::call<int>> m_spCall;
SharedPtr<Concurrency::timer<int>> m_spTimer;
SharedPtr<Concurrency::call<int>> m_spCall;
std::function<void(Timer*)> m_Func;
};

Просмотреть файл

@ -115,22 +115,6 @@ static V8ContextImpl* UnwrapContextImplFromData(const v8::FunctionCallbackInfo<T
//-----------------------------------------------------------------------------
template <typename T>
static void* UnwrapHostObject(const v8::PropertyCallbackInfo<T>& info)
{
return ::GetHostObject(info.Holder());
}
//-----------------------------------------------------------------------------
template <typename T>
static void* UnwrapHostObject(const v8::FunctionCallbackInfo<T>& info)
{
return ::GetHostObject(info.Holder());
}
//-----------------------------------------------------------------------------
template <typename T>
static T CombineFlags(T flag1, T flag2)
{
@ -195,6 +179,8 @@ V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name,
BEGIN_ISOLATE_SCOPE
auto propertyHandlerFlags = ::CombineFlags(v8::PropertyHandlerFlags::kNonMasking, v8::PropertyHandlerFlags::kOnlyInterceptStrings);
if (disableGlobalMembers)
{
m_hContext = CreatePersistent(CreateContext());
@ -203,7 +189,6 @@ V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name,
{
auto hGlobalTemplate = CreateObjectTemplate();
hGlobalTemplate->SetInternalFieldCount(1);
auto propertyHandlerFlags = ::CombineFlags(v8::PropertyHandlerFlags::kNonMasking, v8::PropertyHandlerFlags::kOnlyInterceptStrings);
hGlobalTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(GetGlobalProperty, SetGlobalProperty, QueryGlobalProperty, DeleteGlobalProperty, GetGlobalPropertyNames, v8::Local<v8::Value>(), propertyHandlerFlags));
hGlobalTemplate->SetHandler(v8::IndexedPropertyHandlerConfiguration(GetGlobalProperty, SetGlobalProperty, QueryGlobalProperty, DeleteGlobalProperty, GetGlobalPropertyIndices));
@ -219,30 +204,44 @@ V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const StdString& name,
m_hHostObjectCookieName = CreatePersistent(CreateString(StdString(L"{c2cf47d3-916b-4a3f-be2a-6ff567425808}")));
m_hHostExceptionName = CreatePersistent(CreateString(StdString(L"hostException")));
m_hEnumeratorPropertyName = CreatePersistent(CreateString(StdString(L"enumerator")));
m_hDonePropertyName = CreatePersistent(CreateString(StdString(L"done")));
m_hValuePropertyName = CreatePersistent(CreateString(StdString(L"value")));
m_hAccessTokenName = CreatePersistent(CreateString(StdString(L"{cdc19e6e-5d80-4627-a605-bb4805f15086}")));
v8::Local<v8::Function> hGetIteratorFunction;
v8::Local<v8::Function> hToFunctionFunction;
v8::Local<v8::Function> hNextFunction;
BEGIN_CONTEXT_SCOPE
hGetIteratorFunction = CreateFunction(GetIteratorForHostObject, Wrap());
hToFunctionFunction = CreateFunction(CreateFunctionForHostDelegate, Wrap());
hNextFunction = CreateFunction(AdvanceHostObjectIterator, Wrap());
m_hTerminationException = CreatePersistent(v8::Exception::Error(CreateString(StdString(L"Script execution was interrupted"))));
END_CONTEXT_SCOPE
m_hHostObjectTemplate = CreatePersistent(CreateFunctionTemplate());
m_hHostObjectTemplate->SetClassName(CreateString(StdString(L"HostObject")));
m_hHostObjectTemplate->SetCallHandler(HostObjectConstructorCallHandler, Wrap());
m_hHostObjectTemplate->InstanceTemplate()->SetInternalFieldCount(1);
m_hHostObjectTemplate->InstanceTemplate()->SetNamedPropertyHandler(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyNames, Wrap());
m_hHostObjectTemplate->InstanceTemplate()->SetIndexedPropertyHandler(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyIndices, Wrap());
m_hHostObjectTemplate->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyNames, Wrap(), propertyHandlerFlags));
m_hHostObjectTemplate->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyIndices, Wrap()));
m_hHostObjectTemplate->InstanceTemplate()->SetCallAsFunctionHandler(InvokeHostObject, Wrap());
v8::Local<v8::Function> hToFunction;
BEGIN_CONTEXT_SCOPE
hToFunction = CreateFunction(CreateFunctionForHostDelegate, Wrap());
m_hTerminationException = CreatePersistent(v8::Exception::Error(CreateString(StdString(L"Script execution was interrupted"))));
END_CONTEXT_SCOPE
m_hHostObjectTemplate->PrototypeTemplate()->Set(GetIteratorSymbol(), hGetIteratorFunction);
m_hHostDelegateTemplate = CreatePersistent(CreateFunctionTemplate());
m_hHostDelegateTemplate->SetClassName(CreateString(StdString(L"HostDelegate")));
m_hHostDelegateTemplate->SetCallHandler(HostObjectConstructorCallHandler, Wrap());
m_hHostDelegateTemplate->InstanceTemplate()->SetInternalFieldCount(1);
m_hHostDelegateTemplate->InstanceTemplate()->SetNamedPropertyHandler(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyNames, Wrap());
m_hHostDelegateTemplate->InstanceTemplate()->SetIndexedPropertyHandler(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyIndices, Wrap());
m_hHostDelegateTemplate->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyNames, Wrap(), propertyHandlerFlags));
m_hHostDelegateTemplate->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration(GetHostObjectProperty, SetHostObjectProperty, QueryHostObjectProperty, DeleteHostObjectProperty, GetHostObjectPropertyIndices, Wrap()));
m_hHostDelegateTemplate->InstanceTemplate()->SetCallAsFunctionHandler(InvokeHostObject, Wrap());
m_hHostDelegateTemplate->PrototypeTemplate()->Set(CreateString(StdString(L"toFunction")), hToFunction);
m_hHostDelegateTemplate->PrototypeTemplate()->Set(GetIteratorSymbol(), hGetIteratorFunction);
m_hHostDelegateTemplate->PrototypeTemplate()->Set(CreateString(StdString(L"toFunction")), hToFunctionFunction);
m_hHostIteratorTemplate = CreatePersistent(CreateFunctionTemplate());
m_hHostIteratorTemplate->SetClassName(CreateString(StdString(L"HostIterator")));
m_hHostIteratorTemplate->SetCallHandler(HostObjectConstructorCallHandler, Wrap());
m_hHostIteratorTemplate->PrototypeTemplate()->Set(CreateString(StdString(L"next")), hNextFunction);
m_spIsolateImpl->AddContext(this, enableDebugging, debugPort);
m_pvV8ObjectCache = HostObjectHelpers::CreateV8ObjectCache();
@ -340,7 +339,7 @@ void V8ContextImpl::SetGlobalProperty(const StdString& name, const V8Value& valu
hOldValue = m_hContext->Global()->GetRealNamedProperty(hName);
}
m_hContext->Global()->ForceSet(hName, hValue, (v8::PropertyAttribute)(v8::ReadOnly | v8::DontDelete));
m_hContext->Global()->ForceSet(hName, hValue, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
if (globalMembers && hValue->IsObject())
{
if (!hOldValue.IsEmpty() && hOldValue->IsObject())
@ -573,7 +572,7 @@ V8Value V8ContextImpl::InvokeV8Object(void* pvObject, const std::vector<V8Value>
BEGIN_CONTEXT_SCOPE
BEGIN_EXECUTION_SCOPE
auto hObject = ::ObjectHandleFromPtr(pvObject);
v8::Local<v8::Object> hObject = ::ObjectHandleFromPtr(pvObject);
std::vector<v8::Local<v8::Value>> importedArgs;
ImportValues(args, importedArgs);
@ -596,7 +595,7 @@ V8Value V8ContextImpl::InvokeV8ObjectMethod(void* pvObject, const StdString& nam
BEGIN_CONTEXT_SCOPE
BEGIN_EXECUTION_SCOPE
auto hObject = ::ObjectHandleFromPtr(pvObject);
v8::Local<v8::Object> hObject = ::ObjectHandleFromPtr(pvObject);
auto hName = CreateString(name);
if (!hObject->Has(hName))
@ -624,6 +623,84 @@ V8Value V8ContextImpl::InvokeV8ObjectMethod(void* pvObject, const StdString& nam
//-----------------------------------------------------------------------------
void V8ContextImpl::GetV8ObjectArrayBufferOrViewInfo(void* pvObject, V8Value& arrayBuffer, size_t& offset, size_t& size, size_t& length)
{
BEGIN_CONTEXT_SCOPE
v8::Local<v8::Object> hObject = ::ObjectHandleFromPtr(pvObject);
if (hObject->IsArrayBuffer())
{
auto hArrayBuffer = v8::Local<v8::ArrayBuffer>::Cast(hObject);
arrayBuffer = ExportValue(hObject);
offset = 0;
size = hArrayBuffer->ByteLength();
length = size;
return;
}
if (hObject->IsDataView())
{
auto hDataView = v8::Local<v8::DataView>::Cast(hObject);
arrayBuffer = ExportValue(hDataView->Buffer());
offset = hDataView->ByteOffset();
size = hDataView->ByteLength();
length = size;
return;
}
if (hObject->IsTypedArray())
{
auto hTypedArray = v8::Local<v8::TypedArray>::Cast(hObject);
arrayBuffer = ExportValue(hTypedArray->Buffer());
offset = hTypedArray->ByteOffset();
size = hTypedArray->ByteLength();
length = hTypedArray->Length();
return;
}
throw V8Exception(V8Exception::Type_General, m_Name, StdString(L"Object is not a V8 array buffer or view"));
END_CONTEXT_SCOPE
}
//-----------------------------------------------------------------------------
void V8ContextImpl::InvokeWithV8ObjectArrayBufferOrViewData(void* pvObject, V8ObjectHelpers::ArrayBufferOrViewDataCallbackT* pCallback, void* pvArg)
{
BEGIN_CONTEXT_SCOPE
v8::Local<v8::Object> hObject = ::ObjectHandleFromPtr(pvObject);
if (hObject->IsArrayBuffer())
{
auto hArrayBuffer = v8::Local<v8::ArrayBuffer>::Cast(hObject);
(*pCallback)(hArrayBuffer->GetContents().Data(), pvArg);
return;
}
if (hObject->IsDataView())
{
auto hDataView = v8::Local<v8::DataView>::Cast(hObject);
(*pCallback)(static_cast<std::uint8_t*>(hDataView->Buffer()->GetContents().Data()) + hDataView->ByteOffset(), pvArg);
return;
}
if (hObject->IsTypedArray())
{
auto hTypedArray = v8::Local<v8::TypedArray>::Cast(hObject);
(*pCallback)(static_cast<std::uint8_t*>(hTypedArray->Buffer()->GetContents().Data()) + hTypedArray->ByteOffset(), pvArg);
return;
}
throw V8Exception(V8Exception::Type_General, m_Name, StdString(L"Object is not a V8 array buffer or view"));
END_CONTEXT_SCOPE
}
//-----------------------------------------------------------------------------
void V8ContextImpl::ProcessDebugMessages()
{
BEGIN_CONTEXT_SCOPE
@ -658,10 +735,14 @@ V8ContextImpl::~V8ContextImpl()
Dispose(it->second);
}
Dispose(m_hHostIteratorTemplate);
Dispose(m_hHostDelegateTemplate);
Dispose(m_hHostObjectTemplate);
Dispose(m_hAccessToken);
Dispose(m_hAccessTokenName);
Dispose(m_hValuePropertyName);
Dispose(m_hDonePropertyName);
Dispose(m_hEnumeratorPropertyName);
Dispose(m_hHostExceptionName);
Dispose(m_hHostObjectCookieName);
@ -799,7 +880,7 @@ void V8ContextImpl::GetV8ObjectPropertyIndices(v8::Local<v8::Object> hObject, st
//-----------------------------------------------------------------------------
void V8ContextImpl::GetGlobalProperty(v8::Local<v8::Name> hName, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::GetGlobalProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -807,14 +888,14 @@ void V8ContextImpl::GetGlobalProperty(v8::Local<v8::Name> hName, const v8::Prope
const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
auto hKey = hName->ToString();
if (!hKey->Equals(pContextImpl->m_hHostObjectCookieName))
auto hName = hKey->ToString();
if (!hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
if (it->second->HasOwnProperty(hKey))
if (it->second->HasOwnProperty(hName))
{
CALLBACK_RETURN(it->second->Get(hKey));
CALLBACK_RETURN(it->second->Get(hName));
}
}
}
@ -824,7 +905,7 @@ void V8ContextImpl::GetGlobalProperty(v8::Local<v8::Name> hName, const v8::Prope
//-----------------------------------------------------------------------------
void V8ContextImpl::SetGlobalProperty(v8::Local<v8::Name> hName, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::SetGlobalProperty(v8::Local<v8::Name> hKey, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -832,14 +913,14 @@ void V8ContextImpl::SetGlobalProperty(v8::Local<v8::Name> hName, v8::Local<v8::V
const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
auto hKey = hName->ToString();
if (!hKey->Equals(pContextImpl->m_hHostObjectCookieName))
auto hName = hKey->ToString();
if (!hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
if (it->second->HasOwnProperty(hKey))
if (it->second->HasOwnProperty(hName))
{
it->second->Set(hKey, hValue);
it->second->Set(hName, hValue);
CALLBACK_RETURN(hValue);
}
}
@ -850,7 +931,7 @@ void V8ContextImpl::SetGlobalProperty(v8::Local<v8::Name> hName, v8::Local<v8::V
//-----------------------------------------------------------------------------
void V8ContextImpl::QueryGlobalProperty(v8::Local<v8::Name> hName, const v8::PropertyCallbackInfo<v8::Integer>& info)
void V8ContextImpl::QueryGlobalProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Integer>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -858,14 +939,14 @@ void V8ContextImpl::QueryGlobalProperty(v8::Local<v8::Name> hName, const v8::Pro
const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
auto hKey = hName->ToString();
if (!hKey->Equals(pContextImpl->m_hHostObjectCookieName))
auto hName = hKey->ToString();
if (!hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
if (it->second->HasOwnProperty(hKey))
if (it->second->HasOwnProperty(hName))
{
CALLBACK_RETURN(it->second->GetPropertyAttributes(hKey));
CALLBACK_RETURN(it->second->GetPropertyAttributes(hName));
}
}
}
@ -875,7 +956,7 @@ void V8ContextImpl::QueryGlobalProperty(v8::Local<v8::Name> hName, const v8::Pro
//-----------------------------------------------------------------------------
void V8ContextImpl::DeleteGlobalProperty(v8::Local<v8::Name> hName, const v8::PropertyCallbackInfo<v8::Boolean>& info)
void V8ContextImpl::DeleteGlobalProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Boolean>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -883,10 +964,10 @@ void V8ContextImpl::DeleteGlobalProperty(v8::Local<v8::Name> hName, const v8::Pr
const auto& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
{
auto hKey = hName->ToString();
auto hName = hKey->ToString();
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
if (it->second->HasOwnProperty(hKey))
if (it->second->HasOwnProperty(hName))
{
// WORKAROUND: v8::Object::Delete() crashes if a custom property deleter calls
// ThrowException(). Interestingly, there is no crash if the same deleter is
@ -896,7 +977,7 @@ void V8ContextImpl::DeleteGlobalProperty(v8::Local<v8::Name> hName, const v8::Pr
{
try
{
CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::GetHostObject(it->second), StdString(hKey)));
CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::GetHostObject(it->second), StdString(hName)));
}
catch (const HostException&)
{
@ -904,7 +985,7 @@ void V8ContextImpl::DeleteGlobalProperty(v8::Local<v8::Name> hName, const v8::Pr
}
}
CALLBACK_RETURN(it->second->Delete(hKey));
CALLBACK_RETURN(it->second->Delete(hName));
}
}
}
@ -961,7 +1042,7 @@ void V8ContextImpl::GetGlobalPropertyNames(const v8::PropertyCallbackInfo<v8::Ar
//-----------------------------------------------------------------------------
void V8ContextImpl::GetGlobalProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::GetGlobalProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -983,7 +1064,7 @@ void V8ContextImpl::GetGlobalProperty(unsigned __int32 index, const v8::Property
//-----------------------------------------------------------------------------
void V8ContextImpl::SetGlobalProperty(unsigned __int32 index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::SetGlobalProperty(std::uint32_t index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -1006,7 +1087,7 @@ void V8ContextImpl::SetGlobalProperty(unsigned __int32 index, v8::Local<v8::Valu
//-----------------------------------------------------------------------------
void V8ContextImpl::QueryGlobalProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Integer>& info)
void V8ContextImpl::QueryGlobalProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -1029,7 +1110,7 @@ void V8ContextImpl::QueryGlobalProperty(unsigned __int32 index, const v8::Proper
//-----------------------------------------------------------------------------
void V8ContextImpl::DeleteGlobalProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Boolean>& info)
void V8ContextImpl::DeleteGlobalProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)
{
auto pContextImpl = ::UnwrapContextImplFromHolder(info);
if (CheckContextImplForGlobalObjectCallback(pContextImpl))
@ -1110,12 +1191,70 @@ void V8ContextImpl::HostObjectConstructorCallHandler(const v8::FunctionCallbackI
//-----------------------------------------------------------------------------
void V8ContextImpl::GetIteratorForHostObject(const v8::FunctionCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (pContextImpl != nullptr)
{
try
{
auto hEnumerator = pContextImpl->ImportValue(HostObjectHelpers::GetEnumerator(::GetHostObject(info.Holder())));
v8::Local<v8::Object> hIterator;
BEGIN_PULSE_VALUE_SCOPE(&pContextImpl->m_AllowHostObjectConstructorCall, true)
hIterator = pContextImpl->m_hHostIteratorTemplate->InstanceTemplate()->NewInstance();
END_PULSE_VALUE_SCOPE
hIterator->SetHiddenValue(pContextImpl->m_hEnumeratorPropertyName, hEnumerator);
CALLBACK_RETURN(hIterator);
}
catch (const HostException& exception)
{
pContextImpl->ThrowScriptException(exception);
}
}
}
//-----------------------------------------------------------------------------
void V8ContextImpl::AdvanceHostObjectIterator(const v8::FunctionCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (pContextImpl != nullptr)
{
try
{
auto hEnumerator = info.Holder()->GetHiddenValue(pContextImpl->m_hEnumeratorPropertyName)->ToObject();
auto hResult = pContextImpl->CreateObject();
V8Value value(V8Value::Undefined);
if (HostObjectHelpers::AdvanceEnumerator(::GetHostObject(hEnumerator), value))
{
hResult->Set(pContextImpl->m_hDonePropertyName, pContextImpl->GetFalse());
hResult->Set(pContextImpl->m_hValuePropertyName, pContextImpl->ImportValue(value));
}
else
{
hResult->Set(pContextImpl->m_hDonePropertyName, pContextImpl->GetTrue());
}
CALLBACK_RETURN(hResult);
}
catch (const HostException& exception)
{
pContextImpl->ThrowScriptException(exception);
}
}
}
//-----------------------------------------------------------------------------
void V8ContextImpl::CreateFunctionForHostDelegate(const v8::FunctionCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (pContextImpl != nullptr)
{
CALLBACK_RETURN(pContextImpl->CreateFunction(InvokeHostDelegate, info.This()));
CALLBACK_RETURN(pContextImpl->CreateFunction(InvokeHostDelegate, info.Holder()));
}
}
@ -1154,13 +1293,14 @@ void V8ContextImpl::InvokeHostDelegate(const v8::FunctionCallbackInfo<v8::Value>
//-----------------------------------------------------------------------------
void V8ContextImpl::GetHostObjectProperty(v8::Local<v8::String> hName, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::GetHostObjectProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
auto hName = hKey->ToString();
if (hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
CALLBACK_RETURN(true);
@ -1184,11 +1324,11 @@ void V8ContextImpl::GetHostObjectProperty(v8::Local<v8::String> hName, const v8:
END_PULSE_VALUE_SCOPE
}
auto hResult = hHolder->GetHiddenValue(hName);
auto hResult = hHolder->GetRealNamedProperty(hName);
if (hResult.IsEmpty())
{
bool isCacheable;
hResult = pContextImpl->ImportValue(HostObjectHelpers::GetProperty(::UnwrapHostObject(info), StdString(hName), isCacheable));
hResult = pContextImpl->ImportValue(HostObjectHelpers::GetProperty(::GetHostObject(info.Holder()), StdString(hName), isCacheable));
if (isCacheable)
{
hHolder->ForceSet(hName, hResult);
@ -1206,14 +1346,15 @@ void V8ContextImpl::GetHostObjectProperty(v8::Local<v8::String> hName, const v8:
//-----------------------------------------------------------------------------
void V8ContextImpl::SetHostObjectProperty(v8::Local<v8::String> hName, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::SetHostObjectProperty(v8::Local<v8::Name> hKey, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
HostObjectHelpers::SetProperty(::UnwrapHostObject(info), StdString(hName), pContextImpl->ExportValue(hValue));
auto hName = hKey->ToString();
HostObjectHelpers::SetProperty(::GetHostObject(info.Holder()), StdString(hName), pContextImpl->ExportValue(hValue));
CALLBACK_RETURN(hValue);
}
catch (const HostException& exception)
@ -1225,20 +1366,21 @@ void V8ContextImpl::SetHostObjectProperty(v8::Local<v8::String> hName, v8::Local
//-----------------------------------------------------------------------------
void V8ContextImpl::QueryHostObjectProperty(v8::Local<v8::String> hName, const v8::PropertyCallbackInfo<v8::Integer>& info)
void V8ContextImpl::QueryHostObjectProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Integer>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
auto hName = hKey->ToString();
if (hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
CALLBACK_RETURN(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
}
std::vector<StdString> names;
HostObjectHelpers::GetPropertyNames(::UnwrapHostObject(info), names);
HostObjectHelpers::GetPropertyNames(::GetHostObject(info.Holder()), names);
StdString name(hName);
for (auto it = names.begin(); it != names.end(); it++)
@ -1258,14 +1400,15 @@ void V8ContextImpl::QueryHostObjectProperty(v8::Local<v8::String> hName, const v
//-----------------------------------------------------------------------------
void V8ContextImpl::DeleteHostObjectProperty(v8::Local<v8::String> hName, const v8::PropertyCallbackInfo<v8::Boolean>& info)
void V8ContextImpl::DeleteHostObjectProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Boolean>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::UnwrapHostObject(info), StdString(hName)));
auto hName = hKey->ToString();
CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::GetHostObject(info.Holder()), StdString(hName)));
}
catch (const HostException& exception)
{
@ -1284,7 +1427,7 @@ void V8ContextImpl::GetHostObjectPropertyNames(const v8::PropertyCallbackInfo<v8
try
{
std::vector<StdString> names;
HostObjectHelpers::GetPropertyNames(::UnwrapHostObject(info), names);
HostObjectHelpers::GetPropertyNames(::GetHostObject(info.Holder()), names);
auto nameCount = static_cast<int>(names.size());
auto hImportedNames = pContextImpl->CreateArray(nameCount);
@ -1304,14 +1447,14 @@ void V8ContextImpl::GetHostObjectPropertyNames(const v8::PropertyCallbackInfo<v8
//-----------------------------------------------------------------------------
void V8ContextImpl::GetHostObjectProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::GetHostObjectProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
CALLBACK_RETURN(pContextImpl->ImportValue(HostObjectHelpers::GetProperty(::UnwrapHostObject(info), index)));
CALLBACK_RETURN(pContextImpl->ImportValue(HostObjectHelpers::GetProperty(::GetHostObject(info.Holder()), index)));
}
catch (const HostException& exception)
{
@ -1322,14 +1465,14 @@ void V8ContextImpl::GetHostObjectProperty(unsigned __int32 index, const v8::Prop
//-----------------------------------------------------------------------------
void V8ContextImpl::SetHostObjectProperty(unsigned __int32 index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
void V8ContextImpl::SetHostObjectProperty(std::uint32_t index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
HostObjectHelpers::SetProperty(::UnwrapHostObject(info), index, pContextImpl->ExportValue(hValue));
HostObjectHelpers::SetProperty(::GetHostObject(info.Holder()), index, pContextImpl->ExportValue(hValue));
CALLBACK_RETURN(hValue);
}
catch (const HostException& exception)
@ -1341,7 +1484,7 @@ void V8ContextImpl::SetHostObjectProperty(unsigned __int32 index, v8::Local<v8::
//-----------------------------------------------------------------------------
void V8ContextImpl::QueryHostObjectProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Integer>& info)
void V8ContextImpl::QueryHostObjectProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
@ -1349,7 +1492,7 @@ void V8ContextImpl::QueryHostObjectProperty(unsigned __int32 index, const v8::Pr
try
{
std::vector<int> indices;
HostObjectHelpers::GetPropertyIndices(::UnwrapHostObject(info), indices);
HostObjectHelpers::GetPropertyIndices(::GetHostObject(info.Holder()), indices);
for (auto it = indices.begin(); it < indices.end(); it++)
{
@ -1368,14 +1511,14 @@ void V8ContextImpl::QueryHostObjectProperty(unsigned __int32 index, const v8::Pr
//-----------------------------------------------------------------------------
void V8ContextImpl::DeleteHostObjectProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Boolean>& info)
void V8ContextImpl::DeleteHostObjectProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)
{
auto pContextImpl = ::UnwrapContextImplFromData(info);
if (CheckContextImplForHostObjectCallback(pContextImpl))
{
try
{
CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::UnwrapHostObject(info), index));
CALLBACK_RETURN(HostObjectHelpers::DeleteProperty(::GetHostObject(info.Holder()), index));
}
catch (const HostException& exception)
{
@ -1394,7 +1537,7 @@ void V8ContextImpl::GetHostObjectPropertyIndices(const v8::PropertyCallbackInfo<
try
{
std::vector<int> indices;
HostObjectHelpers::GetPropertyIndices(::UnwrapHostObject(info), indices);
HostObjectHelpers::GetPropertyIndices(::GetHostObject(info.Holder()), indices);
auto indexCount = static_cast<int>(indices.size());
auto hImportedIndices = pContextImpl->CreateArray(indexCount);
@ -1431,7 +1574,7 @@ void V8ContextImpl::InvokeHostObject(const v8::FunctionCallbackInfo<v8::Value>&
exportedArgs.push_back(pContextImpl->ExportValue(info[index]));
}
CALLBACK_RETURN(pContextImpl->ImportValue(HostObjectHelpers::Invoke(::UnwrapHostObject(info), exportedArgs, info.IsConstructCall())));
CALLBACK_RETURN(pContextImpl->ImportValue(HostObjectHelpers::Invoke(::GetHostObject(info.Holder()), exportedArgs, info.IsConstructCall())));
}
catch (const HostException& exception)
{
@ -1489,7 +1632,7 @@ v8::Local<v8::Value> V8ContextImpl::ImportValue(const V8Value& value)
}
{
__int32 result;
std::int32_t result;
if (value.AsInt32(result))
{
return CreateInteger(result);
@ -1497,7 +1640,7 @@ v8::Local<v8::Value> V8ContextImpl::ImportValue(const V8Value& value)
}
{
unsigned __int32 result;
std::uint32_t result;
if (value.AsUInt32(result))
{
return CreateInteger(result);
@ -1553,7 +1696,8 @@ v8::Local<v8::Value> V8ContextImpl::ImportValue(const V8Value& value)
{
V8ObjectHolder* pHolder;
if (value.AsV8Object(pHolder))
V8Value::Subtype subtype;
if (value.AsV8Object(pHolder, subtype))
{
return CreateLocal(::ObjectHandleFromPtr(pHolder->GetObject()));
}
@ -1614,7 +1758,33 @@ V8Value V8ContextImpl::ExportValue(v8::Local<v8::Value> hValue)
return V8Value(::GetHostObjectHolder(hObject)->Clone());
}
return V8Value(new V8ObjectHolderImpl(GetWeakBinding(), ::PtrFromObjectHandle(CreatePersistent(hObject))));
auto subtype = V8Value::Subtype::None;
if (hObject->IsArrayBuffer())
subtype = V8Value::Subtype::ArrayBuffer;
else if (hObject->IsArrayBufferView())
if (hObject->IsDataView())
subtype = V8Value::Subtype::DataView;
else if (hObject->IsTypedArray())
if (hObject->IsUint8Array())
subtype = V8Value::Subtype::Uint8Array;
else if (hObject->IsUint8ClampedArray())
subtype = V8Value::Subtype::Uint8ClampedArray;
else if (hObject->IsInt8Array())
subtype = V8Value::Subtype::Int8Array;
else if (hObject->IsUint16Array())
subtype = V8Value::Subtype::Uint16Array;
else if (hObject->IsInt16Array())
subtype = V8Value::Subtype::Int16Array;
else if (hObject->IsUint32Array())
subtype = V8Value::Subtype::Uint32Array;
else if (hObject->IsInt32Array())
subtype = V8Value::Subtype::Int32Array;
else if (hObject->IsFloat32Array())
subtype = V8Value::Subtype::Float32Array;
else if (hObject->IsFloat64Array())
subtype = V8Value::Subtype::Float64Array;
return V8Value(new V8ObjectHolderImpl(GetWeakBinding(), ::PtrFromObjectHandle(CreatePersistent(hObject))), subtype);
}
return V8Value(V8Value::Undefined);

Просмотреть файл

@ -120,6 +120,9 @@ public:
V8Value InvokeV8Object(void* pvObject, const std::vector<V8Value>& args, bool asConstructor);
V8Value InvokeV8ObjectMethod(void* pvObject, const StdString& name, const std::vector<V8Value>& args);
void GetV8ObjectArrayBufferOrViewInfo(void* pvObject, V8Value& arrayBuffer, size_t& offset, size_t& size, size_t& length);
void InvokeWithV8ObjectArrayBufferOrViewData(void* pvObject, V8ObjectHelpers::ArrayBufferOrViewDataCallbackT* pCallback, void* pvArg);
void ProcessDebugMessages();
private:
@ -168,6 +171,11 @@ private:
return m_spIsolateImpl->GetFalse();
}
v8::Local<v8::Symbol> GetIteratorSymbol()
{
return m_spIsolateImpl->GetIteratorSymbol();
}
v8::Local<v8::Object> CreateObject()
{
return m_spIsolateImpl->CreateObject();
@ -178,12 +186,12 @@ private:
return m_spIsolateImpl->CreateNumber(value);
}
v8::Local<v8::Integer> CreateInteger(__int32 value)
v8::Local<v8::Integer> CreateInteger(std::int32_t value)
{
return m_spIsolateImpl->CreateInteger(value);
}
v8::Local<v8::Integer> CreateInteger(unsigned __int32 value)
v8::Local<v8::Integer> CreateInteger(std::uint32_t value)
{
return m_spIsolateImpl->CreateInteger(value);
}
@ -285,6 +293,11 @@ private:
return m_spIsolateImpl->IsExecutionTerminating();
}
void CancelTerminateExecution()
{
m_spIsolateImpl->CancelTerminateExecution();
}
int ContextDisposedNotification()
{
return m_spIsolateImpl->ContextDisposedNotification();
@ -318,32 +331,34 @@ private:
void GetV8ObjectPropertyNames(v8::Local<v8::Object> hObject, std::vector<StdString>& names);
void GetV8ObjectPropertyIndices(v8::Local<v8::Object> hObject, std::vector<int>& indices);
static void GetGlobalProperty(v8::Local<v8::Name> hName, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetGlobalProperty(v8::Local<v8::Name> hName, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryGlobalProperty(v8::Local<v8::Name> hName, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteGlobalProperty(v8::Local<v8::Name> hName, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetGlobalProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetGlobalProperty(v8::Local<v8::Name> hKey, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryGlobalProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteGlobalProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetGlobalPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info);
static void GetGlobalProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetGlobalProperty(unsigned __int32 index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryGlobalProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteGlobalProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetGlobalProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetGlobalProperty(std::uint32_t index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryGlobalProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteGlobalProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetGlobalPropertyIndices(const v8::PropertyCallbackInfo<v8::Array>& info);
static void HostObjectConstructorCallHandler(const v8::FunctionCallbackInfo<v8::Value>& info);
static void GetIteratorForHostObject(const v8::FunctionCallbackInfo<v8::Value>& info);
static void AdvanceHostObjectIterator(const v8::FunctionCallbackInfo<v8::Value>& info);
static void CreateFunctionForHostDelegate(const v8::FunctionCallbackInfo<v8::Value>& info);
static void InvokeHostDelegate(const v8::FunctionCallbackInfo<v8::Value>& info);
static void GetHostObjectProperty(v8::Local<v8::String> hName, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetHostObjectProperty(v8::Local<v8::String> hName, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryHostObjectProperty(v8::Local<v8::String> hName, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteHostObjectProperty(v8::Local<v8::String> hName, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetHostObjectProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetHostObjectProperty(v8::Local<v8::Name> hKey, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryHostObjectProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteHostObjectProperty(v8::Local<v8::Name> hKey, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetHostObjectPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info);
static void GetHostObjectProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetHostObjectProperty(unsigned __int32 index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryHostObjectProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteHostObjectProperty(unsigned __int32 index, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetHostObjectProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info);
static void SetHostObjectProperty(std::uint32_t index, v8::Local<v8::Value> hValue, const v8::PropertyCallbackInfo<v8::Value>& info);
static void QueryHostObjectProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info);
static void DeleteHostObjectProperty(std::uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info);
static void GetHostObjectPropertyIndices(const v8::PropertyCallbackInfo<v8::Array>& info);
static void InvokeHostObject(const v8::FunctionCallbackInfo<v8::Value>& info);
@ -364,10 +379,14 @@ private:
std::vector<std::pair<StdString, Persistent<v8::Object>>> m_GlobalMembersStack;
Persistent<v8::String> m_hHostObjectCookieName;
Persistent<v8::String> m_hHostExceptionName;
Persistent<v8::String> m_hEnumeratorPropertyName;
Persistent<v8::String> m_hDonePropertyName;
Persistent<v8::String> m_hValuePropertyName;
Persistent<v8::String> m_hAccessTokenName;
Persistent<v8::Object> m_hAccessToken;
Persistent<v8::FunctionTemplate> m_hHostObjectTemplate;
Persistent<v8::FunctionTemplate> m_hHostDelegateTemplate;
Persistent<v8::FunctionTemplate> m_hHostIteratorTemplate;
Persistent<v8::Value> m_hTerminationException;
SharedPtr<V8WeakContextBinding> m_spWeakBinding;
void* m_pvV8ObjectCache;

Просмотреть файл

@ -69,9 +69,9 @@ namespace V8 {
// local helper functions
//-------------------------------------------------------------------------
static void InvokeAction(void* pvActionRef)
static void LockCallback(void* pvArg)
{
(*static_cast<Action^*>(pvActionRef))();
(*static_cast<Action^*>(pvArg))();
}
//-------------------------------------------------------------------------
@ -140,7 +140,7 @@ namespace V8 {
{
try
{
GetContext()->CallWithLock(InvokeAction, &gcAction);
GetContext()->CallWithLock(LockCallback, &gcAction);
}
catch (const V8Exception& exception)
{
@ -433,7 +433,7 @@ namespace V8 {
auto gcValue = dynamic_cast<V8ObjectImpl^>(gcObject);
if (gcValue != nullptr)
{
return V8Value(gcValue->GetHolder()->Clone());
return V8Value(gcValue->GetHolder()->Clone(), gcValue->GetSubtype());
}
}
@ -476,7 +476,7 @@ namespace V8 {
}
{
__int32 result;
std::int32_t result;
if (value.AsInt32(result))
{
return result;
@ -484,7 +484,7 @@ namespace V8 {
}
{
unsigned __int32 result;
std::uint32_t result;
if (value.AsUInt32(result))
{
return result;
@ -501,9 +501,10 @@ namespace V8 {
{
V8ObjectHolder* pHolder;
if (value.AsV8Object(pHolder))
V8Value::Subtype subtype;
if (value.AsV8Object(pHolder, subtype))
{
return gcnew V8ObjectImpl(pHolder->Clone());
return gcnew V8ObjectImpl(pHolder->Clone(), subtype);
}
}

Просмотреть файл

@ -73,6 +73,9 @@ public:
virtual void CallOnBackgroundThread(v8::Task* pTask, ExpectedRuntime runtime) override;
virtual void CallOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask) override;
virtual void CallDelayedOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask, double delayInSeconds) override;
virtual void CallIdleOnForegroundThread(v8::Isolate* pIsolate, v8::IdleTask* pTask) override;
virtual bool IdleTasksEnabled(v8::Isolate* pIsolate) override;
virtual double MonotonicallyIncreasingTime() override;
private:
@ -98,13 +101,30 @@ void V8Platform::EnsureInstalled()
void V8Platform::CallOnBackgroundThread(v8::Task* pTask, ExpectedRuntime /*runtime*/)
{
std::shared_ptr<v8::Task> spTask(pTask);
Concurrency::create_task([spTask] { spTask->Run(); });
SharedPtr<v8::Task> spTask(pTask);
Concurrency::create_task([spTask]
{
spTask->Run();
});
}
//-----------------------------------------------------------------------------
void V8Platform::CallOnForegroundThread(v8::Isolate* /*pIsolate*/, v8::Task* /*pTask*/)
void V8Platform::CallOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask)
{
static_cast<V8IsolateImpl*>(pIsolate->GetData(0))->RunTaskWithLock(pTask);
}
//-----------------------------------------------------------------------------
void V8Platform::CallDelayedOnForegroundThread(v8::Isolate* pIsolate, v8::Task* pTask, double delayInSeconds)
{
static_cast<V8IsolateImpl*>(pIsolate->GetData(0))->RunDelayedTaskWithLock(pTask, delayInSeconds);
}
//-----------------------------------------------------------------------------
void V8Platform::CallIdleOnForegroundThread(v8::Isolate* /*pIsolate*/, v8::IdleTask* /*pTask*/)
{
// unexpected call to unsupported method
std::terminate();
@ -112,6 +132,13 @@ void V8Platform::CallOnForegroundThread(v8::Isolate* /*pIsolate*/, v8::Task* /*p
//-----------------------------------------------------------------------------
bool V8Platform::IdleTasksEnabled(v8::Isolate* /*pIsolate*/)
{
return false;
}
//-----------------------------------------------------------------------------
double V8Platform::MonotonicallyIncreasingTime()
{
return HighResolutionClock::GetRelativeSeconds();
@ -136,7 +163,7 @@ class V8ArrayBufferAllocator: public v8::ArrayBuffer::Allocator
{
public:
static void EnsureInstalled();
static V8ArrayBufferAllocator& GetInstance();
virtual void* Allocate(size_t size) override;
virtual void* AllocateUninitialized(size_t size) override;
@ -152,12 +179,9 @@ private:
//-----------------------------------------------------------------------------
void V8ArrayBufferAllocator::EnsureInstalled()
V8ArrayBufferAllocator& V8ArrayBufferAllocator::GetInstance()
{
std::call_once(ms_InstallationFlag, []
{
v8::V8::SetArrayBufferAllocator(&ms_Instance);
});
return ms_Instance;
}
//-----------------------------------------------------------------------------
@ -241,9 +265,9 @@ V8IsolateImpl::V8IsolateImpl(const StdString& name, const V8IsolateConstraints*
m_IsExecutionTerminating(false)
{
V8Platform::EnsureInstalled();
V8ArrayBufferAllocator::EnsureInstalled();
v8::Isolate::CreateParams params;
params.array_buffer_allocator = &V8ArrayBufferAllocator::GetInstance();
if (pConstraints != nullptr)
{
params.constraints.set_max_semi_space_size(pConstraints->GetMaxNewSpaceSize());
@ -318,19 +342,18 @@ void V8IsolateImpl::EnableDebugging(int debugPort)
}
auto wrIsolate = CreateWeakRef();
m_pvDebugAgent = HostObjectHelpers::CreateDebugAgent(m_Name, version, debugPort, [wrIsolate] (HostObjectHelpers::DebugDirective directive, const StdString* pCommand)
m_pvDebugAgent = HostObjectHelpers::CreateDebugAgent(m_Name, version, debugPort, [this, wrIsolate] (HostObjectHelpers::DebugDirective directive, const StdString* pCommand)
{
auto spIsolate = wrIsolate.GetTarget();
if (!spIsolate.IsEmpty())
{
auto pIsolateImpl = static_cast<V8IsolateImpl*>(spIsolate.GetRawPtr());
if ((directive == HostObjectHelpers::DebugDirective::SendDebugCommand) && pCommand)
{
pIsolateImpl->SendDebugCommand(*pCommand);
SendDebugCommand(*pCommand);
}
else if (directive == HostObjectHelpers::DebugDirective::DispatchDebugMessages)
{
pIsolateImpl->DispatchDebugMessages();
DispatchDebugMessages();
}
}
});
@ -494,6 +517,54 @@ void V8IsolateImpl::ReleaseV8Script(void* pvScript)
//-----------------------------------------------------------------------------
void V8IsolateImpl::RunTaskWithLock(v8::Task* pTask)
{
SharedPtr<v8::Task> spTask(pTask);
auto wrIsolate = CreateWeakRef();
Concurrency::create_task([this, wrIsolate, spTask]
{
auto spIsolate = wrIsolate.GetTarget();
if (!spIsolate.IsEmpty())
{
CallWithLockNoWait([spTask] (V8IsolateImpl* /*pIsolateImpl*/)
{
spTask->Run();
});
}
});
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::RunDelayedTaskWithLock(v8::Task* pTask, double delayInSeconds)
{
SharedPtr<v8::Task> spTask(pTask);
auto wrIsolate = CreateWeakRef();
SharedPtr<Timer> spTimer(new Timer(static_cast<unsigned int>(delayInSeconds * 1000), false, [this, wrIsolate, spTask] (Timer* pTimer)
{
auto spIsolate = wrIsolate.GetTarget();
if (!spIsolate.IsEmpty())
{
CallWithLockNoWait([spTask] (V8IsolateImpl* /*pIsolateImpl*/)
{
spTask->Run();
});
BEGIN_MUTEX_SCOPE(m_DataMutex)
m_TaskTimers.erase(std::remove(m_TaskTimers.begin(), m_TaskTimers.end(), pTimer), m_TaskTimers.end());
END_MUTEX_SCOPE
}
}));
BEGIN_MUTEX_SCOPE(m_DataMutex)
m_TaskTimers.push_back(spTimer);
END_MUTEX_SCOPE
spTimer->Start();
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::CallWithLockNoWait(std::function<void(V8IsolateImpl*)>&& callback)
{
if (m_Mutex.TryLock())
@ -545,7 +616,7 @@ void V8IsolateImpl::CallWithLockAsync(std::function<void(V8IsolateImpl*)>&& call
{
size_t queueLength;
BEGIN_MUTEX_SCOPE(m_CallWithLockQueueMutex)
BEGIN_MUTEX_SCOPE(m_DataMutex)
m_CallWithLockQueue.push(std::move(callback));
queueLength = m_CallWithLockQueue.size();
END_MUTEX_SCOPE
@ -570,7 +641,7 @@ void V8IsolateImpl::ProcessCallWithLockQueue()
{
std::queue<std::function<void(V8IsolateImpl*)>> callWithLockQueue;
BEGIN_MUTEX_SCOPE(m_CallWithLockQueueMutex)
BEGIN_MUTEX_SCOPE(m_DataMutex)
std::swap(callWithLockQueue, m_CallWithLockQueue);
END_MUTEX_SCOPE
@ -585,7 +656,7 @@ void V8IsolateImpl::ProcessCallWithLockQueue()
void V8IsolateImpl::SendDebugCommand(const StdString& command)
{
v8::Debug::SendCommand(m_pIsolate, command.ToCString(), command.GetLength());
v8::Debug::SendCommand(m_pIsolate, reinterpret_cast<const uint16_t*>(command.ToCString()), command.GetLength());
}
//-----------------------------------------------------------------------------
@ -686,7 +757,7 @@ void V8IsolateImpl::EnterExecutionScope(size_t* pStackMarker)
}
// set and record stack address limit
m_pIsolate->SetStackLimit(reinterpret_cast<uintptr_t>(pStackLimit));
m_pIsolate->SetStackLimit(reinterpret_cast<std::uintptr_t>(pStackLimit));
m_pStackLimit = pStackLimit;
// enter outermost stack usage monitoring scope
@ -716,6 +787,9 @@ void V8IsolateImpl::ExitExecutionScope()
{
_ASSERTE(IsCurrent() && IsLocked());
// cancel termination to allow remaining script frames to execute
CancelTerminateExecution();
// is stack usage monitoring in progress?
if (m_StackWatchLevel > 0)
{
@ -726,7 +800,7 @@ void V8IsolateImpl::ExitExecutionScope()
if (m_pStackLimit != nullptr)
{
// V8 has no API for removing a stack address limit
m_pIsolate->SetStackLimit(reinterpret_cast<uintptr_t>(s_pMinStackLimit));
m_pIsolate->SetStackLimit(reinterpret_cast<std::uintptr_t>(s_pMinStackLimit));
m_pStackLimit = nullptr;
}
}
@ -752,7 +826,7 @@ void V8IsolateImpl::SetUpHeapWatchTimer(size_t maxHeapSize)
// create heap watch timer
auto wrIsolate = CreateWeakRef();
m_spHeapWatchTimer = new Timer(static_cast<unsigned int>(std::max(GetHeapSizeSampleInterval(), 250.0)), false, [wrIsolate, maxHeapSize] (Timer* pTimer)
m_spHeapWatchTimer = new Timer(static_cast<unsigned int>(std::max(GetHeapSizeSampleInterval(), 250.0)), false, [this, wrIsolate, maxHeapSize] (Timer* pTimer)
{
// heap watch callback; is the isolate still alive?
auto spIsolate = wrIsolate.GetTarget();
@ -760,7 +834,7 @@ void V8IsolateImpl::SetUpHeapWatchTimer(size_t maxHeapSize)
{
// yes; request callback on execution thread
auto wrTimer = pTimer->CreateWeakRef();
static_cast<V8IsolateImpl*>(spIsolate.GetRawPtr())->CallWithLockAsync([wrTimer, maxHeapSize] (V8IsolateImpl* pIsolateImpl)
CallWithLockAsync([wrTimer, maxHeapSize] (V8IsolateImpl* pIsolateImpl)
{
// execution thread callback; is the timer still alive?
auto spTimer = wrTimer.GetTarget();

Просмотреть файл

@ -178,6 +178,11 @@ public:
return v8::False(m_pIsolate);
}
v8::Local<v8::Symbol> GetIteratorSymbol()
{
return v8::Symbol::GetIterator(m_pIsolate);
}
v8::Local<v8::Object> CreateObject()
{
return v8::Object::New(m_pIsolate);
@ -188,12 +193,12 @@ public:
return v8::Number::New(m_pIsolate, value);
}
v8::Local<v8::Integer> CreateInteger(__int32 value)
v8::Local<v8::Integer> CreateInteger(std::int32_t value)
{
return v8::Int32::New(m_pIsolate, value);
}
v8::Local<v8::Integer> CreateInteger(unsigned __int32 value)
v8::Local<v8::Integer> CreateInteger(std::uint32_t value)
{
return v8::Uint32::NewFromUnsigned(m_pIsolate, value);
}
@ -296,6 +301,12 @@ public:
return m_pIsolate->IsExecutionTerminating() || m_IsExecutionTerminating;
}
void CancelTerminateExecution()
{
m_pIsolate->CancelTerminateExecution();
m_IsExecutionTerminating = false;
}
int ContextDisposedNotification()
{
return m_pIsolate->ContextDisposedNotification();
@ -355,6 +366,9 @@ public:
void* AddRefV8Script(void* pvScript);
void ReleaseV8Script(void* pvScript);
void RunTaskWithLock(v8::Task* pTask);
void RunDelayedTaskWithLock(v8::Task* pTask, double delayInSeconds);
void CallWithLockNoWait(std::function<void(V8IsolateImpl*)>&& callback);
void DECLSPEC_NORETURN ThrowOutOfMemoryException();
@ -382,8 +396,9 @@ private:
v8::Isolate* m_pIsolate;
RecursiveMutex m_Mutex;
std::list<V8ContextImpl*> m_ContextPtrs;
SimpleMutex m_CallWithLockQueueMutex;
SimpleMutex m_DataMutex;
std::queue<std::function<void(V8IsolateImpl*)>> m_CallWithLockQueue;
std::vector<SharedPtr<Timer>> m_TaskTimers;
bool m_DebuggingEnabled;
int m_DebugPort;
void* m_pvDebugAgent;

Просмотреть файл

@ -141,3 +141,17 @@ V8Value V8ObjectHelpers::InvokeMethod(V8ObjectHolder* pHolder, const StdString&
{
return GetHolderImpl(pHolder)->InvokeMethod(name, args);
}
//-----------------------------------------------------------------------------
void V8ObjectHelpers::GetArrayBufferOrViewInfo(V8ObjectHolder* pHolder, V8Value& arrayBuffer, size_t& offset, size_t& size, size_t& length)
{
return GetHolderImpl(pHolder)->GetArrayBufferOrViewInfo(arrayBuffer, offset, size, length);
}
//-----------------------------------------------------------------------------
void V8ObjectHelpers::InvokeWithArrayBufferOrViewData(V8ObjectHolder* pHolder, ArrayBufferOrViewDataCallbackT* pCallback, void* pvArg)
{
return GetHolderImpl(pHolder)->InvokeWithArrayBufferOrViewData(pCallback, pvArg);
}

Просмотреть файл

@ -83,4 +83,8 @@ public:
static V8Value Invoke(V8ObjectHolder* pHolder, const std::vector<V8Value>& args, bool asConstructor);
static V8Value InvokeMethod(V8ObjectHolder* pHolder, const StdString& name, const std::vector<V8Value>& args);
typedef void ArrayBufferOrViewDataCallbackT(void* pvData, void* pvArg);
static void GetArrayBufferOrViewInfo(V8ObjectHolder* pHolder, V8Value& arrayBuffer, size_t& offset, size_t& size, size_t& length);
static void InvokeWithArrayBufferOrViewData(V8ObjectHolder* pHolder, ArrayBufferOrViewDataCallbackT* pCallback, void* pvArg);
};

Просмотреть файл

@ -157,6 +157,20 @@ V8Value V8ObjectHolderImpl::InvokeMethod(const StdString& name, const std::vecto
//-----------------------------------------------------------------------------
void V8ObjectHolderImpl::GetArrayBufferOrViewInfo(V8Value& arrayBuffer, size_t& offset, size_t& size, size_t& length) const
{
m_spBinding->GetContextImpl()->GetV8ObjectArrayBufferOrViewInfo(m_pvObject, arrayBuffer, offset, size, length);
}
//-----------------------------------------------------------------------------
void V8ObjectHolderImpl::InvokeWithArrayBufferOrViewData(V8ObjectHelpers::ArrayBufferOrViewDataCallbackT* pCallback, void* pvArg) const
{
m_spBinding->GetContextImpl()->InvokeWithV8ObjectArrayBufferOrViewData(m_pvObject, pCallback, pvArg);
}
//-----------------------------------------------------------------------------
V8ObjectHolderImpl::~V8ObjectHolderImpl()
{
SharedPtr<V8IsolateImpl> spIsolateImpl;

Просмотреть файл

@ -89,6 +89,9 @@ public:
V8Value Invoke(const std::vector<V8Value>& args, bool asConstructor) const;
V8Value InvokeMethod(const StdString& name, const std::vector<V8Value>& args) const;
void GetArrayBufferOrViewInfo(V8Value& arrayBuffer, size_t& offset, size_t& size, size_t& length) const;
void InvokeWithArrayBufferOrViewData(V8ObjectHelpers::ArrayBufferOrViewDataCallbackT* pCallback, void* pvArg) const;
~V8ObjectHolderImpl();
private:

Просмотреть файл

@ -65,13 +65,23 @@ namespace Microsoft {
namespace ClearScript {
namespace V8 {
//-------------------------------------------------------------------------
// local helper functions
//-------------------------------------------------------------------------
static void ArrayBufferOrViewDataCallback(void* pvData, void* pvArg)
{
(*static_cast<Action<IntPtr>^*>(pvArg))(IntPtr(pvData));
}
//-------------------------------------------------------------------------
// V8ObjectImpl implementation
//-------------------------------------------------------------------------
V8ObjectImpl::V8ObjectImpl(V8ObjectHolder* pHolder):
V8ObjectImpl::V8ObjectImpl(V8ObjectHolder* pHolder, V8Value::Subtype subtype):
m_gcLock(gcnew Object),
m_pspHolder(new SharedPtr<V8ObjectHolder>(pHolder))
m_pspHolder(new SharedPtr<V8ObjectHolder>(pHolder)),
m_Subtype(subtype)
{
}
@ -251,6 +261,85 @@ namespace V8 {
//-------------------------------------------------------------------------
bool V8ObjectImpl::IsArrayBufferOrView()
{
return m_Subtype != V8Value::Subtype::None;
}
//-------------------------------------------------------------------------
V8ArrayBufferOrViewKind V8ObjectImpl::GetArrayBufferOrViewKind()
{
auto kind = V8ArrayBufferOrViewKind::None;
if (m_Subtype == V8Value::Subtype::ArrayBuffer)
kind = V8ArrayBufferOrViewKind::ArrayBuffer;
else if (m_Subtype == V8Value::Subtype::DataView)
kind = V8ArrayBufferOrViewKind::DataView;
else if (m_Subtype == V8Value::Subtype::Uint8Array)
kind = V8ArrayBufferOrViewKind::Uint8Array;
else if (m_Subtype == V8Value::Subtype::Uint8ClampedArray)
kind = V8ArrayBufferOrViewKind::Uint8ClampedArray;
else if (m_Subtype == V8Value::Subtype::Int8Array)
kind = V8ArrayBufferOrViewKind::Int8Array;
else if (m_Subtype == V8Value::Subtype::Uint16Array)
kind = V8ArrayBufferOrViewKind::Uint16Array;
else if (m_Subtype == V8Value::Subtype::Int16Array)
kind = V8ArrayBufferOrViewKind::Int16Array;
else if (m_Subtype == V8Value::Subtype::Uint32Array)
kind = V8ArrayBufferOrViewKind::Uint32Array;
else if (m_Subtype == V8Value::Subtype::Int32Array)
kind = V8ArrayBufferOrViewKind::Int32Array;
else if (m_Subtype == V8Value::Subtype::Float32Array)
kind = V8ArrayBufferOrViewKind::Float32Array;
else if (m_Subtype == V8Value::Subtype::Float64Array)
kind = V8ArrayBufferOrViewKind::Float64Array;
return kind;
}
//-------------------------------------------------------------------------
V8ArrayBufferOrViewInfo^ V8ObjectImpl::GetArrayBufferOrViewInfo()
{
try
{
auto kind = GetArrayBufferOrViewKind();
if (kind != V8ArrayBufferOrViewKind::None)
{
V8Value arrayBuffer(V8Value::Null);
size_t offset;
size_t size;
size_t length;
V8ObjectHelpers::GetArrayBufferOrViewInfo(GetHolder(), arrayBuffer, offset, size, length);
return gcnew V8ArrayBufferOrViewInfo(kind, (IV8Object^)V8ContextProxyImpl::ExportValue(arrayBuffer), offset, size, length);
}
return nullptr;
}
catch (const V8Exception& exception)
{
exception.ThrowScriptEngineException();
}
}
//-------------------------------------------------------------------------
void V8ObjectImpl::InvokeWithArrayBufferOrViewData(Action<IntPtr>^ gcAction)
{
try
{
V8ObjectHelpers::InvokeWithArrayBufferOrViewData(GetHolder(), ArrayBufferOrViewDataCallback, &gcAction);
}
catch (const V8Exception& exception)
{
exception.ThrowScriptEngineException();
}
}
//-------------------------------------------------------------------------
SharedPtr<V8ObjectHolder> V8ObjectImpl::GetHolder()
{
BEGIN_LOCK_SCOPE(m_gcLock)
@ -267,6 +356,13 @@ namespace V8 {
//-------------------------------------------------------------------------
V8Value::Subtype V8ObjectImpl::GetSubtype()
{
return m_Subtype;
}
//-------------------------------------------------------------------------
V8ObjectImpl::~V8ObjectImpl()
{
SharedPtr<V8ObjectHolder> spHolder;

Просмотреть файл

@ -73,7 +73,7 @@ namespace V8 {
{
public:
V8ObjectImpl(V8ObjectHolder* pHolder);
V8ObjectImpl(V8ObjectHolder* pHolder, V8Value::Subtype subtype);
virtual Object^ GetProperty(String^ gcName);
virtual Object^ GetProperty(String^ gcName, [Out] Boolean% isCacheable);
@ -89,7 +89,13 @@ namespace V8 {
virtual Object^ Invoke(array<Object^>^ gcArgs, bool asConstructor);
virtual Object^ InvokeMethod(String^ gcName, array<Object^>^ gcArgs);
virtual bool IsArrayBufferOrView();
virtual V8ArrayBufferOrViewKind GetArrayBufferOrViewKind();
virtual V8ArrayBufferOrViewInfo^ GetArrayBufferOrViewInfo();
virtual void InvokeWithArrayBufferOrViewData(Action<IntPtr>^ gcAction);
SharedPtr<V8ObjectHolder> GetHolder();
V8Value::Subtype GetSubtype();
~V8ObjectImpl();
!V8ObjectImpl();
@ -100,6 +106,7 @@ namespace V8 {
Object^ m_gcLock;
SharedPtr<V8ObjectHolder>* m_pspHolder;
V8Value::Subtype m_Subtype;
};
}}}

Просмотреть файл

@ -84,59 +84,85 @@ public:
Null
};
enum class Subtype: std::uint16_t
{
None,
ArrayBuffer,
DataView,
Uint8Array,
Uint8ClampedArray,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Float32Array,
Float64Array
};
explicit V8Value(NonexistentInitializer):
m_Type(Type_Nonexistent)
m_Type(Type::Nonexistent),
m_Subtype(Subtype::None)
{
}
explicit V8Value(UndefinedInitializer):
m_Type(Type_Undefined)
m_Type(Type::Undefined),
m_Subtype(Subtype::None)
{
}
explicit V8Value(NullInitializer):
m_Type(Type_Null)
m_Type(Type::Null),
m_Subtype(Subtype::None)
{
}
explicit V8Value(bool value):
m_Type(Type_Boolean)
m_Type(Type::Boolean),
m_Subtype(Subtype::None)
{
m_Data.BooleanValue = value;
}
explicit V8Value(double value):
m_Type(Type_Number)
m_Type(Type::Number),
m_Subtype(Subtype::None)
{
m_Data.DoubleValue = value;
}
explicit V8Value(__int32 value):
m_Type(Type_Int32)
explicit V8Value(std::int32_t value):
m_Type(Type::Int32),
m_Subtype(Subtype::None)
{
m_Data.Int32Value = value;
}
explicit V8Value(unsigned __int32 value):
m_Type(Type_UInt32)
explicit V8Value(std::uint32_t value):
m_Type(Type::UInt32),
m_Subtype(Subtype::None)
{
m_Data.UInt32Value = value;
}
explicit V8Value(const StdString* pString):
m_Type(Type_String)
m_Type(Type::String),
m_Subtype(Subtype::None)
{
m_Data.pString = pString;
}
explicit V8Value(V8ObjectHolder* pV8ObjectHolder):
m_Type(Type_V8Object)
V8Value(V8ObjectHolder* pV8ObjectHolder, Subtype subtype):
m_Type(Type::V8Object),
m_Subtype(subtype)
{
m_Data.pV8ObjectHolder = pV8ObjectHolder;
}
explicit V8Value(HostObjectHolder* pHostObjectHolder):
m_Type(Type_HostObject)
m_Type(Type::HostObject),
m_Subtype(Subtype::None)
{
m_Data.pHostObjectHolder = pHostObjectHolder;
}
@ -167,22 +193,22 @@ public:
bool IsNonexistent() const
{
return m_Type == Type_Nonexistent;
return m_Type == Type::Nonexistent;
}
bool IsUndefined() const
{
return m_Type == Type_Undefined;
return m_Type == Type::Undefined;
}
bool IsNull() const
{
return m_Type == Type_Null;
return m_Type == Type::Null;
}
bool AsBoolean(bool& result) const
{
if (m_Type == Type_Boolean)
if (m_Type == Type::Boolean)
{
result = m_Data.BooleanValue;
return true;
@ -193,7 +219,7 @@ public:
bool AsNumber(double& result) const
{
if (m_Type == Type_Number)
if (m_Type == Type::Number)
{
result = m_Data.DoubleValue;
return true;
@ -202,9 +228,9 @@ public:
return false;
}
bool AsInt32(__int32& result) const
bool AsInt32(std::int32_t& result) const
{
if (m_Type == Type_Int32)
if (m_Type == Type::Int32)
{
result = m_Data.Int32Value;
return true;
@ -213,9 +239,9 @@ public:
return false;
}
bool AsUInt32(unsigned __int32& result) const
bool AsUInt32(std::uint32_t& result) const
{
if (m_Type == Type_UInt32)
if (m_Type == Type::UInt32)
{
result = m_Data.UInt32Value;
return true;
@ -226,7 +252,7 @@ public:
bool AsString(const StdString*& pString) const
{
if (m_Type == Type_String)
if (m_Type == Type::String)
{
pString = m_Data.pString;
return true;
@ -235,11 +261,12 @@ public:
return false;
}
bool AsV8Object(V8ObjectHolder*& pV8ObjectHolder) const
bool AsV8Object(V8ObjectHolder*& pV8ObjectHolder, Subtype& subtype) const
{
if (m_Type == Type_V8Object)
if (m_Type == Type::V8Object)
{
pV8ObjectHolder = m_Data.pV8ObjectHolder;
subtype = m_Subtype;
return true;
}
@ -248,7 +275,7 @@ public:
bool AsHostObject(HostObjectHolder*& pHostObjectHolder) const
{
if (m_Type == Type_HostObject)
if (m_Type == Type::HostObject)
{
pHostObjectHolder = m_Data.pHostObjectHolder;
return true;
@ -264,26 +291,26 @@ public:
private:
enum Type
enum class Type: std::uint16_t
{
Type_Nonexistent,
Type_Undefined,
Type_Null,
Type_Boolean,
Type_Number,
Type_Int32,
Type_UInt32,
Type_String,
Type_V8Object,
Type_HostObject
Nonexistent,
Undefined,
Null,
Boolean,
Number,
Int32,
UInt32,
String,
V8Object,
HostObject
};
union Data
{
bool BooleanValue;
double DoubleValue;
__int32 Int32Value;
unsigned __int32 UInt32Value;
std::int32_t Int32Value;
std::uint32_t UInt32Value;
const StdString* pString;
V8ObjectHolder* pV8ObjectHolder;
HostObjectHolder* pHostObjectHolder;
@ -292,32 +319,33 @@ private:
void Copy(const V8Value& that)
{
m_Type = that.m_Type;
m_Subtype = that.m_Subtype;
if (m_Type == Type_Boolean)
if (m_Type == Type::Boolean)
{
m_Data.BooleanValue = that.m_Data.BooleanValue;
}
else if (m_Type == Type_Number)
else if (m_Type == Type::Number)
{
m_Data.DoubleValue = that.m_Data.DoubleValue;
}
else if (m_Type == Type_Int32)
else if (m_Type == Type::Int32)
{
m_Data.Int32Value = that.m_Data.Int32Value;
}
else if (m_Type == Type_UInt32)
else if (m_Type == Type::UInt32)
{
m_Data.UInt32Value = that.m_Data.UInt32Value;
}
else if (m_Type == Type_String)
else if (m_Type == Type::String)
{
m_Data.pString = new StdString(*that.m_Data.pString);
}
else if (m_Type == Type_V8Object)
else if (m_Type == Type::V8Object)
{
m_Data.pV8ObjectHolder = that.m_Data.pV8ObjectHolder->Clone();
}
else if (m_Type == Type_HostObject)
else if (m_Type == Type::HostObject)
{
m_Data.pHostObjectHolder = that.m_Data.pHostObjectHolder->Clone();
}
@ -326,26 +354,28 @@ private:
void Move(V8Value& that)
{
m_Type = that.m_Type;
m_Subtype = that.m_Subtype;
m_Data = that.m_Data;
that.m_Type = Type_Undefined;
that.m_Type = Type::Undefined;
}
void Dispose()
{
if (m_Type == Type_String)
if (m_Type == Type::String)
{
delete m_Data.pString;
}
else if (m_Type == Type_V8Object)
else if (m_Type == Type::V8Object)
{
delete m_Data.pV8ObjectHolder;
}
else if (m_Type == Type_HostObject)
else if (m_Type == Type::HostObject)
{
delete m_Data.pHostObjectHolder;
}
}
Type m_Type;
Subtype m_Subtype;
Data m_Data;
};

Просмотреть файл

@ -60,11 +60,28 @@
//
using System;
using Microsoft.ClearScript.Util;
namespace Microsoft.ClearScript.V8
{
internal interface IV8Object : IDynamic, IDisposable
internal interface IV8Object : IDisposable
{
object GetProperty(string name);
object GetProperty(string name, out bool isCacheable);
void SetProperty(string name, object value);
bool DeleteProperty(string name);
string[] GetPropertyNames();
object GetProperty(int index);
void SetProperty(int index, object value);
bool DeleteProperty(int index);
int[] GetPropertyIndices();
object Invoke(object[] args, bool asConstructor);
object InvokeMethod(string name, object[] args);
bool IsArrayBufferOrView();
V8ArrayBufferOrViewKind GetArrayBufferOrViewKind();
V8ArrayBufferOrViewInfo GetArrayBufferOrViewInfo();
void InvokeWithArrayBufferOrViewData(Action<IntPtr> action);
}
}

Просмотреть файл

@ -1,8 +1,8 @@
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 7c96720..0b046cd 100644
index 7250579..86c6334 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -464,7 +464,7 @@
@@ -821,7 +821,7 @@
'EnableFunctionLevelLinking': 'true',
'RuntimeTypeInfo': 'false',
'WarningLevel': '3',
@ -11,39 +11,11 @@ index 7c96720..0b046cd 100644
'DebugInformationFormat': '3',
'Detect64BitPortabilityProblems': 'false',
'conditions': [
diff --git a/src/api.cc b/src/api.cc
index 4f06873..546f1f5 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5319,10 +5319,6 @@ void v8::V8::SetReturnAddressLocationResolver(
void v8::V8::SetArrayBufferAllocator(
ArrayBuffer::Allocator* allocator) {
- if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
- "v8::V8::SetArrayBufferAllocator",
- "ArrayBufferAllocator might only be set once"))
- return;
i::V8::SetArrayBufferAllocator(allocator);
}
diff --git a/src/objects.cc b/src/objects.cc
index f0dcaab..4cc1d99 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -6690,7 +6690,7 @@ MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
if (is_observed) {
if (is_element) {
Maybe<bool> maybe = HasOwnElement(object, index);
- // Workaround for a GCC 4.4.3 bug which leads to "preexists may be used
+ // Workaround for a GCC 4.4.3 bug which leads to "'preexists' may be used
// uninitialized in this function".
if (!maybe.IsJust()) {
DCHECK(false);
diff --git a/src/parser.cc b/src/parser.cc
index 3b537d2..17d8c97 100644
index 1bd163c..71fbe15 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2642,7 +2642,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
@@ -2623,7 +2623,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
// Identifier ':' Statement
//
// ExpressionStatement[Yield] :
@ -53,10 +25,10 @@ index 3b537d2..17d8c97 100644
int pos = peek_position();
diff --git a/src/v8.cc b/src/v8.cc
index 49a104f..08fd6f3 100644
index 760a9b5..2618312 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -109,7 +109,6 @@ void V8::InitializeOncePerProcess() {
@@ -101,7 +101,6 @@ void V8::InitializeOncePerProcess() {
void V8::InitializePlatform(v8::Platform* platform) {
@ -64,23 +36,11 @@ index 49a104f..08fd6f3 100644
CHECK(platform);
platform_ = platform;
}
diff --git a/src/v8.h b/src/v8.h
index 211f3c6..7e29fc2 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -74,7 +74,6 @@ class V8 : public AllStatic {
}
static void SetArrayBufferAllocator(v8::ArrayBuffer::Allocator *allocator) {
- CHECK_NULL(array_buffer_allocator_);
array_buffer_allocator_ = allocator;
}
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 70d4dee..7fd3018 100644
index bcb5801..efc51ba 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -38,6 +38,7 @@
@@ -40,6 +40,7 @@
'targets': [
{
'target_name': 'v8',

Просмотреть файл

@ -0,0 +1,85 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
namespace Microsoft.ClearScript.V8
{
internal class V8ArrayBufferOrViewInfo
{
public V8ArrayBufferOrViewInfo(V8ArrayBufferOrViewKind kind, IV8Object arrayBuffer, ulong offset, ulong size, ulong length)
{
Kind = kind;
ArrayBuffer = arrayBuffer;
Offset = offset;
Size = size;
Length = length;
}
public V8ArrayBufferOrViewKind Kind { get; private set; }
public IV8Object ArrayBuffer { get; private set; }
public ulong Offset { get; private set; }
public ulong Size { get; private set; }
public ulong Length { get; private set; }
}
}

Просмотреть файл

@ -0,0 +1,79 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
namespace Microsoft.ClearScript.V8
{
internal enum V8ArrayBufferOrViewKind
{
None,
ArrayBuffer,
DataView,
Uint8Array,
Uint8ClampedArray,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Float32Array,
Float64Array
}
}

Просмотреть файл

@ -65,7 +65,6 @@ using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.ClearScript.Util;
@ -170,7 +169,7 @@ namespace Microsoft.ClearScript.V8
return hLibrary;
}
var exception = new Win32Exception(Marshal.GetLastWin32Error());
var exception = new Win32Exception();
messageBuilder.AppendInvariant("\n{0}: {1}", path, MiscHelpers.EnsureNonBlank(exception.Message, "Unknown error"));
}

Просмотреть файл

@ -60,6 +60,7 @@
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
@ -116,7 +117,7 @@ namespace Microsoft.ClearScript.V8
public static object GetHostObjectProperty(object obj, string name)
{
return ((IDynamic)obj).GetProperty(name);
return ((IDynamic)obj).GetProperty(name, MiscHelpers.GetEmptyArray<object>());
}
public static unsafe object GetHostObjectProperty(void* pObject, string name, out bool isCacheable)
@ -126,7 +127,7 @@ namespace Microsoft.ClearScript.V8
public static object GetHostObjectProperty(object obj, string name, out bool isCacheable)
{
return ((IDynamic)obj).GetProperty(name, out isCacheable);
return ((IDynamic)obj).GetProperty(name, MiscHelpers.GetEmptyArray<object>(), out isCacheable);
}
public static unsafe void SetHostObjectProperty(void* pObject, string name, object value)
@ -136,7 +137,7 @@ namespace Microsoft.ClearScript.V8
public static void SetHostObjectProperty(object obj, string name, object value)
{
((IDynamic)obj).SetProperty(name, value);
((IDynamic)obj).SetProperty(name, new[] { value });
}
public static unsafe bool DeleteHostObjectProperty(void* pObject, string name)
@ -241,6 +242,34 @@ namespace Microsoft.ClearScript.V8
return hostTarget.Flags.HasFlag(HostTargetFlags.AllowInstanceMembers) && typeof(Delegate).IsAssignableFrom(hostTarget.Type);
}
public static unsafe object GetEnumeratorForHostObject(void* pObject)
{
return GetEnumeratorForHostObject(GetHostObject(pObject));
}
public static object GetEnumeratorForHostObject(object obj)
{
return ((IDynamic)obj).InvokeMethod(SpecialMemberNames.NewEnum, MiscHelpers.GetEmptyArray<object>());
}
public static unsafe bool AdvanceEnumerator(void* pEnumerator, out object value)
{
return AdvanceEnumerator(GetHostObject(pEnumerator), out value);
}
public static bool AdvanceEnumerator(object enumerator, out object value)
{
var wrapper = (IScriptMarshalWrapper)enumerator;
if (((IEnumerator)wrapper.Unwrap()).MoveNext())
{
value = ((IDynamic)enumerator).GetProperty("Current", MiscHelpers.GetEmptyArray<object>());
return true;
}
value = null;
return false;
}
#endregion
#region exception marshaling

Просмотреть файл

@ -289,8 +289,8 @@ namespace Microsoft.ClearScript.V8
return {
getCommandResult: function (value) {
if (value != null) {
if (((typeof(value) == 'object') && !value.hasOwnProperty('{c2cf47d3-916b-4a3f-be2a-6ff567425808}')) || (typeof(value) == 'function')) {
if ((value != null) && !value.hasOwnProperty('{c2cf47d3-916b-4a3f-be2a-6ff567425808}')) {
if ((typeof(value) == 'object') || (typeof(value) == 'function')) {
if (typeof(value.toString) == 'function') {
return value.toString();
}
@ -719,7 +719,7 @@ namespace Microsoft.ClearScript.V8
}
var hostTarget = obj as HostTarget;
if (hostTarget != null)
if ((hostTarget != null) && !(hostTarget is IHostVariable))
{
obj = hostTarget.Target;
}

Просмотреть файл

@ -62,6 +62,7 @@
using System;
using System.Diagnostics;
using System.Dynamic;
using Microsoft.ClearScript.JavaScript;
using Microsoft.ClearScript.Util;
namespace Microsoft.ClearScript.V8
@ -91,7 +92,37 @@ namespace Microsoft.ClearScript.V8
var target = obj as IV8Object;
if (target != null)
{
return new V8ScriptItem(engine, target);
if (!target.IsArrayBufferOrView())
{
return new V8ScriptItem(engine, target);
}
switch (target.GetArrayBufferOrViewKind())
{
case V8ArrayBufferOrViewKind.ArrayBuffer:
return new V8ArrayBuffer(engine, target);
case V8ArrayBufferOrViewKind.DataView:
return new V8DataView(engine, target);
case V8ArrayBufferOrViewKind.Uint8Array:
case V8ArrayBufferOrViewKind.Uint8ClampedArray:
return new V8TypedArray<byte>(engine, target);
case V8ArrayBufferOrViewKind.Int8Array:
return new V8TypedArray<sbyte>(engine, target);
case V8ArrayBufferOrViewKind.Uint16Array:
return new V8UInt16Array(engine, target);
case V8ArrayBufferOrViewKind.Int16Array:
return new V8TypedArray<short>(engine, target);
case V8ArrayBufferOrViewKind.Uint32Array:
return new V8TypedArray<uint>(engine, target);
case V8ArrayBufferOrViewKind.Int32Array:
return new V8TypedArray<int>(engine, target);
case V8ArrayBufferOrViewKind.Float32Array:
return new V8TypedArray<float>(engine, target);
case V8ArrayBufferOrViewKind.Float64Array:
return new V8TypedArray<double>(engine, target);
default:
return new V8ScriptItem(engine, target);
}
}
return obj;
@ -209,9 +240,13 @@ namespace Microsoft.ClearScript.V8
#region IDynamic implementation
public override object GetProperty(string name)
public override object GetProperty(string name, object[] args)
{
VerifyNotDisposed();
if ((args != null) && (args.Length != 0))
{
throw new InvalidOperationException("Invalid argument or index count");
}
var result = engine.MarshalToHost(engine.ScriptInvoke(() => target.GetProperty(name)), false);
@ -224,10 +259,15 @@ namespace Microsoft.ClearScript.V8
return result;
}
public override void SetProperty(string name, object value)
public override void SetProperty(string name, object[] args)
{
VerifyNotDisposed();
engine.ScriptInvoke(() => target.SetProperty(name, engine.MarshalToScript(value)));
if ((args == null) || (args.Length != 1))
{
throw new InvalidOperationException("Invalid argument or index count");
}
engine.ScriptInvoke(() => target.SetProperty(name, engine.MarshalToScript(args[0])));
}
public override bool DeleteProperty(string name)
@ -311,5 +351,391 @@ namespace Microsoft.ClearScript.V8
}
#endregion
#region Nested type: V8ArrayBufferOrView
private class V8ArrayBufferOrView : V8ScriptItem
{
private V8ArrayBufferOrViewInfo info;
private IArrayBuffer arrayBuffer;
protected V8ArrayBufferOrView(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
protected IArrayBuffer ArrayBuffer
{
get { return GetArrayBuffer(); }
}
protected ulong Offset
{
get { return GetInfo().Offset; }
}
protected ulong Size
{
get { return GetInfo().Size; }
}
protected ulong Length
{
get { return GetInfo().Length; }
}
protected byte[] GetBytes()
{
return engine.ScriptInvoke(() =>
{
var result = new byte[Size];
target.InvokeWithArrayBufferOrViewData(pData =>
{
UnmanagedMemoryHelpers.Copy(pData, Size, result, 0);
});
return result;
});
}
protected ulong ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex)
{
var size = Size;
if (offset >= size)
{
throw new ArgumentOutOfRangeException("offset");
}
count = Math.Min(count, size - offset);
return engine.ScriptInvoke(() =>
{
target.InvokeWithArrayBufferOrViewData(pData =>
{
count = UnmanagedMemoryHelpers.Copy(GetPtrWithOffset(pData, offset), count, destination, destinationIndex);
});
return count;
});
}
protected ulong WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset)
{
var size = Size;
if (offset >= size)
{
throw new ArgumentOutOfRangeException("offset");
}
count = Math.Min(count, size - offset);
return engine.ScriptInvoke(() =>
{
target.InvokeWithArrayBufferOrViewData(pData =>
{
count = UnmanagedMemoryHelpers.Copy(source, sourceIndex, count, GetPtrWithOffset(pData, offset));
});
return count;
});
}
private V8ArrayBufferOrViewInfo GetInfo()
{
VerifyNotDisposed();
if (info == null)
{
engine.ScriptInvoke(() =>
{
if (info == null)
{
info = target.GetArrayBufferOrViewInfo();
}
});
}
return info;
}
private IArrayBuffer GetArrayBuffer()
{
if (arrayBuffer == null)
{
arrayBuffer = (IArrayBuffer)engine.MarshalToHost(GetInfo().ArrayBuffer, false);
}
return arrayBuffer;
}
private static IntPtr GetPtrWithOffset(IntPtr pData, ulong offset)
{
var baseAddr = unchecked((ulong)pData.ToInt64());
return new IntPtr(unchecked((long)checked(baseAddr + offset)));
}
}
#endregion
#region Nested type: V8ArrayBuffer
private class V8ArrayBuffer : V8ArrayBufferOrView, IArrayBuffer
{
public V8ArrayBuffer(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
#region IArrayBuffer implementation
ulong IArrayBuffer.Size
{
get { return Size; }
}
byte[] IArrayBuffer.GetBytes()
{
return GetBytes();
}
ulong IArrayBuffer.ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex)
{
return ReadBytes(offset, count, destination, destinationIndex);
}
ulong IArrayBuffer.WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset)
{
return WriteBytes(source, sourceIndex, count, offset);
}
#endregion
}
#endregion
#region Nested type: V8ArrayBufferView
private class V8ArrayBufferView : V8ArrayBufferOrView, IArrayBufferView
{
protected V8ArrayBufferView(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
#region IArrayBufferView implementation
IArrayBuffer IArrayBufferView.ArrayBuffer
{
get { return ArrayBuffer; }
}
ulong IArrayBufferView.Offset
{
get { return Offset; }
}
ulong IArrayBufferView.Size
{
get { return Size; }
}
byte[] IArrayBufferView.GetBytes()
{
return GetBytes();
}
ulong IArrayBufferView.ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex)
{
return ReadBytes(offset, count, destination, destinationIndex);
}
ulong IArrayBufferView.WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset)
{
return WriteBytes(source, sourceIndex, count, offset);
}
#endregion
}
#endregion
#region Nested type: V8DataView
private class V8DataView : V8ArrayBufferView, IDataView
{
public V8DataView(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
}
#endregion
#region Nested type: V8TypedArray
private class V8TypedArray : V8ArrayBufferView, ITypedArray
{
protected V8TypedArray(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
protected IntPtr GetPtrWithIndex(IntPtr pData, ulong index)
{
var baseAddr = unchecked((ulong)pData.ToInt64());
return new IntPtr(unchecked((long)checked(baseAddr + (index * (Size / Length)))));
}
#region ITypedArray implementation
ulong ITypedArray.Length
{
get { return Length; }
}
#endregion
}
#endregion
#region Nested type: V8TypedArray<T>
private class V8TypedArray<T> : V8TypedArray, ITypedArray<T>
{
public V8TypedArray(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
#region ITypedArray<T> implementation
T[] ITypedArray<T>.ToArray()
{
return engine.ScriptInvoke(() =>
{
var result = new T[Length];
target.InvokeWithArrayBufferOrViewData(pData =>
{
UnmanagedMemoryHelpers.Copy(pData, Length, result, 0);
});
return result;
});
}
ulong ITypedArray<T>.Read(ulong index, ulong length, T[] destination, ulong destinationIndex)
{
var totalLength = Length;
if (index >= totalLength)
{
throw new ArgumentOutOfRangeException("index");
}
length = Math.Min(length, totalLength - index);
return engine.ScriptInvoke(() =>
{
target.InvokeWithArrayBufferOrViewData(pData =>
{
length = UnmanagedMemoryHelpers.Copy(GetPtrWithIndex(pData, index), length, destination, destinationIndex);
});
return length;
});
}
ulong ITypedArray<T>.Write(T[] source, ulong sourceIndex, ulong length, ulong index)
{
var totalLength = Length;
if (index >= totalLength)
{
throw new ArgumentOutOfRangeException("index");
}
length = Math.Min(length, totalLength - index);
return engine.ScriptInvoke(() =>
{
target.InvokeWithArrayBufferOrViewData(pData =>
{
length = UnmanagedMemoryHelpers.Copy(source, sourceIndex, length, GetPtrWithIndex(pData, index));
});
return length;
});
}
#endregion
}
#endregion
#region Nested type: V8UInt16Array
// special case to support both ITypedArray<ushort> and ITypedArray<char>
private class V8UInt16Array : V8TypedArray<ushort>, ITypedArray<char>
{
public V8UInt16Array(V8ScriptEngine engine, IV8Object target)
: base(engine, target)
{
}
#region ITypedArray<char> implementation
char[] ITypedArray<char>.ToArray()
{
return engine.ScriptInvoke(() =>
{
var result = new char[Length];
target.InvokeWithArrayBufferOrViewData(pData =>
{
UnmanagedMemoryHelpers.Copy(pData, Length, result, 0);
});
return result;
});
}
ulong ITypedArray<char>.Read(ulong index, ulong length, char[] destination, ulong destinationIndex)
{
var totalLength = Length;
if (index >= totalLength)
{
throw new ArgumentOutOfRangeException("index");
}
length = Math.Min(length, totalLength - index);
return engine.ScriptInvoke(() =>
{
target.InvokeWithArrayBufferOrViewData(pData =>
{
length = UnmanagedMemoryHelpers.Copy(GetPtrWithIndex(pData, index), length, destination, destinationIndex);
});
return length;
});
}
ulong ITypedArray<char>.Write(char[] source, ulong sourceIndex, ulong length, ulong index)
{
var totalLength = Length;
if (index >= totalLength)
{
throw new ArgumentOutOfRangeException("index");
}
length = Math.Min(length, totalLength - index);
return engine.ScriptInvoke(() =>
{
target.InvokeWithArrayBufferOrViewData(pData =>
{
length = UnmanagedMemoryHelpers.Copy(source, sourceIndex, length, GetPtrWithIndex(pData, index));
});
return length;
});
}
#endregion
}
#endregion
}
}

Просмотреть файл

@ -167,6 +167,11 @@ namespace Microsoft.ClearScript.Windows
activeScriptProperty.SetProperty(ScriptProp.InvokeVersioning, IntPtr.Zero, ref value);
}
}
if (!flags.HasFlag(WindowsScriptEngineFlags.DoNotEnableVTablePatching) && MiscHelpers.IsX86InstructionSet())
{
HostItem.EnableVTablePatching = true;
}
}
// ReSharper restore SuspiciousTypeConversion.Global
@ -313,6 +318,11 @@ namespace Microsoft.ClearScript.Windows
activeScriptProperty.SetProperty(ScriptProp.InvokeVersioning, IntPtr.Zero, ref value);
}
}
if (!flags.HasFlag(WindowsScriptEngineFlags.DoNotEnableVTablePatching) && MiscHelpers.IsX86InstructionSet())
{
HostItem.EnableVTablePatching = true;
}
}
// ReSharper restore SuspiciousTypeConversion.Global

Просмотреть файл

@ -501,7 +501,7 @@ namespace Microsoft.ClearScript.Windows
}
var hostTarget = obj as HostTarget;
if (hostTarget != null)
if ((hostTarget != null) && !(hostTarget is IHostVariable))
{
obj = hostTarget.Target;
}

Просмотреть файл

@ -118,6 +118,17 @@ namespace Microsoft.ClearScript.Windows
/// <see href="http://msdn.microsoft.com/en-us/library/y39d47w8(v=vs.84).aspx">VBArray</see>
/// object to to access them.
/// </summary>
MarshalArraysByValue = 0x00000040
MarshalArraysByValue = 0x00000040,
/// <summary>
/// When <see cref="EnableStandardsMode"/> is specified, the ClearScript library uses
/// virtual method table patching to support JScript-specific
/// <see href="https://msdn.microsoft.com/en-us/library/sky96ah7(VS.94).aspx">IDispatchEx</see>
/// extensions that otherwise interfere with some host object functionality. Virtual method
/// table patching is a very low-level mechanism with global effect. This option specifies
/// that virtual method table patching is not to be enabled on behalf of the current
/// <see cref="JScriptEngine"/> instance.
/// </summary>
DoNotEnableVTablePatching = 0x00000080,
}
}

Просмотреть файл

@ -229,7 +229,7 @@ namespace Microsoft.ClearScript.Windows
#region IDynamic implementation
public override object GetProperty(string name)
public override object GetProperty(string name, object[] args)
{
VerifyNotDisposed();
@ -237,7 +237,7 @@ namespace Microsoft.ClearScript.Windows
{
try
{
return target.InvokeMember(name, BindingFlags.GetProperty, null, target, MiscHelpers.GetEmptyArray<object>(), null, CultureInfo.InvariantCulture, null);
return target.InvokeMember(name, BindingFlags.GetProperty, null, target, engine.MarshalToScript(args), null, CultureInfo.InvariantCulture, null);
}
catch (Exception)
{
@ -262,13 +262,13 @@ namespace Microsoft.ClearScript.Windows
return result;
}
public override void SetProperty(string name, object value)
public override void SetProperty(string name, object[] args)
{
VerifyNotDisposed();
engine.ScriptInvoke(() =>
{
var marshaledArgs = new[] { engine.MarshalToScript(value) };
var marshaledArgs = engine.MarshalToScript(args);
try
{
target.InvokeMember(name, BindingFlags.SetProperty, null, target, marshaledArgs, null, CultureInfo.InvariantCulture, null);
@ -314,13 +314,13 @@ namespace Microsoft.ClearScript.Windows
public override object GetProperty(int index)
{
VerifyNotDisposed();
return GetProperty(index.ToString(CultureInfo.InvariantCulture));
return GetProperty(index.ToString(CultureInfo.InvariantCulture), MiscHelpers.GetEmptyArray<object>());
}
public override void SetProperty(int index, object value)
{
VerifyNotDisposed();
SetProperty(index.ToString(CultureInfo.InvariantCulture), value);
SetProperty(index.ToString(CultureInfo.InvariantCulture), new[] { value });
}
public override bool DeleteProperty(int index)

Двоичные данные
ClearScript/doc/Reference.chm

Двоичный файл не отображается.

Просмотреть файл

@ -8,7 +8,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5e8abcfa-8cbd-4d77-bfcc-d396e945a10e}</ProjectGuid>
<SHFBSchemaVersion>1.9.9.0</SHFBSchemaVersion>
<SHFBSchemaVersion>2015.6.5.0</SHFBSchemaVersion>
<!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
Studio adds them anyway -->
<AssemblyName>Documentation</AssemblyName>
@ -27,7 +27,7 @@
<FeedbackEMailAddress>ClearScript%40microsoft.com</FeedbackEMailAddress>
<FeedbackEMailLinkText>Microsoft</FeedbackEMailLinkText>
<FrameworkVersion>.NET Framework 4.0</FrameworkVersion>
<PresentationStyle>VS2010</PresentationStyle>
<PresentationStyle>VS2013</PresentationStyle>
<Preliminary>False</Preliminary>
<BuildAssemblerVerbosity>OnlyWarningsAndErrors</BuildAssemblerVerbosity>
<HelpFileFormat>HtmlHelp1</HelpFileFormat>
@ -44,14 +44,15 @@
<CopyrightText>Copyright &amp;#169%3b Microsoft Corporation. All rights reserved.</CopyrightText>
<NamespaceSummaries>
<NamespaceSummaryItem name="Microsoft.ClearScript" isDocumented="True">The Microsoft.ClearScript namespace contains types that support all script engines.</NamespaceSummaryItem>
<NamespaceSummaryItem name="Microsoft.ClearScript.V8" isDocumented="True">The Microsoft.ClearScript.V8 namespace contains types that provide access to the V8 high-performance open-source JavaScript engine.</NamespaceSummaryItem>
<NamespaceSummaryItem name="Microsoft.ClearScript.Windows" isDocumented="True">The Microsoft.ClearScript.Windows namespace contains types that provide access to Windows Script engines such as JScript and VBScript.</NamespaceSummaryItem>
<NamespaceSummaryItem name="(global)" isDocumented="False" />
</NamespaceSummaries>
<NamespaceSummaryItem name="Microsoft.ClearScript.V8" isDocumented="True">The Microsoft.ClearScript.V8 namespace contains types that provide access to the V8 high-performance open-source JavaScript engine.</NamespaceSummaryItem>
<NamespaceSummaryItem name="Microsoft.ClearScript.Windows" isDocumented="True">The Microsoft.ClearScript.Windows namespace contains types that provide access to Windows Script engines such as JScript and VBScript.</NamespaceSummaryItem>
<NamespaceSummaryItem name="(global)" isDocumented="False" />
<NamespaceSummaryItem name="Microsoft.ClearScript.JavaScript" isDocumented="True">The Microsoft.ClearScript.JavaScript namespace contains types that provide access to JavaScript-specific features.</NamespaceSummaryItem></NamespaceSummaries>
<RootNamespaceTitle>ClearScript Library Reference</RootNamespaceTitle>
<ProjectSummary>The ClearScript library makes it easy to add scripting to your .NET applications.</ProjectSummary>
<MaximumGroupParts>2</MaximumGroupParts>
<NamespaceGrouping>False</NamespaceGrouping>
<HelpFileVersion>1.0.0.0</HelpFileVersion>
</PropertyGroup>
<!-- There are no properties for these groups. AnyCPU needs to appear in
order for Visual Studio to perform the build. The others are optional

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.3.0")]
[assembly: AssemblyFileVersion("5.4.3.0")]
[assembly: AssemblyVersion("5.4.4.0")]
[assembly: AssemblyFileVersion("5.4.4.0")]

Просмотреть файл

@ -71,7 +71,7 @@ namespace Microsoft.ClearScript.Test
internal static class SunSpider
{
private const string version = "sunspider-1.0.2";
private const string baseUrl = "http://www.webkit.org/perf/" + version + "/" + version + "/";
private const string baseUrl = "https://webkit.org/perf/" + version + "/" + version + "/";
private const int repeatCount = 10;
private const string scriptBegin = "<script>";

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.3.0")]
[assembly: AssemblyFileVersion("5.4.3.0")]
[assembly: AssemblyVersion("5.4.4.0")]
[assembly: AssemblyFileVersion("5.4.4.0")]

Просмотреть файл

@ -1292,6 +1292,516 @@ namespace Microsoft.ClearScript.Test
Assert.AreEqual("123 456.789 hello", engine.Evaluate("foo.RunTest(123, 456.789, 'hello')"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_NestedInterrupt()
{
var context = new PropertyBag();
engine.AddHostObject("context", context);
using (var startEvent = new ManualResetEventSlim(false))
{
object result = null;
var interruptedInner = false;
var interruptedOuter = false;
context["startEvent"] = startEvent;
context["foo"] = new Action(() =>
{
try
{
engine.Execute("while (true) { context.startEvent.Set(); }");
}
catch (ScriptInterruptedException)
{
interruptedInner = true;
}
});
var thread = new Thread(() =>
{
try
{
result = engine.Evaluate("context.foo(); 123");
}
catch (ScriptInterruptedException)
{
interruptedOuter = true;
}
});
thread.Start();
startEvent.Wait();
engine.Interrupt();
thread.Join();
Assert.IsTrue(interruptedInner);
Assert.IsFalse(interruptedOuter);
Assert.AreEqual(123, result);
}
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_NestedInterrupt_JScript()
{
engine.Dispose();
try
{
using (var startEvent = new ManualResetEventSlim(false))
{
object result = null;
var interruptedInner = false;
var interruptedOuter = false;
var thread = new Thread(() =>
{
using (engine = new JScriptEngine(WindowsScriptEngineFlags.EnableDebugging))
{
var context = new PropertyBag();
engine.AddHostObject("context", context);
// ReSharper disable once AccessToDisposedClosure
context["startEvent"] = startEvent;
context["foo"] = new Action(() =>
{
try
{
engine.Execute("while (true) { context.startEvent.Set(); }");
}
catch (ScriptInterruptedException)
{
interruptedInner = true;
}
});
try
{
result = engine.Evaluate("context.foo(); 123");
}
catch (ScriptInterruptedException)
{
interruptedOuter = true;
}
}
});
thread.Start();
startEvent.Wait();
engine.Interrupt();
thread.Join();
Assert.IsTrue(interruptedInner);
Assert.IsFalse(interruptedOuter);
Assert.AreEqual(123, result);
}
}
finally
{
engine = new V8ScriptEngine(V8ScriptEngineFlags.EnableDebugging);
}
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_PropertyBag_NativeEnumerator_JScript()
{
engine.Dispose();
engine = new JScriptEngine();
var x = new PropertyBag();
x["foo"] = 123;
x["bar"] = "blah";
engine.Script.x = x;
var result = (string)engine.Evaluate(@"
var result = '';
for (var e = new Enumerator(x); !e.atEnd(); e.moveNext()) {
result += e.item().Value;
}
result
");
Assert.AreEqual(7, result.Length);
Assert.IsTrue(result.IndexOf("123", StringComparison.Ordinal) >= 0);
Assert.IsTrue(result.IndexOf("blah", StringComparison.Ordinal) >= 0);
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_PropertyBag_NativeEnumerator_VBScript()
{
engine.Dispose();
engine = new VBScriptEngine();
var x = new PropertyBag();
x["foo"] = 123;
x["bar"] = "blah";
engine.Script.x = x;
engine.Execute(@"
function getResult(arg)
dim result
result = """"
for each item in arg
result = result & item.Value
next
getResult = result
end function
");
var result = (string)engine.Evaluate("getResult(x)");
Assert.AreEqual(7, result.Length);
Assert.IsTrue(result.IndexOf("123", StringComparison.Ordinal) >= 0);
Assert.IsTrue(result.IndexOf("blah", StringComparison.Ordinal) >= 0);
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_JScriptStandardsMode_PropertyAccess()
{
engine.Dispose();
engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
engine.Script.x = new { foo = 123 };
Assert.AreEqual(123, engine.Evaluate("x.foo"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_JScriptStandardsMode_MemberEnumeration()
{
engine.Dispose();
engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
engine.Script.x = new { foo = 123, bar = "blah" };
var result = (string)engine.Evaluate(@"
var result = '';
for (var i in x) {
if ((i == 'foo') || (i == 'bar')) {
result += x[i];
}
}
result
");
Assert.AreEqual(7, result.Length);
Assert.IsTrue(result.IndexOf("123", StringComparison.Ordinal) >= 0);
Assert.IsTrue(result.IndexOf("blah", StringComparison.Ordinal) >= 0);
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_JScriptStandardsMode_MemberEnumeration_PropertyBag()
{
engine.Dispose();
engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
var x = new PropertyBag();
x["foo"] = 123;
x["bar"] = "blah";
engine.Script.x = x;
var result = (string)engine.Evaluate(@"
var result = '';
for (var i in x) {
result += x[i];
}
result
");
Assert.AreEqual(7, result.Length);
Assert.IsTrue(result.IndexOf("123", StringComparison.Ordinal) >= 0);
Assert.IsTrue(result.IndexOf("blah", StringComparison.Ordinal) >= 0);
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_JScriptStandardsMode_MemberEnumeration_Dynamic()
{
engine.Dispose();
engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
dynamic x = new ExpandoObject();
x.foo = 123;
x.bar = "blah";
engine.Script.x = x;
var result = (string)engine.Evaluate(@"
var result = '';
for (var i in x) {
if ((i == 'foo') || (i == 'bar')) {
result += x[i];
}
}
result
");
Assert.AreEqual(7, result.Length);
Assert.IsTrue(result.IndexOf("123", StringComparison.Ordinal) >= 0);
Assert.IsTrue(result.IndexOf("blah", StringComparison.Ordinal) >= 0);
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_JScriptStandardsMode_MemberDeletion_PropertyBag()
{
engine.Dispose();
engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
var x = new PropertyBag();
x["foo"] = 123;
x["bar"] = "blah";
engine.Script.x = x;
Assert.AreEqual(123, engine.Evaluate("x.foo"));
Assert.AreEqual("blah", engine.Evaluate("x.bar"));
Assert.AreEqual(true, engine.Evaluate("delete x.foo"));
Assert.IsInstanceOfType(engine.Evaluate("x.foo"), typeof(Undefined));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_JScriptStandardsMode_MemberDeletion_Dynamic()
{
engine.Dispose();
engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
dynamic x = new ExpandoObject();
x.foo = 123;
x.bar = "blah";
engine.Script.x = x;
Assert.AreEqual(123, engine.Evaluate("x.foo"));
Assert.AreEqual("blah", engine.Evaluate("x.bar"));
Assert.AreEqual(true, engine.Evaluate("delete x.foo"));
Assert.IsInstanceOfType(engine.Evaluate("x.foo"), typeof(Undefined));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_NumericArgConversion_Delegate()
{
engine.Script.host = new HostFunctions();
engine.Script.sbyteFunc = new Func<sbyte, sbyte>(arg => arg);
engine.Script.nullableSByteFunc = new Func<sbyte?, sbyte?>(arg => arg);
engine.Script.floatFunc = new Func<float, float>(arg => arg);
engine.Script.nullableFloatFunc = new Func<float?, float?>(arg => arg);
engine.Script.doubleFunc = new Func<double, double>(arg => arg);
engine.Script.nullableDoubleFunc = new Func<double?, double?>(arg => arg);
engine.Script.decimalFunc = new Func<decimal, decimal>(arg => arg);
engine.Script.nullableDecimalFunc = new Func<decimal?, decimal?>(arg => arg);
Assert.AreEqual(123, engine.Evaluate("sbyteFunc(123)"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("sbyteFunc(234)"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("sbyteFunc(123.5)"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("sbyteFunc(Math.PI)"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("sbyteFunc(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("nullableSByteFunc(123)"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("nullableSByteFunc(234)"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("nullableSByteFunc(123.5)"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("nullableSByteFunc(Math.PI)"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("nullableSByteFunc(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("nullableSByteFunc(null)"));
Assert.AreEqual(123, engine.Evaluate("floatFunc(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("floatFunc(123.5)"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("floatFunc(Math.PI)"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("floatFunc(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("nullableFloatFunc(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("nullableFloatFunc(123.5)"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("nullableFloatFunc(Math.PI)"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("nullableFloatFunc(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("nullableFloatFunc(null)"));
Assert.AreEqual(123, engine.Evaluate("doubleFunc(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("doubleFunc(123.5)"));
Assert.AreEqual(Math.PI, engine.Evaluate("doubleFunc(Math.PI)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("doubleFunc(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("nullableDoubleFunc(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("nullableDoubleFunc(123.5)"));
Assert.AreEqual(Math.PI, engine.Evaluate("nullableDoubleFunc(Math.PI)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("nullableDoubleFunc(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("nullableDoubleFunc(null)"));
Assert.AreEqual(123, engine.Evaluate("decimalFunc(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("decimalFunc(123.5)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("decimalFunc(Math.PI)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("decimalFunc(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("nullableDecimalFunc(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("nullableDecimalFunc(123.5)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("nullableDecimalFunc(Math.PI)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("nullableDecimalFunc(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("nullableDecimalFunc(null)"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_NumericArgConversion_Field()
{
engine.Script.host = new HostFunctions();
engine.Script.test = new NumericArgConversionTest();
Assert.AreEqual(123, engine.Evaluate("test.SByteField = 123; test.SByteField"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("test.SByteField = 234"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.SByteField = 123.5"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.SByteField = Math.PI"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.SByteField = host.toDecimal(Math.PI)"));
Assert.AreEqual(123, engine.Evaluate("test.NullableSByteField = 123; test.NullableSByteField"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("test.NullableSByteField = 234"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.NullableSByteField = 123.5"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.NullableSByteField = Math.PI"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.NullableSByteField = host.toDecimal(Math.PI)"));
Assert.IsNull(engine.Evaluate("test.NullableSByteField = null; test.NullableSByteField"));
Assert.AreEqual(123, engine.Evaluate("test.FloatField = 123; test.FloatField"));
Assert.AreEqual(123.5f, engine.Evaluate("test.FloatField = 123.5; test.FloatField"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.FloatField = Math.PI; test.FloatField"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.FloatField = host.toDecimal(Math.PI); test.FloatField"));
Assert.AreEqual(123, engine.Evaluate("test.NullableFloatField = 123; test.NullableFloatField"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableFloatField = 123.5; test.NullableFloatField"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.NullableFloatField = Math.PI; test.NullableFloatField"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.NullableFloatField = host.toDecimal(Math.PI); test.NullableFloatField"));
Assert.IsNull(engine.Evaluate("test.NullableFloatField = null; test.NullableFloatField"));
Assert.AreEqual(123, engine.Evaluate("test.DoubleField = 123; test.DoubleField"));
Assert.AreEqual(123.5f, engine.Evaluate("test.DoubleField = 123.5; test.DoubleField"));
Assert.AreEqual(Math.PI, engine.Evaluate("test.DoubleField = Math.PI; test.DoubleField"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DoubleField = host.toDecimal(Math.PI); test.DoubleField"));
Assert.AreEqual(123, engine.Evaluate("test.NullableDoubleField = 123; test.NullableDoubleField"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableDoubleField = 123.5; test.NullableDoubleField"));
Assert.AreEqual(Math.PI, engine.Evaluate("test.NullableDoubleField = Math.PI; test.NullableDoubleField"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDoubleField = host.toDecimal(Math.PI); test.NullableDoubleField"));
Assert.IsNull(engine.Evaluate("test.NullableDoubleField = null; test.NullableDoubleField"));
Assert.AreEqual(123, engine.Evaluate("test.DecimalField = 123; test.DecimalField"));
Assert.AreEqual(123.5f, engine.Evaluate("test.DecimalField = 123.5; test.DecimalField"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DecimalField = Math.PI; test.DecimalField"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DecimalField = host.toDecimal(Math.PI); test.DecimalField"));
Assert.AreEqual(123, engine.Evaluate("test.NullableDecimalField = 123; test.NullableDecimalField"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableDecimalField = 123.5; test.NullableDecimalField"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDecimalField = Math.PI; test.NullableDecimalField"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDecimalField = host.toDecimal(Math.PI); test.NullableDecimalField"));
Assert.IsNull(engine.Evaluate("test.NullableDecimalField = null; test.NullableDecimalField"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_NumericArgConversion_Method()
{
engine.Script.host = new HostFunctions();
engine.Script.test = new NumericArgConversionTest();
Assert.AreEqual(123, engine.Evaluate("test.SByteMethod(123)"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("test.SByteMethod(234)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.SByteMethod(123.5)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.SByteMethod(Math.PI)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.SByteMethod(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("test.NullableSByteMethod(123)"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("test.NullableSByteMethod(234)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableSByteMethod(123.5)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableSByteMethod(Math.PI)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableSByteMethod(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("test.NullableSByteMethod(null)"));
Assert.AreEqual(123, engine.Evaluate("test.FloatMethod(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("test.FloatMethod(123.5)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.FloatMethod(Math.PI)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.FloatMethod(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("test.NullableFloatMethod(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableFloatMethod(123.5)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableFloatMethod(Math.PI)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableFloatMethod(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("test.NullableFloatMethod(null)"));
Assert.AreEqual(123, engine.Evaluate("test.DoubleMethod(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("test.DoubleMethod(123.5)"));
Assert.AreEqual(Math.PI, engine.Evaluate("test.DoubleMethod(Math.PI)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.DoubleMethod(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("test.NullableDoubleMethod(123)"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableDoubleMethod(123.5)"));
Assert.AreEqual(Math.PI, engine.Evaluate("test.NullableDoubleMethod(Math.PI)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableDoubleMethod(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("test.NullableDoubleMethod(null)"));
Assert.AreEqual(123, engine.Evaluate("test.DecimalMethod(123)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.DecimalMethod(123.5)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.DecimalMethod(Math.PI)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DecimalMethod(host.toDecimal(Math.PI))"));
Assert.AreEqual(123, engine.Evaluate("test.NullableDecimalMethod(123)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableDecimalMethod(123.5)"));
TestUtil.AssertException<RuntimeBinderException>(() => engine.Execute("test.NullableDecimalMethod(Math.PI)"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDecimalMethod(host.toDecimal(Math.PI))"));
Assert.IsNull(engine.Evaluate("test.NullableDecimalMethod(null)"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_NumericArgConversion_Property()
{
engine.Script.host = new HostFunctions();
engine.Script.test = new NumericArgConversionTest();
Assert.AreEqual(123, engine.Evaluate("test.SByteProperty = 123; test.SByteProperty"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("test.SByteProperty = 234"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.SByteProperty = 123.5"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.SByteProperty = Math.PI"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.SByteProperty = host.toDecimal(Math.PI)"));
Assert.AreEqual(123, engine.Evaluate("test.NullableSByteProperty = 123; test.NullableSByteProperty"));
TestUtil.AssertException<OverflowException>(() => engine.Execute("test.NullableSByteProperty = 234"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.NullableSByteProperty = 123.5"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.NullableSByteProperty = Math.PI"));
TestUtil.AssertException<ArgumentException>(() => engine.Execute("test.NullableSByteProperty = host.toDecimal(Math.PI)"));
Assert.IsNull(engine.Evaluate("test.NullableSByteProperty = null; test.NullableSByteProperty"));
Assert.AreEqual(123, engine.Evaluate("test.FloatProperty = 123; test.FloatProperty"));
Assert.AreEqual(123.5f, engine.Evaluate("test.FloatProperty = 123.5; test.FloatProperty"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.FloatProperty = Math.PI; test.FloatProperty"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.FloatProperty = host.toDecimal(Math.PI); test.FloatProperty"));
Assert.AreEqual(123, engine.Evaluate("test.NullableFloatProperty = 123; test.NullableFloatProperty"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableFloatProperty = 123.5; test.NullableFloatProperty"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.NullableFloatProperty = Math.PI; test.NullableFloatProperty"));
Assert.AreEqual((float)Math.PI, engine.Evaluate("test.NullableFloatProperty = host.toDecimal(Math.PI); test.NullableFloatProperty"));
Assert.IsNull(engine.Evaluate("test.NullableFloatProperty = null; test.NullableFloatProperty"));
Assert.AreEqual(123, engine.Evaluate("test.DoubleProperty = 123; test.DoubleProperty"));
Assert.AreEqual(123.5f, engine.Evaluate("test.DoubleProperty = 123.5; test.DoubleProperty"));
Assert.AreEqual(Math.PI, engine.Evaluate("test.DoubleProperty = Math.PI; test.DoubleProperty"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DoubleProperty = host.toDecimal(Math.PI); test.DoubleProperty"));
Assert.AreEqual(123, engine.Evaluate("test.NullableDoubleProperty = 123; test.NullableDoubleProperty"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableDoubleProperty = 123.5; test.NullableDoubleProperty"));
Assert.AreEqual(Math.PI, engine.Evaluate("test.NullableDoubleProperty = Math.PI; test.NullableDoubleProperty"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDoubleProperty = host.toDecimal(Math.PI); test.NullableDoubleProperty"));
Assert.IsNull(engine.Evaluate("test.NullableDoubleProperty = null; test.NullableDoubleProperty"));
Assert.AreEqual(123, engine.Evaluate("test.DecimalProperty = 123; test.DecimalProperty"));
Assert.AreEqual(123.5f, engine.Evaluate("test.DecimalProperty = 123.5; test.DecimalProperty"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DecimalProperty = Math.PI; test.DecimalProperty"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.DecimalProperty = host.toDecimal(Math.PI); test.DecimalProperty"));
Assert.AreEqual(123, engine.Evaluate("test.NullableDecimalProperty = 123; test.NullableDecimalProperty"));
Assert.AreEqual(123.5f, engine.Evaluate("test.NullableDecimalProperty = 123.5; test.NullableDecimalProperty"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDecimalProperty = Math.PI; test.NullableDecimalProperty"));
Assert.AreEqual((double)(decimal)Math.PI, engine.Evaluate("test.NullableDecimalProperty = host.toDecimal(Math.PI); test.NullableDecimalProperty"));
Assert.IsNull(engine.Evaluate("test.NullableDecimalProperty = null; test.NullableDecimalProperty"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_ScriptObjectInHostVariable()
{
engine.Script.host = new HostFunctions();
Assert.IsTrue(engine.Evaluate(null, true, "host.newVar({})", false).ToString().StartsWith("[HostVariable:", StringComparison.Ordinal));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_ScriptObjectInHostVariable_JScript()
{
engine.Dispose();
engine = new JScriptEngine();
BugFix_ScriptObjectInHostVariable();
}
// ReSharper restore InconsistentNaming
#endregion
@ -1480,6 +1990,36 @@ namespace Microsoft.ClearScript.Test
}
}
public class NumericArgConversionTest
{
public sbyte SByteField;
public sbyte? NullableSByteField;
public float FloatField;
public float? NullableFloatField;
public double DoubleField;
public double? NullableDoubleField;
public decimal DecimalField;
public decimal? NullableDecimalField;
public sbyte SByteMethod(sbyte arg) { return arg; }
public sbyte? NullableSByteMethod(sbyte? arg) { return arg; }
public float FloatMethod(float arg) { return arg; }
public float? NullableFloatMethod(float? arg) { return arg; }
public double DoubleMethod(double arg) { return arg; }
public double? NullableDoubleMethod(double? arg) { return arg; }
public decimal DecimalMethod(decimal arg) { return arg; }
public decimal? NullableDecimalMethod(decimal? arg) { return arg; }
public sbyte SByteProperty { get; set; }
public sbyte? NullableSByteProperty { get; set; }
public float FloatProperty { get; set; }
public float? NullableFloatProperty { get; set; }
public double DoubleProperty { get; set; }
public double? NullableDoubleProperty { get; set; }
public decimal DecimalProperty { get; set; }
public decimal? NullableDecimalProperty { get; set; }
}
#endregion
}
}

Просмотреть файл

@ -96,6 +96,7 @@
<Compile Include="StaticTestClass.cs" />
<Compile Include="TestObject.cs" />
<Compile Include="TypeRestrictionTest.cs" />
<Compile Include="V8ArrayBufferOrViewTest.cs" />
<Compile Include="V8ScriptEngineTest.cs" />
<Compile Include="VBScriptEngineTest.cs" />
</ItemGroup>

Просмотреть файл

@ -116,6 +116,8 @@ namespace Microsoft.ClearScript.Test
internal static void Test(HostTypeCollection typeCollection, string[] assemblyNames, Predicate<Type> filter, Func<Type, Type, bool> comparer)
{
// ReSharper disable CollectionNeverQueried.Local
typeCollection = typeCollection ?? new HostTypeCollection(filter, assemblyNames);
var allNodes = GetLeafNodes(typeCollection).OrderBy(hostType => hostType.Type.GetLocator());
@ -138,6 +140,8 @@ namespace Microsoft.ClearScript.Test
{
Assert.IsTrue(allNodes.All(hostType => hostType.Types.All(type => filter(type))));
}
// ReSharper restore CollectionNeverQueried.Local
}
private static IEnumerable<Type> GetImportableTypes(string[] assemblyNames, Predicate<Type> filter)

Просмотреть файл

@ -2050,6 +2050,70 @@ namespace Microsoft.ClearScript.Test
TestUtil.AssertException<RuntimeBinderException>(() => engine.Evaluate("listDict.Count()"));
}
[TestMethod, TestCategory("JScriptEngine")]
public void JScriptEngine_NativeEnumerator()
{
var array = Enumerable.Range(0, 10).ToArray();
engine.Execute(@"
function sum(array) {
var result = 0;
for (var e = new Enumerator(array); !e.atEnd(); e.moveNext()) {
result += e.item();
}
return result;
}
");
Assert.AreEqual(array.Aggregate((current, next) => current + next), engine.Script.sum(array));
}
[TestMethod, TestCategory("JScriptEngine")]
public void JScriptEngine_NativeEnumerator_Generic()
{
var array = Enumerable.Range(0, 10).Select(value => (IConvertible)value).ToArray();
engine.Script.culture = CultureInfo.InvariantCulture;
engine.Execute(@"
function sum(array) {
var result = 0;
for (var e = new Enumerator(array); !e.atEnd(); e.moveNext()) {
result += e.item().ToInt32(culture);
}
return result;
}
");
Assert.AreEqual(array.Aggregate((current, next) => Convert.ToInt32(current) + Convert.ToInt32(next)), engine.Script.sum(array));
}
[TestMethod, TestCategory("JScriptEngine")]
public void JScriptEngine_NativeEnumerator_NonGeneric()
{
var array = Enumerable.Range(0, 10).ToArray();
engine.Execute(@"
function sum(array) {
var result = 0;
for (var e = new Enumerator(array); !e.atEnd(); e.moveNext()) {
result += e.item();
}
return result;
}
");
Assert.AreEqual(array.Aggregate((current, next) => current + next), engine.Script.sum(HostObject.Wrap(array, typeof(IEnumerable))));
}
[TestMethod, TestCategory("JScriptEngine")]
public void JScriptEngine_NativeEnumerator_NonEnumerable()
{
engine.Execute(@"
function sum(array) {
var result = 0;
for (var e = new Enumerator(array); !e.atEnd(); e.moveNext()) {
result += e.item();
}
return result;
}
");
TestUtil.AssertException<ScriptEngineException>(() => engine.Script.sum(DayOfWeek.Monday));
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.3.0")]
[assembly: AssemblyFileVersion("5.4.3.0")]
[assembly: AssemblyVersion("5.4.4.0")]
[assembly: AssemblyFileVersion("5.4.4.0")]

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1144,7 +1144,7 @@ namespace Microsoft.ClearScript.Test
public void V8ScriptEngine_MaxRuntimeHeapSize_Dual()
{
const int limit = 4 * 1024 * 1024;
const string code = @"x = []; for (i = 0; i < 8 * 1024 * 1024; i++) { x.push(x); }";
const string code = @"x = []; for (i = 0; i < 16 * 1024 * 1024; i++) { x.push(x); }";
engine.Execute(code);
engine.CollectGarbage(true);
@ -2225,6 +2225,70 @@ namespace Microsoft.ClearScript.Test
Assert.IsInstanceOfType(engine.Evaluate("foo.toFunction"), typeof(Undefined));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_NativeEnumerator()
{
var array = Enumerable.Range(0, 10).ToArray();
engine.Execute(@"
function sum(array) {
var result = 0;
for (var item of array) {
result += item;
}
return result;
}
");
Assert.AreEqual(array.Aggregate((current, next) => current + next), engine.Script.sum(array));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_NativeEnumerator_Generic()
{
var array = Enumerable.Range(0, 10).Select(value => (IConvertible)value).ToArray();
engine.Script.culture = CultureInfo.InvariantCulture;
engine.Execute(@"
function sum(array) {
var result = 0;
for (var item of array) {
result += item.ToInt32(culture);
}
return result;
}
");
Assert.AreEqual(array.Aggregate((current, next) => Convert.ToInt32(current) + Convert.ToInt32(next)), engine.Script.sum(array));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_NativeEnumerator_NonGeneric()
{
var array = Enumerable.Range(0, 10).ToArray();
engine.Execute(@"
function sum(array) {
var result = 0;
for (var item of array) {
result += item;
}
return result;
}
");
Assert.AreEqual(array.Aggregate((current, next) => current + next), engine.Script.sum(HostObject.Wrap(array, typeof(IEnumerable))));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_NativeEnumerator_NonEnumerable()
{
engine.Execute(@"
function sum(array) {
var result = 0;
for (var item of array) {
result += item;
}
return result;
}
");
TestUtil.AssertException<NotSupportedException>(() => engine.Script.sum(DayOfWeek.Monday));
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -2208,6 +2208,74 @@ namespace Microsoft.ClearScript.Test
TestUtil.AssertException<RuntimeBinderException>(() => engine.Evaluate("listDict.Count()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_NativeEnumerator()
{
var array = Enumerable.Range(0, 10).ToArray();
engine.Execute(@"
function sum(array)
dim result
result = 0
for each item in array
result = result + item
next
sum = result
end function
");
Assert.AreEqual(array.Aggregate((current, next) => current + next), engine.Script.sum(array));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_NativeEnumerator_Generic()
{
var array = Enumerable.Range(0, 10).Select(value => (IConvertible)value).ToArray();
engine.Script.culture = CultureInfo.InvariantCulture;
engine.Execute(@"
function sum(array)
dim result
result = 0
for each item in array
result = result + item.ToInt32(culture)
next
sum = result
end function
");
Assert.AreEqual(array.Aggregate((current, next) => Convert.ToInt32(current) + Convert.ToInt32(next)), engine.Script.sum(array));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_NativeEnumerator_NonGeneric()
{
var array = Enumerable.Range(0, 10).ToArray();
engine.Execute(@"
function sum(array)
dim result
result = 0
for each item in array
result = result + item
next
sum = result
end function
");
Assert.AreEqual(array.Aggregate((current, next) => current + next), engine.Script.sum(HostObject.Wrap(array, typeof(IEnumerable))));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_NativeEnumerator_NonEnumerable()
{
engine.Execute(@"
function sum(array)
dim result
result = 0
for each item in array
result = result + item
next
sum = result
end function
");
TestUtil.AssertException<NotSupportedException>(() => engine.Script.sum(DayOfWeek.Monday));
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -5,9 +5,9 @@ setlocal
:: process arguments
::-----------------------------------------------------------------------------
set v8testedrev=4.4.63.29
set v8testedrev=4.7.80.25
set gyprev=0bb67471bca068996e15b56738fa4824dfa19de0
set gyprev=01528c7244837168a1c80f06ff60fa5a9793c824
set cygwinrev=c89e446b273697fadf3a10ff1007a97c0b7de6df
:ProcessArgs
@ -167,7 +167,7 @@ cd ..\..
:DownloadCygwin
echo Downloading Cygwin ...
git clone -n -q https://chromium.googlesource.com/chromium/deps/cygwin.git third_party/cygwin
git clone -n -q https://chromium.googlesource.com/chromium/deps/cygwin.git third_party\cygwin
if errorlevel 1 goto Error
cd third_party/cygwin
git checkout -q "%cygwinrev%"
@ -185,6 +185,8 @@ cd ..
:Build
set DEPOT_TOOLS_WIN_TOOLCHAIN=0
:CreatePatchFile
echo Creating patch file ...
cd v8

Просмотреть файл

@ -1 +1 @@
<# var version = new Version(5, 4, 3, 0); #>
<# var version = new Version(5, 4, 4, 0); #>