diff --git a/build-js.cmd b/build-js.cmd new file mode 100644 index 0000000..1e607da --- /dev/null +++ b/build-js.cmd @@ -0,0 +1,34 @@ +@echo off +setlocal + +cd ./src/MsieJavaScriptEngine/ + +::-------------------------------------------------------------------------------- +:: Build +::-------------------------------------------------------------------------------- + +echo Installing Node.js packages ... +echo. +call npm install +if errorlevel 1 goto error +echo. + +echo Minifying JS files ... +echo. +call npm run -s minify-js +if errorlevel 1 goto error +echo. + +::-------------------------------------------------------------------------------- +:: Exit +::-------------------------------------------------------------------------------- + +echo Succeeded! +goto exit + +:error +echo *** Error: The previous step failed! + +:exit +cd ../../ +endlocal \ No newline at end of file diff --git a/global.json b/global.json index 9b92080..4347eeb 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "7.0.102" + "version": "7.0.200" } } diff --git a/src/MsieJavaScriptEngine/.uglifyjsrc b/src/MsieJavaScriptEngine/.uglifyjsrc new file mode 100644 index 0000000..8a91584 --- /dev/null +++ b/src/MsieJavaScriptEngine/.uglifyjsrc @@ -0,0 +1,11 @@ +{ + "compress": { + "hoist_funs": true, + "hoist_vars": true, + "passes": 2 + }, + "mangle": {}, + "output": { + "comments": "/^!/" + } +} diff --git a/src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.cs b/src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.cs index 1b71fa8..eeabc4e 100644 --- a/src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.cs +++ b/src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.cs @@ -571,7 +571,7 @@ private void InnerCollectGarbage(ScriptGCType type) /// The mapped value private object MapToScriptType(object value) { - return TypeMappingHelpers.MapToScriptType(value, _settings.EngineMode); + return TypeMappingHelpers.MapToScriptType(value, _settings.EngineMode, _settings.AllowReflection); } /// @@ -581,7 +581,7 @@ private object MapToScriptType(object value) /// The mapped array private object[] MapToScriptType(object[] args) { - return TypeMappingHelpers.MapToScriptType(args, _settings.EngineMode); + return TypeMappingHelpers.MapToScriptType(args, _settings.EngineMode, _settings.AllowReflection); } /// @@ -900,7 +900,7 @@ public override void EmbedHostObject(string itemName, object value) public override void EmbedHostType(string itemName, Type type) { - var typeValue = new HostType(type, _settings.EngineMode); + var typeValue = new HostType(type, _settings.EngineMode, _settings.AllowReflection); _dispatcher.Invoke(() => { diff --git a/src/MsieJavaScriptEngine/ActiveScript/HostItemBase.cs b/src/MsieJavaScriptEngine/ActiveScript/HostItemBase.cs index 5e9cbf7..7d0b945 100644 --- a/src/MsieJavaScriptEngine/ActiveScript/HostItemBase.cs +++ b/src/MsieJavaScriptEngine/ActiveScript/HostItemBase.cs @@ -27,6 +27,11 @@ internal abstract class HostItemBase : IReflect /// protected readonly JsEngineMode _engineMode; + /// + /// Flag for whether to allow the usage of reflection API in the script code + /// + protected readonly bool _allowReflection; + /// /// List of fields /// @@ -57,20 +62,26 @@ public object Target /// Target type /// Target object /// JS engine mode + /// Flag for whether to allow the usage of reflection API in the script code /// Flag for whether to allow access to members of the instance - protected HostItemBase(Type type, object target, JsEngineMode engineMode, bool instance) + protected HostItemBase(Type type, object target, JsEngineMode engineMode, bool allowReflection, bool instance) { _type = type; _target = target; + _allowReflection = allowReflection; _engineMode = engineMode; BindingFlags defaultBindingFlags = ReflectionHelpers.GetDefaultBindingFlags(instance); FieldInfo[] fields = _type.GetFields(defaultBindingFlags); PropertyInfo[] properties = _type.GetProperties(defaultBindingFlags); + if (properties.Length > 0 && !allowReflection) + { + properties = GetAvailableProperties(properties); + } MethodInfo[] methods = _type.GetMethods(defaultBindingFlags); - if (methods.Length > 0 && properties.Length > 0) + if (methods.Length > 0 && (properties.Length > 0 || !allowReflection)) { - methods = ReflectionHelpers.GetFullyFledgedMethods(methods); + methods = GetAvailableMethods(methods, allowReflection); } _fields = fields; @@ -79,6 +90,49 @@ protected HostItemBase(Type type, object target, JsEngineMode engineMode, bool i } + private static PropertyInfo[] GetAvailableProperties(PropertyInfo[] properties) + { + int propertyCount = properties.Length; + var availableProperties = new PropertyInfo[propertyCount]; + int availablePropertyIndex = 0; + + for (int propertyIndex = 0; propertyIndex < propertyCount; propertyIndex++) + { + PropertyInfo property = properties[propertyIndex]; + if (ReflectionHelpers.IsAllowedProperty(property)) + { + availableProperties[availablePropertyIndex] = property; + availablePropertyIndex++; + } + } + + Array.Resize(ref availableProperties, availablePropertyIndex); + + return availableProperties; + } + + private static MethodInfo[] GetAvailableMethods(MethodInfo[] methods, bool allowReflection) + { + int methodCount = methods.Length; + var availableMethods = new MethodInfo[methodCount]; + int availableMethodIndex = 0; + + for (int methodIndex = 0; methodIndex < methodCount; methodIndex++) + { + MethodInfo method = methods[methodIndex]; + if (ReflectionHelpers.IsFullyFledgedMethod(method) + && (allowReflection || ReflectionHelpers.IsAllowedMethod(method))) + { + availableMethods[availableMethodIndex] = method; + availableMethodIndex++; + } + } + + Array.Resize(ref availableMethods, availableMethodIndex); + + return availableMethods; + } + private bool IsField(string name) { bool isField = false; diff --git a/src/MsieJavaScriptEngine/ActiveScript/HostObject.cs b/src/MsieJavaScriptEngine/ActiveScript/HostObject.cs index fd91ba0..cb00656 100644 --- a/src/MsieJavaScriptEngine/ActiveScript/HostObject.cs +++ b/src/MsieJavaScriptEngine/ActiveScript/HostObject.cs @@ -25,8 +25,9 @@ internal sealed class HostObject : HostItemBase /// /// Target object /// JS engine mode - public HostObject(object target, JsEngineMode engineMode) - : base(target.GetType(), target, engineMode, true) + /// Flag for whether to allow the usage of reflection API in the script code + public HostObject(object target, JsEngineMode engineMode, bool allowReflection) + : base(target.GetType(), target, engineMode, allowReflection, true) { var del = _target as Delegate; if (del != null) @@ -88,7 +89,7 @@ protected override object InnerInvokeMember(string name, BindingFlags invokeAttr processedArgs, modifiers, culture, namedParameters); } - return TypeMappingHelpers.MapToScriptType(result, _engineMode); + return TypeMappingHelpers.MapToScriptType(result, _engineMode, _allowReflection); } #endregion diff --git a/src/MsieJavaScriptEngine/ActiveScript/HostType.cs b/src/MsieJavaScriptEngine/ActiveScript/HostType.cs index 0071c0b..855d02d 100644 --- a/src/MsieJavaScriptEngine/ActiveScript/HostType.cs +++ b/src/MsieJavaScriptEngine/ActiveScript/HostType.cs @@ -19,8 +19,9 @@ internal sealed class HostType : HostItemBase /// /// Target type /// JS engine mode - public HostType(Type type, JsEngineMode engineMode) - : base(type, null, engineMode, false) + /// Flag for whether to allow the usage of reflection API in the script code + public HostType(Type type, JsEngineMode engineMode, bool allowReflection) + : base(type, null, engineMode, allowReflection, false) { } @@ -51,7 +52,7 @@ protected override object InnerInvokeMember(string name, BindingFlags invokeAttr processedArgs, modifiers, culture, namedParameters); } - return TypeMappingHelpers.MapToScriptType(result, _engineMode); + return TypeMappingHelpers.MapToScriptType(result, _engineMode, _allowReflection); } #endregion diff --git a/src/MsieJavaScriptEngine/Helpers/ReflectionHelpers.cs b/src/MsieJavaScriptEngine/Helpers/ReflectionHelpers.cs index 0f37cf5..304edc0 100644 --- a/src/MsieJavaScriptEngine/Helpers/ReflectionHelpers.cs +++ b/src/MsieJavaScriptEngine/Helpers/ReflectionHelpers.cs @@ -12,6 +12,19 @@ namespace MsieJavaScriptEngine.Helpers /// internal static class ReflectionHelpers { + private static readonly PropertyInfo[] _disallowedProperties = + { + typeof(Delegate).GetProperty("Method"), + typeof(Exception).GetProperty("TargetSite") + }; + + private static readonly MethodInfo[] _disallowedMethods = + { + typeof(object).GetMethod("GetType"), + typeof(Exception).GetMethod("GetType") + }; + + public static BindingFlags GetDefaultBindingFlags(bool instance) { BindingFlags bindingFlags = BindingFlags.Public; @@ -27,6 +40,20 @@ public static BindingFlags GetDefaultBindingFlags(bool instance) return bindingFlags; } + public static bool IsAllowedProperty(PropertyInfo property) + { + bool isAllowed = !_disallowedProperties.Contains(property, MemberComparer.Instance); + + return isAllowed; + } + + public static bool IsAllowedMethod(MethodInfo method) + { + bool isAllowed = !_disallowedMethods.Contains(method, MemberComparer.Instance); + + return isAllowed; + } + public static bool IsFullyFledgedMethod(MethodInfo method) { if (!method.Attributes.HasFlag(MethodAttributes.SpecialName)) @@ -40,29 +67,6 @@ public static bool IsFullyFledgedMethod(MethodInfo method) return isFullyFledged; } -#if NETFRAMEWORK - - public static MethodInfo[] GetFullyFledgedMethods(MethodInfo[] methods) - { - int methodCount = methods.Length; - var fullyFledgedMethods = new MethodInfo[methodCount]; - int fullyFledgedMethodIndex = 0; - - for (int methodIndex = 0; methodIndex < methodCount; methodIndex++) - { - MethodInfo method = methods[methodIndex]; - if (IsFullyFledgedMethod(method)) - { - fullyFledgedMethods[fullyFledgedMethodIndex] = method; - fullyFledgedMethodIndex++; - } - } - - Array.Resize(ref fullyFledgedMethods, fullyFledgedMethodIndex); - - return fullyFledgedMethods; - } -#endif public static void FixFieldValueType(ref object value, FieldInfo field) { @@ -244,6 +248,38 @@ private static bool CompareParameterTypes(object[] argValues, Type[] argTypes, T } + private sealed class MemberComparer : EqualityComparer + where T : MemberInfo + { + public static MemberComparer Instance { get; } = new MemberComparer(); + + + private MemberComparer() + { } + + + #region MemberComparer overrides + + public override bool Equals(T x, T y) + { + return x.Module == y.Module +#if !NETSTANDARD1_3 + && x.MetadataToken == y.MetadataToken +#else + && x.DeclaringType == y.DeclaringType + && x.Name == y.Name +#endif + ; + } + + public override int GetHashCode(T obj) + { + return obj != null ? obj.GetHashCode() : 0; + } + + #endregion + } + private sealed class MethodWithMetadata { public MethodBase Method diff --git a/src/MsieJavaScriptEngine/Helpers/TypeMappingHelpers.cs b/src/MsieJavaScriptEngine/Helpers/TypeMappingHelpers.cs index 424f45a..843ef9c 100644 --- a/src/MsieJavaScriptEngine/Helpers/TypeMappingHelpers.cs +++ b/src/MsieJavaScriptEngine/Helpers/TypeMappingHelpers.cs @@ -17,8 +17,9 @@ internal static class TypeMappingHelpers /// /// The source value /// JavaScript engine mode + /// Flag for whether to allow the usage of reflection API in the script code /// The mapped value - public static object MapToScriptType(object value, JsEngineMode engineMode) + public static object MapToScriptType(object value, JsEngineMode engineMode, bool allowReflection) { if (value == null) { @@ -36,7 +37,7 @@ public static object MapToScriptType(object value, JsEngineMode engineMode) return value; } - var result = new HostObject(value, engineMode); + var result = new HostObject(value, engineMode, allowReflection); return result; } @@ -46,10 +47,11 @@ public static object MapToScriptType(object value, JsEngineMode engineMode) /// /// The source array /// JavaScript engine mode + /// Flag for whether to allow the usage of reflection API in the script code /// The mapped array - public static object[] MapToScriptType(object[] args, JsEngineMode engineMode) + public static object[] MapToScriptType(object[] args, JsEngineMode engineMode, bool allowReflection) { - return args.Select(arg => MapToScriptType(arg, engineMode)).ToArray(); + return args.Select(arg => MapToScriptType(arg, engineMode, allowReflection)).ToArray(); } /// diff --git a/src/MsieJavaScriptEngine/JsEngineSettings.cs b/src/MsieJavaScriptEngine/JsEngineSettings.cs index 85c0e6f..ff92ee5 100644 --- a/src/MsieJavaScriptEngine/JsEngineSettings.cs +++ b/src/MsieJavaScriptEngine/JsEngineSettings.cs @@ -27,6 +27,19 @@ public sealed class JsEngineSettings private int _maxStackSize; #endif + /// + /// Gets or sets a flag for whether to allow the usage of reflection API in the script code + /// + /// + /// This affects , Exception.GetType, + /// Exception.TargetSite and Delegate.Method. + /// + public bool AllowReflection + { + get; + set; + } + /// /// Gets or sets a flag for whether to enable script debugging features /// @@ -95,6 +108,7 @@ public bool UseJson2Library /// public JsEngineSettings() { + AllowReflection = false; EnableDebugging = false; EngineMode = JsEngineMode.Auto; #if !NETSTANDARD1_3 diff --git a/src/MsieJavaScriptEngine/JsRt/Edge/ChakraEdgeJsRtJsEngine.cs b/src/MsieJavaScriptEngine/JsRt/Edge/ChakraEdgeJsRtJsEngine.cs index d7271ac..7ed6c07 100644 --- a/src/MsieJavaScriptEngine/JsRt/Edge/ChakraEdgeJsRtJsEngine.cs +++ b/src/MsieJavaScriptEngine/JsRt/Edge/ChakraEdgeJsRtJsEngine.cs @@ -61,7 +61,7 @@ internal sealed class ChakraEdgeJsRtJsEngine : ChakraJsRtJsEngineBase public ChakraEdgeJsRtJsEngine(JsEngineSettings settings) : base(settings) { - _typeMapper = new EdgeTypeMapper(); + _typeMapper = new EdgeTypeMapper(settings.AllowReflection); try { diff --git a/src/MsieJavaScriptEngine/JsRt/Edge/EdgeTypeMapper.cs b/src/MsieJavaScriptEngine/JsRt/Edge/EdgeTypeMapper.cs index 37ca65b..eabfe7a 100644 --- a/src/MsieJavaScriptEngine/JsRt/Edge/EdgeTypeMapper.cs +++ b/src/MsieJavaScriptEngine/JsRt/Edge/EdgeTypeMapper.cs @@ -26,7 +26,9 @@ internal sealed class EdgeTypeMapper : TypeMapper /// Constructs an instance of the “Edge” type mapper /// - public EdgeTypeMapper() + /// Flag for whether to allow the usage of reflection API in the script code + public EdgeTypeMapper(bool allowReflection) + : base(allowReflection) { } @@ -437,6 +439,11 @@ private void ProjectProperties(EdgeEmbeddedItem externalItem) foreach (PropertyInfo property in properties) { + if (!IsAvailableProperty(property)) + { + continue; + } + string propertyName = property.Name; EdgeJsValue descriptorValue = EdgeJsValue.CreateObject(); @@ -565,11 +572,10 @@ private void ProjectMethods(EdgeEmbeddedItem externalItem) string typeName = type.FullName; BindingFlags defaultBindingFlags = ReflectionHelpers.GetDefaultBindingFlags(instance); - IEnumerable methods = type.GetMethods(defaultBindingFlags) - .Where(ReflectionHelpers.IsFullyFledgedMethod); - IEnumerable> methodGroups = methods.GroupBy(m => m.Name); + MethodInfo[] methods = type.GetMethods(defaultBindingFlags); + IEnumerable> availableMethodGroups = GetAvailableMethodGroups(methods); - foreach (IGrouping methodGroup in methodGroups) + foreach (IGrouping methodGroup in availableMethodGroups) { string methodName = methodGroup.Key; MethodInfo[] methodCandidates = methodGroup.ToArray(); diff --git a/src/MsieJavaScriptEngine/JsRt/Ie/ChakraIeJsRtJsEngine.cs b/src/MsieJavaScriptEngine/JsRt/Ie/ChakraIeJsRtJsEngine.cs index 11fddd7..c405866 100644 --- a/src/MsieJavaScriptEngine/JsRt/Ie/ChakraIeJsRtJsEngine.cs +++ b/src/MsieJavaScriptEngine/JsRt/Ie/ChakraIeJsRtJsEngine.cs @@ -69,7 +69,7 @@ internal sealed class ChakraIeJsRtJsEngine : ChakraJsRtJsEngineBase public ChakraIeJsRtJsEngine(JsEngineSettings settings) : base(settings) { - _typeMapper = new IeTypeMapper(); + _typeMapper = new IeTypeMapper(settings.AllowReflection); try { diff --git a/src/MsieJavaScriptEngine/JsRt/Ie/IeTypeMapper.cs b/src/MsieJavaScriptEngine/JsRt/Ie/IeTypeMapper.cs index 5d50d7c..a3e4944 100644 --- a/src/MsieJavaScriptEngine/JsRt/Ie/IeTypeMapper.cs +++ b/src/MsieJavaScriptEngine/JsRt/Ie/IeTypeMapper.cs @@ -26,7 +26,9 @@ internal sealed class IeTypeMapper : TypeMapper /// /// Constructs an instance of the “IE” type mapper /// - public IeTypeMapper() + /// Flag for whether to allow the usage of reflection API in the script code + public IeTypeMapper(bool allowReflection) + : base(allowReflection) { } @@ -437,6 +439,11 @@ private void ProjectProperties(IeEmbeddedItem externalItem) foreach (PropertyInfo property in properties) { + if (!IsAvailableProperty(property)) + { + continue; + } + string propertyName = property.Name; IeJsValue descriptorValue = IeJsValue.CreateObject(); @@ -565,11 +572,10 @@ private void ProjectMethods(IeEmbeddedItem externalItem) string typeName = type.FullName; BindingFlags defaultBindingFlags = ReflectionHelpers.GetDefaultBindingFlags(instance); - IEnumerable methods = type.GetMethods(defaultBindingFlags) - .Where(ReflectionHelpers.IsFullyFledgedMethod); - IEnumerable> methodGroups = methods.GroupBy(m => m.Name); + MethodInfo[] methods = type.GetMethods(defaultBindingFlags); + IEnumerable> availableMethodGroups = GetAvailableMethodGroups(methods); - foreach (IGrouping methodGroup in methodGroups) + foreach (IGrouping methodGroup in availableMethodGroups) { string methodName = methodGroup.Key; MethodInfo[] methodCandidates = methodGroup.ToArray(); diff --git a/src/MsieJavaScriptEngine/JsRt/TypeMapper.cs b/src/MsieJavaScriptEngine/JsRt/TypeMapper.cs index a4a50f6..8615e09 100644 --- a/src/MsieJavaScriptEngine/JsRt/TypeMapper.cs +++ b/src/MsieJavaScriptEngine/JsRt/TypeMapper.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using MsieJavaScriptEngine.Helpers; using MsieJavaScriptEngine.JsRt.Embedding; using MsieJavaScriptEngine.Utilities; @@ -23,6 +25,11 @@ internal abstract class TypeMapper : IDisposable /// protected const string ExternalObjectPropertyName = "_MsieJavaScriptEngine_externalObject"; + /// + /// Flag for whether to allow the usage of reflection API in the script code + /// + protected readonly bool _allowReflection; + /// /// Storage for lazy-initialized embedded objects /// @@ -69,6 +76,16 @@ internal abstract class TypeMapper : IDisposable private InterlockedStatedFlag _disposedFlag = new InterlockedStatedFlag(); + /// + /// Constructs an instance of the type mapper + /// + /// Flag for whether to allow the usage of reflection API in the script code + protected TypeMapper(bool allowReflection) + { + _allowReflection = allowReflection; + } + + /// /// Creates a JavaScript value from an host object if the it does not already exist /// @@ -200,6 +217,30 @@ private void EmbeddedTypeFinalizeCallback(IntPtr ptr) embeddedTypeHandle.Free(); } + protected bool IsAvailableProperty(PropertyInfo property) + { + if (_allowReflection) + { + return true; + } + + bool isAvailable = ReflectionHelpers.IsAllowedProperty(property); + + return isAvailable; + } + + protected IEnumerable> GetAvailableMethodGroups(MethodInfo[] methods) + { + IEnumerable availableMethods = methods.Where(ReflectionHelpers.IsFullyFledgedMethod); + if (!_allowReflection) + { + availableMethods = availableMethods.Where(ReflectionHelpers.IsAllowedMethod); + } + IEnumerable> availableMethodGroups = availableMethods.GroupBy(m => m.Name); + + return availableMethodGroups; + } + protected object[] GetHostItemMemberArguments(TValue[] args, int maxArgCount = -1) { if (args == null) diff --git a/src/MsieJavaScriptEngine/MsieJavaScriptEngine.csproj b/src/MsieJavaScriptEngine/MsieJavaScriptEngine.csproj index 41e1e91..72acc70 100644 --- a/src/MsieJavaScriptEngine/MsieJavaScriptEngine.csproj +++ b/src/MsieJavaScriptEngine/MsieJavaScriptEngine.csproj @@ -25,8 +25,7 @@ true snupkg JavaScript;ECMAScript;MSIE;IE;Edge;Chakra - 1. In JsRT modes, `JsVariantToValue` and `JsValueToVariant` native methods are no longer used for embedding objects and types; -2. JSON2 library was updated to version of October 30, 2022. + In JavaScript engine settings was added one new property - `AllowReflection` (default `false`). en-US ../../nuget true @@ -40,7 +39,6 @@ - @@ -87,4 +85,10 @@ + + + + \ No newline at end of file diff --git a/src/MsieJavaScriptEngine/bundleconfig.json b/src/MsieJavaScriptEngine/bundleconfig.json deleted file mode 100644 index 9153a95..0000000 --- a/src/MsieJavaScriptEngine/bundleconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "outputFileName": "Resources/ES5.min.js", - "inputFiles": [ - "Resources/ES5.js" - ] - }, - { - "outputFileName": "Resources/json2.min.js", - "inputFiles": [ - "Resources/json2.js" - ] - } -] diff --git a/src/MsieJavaScriptEngine/package.json b/src/MsieJavaScriptEngine/package.json new file mode 100644 index 0000000..381dbb5 --- /dev/null +++ b/src/MsieJavaScriptEngine/package.json @@ -0,0 +1,12 @@ +{ + "name": "MsieJavaScriptEngine", + "version": "3.1.0", + "devDependencies": { + "uglify-js": "3.16.1" + }, + "scripts": { + "minify-es5-js": "uglifyjs ./Resources/ES5.js --output ./Resources/ES5.min.js --config-file ./.uglifyjsrc", + "minify-json2-js": "uglifyjs ./Resources/json2.js --output ./Resources/json2.min.js --config-file ./.uglifyjsrc", + "minify-js": "npm run -s minify-es5-js && npm run -s minify-json2-js" + } +} diff --git a/src/MsieJavaScriptEngine/readme.txt b/src/MsieJavaScriptEngine/readme.txt index 6827039..319849c 100644 --- a/src/MsieJavaScriptEngine/readme.txt +++ b/src/MsieJavaScriptEngine/readme.txt @@ -21,9 +21,8 @@ ============= RELEASE NOTES ============= - 1. In JsRT modes, `JsVariantToValue` and `JsValueToVariant` native methods are - no longer used for embedding objects and types; - 2. JSON2 library was updated to version of October 30, 2022. + In JavaScript engine settings was added one new property - `AllowReflection` + (default `false`). ============ PROJECT SITE diff --git a/test/MsieJavaScriptEngine.Benchmarks/MsieJavaScriptEngine.Benchmarks.csproj b/test/MsieJavaScriptEngine.Benchmarks/MsieJavaScriptEngine.Benchmarks.csproj index c122933..674cebb 100644 --- a/test/MsieJavaScriptEngine.Benchmarks/MsieJavaScriptEngine.Benchmarks.csproj +++ b/test/MsieJavaScriptEngine.Benchmarks/MsieJavaScriptEngine.Benchmarks.csproj @@ -21,7 +21,7 @@ - + diff --git a/test/MsieJavaScriptEngine.Test.Auto/InteropTests.cs b/test/MsieJavaScriptEngine.Test.Auto/InteropTests.cs index c6e4def..3034802 100644 --- a/test/MsieJavaScriptEngine.Test.Auto/InteropTests.cs +++ b/test/MsieJavaScriptEngine.Test.Auto/InteropTests.cs @@ -8,5 +8,45 @@ namespace MsieJavaScriptEngine.Test.Auto public class InteropTests : InteropTestsBase { protected override JsEngineMode EngineMode => JsEngineMode.Auto; + + + #region Embedding of objects + + #region Objects with methods + + public override void EmbeddingOfInstanceOfCustomValueTypeAndCallingOfItsGetTypeMethod() + { } + + public override void EmbeddingOfInstanceOfCustomReferenceTypeAndCallingOfItsGetTypeMethod() + { } + + #endregion + + #region Delegates + + public override void EmbeddingOfInstanceOfDelegateAndCheckingItsPrototype() + { } + + public override void EmbeddingOfInstanceOfDelegateAndGettingItsMethodProperty() + { } + + #endregion + + #endregion + + + #region Embedding of types + + #region Creating of instances + + public override void CreatingAnInstanceOfEmbeddedBuiltinExceptionAndGettingItsTargetSiteProperty() + { } + + public override void CreatingAnInstanceOfEmbeddedCustomExceptionAndCallingOfItsGetTypeMethod() + { } + + #endregion + + #endregion } } \ No newline at end of file diff --git a/test/MsieJavaScriptEngine.Test.Auto/MsieJavaScriptEngine.Test.Auto.csproj b/test/MsieJavaScriptEngine.Test.Auto/MsieJavaScriptEngine.Test.Auto.csproj index ef7fdd3..7748d17 100644 --- a/test/MsieJavaScriptEngine.Test.Auto/MsieJavaScriptEngine.Test.Auto.csproj +++ b/test/MsieJavaScriptEngine.Test.Auto/MsieJavaScriptEngine.Test.Auto.csproj @@ -5,6 +5,7 @@ 3.1.0 net40;net45;netcoreapp2.1;netcoreapp3.1;net5.0;net6.0;net7.0 Library + latest true true false @@ -14,9 +15,15 @@ + + + + + - + + \ No newline at end of file diff --git a/test/MsieJavaScriptEngine.Test.ChakraActiveScript/CommonTests.cs b/test/MsieJavaScriptEngine.Test.ChakraActiveScript/CommonTests.cs index a3d4893..b33e52e 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraActiveScript/CommonTests.cs +++ b/test/MsieJavaScriptEngine.Test.ChakraActiveScript/CommonTests.cs @@ -65,7 +65,7 @@ public void MappingCompilationErrorDuringEvaluationOfExpressionInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -186,7 +186,7 @@ public void MappingCompilationErrorDuringExecutionOfCodeInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -300,7 +300,7 @@ public void GenerationOfCompilationErrorMessageInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { diff --git a/test/MsieJavaScriptEngine.Test.ChakraActiveScript/InteropTests.cs b/test/MsieJavaScriptEngine.Test.ChakraActiveScript/InteropTests.cs index d6c6443..432f127 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraActiveScript/InteropTests.cs +++ b/test/MsieJavaScriptEngine.Test.ChakraActiveScript/InteropTests.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using MsieJavaScriptEngine.Test.Common; +using MsieJavaScriptEngine.Test.Common.Interop.Animals; namespace MsieJavaScriptEngine.Test.ChakraActiveScript { @@ -15,6 +16,35 @@ public class InteropTests : InteropTestsBase #region Embedding of objects + #region Delegates + + [Test] + public override void EmbeddingOfInstanceOfDelegateAndCheckingItsPrototype() + { } + + [Test] + public override void EmbeddingOfInstanceOfDelegateAndGettingItsMethodProperty() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var cat = new Cat(); + var cryFunc = new Func(cat.Cry); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("cry", cryFunc); + return jsEngine.Evaluate("cry.Method;"); + } + } + + // Act and Assert + Assert.AreEqual("System.String Cry()", TestAllowReflectionSetting(true)); + Assert.AreEqual("undefined", TestAllowReflectionSetting(false)); + } + + #endregion + #region Recursive calls #region Mapping of errors diff --git a/test/MsieJavaScriptEngine.Test.ChakraActiveScript/MsieJavaScriptEngine.Test.ChakraActiveScript.csproj b/test/MsieJavaScriptEngine.Test.ChakraActiveScript/MsieJavaScriptEngine.Test.ChakraActiveScript.csproj index 8bd96f8..3ba8b43 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraActiveScript/MsieJavaScriptEngine.Test.ChakraActiveScript.csproj +++ b/test/MsieJavaScriptEngine.Test.ChakraActiveScript/MsieJavaScriptEngine.Test.ChakraActiveScript.csproj @@ -5,6 +5,7 @@ 3.1.0 net40;net45 Library + latest true true false diff --git a/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/CommonTests.cs b/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/CommonTests.cs index 8549729..09acc27 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/CommonTests.cs +++ b/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/CommonTests.cs @@ -66,7 +66,7 @@ public void MappingCompilationErrorDuringEvaluationOfExpressionInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -187,7 +187,7 @@ public virtual void MappingCompilationErrorDuringExecutionOfCodeInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -305,7 +305,7 @@ public void GenerationOfCompilationErrorMessageInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { diff --git a/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/InteropTests.cs b/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/InteropTests.cs index 65bca83..14eefa0 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/InteropTests.cs +++ b/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/InteropTests.cs @@ -15,31 +15,6 @@ public class InteropTests : InteropTestsBase #region Embedding of objects - #region Delegates - - [Test] - public void EmbeddedInstanceOfDelegateHasFunctionPrototype() - { - // Arrange - var someFunc = new Func(() => 42); - - const string input = "Object.getPrototypeOf(embeddedFunc) === Function.prototype"; - - // Act - bool output; - - using (var jsEngine = CreateJsEngine()) - { - jsEngine.EmbedHostObject("embeddedFunc", someFunc); - output = jsEngine.Evaluate(input); - } - - // Assert - Assert.True(output); - } - - #endregion - #region Recursive calls #region Mapping of errors diff --git a/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/MsieJavaScriptEngine.Test.ChakraEdgeJsRt.csproj b/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/MsieJavaScriptEngine.Test.ChakraEdgeJsRt.csproj index b087cc1..07c196f 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/MsieJavaScriptEngine.Test.ChakraEdgeJsRt.csproj +++ b/test/MsieJavaScriptEngine.Test.ChakraEdgeJsRt/MsieJavaScriptEngine.Test.ChakraEdgeJsRt.csproj @@ -5,6 +5,7 @@ 3.1.0 net40;net45;netcoreapp2.1;netcoreapp3.1;net5.0;net6.0;net7.0 Library + latest true true false @@ -14,9 +15,15 @@ + + + + + - + + \ No newline at end of file diff --git a/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/CommonTests.cs b/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/CommonTests.cs index 2c34764..9983e4a 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/CommonTests.cs +++ b/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/CommonTests.cs @@ -65,7 +65,7 @@ public void MappingCompilationErrorDuringEvaluationOfExpressionInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -186,7 +186,7 @@ public virtual void MappingCompilationErrorDuringExecutionOfCodeInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -304,7 +304,7 @@ public void GenerationOfCompilationErrorMessageInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { diff --git a/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/InteropTests.cs b/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/InteropTests.cs index 3d06904..15ee2c5 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/InteropTests.cs +++ b/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/InteropTests.cs @@ -15,31 +15,6 @@ public class InteropTests : InteropTestsBase #region Embedding of objects - #region Delegates - - [Test] - public void EmbeddedInstanceOfDelegateHasFunctionPrototype() - { - // Arrange - var someFunc = new Func(() => 42); - - const string input = "Object.getPrototypeOf(embeddedFunc) === Function.prototype"; - - // Act - bool output; - - using (var jsEngine = CreateJsEngine()) - { - jsEngine.EmbedHostObject("embeddedFunc", someFunc); - output = jsEngine.Evaluate(input); - } - - // Assert - Assert.True(output); - } - - #endregion - #region Recursive calls #region Mapping of errors diff --git a/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/MsieJavaScriptEngine.Test.ChakraIeJsRt.csproj b/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/MsieJavaScriptEngine.Test.ChakraIeJsRt.csproj index a6090e4..d849933 100644 --- a/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/MsieJavaScriptEngine.Test.ChakraIeJsRt.csproj +++ b/test/MsieJavaScriptEngine.Test.ChakraIeJsRt/MsieJavaScriptEngine.Test.ChakraIeJsRt.csproj @@ -5,6 +5,7 @@ 3.1.0 net40;net45;netcoreapp2.1;netcoreapp3.1;net5.0;net6.0;net7.0 Library + latest true true false @@ -14,9 +15,15 @@ + + + + + - + + \ No newline at end of file diff --git a/test/MsieJavaScriptEngine.Test.Classic/CommonTests.cs b/test/MsieJavaScriptEngine.Test.Classic/CommonTests.cs index 43b314c..45a5ac3 100644 --- a/test/MsieJavaScriptEngine.Test.Classic/CommonTests.cs +++ b/test/MsieJavaScriptEngine.Test.Classic/CommonTests.cs @@ -65,7 +65,7 @@ public void MappingCompilationErrorDuringEvaluationOfExpressionInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -186,7 +186,7 @@ public void MappingCompilationErrorDuringExecutionOfCodeInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { @@ -300,7 +300,7 @@ public void GenerationOfCompilationErrorMessageInDebugMode() JsCompilationException exception = null; // Act - using (var jsEngine = CreateJsEngine(true)) + using (var jsEngine = CreateJsEngine(enableDebugging: true)) { try { diff --git a/test/MsieJavaScriptEngine.Test.Classic/InteropTests.cs b/test/MsieJavaScriptEngine.Test.Classic/InteropTests.cs index 41d91a0..48763b5 100644 --- a/test/MsieJavaScriptEngine.Test.Classic/InteropTests.cs +++ b/test/MsieJavaScriptEngine.Test.Classic/InteropTests.cs @@ -4,6 +4,8 @@ using NUnit.Framework; using MsieJavaScriptEngine.Test.Common; +using MsieJavaScriptEngine.Test.Common.Interop; +using MsieJavaScriptEngine.Test.Common.Interop.Animals; namespace MsieJavaScriptEngine.Test.Classic { @@ -15,6 +17,85 @@ public class InteropTests : InteropTestsBase #region Embedding of objects + #region Objects with methods + + [Test] + public override void EmbeddingOfInstanceOfCustomValueTypeAndCallingOfItsGetTypeMethod() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var date = new Date(); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("date", date); + return jsEngine.Evaluate("date.GetType();"); + } + } + + // Act and Assert + Assert.AreEqual(typeof(Date).FullName, TestAllowReflectionSetting(true)); + + var exception = Assert.Throws(() => TestAllowReflectionSetting(false)); + Assert.AreEqual("Runtime error", exception.Category); + Assert.AreEqual("Object doesn't support this property or method", exception.Description); + } + + [Test] + public override void EmbeddingOfInstanceOfCustomReferenceTypeAndCallingOfItsGetTypeMethod() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var cat = new Cat(); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("cat", cat); + return jsEngine.Evaluate("cat.GetType();"); + } + } + + // Act and Assert + Assert.AreEqual(typeof(Cat).FullName, TestAllowReflectionSetting(true)); + + var exception = Assert.Throws(() => TestAllowReflectionSetting(false)); + Assert.AreEqual("Runtime error", exception.Category); + Assert.AreEqual("Object doesn't support this property or method", exception.Description); + } + + #endregion + + #region Delegates + + [Test] + public override void EmbeddingOfInstanceOfDelegateAndCheckingItsPrototype() + { } + + [Test] + public override void EmbeddingOfInstanceOfDelegateAndGettingItsMethodProperty() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var cat = new Cat(); + var cryFunc = new Func(cat.Cry); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("cry", cryFunc); + return jsEngine.Evaluate("cry.Method;"); + } + } + + // Act and Assert + Assert.AreEqual("System.String Cry()", TestAllowReflectionSetting(true)); + Assert.AreEqual("undefined", TestAllowReflectionSetting(false)); + } + + #endregion + #region Recursive calls #region Mapping of errors @@ -67,5 +148,37 @@ public void MappingRuntimeErrorDuringRecursiveEvaluationOfFiles() #endregion #endregion + + + #region Embedding of types + + #region Creating of instances + + [Test] + public override void CreatingAnInstanceOfEmbeddedCustomExceptionAndCallingOfItsGetTypeMethod() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + Type loginFailedExceptionType = typeof(LoginFailedException); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostType("LoginFailedError", loginFailedExceptionType); + return jsEngine.Evaluate("new LoginFailedError(\"Wrong password entered!\").GetType();"); + } + } + + // Act and Assert + Assert.AreEqual(typeof(LoginFailedException).FullName, TestAllowReflectionSetting(true)); + + var exception = Assert.Throws(() => TestAllowReflectionSetting(false)); + Assert.AreEqual("Runtime error", exception.Category); + Assert.AreEqual("Object doesn't support this property or method", exception.Description); + } + + #endregion + + #endregion } } \ No newline at end of file diff --git a/test/MsieJavaScriptEngine.Test.Classic/MsieJavaScriptEngine.Test.Classic.csproj b/test/MsieJavaScriptEngine.Test.Classic/MsieJavaScriptEngine.Test.Classic.csproj index beaee3e..d8d21a3 100644 --- a/test/MsieJavaScriptEngine.Test.Classic/MsieJavaScriptEngine.Test.Classic.csproj +++ b/test/MsieJavaScriptEngine.Test.Classic/MsieJavaScriptEngine.Test.Classic.csproj @@ -5,6 +5,7 @@ 3.1.0 net40;net45 Library + latest true true false diff --git a/test/MsieJavaScriptEngine.Test.Common/Interop/LoginFailedException.cs b/test/MsieJavaScriptEngine.Test.Common/Interop/LoginFailedException.cs new file mode 100644 index 0000000..72e6b20 --- /dev/null +++ b/test/MsieJavaScriptEngine.Test.Common/Interop/LoginFailedException.cs @@ -0,0 +1,50 @@ +using System; +using System.Runtime.Serialization; + +namespace MsieJavaScriptEngine.Test.Common.Interop +{ + [Serializable] + public class LoginFailedException : Exception + { + private string _userName; + + public string UserName + { + get { return _userName; } + set { _userName = value; } + } + + + public LoginFailedException() + { } + + public LoginFailedException(string message) + : base(message) + { } + + public LoginFailedException(string message, Exception innerException) + : base(message, innerException) + { } + + protected LoginFailedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info != null) + { + _userName = info.GetString("UserName"); + } + } + + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + { + throw new ArgumentNullException(nameof(info)); + } + + base.GetObjectData(info, context); + info.AddValue("UserName", this._userName); + } + } +} \ No newline at end of file diff --git a/test/MsieJavaScriptEngine.Test.Common/InteropTestsBase.cs b/test/MsieJavaScriptEngine.Test.Common/InteropTestsBase.cs index 9bd2684..53274a2 100644 --- a/test/MsieJavaScriptEngine.Test.Common/InteropTestsBase.cs +++ b/test/MsieJavaScriptEngine.Test.Common/InteropTestsBase.cs @@ -432,7 +432,7 @@ public virtual void EmbeddingOfInstanceOfCustomReferenceTypeWithMethod() } [Test] - public virtual void CallingOfMethodOfCustomReferenceTypeWithInterfaceParameter() + public virtual void EmbeddingOfInstancesOfCustomReferenceTypesAndCallingOfMethodOfWithInterfaceParameter() { // Arrange var animalTrainer = new AnimalTrainer(); @@ -463,6 +463,52 @@ public virtual void CallingOfMethodOfCustomReferenceTypeWithInterfaceParameter() Assert.AreEqual(targetOutput2, output2); } + [Test] + public virtual void EmbeddingOfInstanceOfCustomValueTypeAndCallingOfItsGetTypeMethod() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var date = new Date(); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("date", date); + return jsEngine.Evaluate("date.GetType();"); + } + } + + // Act and Assert + Assert.AreEqual(typeof(Date).FullName, TestAllowReflectionSetting(true)); + + var exception = Assert.Throws(() => TestAllowReflectionSetting(false)); + Assert.AreEqual("Runtime error", exception.Category); + Assert.AreEqual("Object doesn't support property or method 'GetType'", exception.Description); + } + + [Test] + public virtual void EmbeddingOfInstanceOfCustomReferenceTypeAndCallingOfItsGetTypeMethod() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var cat = new Cat(); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("cat", cat); + return jsEngine.Evaluate("cat.GetType();"); + } + } + + // Act and Assert + Assert.AreEqual(typeof(Cat).FullName, TestAllowReflectionSetting(true)); + + var exception = Assert.Throws(() => TestAllowReflectionSetting(false)); + Assert.AreEqual("Runtime error", exception.Category); + Assert.AreEqual("Object doesn't support property or method 'GetType'", exception.Description); + } + #endregion #region Delegates @@ -597,7 +643,28 @@ public virtual void EmbeddingOfInstanceOfDelegateWithoutResult() } [Test] - public virtual void CallingOfEmbeddedDelegateWithMissingParameter() + public virtual void EmbeddingOfInstanceOfDelegateAndCheckingItsPrototype() + { + // Arrange + var someFunc = new Func(() => 42); + + const string input = "Object.getPrototypeOf(embeddedFunc) === Function.prototype"; + + // Act + bool output; + + using (var jsEngine = CreateJsEngine()) + { + jsEngine.EmbedHostObject("embeddedFunc", someFunc); + output = jsEngine.Evaluate(input); + } + + // Assert + Assert.True(output); + } + + [Test] + public virtual void EmbeddingOfInstanceOfDelegateAndCallingItWithMissingParameter() { // Arrange var sumFunc = new Func((a, b) => a + b); @@ -625,7 +692,7 @@ public virtual void CallingOfEmbeddedDelegateWithMissingParameter() } [Test] - public virtual void CallingOfEmbeddedDelegateWithExtraParameter() + public virtual void EmbeddingOfInstanceOfDelegateAndCallingItWithExtraParameter() { // Arrange var sumFunc = new Func((a, b) => a + b); @@ -646,6 +713,27 @@ public virtual void CallingOfEmbeddedDelegateWithExtraParameter() Assert.AreEqual(targetOutput, output); } + [Test] + public virtual void EmbeddingOfInstanceOfDelegateAndGettingItsMethodProperty() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + var cat = new Cat(); + var cryFunc = new Func(cat.Cry); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostObject("cry", cryFunc); + return jsEngine.Evaluate("cry.Method;"); + } + } + + // Act and Assert + Assert.AreEqual("undefined", TestAllowReflectionSetting(true)); + Assert.AreEqual("undefined", TestAllowReflectionSetting(false)); + } + #endregion #region Integration @@ -888,6 +976,49 @@ public virtual void CreatingAnInstanceOfEmbeddedCustomReferenceType() Assert.AreEqual(targetOutput, output); } + [Test] + public virtual void CreatingAnInstanceOfEmbeddedBuiltinExceptionAndGettingItsTargetSiteProperty() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + Type invalidOperationExceptionType = typeof(InvalidOperationException); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostType("InvalidOperationError", invalidOperationExceptionType); + return jsEngine.Evaluate("new InvalidOperationError(\"A terrible thing happened!\").TargetSite;"); + } + } + + // Act and Assert + Assert.AreEqual(null, TestAllowReflectionSetting(true)); + Assert.AreEqual("undefined", TestAllowReflectionSetting(false)); + } + + [Test] + public virtual void CreatingAnInstanceOfEmbeddedCustomExceptionAndCallingOfItsGetTypeMethod() + { + // Arrange + string TestAllowReflectionSetting(bool allowReflection) + { + Type loginFailedExceptionType = typeof(LoginFailedException); + + using (var jsEngine = CreateJsEngine(allowReflection: allowReflection)) + { + jsEngine.EmbedHostType("LoginFailedError", loginFailedExceptionType); + return jsEngine.Evaluate("new LoginFailedError(\"Wrong password entered!\").GetType();"); + } + } + + // Act and Assert + Assert.AreEqual(typeof(LoginFailedException).FullName, TestAllowReflectionSetting(true)); + + var exception = Assert.Throws(() => TestAllowReflectionSetting(false)); + Assert.AreEqual("Runtime error", exception.Category); + Assert.AreEqual("Object doesn't support property or method 'GetType'", exception.Description); + } + #endregion #region Types with constants diff --git a/test/MsieJavaScriptEngine.Test.Common/MsieJavaScriptEngine.Test.Common.csproj b/test/MsieJavaScriptEngine.Test.Common/MsieJavaScriptEngine.Test.Common.csproj index 1398b23..c32328a 100644 --- a/test/MsieJavaScriptEngine.Test.Common/MsieJavaScriptEngine.Test.Common.csproj +++ b/test/MsieJavaScriptEngine.Test.Common/MsieJavaScriptEngine.Test.Common.csproj @@ -5,6 +5,7 @@ 3.1.0 net40;net45;netcoreapp2.1;netcoreapp3.1;net5.0;net6.0;net7.0 Library + latest true true false @@ -15,12 +16,19 @@ - + + + + + + + + diff --git a/test/MsieJavaScriptEngine.Test.Common/TestsBase.cs b/test/MsieJavaScriptEngine.Test.Common/TestsBase.cs index 81c99f7..6854dfb 100644 --- a/test/MsieJavaScriptEngine.Test.Common/TestsBase.cs +++ b/test/MsieJavaScriptEngine.Test.Common/TestsBase.cs @@ -18,15 +18,11 @@ public abstract class TestsBase protected virtual bool UseJson2Library => false; - protected MsieJsEngine CreateJsEngine() - { - return CreateJsEngine(false); - } - - protected MsieJsEngine CreateJsEngine(bool enableDebugging) + protected MsieJsEngine CreateJsEngine(bool allowReflection = false, bool enableDebugging = false) { var jsEngine = new MsieJsEngine(new JsEngineSettings { + AllowReflection = allowReflection, EnableDebugging = enableDebugging, EngineMode = EngineMode, UseEcmaScript5Polyfill = UseEcmaScript5Polyfill,