Skip to content

Commit ebbdbc7

Browse files
author
Aleksei Konovkin
committed
memory fixes
1 parent 00bb340 commit ebbdbc7

File tree

9 files changed

+132
-83
lines changed

9 files changed

+132
-83
lines changed

test/test-html-build.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function TestHTMLBuild.test_empty_root_dtd_systemid()
2626
local uri = "file:///usr/local/share/test.dtd"
2727
local document = HTML.build({"html"}, uri)
2828
luaunit.assertEquals({
29-
ffi.string(document.document.intSubset.SystemID),
29+
ffi.string(document.raw_document.intSubset.SystemID),
3030
document:to_html()
3131
},
3232
{
@@ -43,8 +43,8 @@ function TestHTMLBuild.test_empty_root_dtd_publicid()
4343
local public_id = "-//W3C//DTD HTML 4.01//EN"
4444
local document = HTML.build({"html"}, uri, public_id)
4545
luaunit.assertEquals({
46-
ffi.string(document.document.intSubset.SystemID),
47-
ffi.string(document.document.intSubset.ExternalID),
46+
ffi.string(document.raw_document.intSubset.SystemID),
47+
ffi.string(document.raw_document.intSubset.ExternalID),
4848
document:to_html()
4949
},
5050
{

xmlua/document.lua

+23-24
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ local Document = {}
33
local libxml2 = require("xmlua.libxml2")
44
local ffi = require("ffi")
55
local converter = require("xmlua.converter")
6-
local to_string = converter.to_string
76

87
local Serializable = require("xmlua.serializable")
98
local Searchable = require("xmlua.searchable")
@@ -40,54 +39,54 @@ function metatable.__index(document, key)
4039
end
4140

4241
function methods:root()
43-
local root_element = libxml2.xmlDocGetRootElement(self.document)
44-
if not root_element then
42+
local node = libxml2.xmlDocGetRootElement(self.raw_document)
43+
if not node then
4544
return nil
4645
end
47-
return Element.new(self.document, root_element)
46+
return Element.new(self, node)
4847
end
4948

5049
function methods:parent()
5150
return nil
5251
end
5352

5453
function methods:encoding()
55-
return ffi.string(self.document.encoding)
54+
return ffi.string(self.raw_document.encoding)
5655
end
5756

5857
function methods:create_cdata_section(data)
5958
local raw_cdata_section_node =
60-
libxml2.xmlNewCDataBlock(self.document,
59+
libxml2.xmlNewCDataBlock(self.raw_document,
6160
data,
6261
data:len())
63-
return CDATASection.new(self.document, raw_cdata_section_node)
62+
return CDATASection.new(self, raw_cdata_section_node)
6463
end
6564

6665
function methods:create_comment(data)
6766
local raw_comment_node =
6867
libxml2.xmlNewComment(data)
69-
return Comment.new(self.document, raw_comment_node)
68+
return Comment.new(self, raw_comment_node)
7069
end
7170

7271
function methods:create_document_fragment()
7372
local raw_document_fragment_node =
74-
libxml2.xmlNewDocFragment(self.document)
75-
return DocumentFragment.new(self.document,
73+
libxml2.xmlNewDocFragment(self.raw_document)
74+
return DocumentFragment.new(self,
7675
raw_document_fragment_node)
7776
end
7877

7978
function methods:create_document_type(name, external_id, system_id)
8079
local raw_document_type =
81-
libxml2.xmlCreateIntSubset(self.document, name, external_id, system_id)
82-
return DocumentType.new(self.document,
80+
libxml2.xmlCreateIntSubset(self.raw_document, name, external_id, system_id)
81+
return DocumentType.new(self,
8382
raw_document_type)
8483
end
8584

8685
function methods:get_internal_subset()
8786
local raw_document_type =
88-
libxml2.xmlGetIntSubset(self.document)
87+
libxml2.xmlGetIntSubset(self.raw_document)
8988
if raw_document_type ~= nil then
90-
return DocumentType.new(self.document,
89+
return DocumentType.new(self,
9190
raw_document_type)
9291
else
9392
return nil
@@ -96,28 +95,28 @@ end
9695

9796
function methods:add_entity_reference(name)
9897
local raw_entity_reference =
99-
libxml2.xmlNewReference(self.document, name)
100-
return EntityReference.new(self.document,
98+
libxml2.xmlNewReference(self.raw_document, name)
99+
return EntityReference.new(self,
101100
raw_entity_reference)
102101
end
103102

104103
function methods:create_namespace(href, prefix)
105104
local raw_namespace =
106105
libxml2.xmlNewNs(self.node, href, prefix)
107-
return Namespace.new(self.document, raw_namespace)
106+
return Namespace.new(self, raw_namespace)
108107
end
109108

110109
function methods:create_processing_instruction(name, content)
111110
local raw_processing_instruction =
112111
libxml2.xmlNewPI(name, content)
113-
return ProcessingInstruction.new(self.document,
112+
return ProcessingInstruction.new(self,
114113
raw_processing_instruction)
115114
end
116115

117116
function methods:add_entity(entity_info)
118117
local entity_type_name = entity_info["entity_type"]
119118
local entity_type = converter.convert_entity_type_name(entity_type_name)
120-
local raw_entity = libxml2.xmlAddDocEntity(self.document,
119+
local raw_entity = libxml2.xmlAddDocEntity(self.raw_document,
121120
entity_info["name"],
122121
entity_type,
123122
entity_info["external_id"],
@@ -127,14 +126,14 @@ function methods:add_entity(entity_info)
127126
end
128127

129128
function methods:get_entity(name)
130-
local raw_entity = libxml2.xmlGetDocEntity(self.document, name)
129+
local raw_entity = libxml2.xmlGetDocEntity(self.raw_document, name)
131130
return converter.convert_xml_entity(raw_entity)
132131
end
133132

134133
function methods:add_dtd_entity(entity_info)
135134
local entity_type_name = entity_info["entity_type"]
136135
local entity_type = converter.convert_entity_type_name(entity_type_name)
137-
local raw_dtd_entity = libxml2.xmlAddDtdEntity(self.document,
136+
local raw_dtd_entity = libxml2.xmlAddDtdEntity(self.raw_document,
138137
entity_info["name"],
139138
entity_type,
140139
entity_info["external_id"],
@@ -144,7 +143,7 @@ function methods:add_dtd_entity(entity_info)
144143
end
145144

146145
function methods:get_dtd_entity(name)
147-
local raw_dtd_entity = libxml2.xmlGetDtdEntity(self.document, name)
146+
local raw_dtd_entity = libxml2.xmlGetDtdEntity(self.raw_document, name)
148147
return converter.convert_xml_entity(raw_dtd_entity)
149148
end
150149

@@ -167,7 +166,7 @@ function Document.build(raw_document, tree)
167166

168167
local root = Element.build(document, tree[1], tree[2])
169168
if not libxml2.xmlDocSetRootElement(raw_document, root.node) then
170-
root:unlink()
169+
--root:unlink()
171170
return nil
172171
end
173172

@@ -187,7 +186,7 @@ function Document.new(raw_document, errors)
187186
errors = {}
188187
end
189188
local document = {
190-
document = raw_document,
189+
raw_document = raw_document,
191190
errors = errors,
192191
}
193192
setmetatable(document, metatable)

xmlua/element.lua

+46-44
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ local function remove_namespace(node, prefix)
8888
end
8989
end
9090

91-
namespace = node.nsDef
91+
local namespace = node.nsDef
9292
local namespace_previous = nil
9393
while namespace ~= ffi.NULL do
9494
if is_target_namespace(namespace) then
@@ -127,65 +127,67 @@ local function set_attributes(element, attributes)
127127
end
128128
end
129129

130-
local function create_sub_element(document, node, name, attributes)
130+
local function create_sub_element(document, parent, name, attributes)
131131
local namespace_prefix, local_name = parse_name(name)
132-
local raw_element = libxml2.xmlNewNode(nil, local_name)
133-
local element = Element.new(document, raw_element)
132+
local node = libxml2.xmlNewNode(nil, local_name)
133+
local element = Element.new(document, node)
134134
set_attributes(element, attributes)
135-
local namespace = libxml2.xmlSearchNs(document, raw_element, namespace_prefix)
136-
if not namespace and node then
137-
namespace = libxml2.xmlSearchNs(document, node, namespace_prefix)
135+
local namespace = libxml2.xmlSearchNs(document.raw_document, node, namespace_prefix)
136+
if not namespace and parent then
137+
namespace = libxml2.xmlSearchNs(document.raw_document, parent, namespace_prefix)
138138
end
139139
if namespace then
140-
libxml2.xmlSetNs(raw_element, namespace)
140+
libxml2.xmlSetNs(node, namespace)
141141
elseif namespace_prefix then
142142
element:unlink()
143-
raw_element = libxml2.xmlNewNode(nil, name)
144-
element = Element.new(document, raw_element)
143+
node = libxml2.xmlNewNode(nil, name)
144+
element = Element.new(document, node)
145145
set_attributes(element, attributes)
146146
end
147147
return element
148148
end
149149

150-
function methods:add_child(node)
151-
if node.node.parent ~= ffi.NULL then
152-
node:unlink()
153-
end
154-
local raw_added_node =
155-
libxml2.xmlAddChild(self.node, node.node)
156-
if raw_added_node ~= ffi.NULL then
157-
ffi.gc(node.node, nil)
150+
function methods:add_child(element)
151+
local node
152+
if self.document == element.document then
153+
if element.node.parent ~= ffi.NULL then
154+
element:unlink()
155+
end
156+
node = element.node
157+
else
158+
node = libxml2.xmlCopyNode(element.node, self.document.raw_document)
158159
end
160+
libxml2.xmlAddChild(self.node, node)
159161
end
160162

161-
function methods:add_previous_sibling(node)
162-
if not self.node and not node.node then
163+
function methods:add_previous_sibling(element)
164+
if not self.node and not element.node then
163165
error("Already freed receiver node and added node")
164166
elseif not self.node then
165167
error("Already freed receiver node")
166-
elseif not node.node then
168+
elseif not element.node then
167169
error("Already freed added node")
168170
end
169171

170172
local raw_added_node, was_freed =
171-
libxml2.xmlAddPrevSibling(self.node, node.node)
173+
libxml2.xmlAddPrevSibling(self.node, element.node)
172174
if was_freed then
173-
node.node = nil
175+
element.node = nil
174176
end
175177
end
176178

177-
function methods:append_sibling(node)
178-
if not self.node and not node.node then
179+
function methods:append_sibling(element)
180+
if not self.node and not element.node then
179181
error("Already freed receiver node and appended node")
180182
elseif not self.node then
181183
error("Already freed receiver node")
182-
elseif not node.node then
184+
elseif not element.node then
183185
error("Already freed appended node")
184186
end
185187

186-
local was_freed = libxml2.xmlAddSibling(self.node, node.node)
188+
local was_freed = libxml2.xmlAddSibling(self.node, element.node)
187189
if was_freed then
188-
node.node = nil
190+
element.node = nil
189191
end
190192
end
191193

@@ -256,28 +258,28 @@ function methods:insert_element(position, name, attributes)
256258
end
257259

258260
function methods:unlink()
259-
local unlinked_node = Node.unlink(self)
260-
return Element.new(nil, unlinked_node)
261+
Node.unlink(self)
262+
return self
261263
end
262264

263265
function methods:get_attribute(name)
264266
local namespace_prefix, local_name = parse_name(name)
265267
if namespace_prefix == "xmlns" then
266-
local namespace = libxml2.xmlSearchNs(self.document, self.node, local_name)
268+
local namespace = libxml2.xmlSearchNs(self.document.raw_document, self.node, local_name)
267269
if namespace then
268270
return ffi.string(namespace.href)
269271
else
270272
return nil
271273
end
272274
elseif namespace_prefix == ffi.NULL and local_name == "xmlns" then
273-
local namespace = libxml2.xmlSearchNs(self.document, self.node, nil)
275+
local namespace = libxml2.xmlSearchNs(self.document.raw_document, self.node, nil)
274276
if namespace then
275277
return ffi.string(namespace.href)
276278
else
277279
return nil
278280
end
279281
elseif namespace_prefix then
280-
local namespace = libxml2.xmlSearchNs(self.document,
282+
local namespace = libxml2.xmlSearchNs(self.document.raw_document,
281283
self.node,
282284
namespace_prefix)
283285
if namespace then
@@ -298,7 +300,7 @@ function methods:set_attribute(name, value)
298300
local namespace_prefix, local_name = parse_name(name)
299301
local namespace
300302
if namespace_prefix == "xmlns" then
301-
namespace = libxml2.xmlSearchNs(self.document,
303+
namespace = libxml2.xmlSearchNs(self.document.raw_document,
302304
self.node,
303305
local_name)
304306
if namespace then
@@ -308,7 +310,7 @@ function methods:set_attribute(name, value)
308310
libxml2.xmlNewNs(self.node, value, local_name)
309311
end
310312
elseif namespace_prefix == nil and local_name == "xmlns" then
311-
namespace = libxml2.xmlSearchNs(self.document, self.node, nil)
313+
namespace = libxml2.xmlSearchNs(self.document.raw_document, self.node, nil)
312314
if namespace then
313315
libxml2.xmlFree(ffi.cast("void *", namespace.href))
314316
namespace.href = libxml2.xmlStrdup(value)
@@ -317,7 +319,7 @@ function methods:set_attribute(name, value)
317319
set_default_namespace(self.node, namespace)
318320
end
319321
elseif namespace_prefix then
320-
namespace = libxml2.xmlSearchNs(self.document,
322+
namespace = libxml2.xmlSearchNs(self.document.raw_document,
321323
self.node,
322324
namespace_prefix)
323325
if namespace then
@@ -341,7 +343,7 @@ function methods:remove_attribute(name)
341343
elseif namespace_prefix == nil and local_name == "xmlns" then
342344
remove_namespace(self.node, nil)
343345
elseif namespace_prefix then
344-
namespace = libxml2.xmlSearchNs(self.document,
346+
namespace = libxml2.xmlSearchNs(self.document.raw_document,
345347
self.node,
346348
namespace_prefix)
347349
if namespace then
@@ -378,12 +380,12 @@ function methods:next()
378380
end
379381

380382
function methods:root()
381-
return Document.new(self.document):root()
383+
return self.document:root()
382384
end
383385

384386
function methods:parent()
385387
if tonumber(self.node.parent.type) == ffi.C.XML_DOCUMENT_NODE then
386-
return Document.new(self.document)
388+
return self.document
387389
else
388390
return Element.new(self.document, self.node.parent)
389391
end
@@ -404,7 +406,7 @@ function methods:text()
404406
end
405407

406408
function methods:namespaces()
407-
local raw_namespaces = libxml2.xmlGetNsList(self.document, self.node)
409+
local raw_namespaces = libxml2.xmlGetNsList(self.document.raw_document, self.node)
408410
if not raw_namespaces then
409411
return nil
410412
end
@@ -427,23 +429,23 @@ function methods:find_namespace(prefix, href)
427429
local raw_namespace
428430
if not prefix and href then
429431
raw_namespace =
430-
libxml2.xmlSearchNsByHref(self.document, self.node, href)
432+
libxml2.xmlSearchNsByHref(self.document.raw_document, self.node, href)
431433
else
432434
raw_namespace =
433-
libxml2.xmlSearchNs(self.document, self.node, prefix)
435+
libxml2.xmlSearchNs(self.document.raw_document, self.node, prefix)
434436
end
435437
return Namespace.new(self.document, raw_namespace)
436438
end
437439

438440
-- For internal use
439441
function Element.build(document, name, attributes)
440-
return create_sub_element(document.node, nil, name, attributes)
442+
return create_sub_element(document, nil, name, attributes)
441443
end
442444

443445
function Element.new(document, node)
444446
local element = {
445447
document = document,
446-
node = node,
448+
node = node
447449
}
448450
setmetatable(element, metatable)
449451
return element

0 commit comments

Comments
 (0)