mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-08 18:09:39 +01:00
dom.pp: Customized memory management, fixes 17 test cases and all memory leaks in testsuite:
* Every node created by Document.CreateXXX method is now guaranteed to be destroyed with the document, whether it is part of the tree or not. Therefore, DOM methods which remove nodes from the tree (namely, TDOMNode.RemoveChild, TDOMNode.ReplaceChild, TDOMElement.SetAttributeNode and TDOMElement.SetAttributeNodeNS) no longer need to destroy their return value and are now conformant to the specs. * Nodes are allocated in arrays of instances (emulates 'placement new operator' in C++ terms). Allocation and freeing are as fast as possible (just assigns a couple of pointers). * Behaviour of nodes that are created by direct call to constructor is unchanged. git-svn-id: trunk@13185 -
This commit is contained in:
parent
d3dd0d6aa0
commit
733d2c38d5
@ -928,9 +928,7 @@ end;
|
|||||||
|
|
||||||
function TDOMNode.RemoveChild(OldChild: TDOMNode): TDOMNode;
|
function TDOMNode.RemoveChild(OldChild: TDOMNode): TDOMNode;
|
||||||
begin
|
begin
|
||||||
DetachChild(OldChild);
|
Result := DetachChild(OldChild);
|
||||||
OldChild.Free;
|
|
||||||
Result:=nil;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMNode.AppendChild(NewChild: TDOMNode): TDOMNode;
|
function TDOMNode.AppendChild(NewChild: TDOMNode): TDOMNode;
|
||||||
@ -1248,8 +1246,7 @@ begin
|
|||||||
InsertBefore(NewChild, OldChild);
|
InsertBefore(NewChild, OldChild);
|
||||||
if Assigned(OldChild) then
|
if Assigned(OldChild) then
|
||||||
RemoveChild(OldChild);
|
RemoveChild(OldChild);
|
||||||
// TODO: per DOM spec, must return OldChild, but OldChild is destroyed
|
Result := OldChild;
|
||||||
Result := NewChild;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMNode_WithChildren.DetachChild(OldChild: TDOMNode): TDOMNode;
|
function TDOMNode_WithChildren.DetachChild(OldChild: TDOMNode): TDOMNode;
|
||||||
@ -1352,7 +1349,8 @@ end;
|
|||||||
procedure TDOMNode_WithChildren.SetTextContent(const AValue: DOMString);
|
procedure TDOMNode_WithChildren.SetTextContent(const AValue: DOMString);
|
||||||
begin
|
begin
|
||||||
Changing;
|
Changing;
|
||||||
FreeChildren;
|
while Assigned(FFirstChild) do
|
||||||
|
DetachChild(FFirstChild);
|
||||||
if AValue <> '' then
|
if AValue <> '' then
|
||||||
AppendChild(FOwnerDocument.CreateTextNode(AValue));
|
AppendChild(FOwnerDocument.CreateTextNode(AValue));
|
||||||
end;
|
end;
|
||||||
@ -1972,31 +1970,36 @@ function TDOMDocument.CreateElement(const tagName: DOMString): TDOMElement;
|
|||||||
begin
|
begin
|
||||||
if not IsXmlName(tagName, FXML11) then
|
if not IsXmlName(tagName, FXML11) then
|
||||||
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'DOMDocument.CreateElement');
|
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'DOMDocument.CreateElement');
|
||||||
Result := TDOMElement.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMElement);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(tagName), Length(tagName));
|
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(tagName), Length(tagName));
|
||||||
// TODO: attach default attributes
|
// TODO: attach default attributes
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateElementBuf(Buf: DOMPChar; Length: Integer): TDOMElement;
|
function TDOMDocument.CreateElementBuf(Buf: DOMPChar; Length: Integer): TDOMElement;
|
||||||
begin
|
begin
|
||||||
Result := TDOMElement.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMElement);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(Buf, Length);
|
Result.FNSI.QName := FNames.FindOrAdd(Buf, Length);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateDocumentFragment: TDOMDocumentFragment;
|
function TDOMDocument.CreateDocumentFragment: TDOMDocumentFragment;
|
||||||
begin
|
begin
|
||||||
Result := TDOMDocumentFragment.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMDocumentFragment);
|
||||||
|
Result.Create(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateTextNode(const data: DOMString): TDOMText;
|
function TDOMDocument.CreateTextNode(const data: DOMString): TDOMText;
|
||||||
begin
|
begin
|
||||||
Result := TDOMText.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMText);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNodeValue := data;
|
Result.FNodeValue := data;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateTextNodeBuf(Buf: DOMPChar; Length: Integer; IgnWS: Boolean): TDOMText;
|
function TDOMDocument.CreateTextNodeBuf(Buf: DOMPChar; Length: Integer; IgnWS: Boolean): TDOMText;
|
||||||
begin
|
begin
|
||||||
Result := TDOMText.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMText);
|
||||||
|
Result.Create(Self);
|
||||||
SetString(Result.FNodeValue, Buf, Length);
|
SetString(Result.FNodeValue, Buf, Length);
|
||||||
if IgnWS then
|
if IgnWS then
|
||||||
Include(Result.FFlags, nfIgnorableWS);
|
Include(Result.FFlags, nfIgnorableWS);
|
||||||
@ -2005,13 +2008,15 @@ end;
|
|||||||
|
|
||||||
function TDOMDocument.CreateComment(const data: DOMString): TDOMComment;
|
function TDOMDocument.CreateComment(const data: DOMString): TDOMComment;
|
||||||
begin
|
begin
|
||||||
Result := TDOMComment.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMComment);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNodeValue := data;
|
Result.FNodeValue := data;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateCommentBuf(Buf: DOMPChar; Length: Integer): TDOMComment;
|
function TDOMDocument.CreateCommentBuf(Buf: DOMPChar; Length: Integer): TDOMComment;
|
||||||
begin
|
begin
|
||||||
Result := TDOMComment.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMComment);
|
||||||
|
Result.Create(Self);
|
||||||
SetString(Result.FNodeValue, Buf, Length);
|
SetString(Result.FNodeValue, Buf, Length);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2033,20 +2038,23 @@ function TDOMDocument.CreateAttribute(const name: DOMString): TDOMAttr;
|
|||||||
begin
|
begin
|
||||||
if not IsXmlName(name, FXML11) then
|
if not IsXmlName(name, FXML11) then
|
||||||
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'DOMDocument.CreateAttribute');
|
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'DOMDocument.CreateAttribute');
|
||||||
Result := TDOMAttr.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMAttr);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(name), Length(name));
|
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(name), Length(name));
|
||||||
Include(Result.FFlags, nfSpecified);
|
Include(Result.FFlags, nfSpecified);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateAttributeBuf(Buf: DOMPChar; Length: Integer): TDOMAttr;
|
function TDOMDocument.CreateAttributeBuf(Buf: DOMPChar; Length: Integer): TDOMAttr;
|
||||||
begin
|
begin
|
||||||
Result := TDOMAttr.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMAttr);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(buf, Length);
|
Result.FNSI.QName := FNames.FindOrAdd(buf, Length);
|
||||||
Include(Result.FFlags, nfSpecified);
|
Include(Result.FFlags, nfSpecified);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateAttributeDef(Buf: DOMPChar; Length: Integer): TDOMAttrDef;
|
function TDOMDocument.CreateAttributeDef(Buf: DOMPChar; Length: Integer): TDOMAttrDef;
|
||||||
begin
|
begin
|
||||||
|
// not using custom allocation here
|
||||||
Result := TDOMAttrDef.Create(Self);
|
Result := TDOMAttrDef.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(Buf, Length);
|
Result.FNSI.QName := FNames.FindOrAdd(Buf, Length);
|
||||||
end;
|
end;
|
||||||
@ -2183,7 +2191,8 @@ end;
|
|||||||
function TXMLDocument.CreateCDATASection(const data: DOMString):
|
function TXMLDocument.CreateCDATASection(const data: DOMString):
|
||||||
TDOMCDATASection;
|
TDOMCDATASection;
|
||||||
begin
|
begin
|
||||||
Result := TDOMCDATASection.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMCDATASection);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FNodeValue := data;
|
Result.FNodeValue := data;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2192,7 +2201,8 @@ function TXMLDocument.CreateProcessingInstruction(const target,
|
|||||||
begin
|
begin
|
||||||
if not IsXmlName(target, FXML11) then
|
if not IsXmlName(target, FXML11) then
|
||||||
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'XMLDocument.CreateProcessingInstruction');
|
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'XMLDocument.CreateProcessingInstruction');
|
||||||
Result := TDOMProcessingInstruction.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMProcessingInstruction);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FTarget := target;
|
Result.FTarget := target;
|
||||||
Result.FNodeValue := data;
|
Result.FNodeValue := data;
|
||||||
end;
|
end;
|
||||||
@ -2205,7 +2215,8 @@ var
|
|||||||
begin
|
begin
|
||||||
if not IsXmlName(name, FXML11) then
|
if not IsXmlName(name, FXML11) then
|
||||||
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'XMLDocument.CreateEntityReference');
|
raise EDOMError.Create(INVALID_CHARACTER_ERR, 'XMLDocument.CreateEntityReference');
|
||||||
Result := TDOMEntityReference.Create(Self);
|
TDOMNode(Result) := Alloc(TDOMEntityReference);
|
||||||
|
Result.Create(Self);
|
||||||
Result.FName := name;
|
Result.FName := name;
|
||||||
dType := DocType;
|
dType := DocType;
|
||||||
if Assigned(dType) then
|
if Assigned(dType) then
|
||||||
@ -2459,25 +2470,11 @@ end;
|
|||||||
function TDOMElement.SetAttributeNode(NewAttr: TDOMAttr): TDOMAttr;
|
function TDOMElement.SetAttributeNode(NewAttr: TDOMAttr): TDOMAttr;
|
||||||
begin
|
begin
|
||||||
Result := Attributes.SetNamedItem(NewAttr) as TDOMAttr;
|
Result := Attributes.SetNamedItem(NewAttr) as TDOMAttr;
|
||||||
|
|
||||||
// TODO -cConformance: here goes inconsistency with DOM 2 - same as in TDOMNode.RemoveChild
|
|
||||||
if Assigned(Result) and (Result <> NewAttr) then
|
|
||||||
begin
|
|
||||||
Result.Free;
|
|
||||||
Result := nil;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMElement.SetAttributeNodeNS(NewAttr: TDOMAttr): TDOMAttr;
|
function TDOMElement.SetAttributeNodeNS(NewAttr: TDOMAttr): TDOMAttr;
|
||||||
begin
|
begin
|
||||||
Result := Attributes.SetNamedItemNS(NewAttr) as TDOMAttr;
|
Result := Attributes.SetNamedItemNS(NewAttr) as TDOMAttr;
|
||||||
|
|
||||||
// TODO -cConformance: here goes inconsistency with DOM 2 - same as in TDOMNode.RemoveChild
|
|
||||||
if Assigned(Result) and (Result <> NewAttr) then
|
|
||||||
begin
|
|
||||||
Result.Free;
|
|
||||||
Result := nil;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user