Skip to content

Commit 2fa4cbf

Browse files
committed
[unity]fix: 修复 C# 侧 Nullable<T>(如 Nullable<bool>)无法正确传入 js
GeneralSetterManager.GetTranslateFunc 未处理 Nullable<T>,反射设置 Nullable 类型字段/属性时会拿到错误(或null)的转换函数。 与 GeneralGetterManager 已有的 nullable 处理对齐:对 Nullable<T> 取 underlying type 的转换函数并包装一层 null -> SetNull 的处理, 结果按 underlying type 缓存。
1 parent 57f0879 commit 2fa4cbf

2 files changed

Lines changed: 80 additions & 8 deletions

File tree

‎unity/Assets/core/upm/Runtime/Src/Default/Translator/DataTranslate.cs‎

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ public static JsValueType GetJsTypeMask(Type type)
390390
public class GeneralSetterManager
391391
{
392392
private Dictionary<Type, GeneralSetter> generalSetterMap = new Dictionary<Type, GeneralSetter>();
393+
private Dictionary<Type, GeneralSetter> nullableTypeGeneralGetterMap = new Dictionary<Type, GeneralSetter>();
393394

394395
public GeneralSetterManager()
395396
{
@@ -500,7 +501,7 @@ private static void GenericDelegateTranslator(int jsEnvIdx, IntPtr isolate, ISet
500501
}
501502

502503
private static void JSObjectTranslator(int jsEnvIdx, IntPtr isolate, ISetValueToJs setValueApi, IntPtr holder, object obj)
503-
{
504+
{
504505
var jsObj = obj as JSObject;
505506
if (jsObj == null || jsObj.jsEnv == null || !jsObj.jsEnv.CheckLiveness(false) || jsObj.jsEnv.Idx != jsEnvIdx)
506507
{
@@ -579,19 +580,48 @@ private GeneralSetter MakeTranslateFunc(Type type)
579580
}
580581
}
581582

583+
GeneralSetter MakeNullableTranslateFunc(GeneralSetter jvt)
584+
{
585+
return (int jsEnvIdx, IntPtr isolate, ISetValueToJs setValueApi, IntPtr holder, object obj) =>
586+
{
587+
if (obj == null)
588+
{
589+
setValueApi.SetNull(isolate, holder);
590+
}
591+
else
592+
{
593+
jvt(jsEnvIdx, isolate, setValueApi, holder, obj);
594+
}
595+
};
596+
}
597+
582598
public GeneralSetter GetTranslateFunc(Type type)
583599
{
584600
if (type.IsByRef) return GetTranslateFunc(type.GetElementType());
585601

586-
if (type.IsEnum) return GetTranslateFunc(Enum.GetUnderlyingType(type));
587-
588-
GeneralSetter jvt;
589-
if (!generalSetterMap.TryGetValue(type, out jvt))
602+
Type underlyingType = Nullable.GetUnderlyingType(type);
603+
if (underlyingType != null)
590604
{
591-
jvt = MakeTranslateFunc(type);
592-
generalSetterMap.Add(type, jvt);
605+
GeneralSetter jvt;
606+
if (!nullableTypeGeneralGetterMap.TryGetValue(underlyingType, out jvt))
607+
{
608+
jvt = MakeNullableTranslateFunc(GetTranslateFunc(underlyingType));
609+
nullableTypeGeneralGetterMap.Add(underlyingType, jvt);
610+
}
611+
return jvt;
612+
}
613+
else
614+
{
615+
if (type.IsEnum) return GetTranslateFunc(Enum.GetUnderlyingType(type));
616+
617+
GeneralSetter jvt;
618+
if (!generalSetterMap.TryGetValue(type, out jvt))
619+
{
620+
jvt = MakeTranslateFunc(type);
621+
generalSetterMap.Add(type, jvt);
622+
}
623+
return jvt;
593624
}
594-
return jvt;
595625
}
596626

597627
public void RegisterSetter(Type type, GeneralSetter generalSetter)

‎unity/test/Src/Cases/CrossLang/CrossLangTest.cs‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,8 @@ public TestStruct? nullableNativeStructTestProp
654654
set { _nullableNativeStructTestProp = value; }
655655
}
656656
public static TestStruct? nullableNativeStructTestFieldStatic = default(TestStruct);
657+
public static bool? nullableBoolStatic = null;
658+
public static int? nullableIntStatic = null;
657659
protected static TestStruct? _nullableNativeStructTestPropStatic = default(TestStruct);
658660
public static TestStruct? nullableNativeStructTestPropStatic
659661
{
@@ -2037,5 +2039,45 @@ public void StaticFeildTest()
20372039
Assert.False(StaticFeildTestHelper.Field1);
20382040
}
20392041

2042+
[Test]
2043+
public void TestNullableBool()
2044+
{
2045+
var jsEnv = UnitTestEnv.GetEnv();
2046+
jsEnv.Eval(@"
2047+
(function() {
2048+
const { $ref, $unref } = puer;
2049+
const TestHelper = CS.Puerts.UnitTest.TestHelper;
2050+
const AssertAndPrint = CS.Puerts.UnitTest.TestHelper.AssertAndPrint;
2051+
console.log(typeof TestHelper.nullableBoolStatic)
2052+
AssertAndPrint('TestHelper.nullableBoolStatic', TestHelper.nullableBoolStatic === null);
2053+
TestHelper.nullableBoolStatic = true
2054+
console.log(TestHelper.nullableBoolStatic, console.log(typeof TestHelper.nullableBoolStatic))
2055+
AssertAndPrint('TestHelper.nullableBoolStatic', TestHelper.nullableBoolStatic == true);
2056+
TestHelper.nullableBoolStatic = false
2057+
AssertAndPrint('TestHelper.nullableBoolStatic', TestHelper.nullableBoolStatic === false);
2058+
})()
2059+
");
2060+
}
2061+
2062+
[Test]
2063+
public void TestNullableInt()
2064+
{
2065+
var jsEnv = UnitTestEnv.GetEnv();
2066+
jsEnv.Eval(@"
2067+
(function() {
2068+
const { $ref, $unref } = puer;
2069+
const TestHelper = CS.Puerts.UnitTest.TestHelper;
2070+
const AssertAndPrint = CS.Puerts.UnitTest.TestHelper.AssertAndPrint;
2071+
console.log(typeof TestHelper.nullableIntStatic)
2072+
AssertAndPrint('TestHelper.nullableIntStatic', TestHelper.nullableIntStatic === null);
2073+
TestHelper.nullableIntStatic = 2
2074+
console.log(TestHelper.nullableIntStatic)
2075+
AssertAndPrint('TestHelper.nullableIntStatic', TestHelper.nullableIntStatic == 2);
2076+
TestHelper.nullableIntStatic = 3
2077+
AssertAndPrint('TestHelper.nullableIntStatic', TestHelper.nullableIntStatic === 3);
2078+
})()
2079+
");
2080+
}
2081+
20402082
}
20412083
}

0 commit comments

Comments
 (0)