Skip to content

Commit 42f4896

Browse files
committed
Non constructor call for UStruct, UClass are casting-operators
1 parent d26a659 commit 42f4896

File tree

1 file changed

+135
-117
lines changed

1 file changed

+135
-117
lines changed

Plugins/UnrealJS/Source/V8/Private/JavascriptIsolate_Private.cpp

Lines changed: 135 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,33 @@ class FJavascriptIsolateImplementation : public FJavascriptIsolate
14681468
Template->Set(I.Keyword("Load"), I.FunctionTemplate(fn, ClassToExport));
14691469
}
14701470

1471+
Local<Value> C_Operator(UStruct* StructToExport, Local<Value> Value)
1472+
{
1473+
auto Instance = FStructMemoryInstance::FromV8(Value);
1474+
1475+
// If given value is an instance
1476+
if (Instance)
1477+
{
1478+
auto GivenStruct = Instance->Struct;
1479+
if (Instance->Struct->IsChildOf(StructToExport))
1480+
{
1481+
return Value;
1482+
}
1483+
}
1484+
else if (auto ScriptStruct = Cast<UScriptStruct>(StructToExport))
1485+
{
1486+
if (Value->IsObject())
1487+
{
1488+
auto v = Value->ToObject();
1489+
auto Target = (uint8*)(FMemory_Alloca(ScriptStruct->GetStructureSize()));
1490+
ReadOffStruct(v, ScriptStruct, Target);
1491+
return ExportStructInstance(ScriptStruct, Target, FNoPropertyOwner());
1492+
}
1493+
}
1494+
1495+
return Local<v8::Value>();
1496+
}
1497+
14711498
void AddMemberFunction_Struct_C(Local<FunctionTemplate> Template, UStruct* StructToExport)
14721499
{
14731500
FIsolateHelper I(isolate_);
@@ -1479,30 +1506,7 @@ class FJavascriptIsolateImplementation : public FJavascriptIsolate
14791506

14801507
if (info.Length() == 1)
14811508
{
1482-
auto Value = info[0];
1483-
1484-
auto Instance = FStructMemoryInstance::FromV8(Value);
1485-
1486-
// If given value is an instance
1487-
if (Instance)
1488-
{
1489-
auto GivenStruct = Instance->Struct;
1490-
if (Instance->Struct->IsChildOf(StructToExport))
1491-
{
1492-
info.GetReturnValue().Set(info[0]);
1493-
}
1494-
}
1495-
else if (auto ScriptStruct = Cast<UScriptStruct>(StructToExport))
1496-
{
1497-
if (Value->IsObject())
1498-
{
1499-
auto v = Value->ToObject();
1500-
auto Target = (uint8*)(FMemory_Alloca(ScriptStruct->GetStructureSize()));
1501-
GetSelf(isolate)->ReadOffStruct(v, ScriptStruct, Target);
1502-
auto out = GetSelf(isolate)->ExportStructInstance(ScriptStruct, Target, FNoPropertyOwner());
1503-
info.GetReturnValue().Set(out);
1504-
}
1505-
}
1509+
info.GetReturnValue().Set(GetSelf(isolate)->C_Operator(StructToExport,info[0]));
15061510
}
15071511
};
15081512

@@ -1622,118 +1626,125 @@ class FJavascriptIsolateImplementation : public FJavascriptIsolate
16221626

16231627
auto ClassToExport = reinterpret_cast<UClass*>((Local<External>::Cast(info.Data()))->Value());
16241628

1625-
auto self = info.This();
1626-
1627-
UObject* Associated = nullptr;
1628-
1629-
// Called by system (via ExportObject)
1630-
if (info.Length() == 1 && info[0]->IsExternal())
1631-
{
1632-
auto ext = Local<External>::Cast(info[0]);
1629+
if (info.IsConstructCall())
1630+
{
1631+
auto self = info.This();
16331632

1634-
Associated = reinterpret_cast<UObject*>(ext->Value());
1633+
UObject* Associated = nullptr;
16351634

1636-
if (!Associated->IsValidLowLevel())
1635+
// Called by system (via ExportObject)
1636+
if (info.Length() == 1 && info[0]->IsExternal())
16371637
{
1638-
Associated = nullptr;
1639-
}
1640-
}
1638+
auto ext = Local<External>::Cast(info[0]);
16411639

1642-
// Called by user (via 'new' operator)
1643-
if (!Associated)
1644-
{
1645-
const bool bIsJavascriptClass =
1646-
ClassToExport->GetClass()->IsChildOf(UJavascriptGeneratedClass::StaticClass()) ||
1647-
ClassToExport->GetClass()->IsChildOf(UJavascriptGeneratedClass_Native::StaticClass());
1640+
Associated = reinterpret_cast<UObject*>(ext->Value());
16481641

1649-
auto PreCreate = [&]() {
1650-
if (bIsJavascriptClass)
1642+
if (!Associated->IsValidLowLevel())
16511643
{
1652-
GetSelf(isolate)->ObjectUnderConstructionStack.Push(FPendingClassConstruction(self, ClassToExport));
1644+
Associated = nullptr;
16531645
}
1654-
};
1646+
}
16551647

1656-
// Custom constructors
1657-
if (ClassToExport->IsChildOf(AActor::StaticClass()))
1648+
// Called by user (via 'new' operator)
1649+
if (!Associated)
16581650
{
1659-
if (info.Length() == 0)
1660-
{
1661-
I.Throw(TEXT("Missing world to spawn"));
1662-
return;
1663-
}
1651+
const bool bIsJavascriptClass =
1652+
ClassToExport->GetClass()->IsChildOf(UJavascriptGeneratedClass::StaticClass()) ||
1653+
ClassToExport->GetClass()->IsChildOf(UJavascriptGeneratedClass_Native::StaticClass());
16641654

1665-
auto World = Cast<UWorld>(UObjectFromV8(info[0]));
1666-
if (!World)
1667-
{
1668-
I.Throw(TEXT("Missing world to spawn"));
1669-
return;
1670-
}
1671-
1672-
FVector Location(ForceInitToZero);
1673-
FRotator Rotation(ForceInitToZero);
1674-
1675-
UPackage* CoreUObjectPackage = UObject::StaticClass()->GetOutermost();
1676-
static UScriptStruct* VectorStruct = FindObjectChecked<UScriptStruct>(CoreUObjectPackage, TEXT("Vector"));
1677-
static UScriptStruct* RotatorStruct = FindObjectChecked<UScriptStruct>(CoreUObjectPackage, TEXT("Rotator"));
1678-
static TStructReader<FVector> VectorReader(VectorStruct);
1679-
static TStructReader<FRotator> RotatorReader(RotatorStruct);
1680-
1681-
if (info.Length() > 1)
1655+
auto PreCreate = [&]() {
1656+
if (bIsJavascriptClass)
1657+
{
1658+
GetSelf(isolate)->ObjectUnderConstructionStack.Push(FPendingClassConstruction(self, ClassToExport));
1659+
}
1660+
};
1661+
1662+
// Custom constructors
1663+
if (ClassToExport->IsChildOf(AActor::StaticClass()))
16821664
{
1683-
if (!VectorReader.Read(isolate, info[1], Location)) return;
1665+
if (info.Length() == 0)
1666+
{
1667+
I.Throw(TEXT("Missing world to spawn"));
1668+
return;
1669+
}
16841670

1685-
if (info.Length() > 2)
1671+
auto World = Cast<UWorld>(UObjectFromV8(info[0]));
1672+
if (!World)
16861673
{
1687-
if (!RotatorReader.Read(isolate, info[2], Rotation)) return;
1674+
I.Throw(TEXT("Missing world to spawn"));
1675+
return;
16881676
}
1689-
}
16901677

1691-
PreCreate();
1692-
Associated = World->SpawnActor(ClassToExport, &Location, &Rotation);
1693-
}
1694-
else
1695-
{
1696-
UObject* Outer = GetTransientPackage();
1697-
FName Name = NAME_None;
1678+
FVector Location(ForceInitToZero);
1679+
FRotator Rotation(ForceInitToZero);
16981680

1699-
if (info.Length() > 0)
1700-
{
1701-
if (auto value = UObjectFromV8(info[0]))
1681+
UPackage* CoreUObjectPackage = UObject::StaticClass()->GetOutermost();
1682+
static UScriptStruct* VectorStruct = FindObjectChecked<UScriptStruct>(CoreUObjectPackage, TEXT("Vector"));
1683+
static UScriptStruct* RotatorStruct = FindObjectChecked<UScriptStruct>(CoreUObjectPackage, TEXT("Rotator"));
1684+
static TStructReader<FVector> VectorReader(VectorStruct);
1685+
static TStructReader<FRotator> RotatorReader(RotatorStruct);
1686+
1687+
if (info.Length() > 1)
17021688
{
1703-
Outer = value;
1689+
if (!VectorReader.Read(isolate, info[1], Location)) return;
1690+
1691+
if (info.Length() > 2)
1692+
{
1693+
if (!RotatorReader.Read(isolate, info[2], Rotation)) return;
1694+
}
17041695
}
1705-
if (info.Length() > 1)
1696+
1697+
PreCreate();
1698+
Associated = World->SpawnActor(ClassToExport, &Location, &Rotation);
1699+
}
1700+
else
1701+
{
1702+
UObject* Outer = GetTransientPackage();
1703+
FName Name = NAME_None;
1704+
1705+
if (info.Length() > 0)
17061706
{
1707-
Name = FName(*StringFromV8(info[1]));
1707+
if (auto value = UObjectFromV8(info[0]))
1708+
{
1709+
Outer = value;
1710+
}
1711+
if (info.Length() > 1)
1712+
{
1713+
Name = FName(*StringFromV8(info[1]));
1714+
}
17081715
}
1716+
1717+
PreCreate();
1718+
Associated = NewObject<UObject>(Outer, ClassToExport, Name);
17091719
}
17101720

1711-
PreCreate();
1712-
Associated = NewObject<UObject>(Outer, ClassToExport, Name);
1713-
}
1721+
if (bIsJavascriptClass)
1722+
{
1723+
const auto& Last = GetSelf(isolate)->ObjectUnderConstructionStack.Last();
17141724

1715-
if (bIsJavascriptClass)
1716-
{
1717-
const auto& Last = GetSelf(isolate)->ObjectUnderConstructionStack.Last();
1725+
bool bSafeToQuit = Last.bCatched;
17181726

1719-
bool bSafeToQuit = Last.bCatched;
1727+
GetSelf(isolate)->ObjectUnderConstructionStack.Pop();
17201728

1721-
GetSelf(isolate)->ObjectUnderConstructionStack.Pop();
1729+
if (bSafeToQuit)
1730+
{
1731+
return;
1732+
}
1733+
}
17221734

1723-
if (bSafeToQuit)
1735+
if (!Associated)
17241736
{
1737+
I.Throw(TEXT("Failed to spawn"));
17251738
return;
17261739
}
17271740
}
17281741

1729-
if (!Associated)
1730-
{
1731-
I.Throw(TEXT("Failed to spawn"));
1732-
return;
1733-
}
1734-
}
1735-
1736-
FPendingClassConstruction(self, ClassToExport).Finalize(GetSelf(isolate), Associated);
1742+
FPendingClassConstruction(self, ClassToExport).Finalize(GetSelf(isolate), Associated);
1743+
}
1744+
else
1745+
{
1746+
info.GetReturnValue().Set(GetSelf(isolate)->C_Operator(ClassToExport, info[0]));
1747+
}
17371748
};
17381749

17391750
auto Template = I.FunctionTemplate(ConstructorBody, ClassToExport);
@@ -1801,24 +1812,31 @@ class FJavascriptIsolateImplementation : public FJavascriptIsolate
18011812

18021813
FIsolateHelper I(isolate);
18031814

1804-
auto self = info.This();
1815+
if (info.IsConstructCall())
1816+
{
1817+
auto self = info.This();
18051818

1806-
TSharedPtr<FStructMemoryInstance> Memory;
1807-
1808-
if (info.Length() == 2 && info[0]->IsExternal() && info[1]->IsExternal())
1809-
{
1810-
IPropertyOwner& Owner = *reinterpret_cast<IPropertyOwner*>(Local<External>::Cast(info[1])->Value());
1819+
TSharedPtr<FStructMemoryInstance> Memory;
1820+
1821+
if (info.Length() == 2 && info[0]->IsExternal() && info[1]->IsExternal())
1822+
{
1823+
IPropertyOwner& Owner = *reinterpret_cast<IPropertyOwner*>(Local<External>::Cast(info[1])->Value());
1824+
1825+
Memory = FStructMemoryInstance::Create(StructToExport, Owner, Local<External>::Cast(info[0])->Value());
1826+
}
1827+
else
1828+
{
1829+
Memory = FStructMemoryInstance::Create(StructToExport, FNoPropertyOwner());
1830+
}
18111831

1812-
Memory = FStructMemoryInstance::Create(StructToExport, Owner, Local<External>::Cast(info[0])->Value());
1832+
GetSelf(isolate)->RegisterScriptStructInstance(Memory, self);
1833+
1834+
self->SetAlignedPointerInInternalField(0, Memory.Get());
18131835
}
18141836
else
18151837
{
1816-
Memory = FStructMemoryInstance::Create(StructToExport, FNoPropertyOwner());
1838+
info.GetReturnValue().Set(GetSelf(isolate)->C_Operator(StructToExport, info[0]));
18171839
}
1818-
1819-
GetSelf(isolate)->RegisterScriptStructInstance(Memory, self);
1820-
1821-
self->SetAlignedPointerInInternalField(0, Memory.Get());
18221840
};
18231841

18241842
auto Template = I.FunctionTemplate(fn, StructToExport);

0 commit comments

Comments
 (0)