Fix ScriptingObject::FromInterface to return object if the pointer is already valid object

This commit is contained in:
Wojtek Figat
2023-01-09 18:03:14 +01:00
parent 17f9219cd0
commit a74b847e65

View File

@@ -108,21 +108,33 @@ ScriptingObject* ScriptingObject::FromInterface(void* interfaceObj, const Script
if (type.Type != ScriptingTypes::Script) if (type.Type != ScriptingTypes::Script)
continue; continue;
auto interfaceImpl = type.GetInterface(interfaceType); 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); // Use vtable from default instance of this type
void* predictedVTable = *(void***)predictedObj; vtable = *(void***)type.GetDefaultInstance();
void* vtable = type.Script.VTable; }
if (!vtable && type.GetDefaultInstance())
{ // Check if object interface vtable matches the type interface vtable value
// Use vtable from default instance of this type ScriptingObject* predictedObj = (ScriptingObject*)((byte*)interfaceObj - interfaceImpl->VTableOffset);
vtable = *(void***)type.GetDefaultInstance(); void* predictedVTable = *(void***)predictedObj;
} if (vtable == predictedVTable)
if (vtable == predictedVTable) {
{ ASSERT(predictedObj->GetType().GetInterface(interfaceType));
ASSERT(predictedObj->GetType().GetInterface(interfaceType)); return predictedObj;
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;
} }
} }
} }