Skip to content

Commit

Permalink
Add IConvertible handling for DateTime and Empty/DBNull (#1010)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Nov 18, 2021
1 parent 2d8f1ec commit b3dc1d4
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 57 deletions.
12 changes: 5 additions & 7 deletions Jint.Tests/Runtime/InteropTests.NewtonsoftJson.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Jint.Native.Date;
using Jint.Runtime;
using Jint.Runtime.Interop;
using Newtonsoft.Json.Linq;
using Xunit;

Expand Down Expand Up @@ -64,10 +64,8 @@ public void ShouldBeAbleToIndexJObjectWithStrings()
var obj = JObject.Parse(json);
engine.SetValue("o", obj);
var value = engine.Evaluate("o.Properties.expirationDate.Value");
var wrapper = Assert.IsAssignableFrom<ObjectWrapper>(value);
var token = wrapper.Target as JToken;
var localDateTimeString = DateTime.Parse("2021-10-09T00:00:00Z").ToUniversalTime();
Assert.Equal(localDateTimeString.ToString(), token.ToString());
var dateInstance = Assert.IsAssignableFrom<DateInstance>(value);
Assert.Equal(DateTime.Parse("2021-10-09T00:00:00Z").ToUniversalTime(), dateInstance.ToDateTime());
}

// https://github.com/OrchardCMS/OrchardCore/issues/10648
Expand Down Expand Up @@ -99,14 +97,14 @@ public void EngineShouldStringifyJObjectFromObjectListWithValuesCorrectly()
var source = new dynamic[]
{
new { Text = "Text1", Value = 1 },
new { Text = "Text2", Value = 2 }
new { Text = "Text2", Value = 2, Null = (object) null, Date = new DateTime(2015, 6, 25, 0, 0, 0, DateTimeKind.Utc) }
};

engine.SetValue("testSubject", source.Select(x => JObject.FromObject(x)).ToList());
var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
var result = fromEngine.ToString();

Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2,\"Null\":null,\"Date\":\"2015-06-25T00:00:00.000Z\"}]", result);
}
}
}
74 changes: 24 additions & 50 deletions Jint/Runtime/Interop/DefaultObjectConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,9 @@ public static bool TryConvert(Engine engine, object value, out JsValue result)
return result is not null;
}

if (value is IConvertible convertible)
if (value is IConvertible convertible && TryConvertConvertible(engine, convertible, out result))
{
result = ConvertConvertible(engine, convertible);
if (result is not null)
{
return true;
}
return true;
}

if (value is Delegate d)
Expand Down Expand Up @@ -117,53 +113,31 @@ public static bool TryConvert(Engine engine, object value, out JsValue result)
return result is not null;
}

private static JsValue ConvertConvertible(Engine engine, IConvertible convertible)
private static bool TryConvertConvertible(Engine engine, IConvertible convertible, out JsValue result)
{
JsValue result = null;
switch (convertible.GetTypeCode())
result = convertible.GetTypeCode() switch
{
case TypeCode.Boolean:
result = convertible.ToBoolean(engine.Options.Culture) ? JsBoolean.True : JsBoolean.False;
break;
case TypeCode.Byte:
result = JsNumber.Create(convertible.ToByte(engine.Options.Culture));
break;
case TypeCode.Char:
result = JsString.Create(convertible.ToChar(engine.Options.Culture));
break;
case TypeCode.Double:
result = JsNumber.Create(convertible.ToDouble(engine.Options.Culture));
break;
case TypeCode.SByte:
result = JsNumber.Create(convertible.ToSByte(engine.Options.Culture));
break;
case TypeCode.Int16:
result = JsNumber.Create(convertible.ToInt16(engine.Options.Culture));
break;
case TypeCode.Int32:
result = JsNumber.Create(convertible.ToInt32(engine.Options.Culture));
break;
case TypeCode.UInt16:
result = JsNumber.Create(convertible.ToUInt16(engine.Options.Culture));
break;
case TypeCode.Int64:
result = JsNumber.Create(convertible.ToInt64(engine.Options.Culture));
break;
case TypeCode.Single:
result = JsNumber.Create(convertible.ToSingle(engine.Options.Culture));
break;
case TypeCode.String:
result = JsString.Create(convertible.ToString(engine.Options.Culture));
break;
case TypeCode.UInt32:
result = JsNumber.Create(convertible.ToUInt32(engine.Options.Culture));
break;
case TypeCode.UInt64:
result = JsNumber.Create(convertible.ToUInt64(engine.Options.Culture));
break;
}
TypeCode.Boolean => convertible.ToBoolean(engine.Options.Culture) ? JsBoolean.True : JsBoolean.False,
TypeCode.Byte => JsNumber.Create(convertible.ToByte(engine.Options.Culture)),
TypeCode.Char => JsString.Create(convertible.ToChar(engine.Options.Culture)),
TypeCode.Double => JsNumber.Create(convertible.ToDouble(engine.Options.Culture)),
TypeCode.SByte => JsNumber.Create(convertible.ToSByte(engine.Options.Culture)),
TypeCode.Int16 => JsNumber.Create(convertible.ToInt16(engine.Options.Culture)),
TypeCode.Int32 => JsNumber.Create(convertible.ToInt32(engine.Options.Culture)),
TypeCode.UInt16 => JsNumber.Create(convertible.ToUInt16(engine.Options.Culture)),
TypeCode.Int64 => JsNumber.Create(convertible.ToInt64(engine.Options.Culture)),
TypeCode.Single => JsNumber.Create(convertible.ToSingle(engine.Options.Culture)),
TypeCode.String => JsString.Create(convertible.ToString(engine.Options.Culture)),
TypeCode.UInt32 => JsNumber.Create(convertible.ToUInt32(engine.Options.Culture)),
TypeCode.UInt64 => JsNumber.Create(convertible.ToUInt64(engine.Options.Culture)),
TypeCode.DateTime => engine.Realm.Intrinsics.Date.Construct(convertible.ToDateTime(engine.Options.Culture)),
TypeCode.Decimal => JsNumber.Create(convertible.ToDecimal(engine.Options.Culture)),
TypeCode.DBNull => JsValue.Null,
TypeCode.Empty => JsValue.Null,
_ => null
};

return result;
return result is not null;
}

private static JsValue ConvertArray(Engine e, object v)
Expand Down

0 comments on commit b3dc1d4

Please sign in to comment.