From a74b847e65da6c52f09470122c13e1e918b751ee Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 9 Jan 2023 18:03:14 +0100 Subject: [PATCH] Fix `ScriptingObject::FromInterface` to return object if the pointer is already valid object --- Source/Engine/Scripting/ScriptingObject.cpp | 40 +++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp index ee3dfc438..2ef15718f 100644 --- a/Source/Engine/Scripting/ScriptingObject.cpp +++ b/Source/Engine/Scripting/ScriptingObject.cpp @@ -108,21 +108,33 @@ ScriptingObject* ScriptingObject::FromInterface(void* interfaceObj, const Script if (type.Type != ScriptingTypes::Script) continue; auto interfaceImpl = type.GetInterface(interfaceType); - if (interfaceImpl && interfaceImpl->IsNative) + if (!interfaceImpl || !interfaceImpl->IsNative) + continue; + + // Get vtable for this type + void* vtable = type.Script.VTable; + if (!vtable && type.GetDefaultInstance()) { - ScriptingObject* predictedObj = (ScriptingObject*)((byte*)interfaceObj - interfaceImpl->VTableOffset); - void* predictedVTable = *(void***)predictedObj; - void* vtable = type.Script.VTable; - if (!vtable && type.GetDefaultInstance()) - { - // Use vtable from default instance of this type - vtable = *(void***)type.GetDefaultInstance(); - } - if (vtable == predictedVTable) - { - ASSERT(predictedObj->GetType().GetInterface(interfaceType)); - return predictedObj; - } + // Use vtable from default instance of this type + vtable = *(void***)type.GetDefaultInstance(); + } + + // Check if object interface vtable matches the type interface vtable value + ScriptingObject* predictedObj = (ScriptingObject*)((byte*)interfaceObj - interfaceImpl->VTableOffset); + void* predictedVTable = *(void***)predictedObj; + if (vtable == predictedVTable) + { + ASSERT(predictedObj->GetType().GetInterface(interfaceType)); + return predictedObj; + } + + // Check for case of passing object directly + predictedObj = (ScriptingObject*)interfaceObj; + predictedVTable = *(void***)predictedObj; + if (vtable == predictedVTable) + { + ASSERT(predictedObj->GetType().GetInterface(interfaceType)); + return predictedObj; } } }