Skip to content

Commit

Permalink
Improve property selection for setting value under interop (#1389)
Browse files Browse the repository at this point in the history
fixes #1375
  • Loading branch information
lahma committed Dec 25, 2022
1 parent 3c45b8c commit fa9b3d9
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 14 deletions.
14 changes: 14 additions & 0 deletions Jint.Tests/Runtime/InteropTests.NewtonsoftJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,19 @@ public void DecimalsShouldBeHandledFromJObjects()
var number = Assert.IsType<JsNumber>(fromInterop);
Assert.Equal(123.456d, number.AsNumber());
}

[Fact]
public void ShouldBeAbleToChangePropertyWithNameValue()
{
var engine = new Engine();

var input = Newtonsoft.Json.JsonConvert.DeserializeObject(@"{ ""value"": ""ORIGINAL"" }");
var result = engine
.SetValue("input", input)
.Evaluate("input.value = \"CHANGED\"; input.value")
.AsString();

Assert.Equal("CHANGED", result);
}
}
}
4 changes: 0 additions & 4 deletions Jint/Native/TypedArray/TypedArrayPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
using Jint.Collections;
using Jint.Native.Array;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;

namespace Jint.Native.TypedArray;

Expand Down
1 change: 0 additions & 1 deletion Jint/Native/WeakSet/WeakSetInstance.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Runtime.CompilerServices;

using Jint.Native.Object;
using Jint.Native.Symbol;
using Jint.Runtime;

namespace Jint.Native.WeakSet;
Expand Down
1 change: 0 additions & 1 deletion Jint/Runtime/Debugger/DebugHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Runtime.CompilerServices;
using Esprima;
using Esprima.Ast;
using Jint.Native;
Expand Down
2 changes: 1 addition & 1 deletion Jint/Runtime/Interop/ObjectWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override bool Set(JsValue property, JsValue value, JsValue receiver)
if (_properties is null || !_properties.ContainsKey(member))
{
// can try utilize fast path
var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, Target.GetType(), member);
var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, Target.GetType(), member, forWrite: true);

if (ReferenceEquals(accessor, ConstantValueAccessor.NullAccessor))
{
Expand Down
21 changes: 14 additions & 7 deletions Jint/Runtime/Interop/TypeResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ private static IEnumerable<string> NameCreator(MemberInfo info)
/// </summary>
public StringComparer MemberNameComparer { get; set; } = DefaultMemberNameComparer.Instance;

internal ReflectionAccessor GetAccessor(Engine engine, Type type, string member, Func<ReflectionAccessor?>? accessorFactory = null)
internal ReflectionAccessor GetAccessor(
Engine engine,
Type type,
string member,
Func<ReflectionAccessor?>? accessorFactory = null,
bool forWrite = false)
{
var key = new ClrPropertyDescriptorFactoriesKey(type, member);

Expand All @@ -55,7 +60,7 @@ internal ReflectionAccessor GetAccessor(Engine engine, Type type, string member,
return accessor;
}

accessor = accessorFactory?.Invoke() ?? ResolvePropertyDescriptorFactory(engine, type, member);
accessor = accessorFactory?.Invoke() ?? ResolvePropertyDescriptorFactory(engine, type, member, forWrite);

// racy, we don't care, worst case we'll catch up later
Interlocked.CompareExchange(ref _reflectionAccessors,
Expand All @@ -70,17 +75,20 @@ internal ReflectionAccessor GetAccessor(Engine engine, Type type, string member,
private ReflectionAccessor ResolvePropertyDescriptorFactory(
Engine engine,
Type type,
string memberName)
string memberName,
bool forWrite)
{
var isNumber = uint.TryParse(memberName, out _);

// we can always check indexer if there's one, and then fall back to properties if indexer returns null
IndexerAccessor.TryFindIndexer(engine, type, memberName, out var indexerAccessor, out var indexer);

const BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;
const BindingFlags BindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;

// properties and fields cannot be numbers
if (!isNumber && TryFindMemberAccessor(engine, type, memberName, bindingFlags, indexer, out var temp))
if (!isNumber
&& TryFindMemberAccessor(engine, type, memberName, BindingFlags, indexer, out var temp)
&& (!forWrite || temp.Writable))
{
return temp;
}
Expand Down Expand Up @@ -280,8 +288,7 @@ internal ReflectionAccessor GetAccessor(Engine engine, Type type, string member,
}

// TPC: need to grab the extension methods here - for overloads
MethodInfo[] extensionMethods;
if (engine._extensionMethods.TryGetExtensionMethods(type, out extensionMethods))
if (engine._extensionMethods.TryGetExtensionMethods(type, out var extensionMethods))
{
foreach (var methodInfo in extensionMethods)
{
Expand Down

0 comments on commit fa9b3d9

Please sign in to comment.