Skip to content

Commit 3bc688e

Browse files
authored
Fix failure to load document if template has not script defined (#7)
Allow copying `ImVue::Document` + test for it. Old implementation also would allow copy but everything will crash if you do that.
1 parent 0b52a1a commit 3bc688e

File tree

4 files changed

+77
-1
lines changed

4 files changed

+77
-1
lines changed

src/imvue.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,27 @@ namespace ImVue {
9292
: mDocument(0)
9393
, mRawData(NULL)
9494
, mMounted(false)
95+
, mRefs((int*)ImGui::MemAlloc(sizeof(int)))
9596
{
97+
*mRefs = 1;
9698
}
9799

98100
ComponentContainer::~ComponentContainer()
99101
{
102+
if((*mRefs) > 1) {
103+
mChildren.clear();
104+
}
105+
destroy();
106+
}
107+
108+
void ComponentContainer::destroy()
109+
{
110+
if(!mRefs || --(*mRefs) > 0) {
111+
return;
112+
}
113+
114+
ImGui::MemFree(mRefs);
115+
100116
fireCallback(ScriptState::BEFORE_DESTROY);
101117
removeChildren();
102118

src/imvue.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ namespace ImVue {
101101

102102
protected:
103103

104+
void destroy();
105+
104106
virtual bool build();
105107

106108
/**
@@ -119,10 +121,43 @@ namespace ImVue {
119121
char* mRawData;
120122
bool mMounted;
121123

124+
/**
125+
* Override copy constructor and assignment
126+
*/
127+
ComponentContainer& operator=(ComponentContainer& other)
128+
{
129+
if(mRefs != other.mRefs) {
130+
destroy();
131+
}
132+
133+
ComponentContainer tmp(other);
134+
swap(*this, tmp);
135+
return *this;
136+
}
137+
138+
ComponentContainer(ComponentContainer& other)
139+
: ContainerElement(other)
140+
, mDocument(other.mDocument)
141+
, mRawData(other.mRawData)
142+
, mMounted(other.mMounted)
143+
, mRefs(other.mRefs)
144+
{
145+
(*mRefs)++;
146+
}
147+
122148
private:
123149

150+
friend void swap(ComponentContainer& first, ComponentContainer& second) // nothrow
151+
{
152+
std::swap(first.mRefs, second.mRefs);
153+
std::swap(first.mDocument, second.mDocument);
154+
std::swap(first.mRawData, second.mRawData);
155+
std::swap(first.mMounted, second.mMounted);
156+
}
157+
124158
typedef std::unordered_map<ImU32, ComponentFactory> ComponentFactories;
125159
ComponentFactories mComponents;
160+
int* mRefs;
126161

127162
};
128163

src/lua/script.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,10 @@ extern "C" {
11251125

11261126
void LuaScriptState::eval(const char* str, std::string* retval, Fields* fields, ScriptState::Context* ctx)
11271127
{
1128+
if(!mImVue) {
1129+
return;
1130+
}
1131+
11281132
StackGuard g(mLuaState);
11291133
std::stringstream script;
11301134
std::string data(str);
@@ -1180,7 +1184,7 @@ extern "C" {
11801184
Object LuaScriptState::getObject(const char* str, Fields* fields, ScriptState::Context* ctx)
11811185
{
11821186
StackGuard g(mLuaState);
1183-
if(str[0] == '\0') {
1187+
if(str[0] == '\0' || !mImVue) {
11841188
return Object();
11851189
}
11861190

tests/unit/parser.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
#include <gtest/gtest.h>
33
#include "imvue.h"
4+
#include "imvue_generated.h"
45
#include "imvue_errors.h"
56
#include "utils.h"
67

@@ -70,3 +71,23 @@ TEST(DocumentParser, BadScript)
7071
document.parse(badScript);
7172
renderDocument(document);
7273
}
74+
75+
/**
76+
* Create document and copy it, should delete, ctx and other pointers only once
77+
*/
78+
TEST(DocumentParser, DocumentCopy)
79+
{
80+
ImVue::Context* ctx = ImVue::createContext(
81+
ImVue::createElementFactory()
82+
);
83+
ImVue::Document document(ctx);
84+
document.parse(simple);
85+
renderDocument(document);
86+
87+
ImVue::Document copied(document);
88+
renderDocument(document);
89+
renderDocument(copied);
90+
91+
ImVue::Document duplicate = document;
92+
renderDocument(duplicate);
93+
}

0 commit comments

Comments
 (0)