Skip to content

Commit dccc117

Browse files
committed
Refactored the CssSelector to remove the circular object graph
This allows the translator and its extensions to be garbage collected based on the refcount rather than requiring the garbage collector run, making it much more likely to happen at the end of the CssSelector::toXPath call.
1 parent 2ff53e8 commit dccc117

File tree

3 files changed

+36
-33
lines changed

3 files changed

+36
-33
lines changed

XPath/Extension/ExtensionInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ interface ExtensionInterface
2424
/**
2525
* Returns node translators.
2626
*
27+
* These callables will receive the node as first argument and the translator as second argument.
28+
*
2729
* @return callable[]
2830
*/
2931
public function getNodeTranslators();

XPath/Extension/NodeExtension.php

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ class NodeExtension extends AbstractExtension
2929
const ATTRIBUTE_NAME_IN_LOWER_CASE = 2;
3030
const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4;
3131

32-
/**
33-
* @var Translator
34-
*/
35-
private $translator;
36-
3732
/**
3833
* @var int
3934
*/
@@ -42,12 +37,10 @@ class NodeExtension extends AbstractExtension
4237
/**
4338
* Constructor.
4439
*
45-
* @param Translator $translator
46-
* @param int $flags
40+
* @param int $flags
4741
*/
48-
public function __construct(Translator $translator, $flags = 0)
42+
public function __construct($flags = 0)
4943
{
50-
$this->translator = $translator;
5144
$this->flags = $flags;
5245
}
5346

@@ -100,33 +93,36 @@ public function getNodeTranslators()
10093

10194
/**
10295
* @param Node\SelectorNode $node
96+
* @param Translator $translator
10397
*
10498
* @return XPathExpr
10599
*/
106-
public function translateSelector(Node\SelectorNode $node)
100+
public function translateSelector(Node\SelectorNode $node, Translator $translator)
107101
{
108-
return $this->translator->nodeToXPath($node->getTree());
102+
return $translator->nodeToXPath($node->getTree());
109103
}
110104

111105
/**
112106
* @param Node\CombinedSelectorNode $node
107+
* @param Translator $translator
113108
*
114109
* @return XPathExpr
115110
*/
116-
public function translateCombinedSelector(Node\CombinedSelectorNode $node)
111+
public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator)
117112
{
118-
return $this->translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector());
113+
return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector());
119114
}
120115

121116
/**
122117
* @param Node\NegationNode $node
118+
* @param Translator $translator
123119
*
124120
* @return XPathExpr
125121
*/
126-
public function translateNegation(Node\NegationNode $node)
122+
public function translateNegation(Node\NegationNode $node, Translator $translator)
127123
{
128-
$xpath = $this->translator->nodeToXPath($node->getSelector());
129-
$subXpath = $this->translator->nodeToXPath($node->getSubSelector());
124+
$xpath = $translator->nodeToXPath($node->getSelector());
125+
$subXpath = $translator->nodeToXPath($node->getSubSelector());
130126
$subXpath->addNameTest();
131127

132128
if ($subXpath->getCondition()) {
@@ -138,34 +134,37 @@ public function translateNegation(Node\NegationNode $node)
138134

139135
/**
140136
* @param Node\FunctionNode $node
137+
* @param Translator $translator
141138
*
142139
* @return XPathExpr
143140
*/
144-
public function translateFunction(Node\FunctionNode $node)
141+
public function translateFunction(Node\FunctionNode $node, Translator $translator)
145142
{
146-
$xpath = $this->translator->nodeToXPath($node->getSelector());
143+
$xpath = $translator->nodeToXPath($node->getSelector());
147144

148-
return $this->translator->addFunction($xpath, $node);
145+
return $translator->addFunction($xpath, $node);
149146
}
150147

151148
/**
152149
* @param Node\PseudoNode $node
150+
* @param Translator $translator
153151
*
154152
* @return XPathExpr
155153
*/
156-
public function translatePseudo(Node\PseudoNode $node)
154+
public function translatePseudo(Node\PseudoNode $node, Translator $translator)
157155
{
158-
$xpath = $this->translator->nodeToXPath($node->getSelector());
156+
$xpath = $translator->nodeToXPath($node->getSelector());
159157

160-
return $this->translator->addPseudoClass($xpath, $node->getIdentifier());
158+
return $translator->addPseudoClass($xpath, $node->getIdentifier());
161159
}
162160

163161
/**
164162
* @param Node\AttributeNode $node
163+
* @param Translator $translator
165164
*
166165
* @return XPathExpr
167166
*/
168-
public function translateAttribute(Node\AttributeNode $node)
167+
public function translateAttribute(Node\AttributeNode $node, Translator $translator)
169168
{
170169
$name = $node->getAttribute();
171170
$safe = $this->isSafeName($name);
@@ -181,37 +180,39 @@ public function translateAttribute(Node\AttributeNode $node)
181180

182181
$attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name));
183182
$value = $node->getValue();
184-
$xpath = $this->translator->nodeToXPath($node->getSelector());
183+
$xpath = $translator->nodeToXPath($node->getSelector());
185184

186185
if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) {
187186
$value = strtolower($value);
188187
}
189188

190-
return $this->translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value);
189+
return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value);
191190
}
192191

193192
/**
194193
* @param Node\ClassNode $node
194+
* @param Translator $translator
195195
*
196196
* @return XPathExpr
197197
*/
198-
public function translateClass(Node\ClassNode $node)
198+
public function translateClass(Node\ClassNode $node, Translator $translator)
199199
{
200-
$xpath = $this->translator->nodeToXPath($node->getSelector());
200+
$xpath = $translator->nodeToXPath($node->getSelector());
201201

202-
return $this->translator->addAttributeMatching($xpath, '~=', '@class', $node->getName());
202+
return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName());
203203
}
204204

205205
/**
206206
* @param Node\HashNode $node
207+
* @param Translator $translator
207208
*
208209
* @return XPathExpr
209210
*/
210-
public function translateHash(Node\HashNode $node)
211+
public function translateHash(Node\HashNode $node, Translator $translator)
211212
{
212-
$xpath = $this->translator->nodeToXPath($node->getSelector());
213+
$xpath = $translator->nodeToXPath($node->getSelector());
213214

214-
return $this->translator->addAttributeMatching($xpath, '=', '@id', $node->getId());
215+
return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId());
215216
}
216217

217218
/**

XPath/Translator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public function __construct(ParserInterface $parser = null)
7676
$this->mainParser = $parser ?: new Parser();
7777

7878
$this
79-
->registerExtension(new Extension\NodeExtension($this))
79+
->registerExtension(new Extension\NodeExtension())
8080
->registerExtension(new Extension\CombinationExtension())
8181
->registerExtension(new Extension\FunctionExtension())
8282
->registerExtension(new Extension\PseudoClassExtension())
@@ -207,7 +207,7 @@ public function nodeToXPath(NodeInterface $node)
207207
throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName()));
208208
}
209209

210-
return call_user_func($this->nodeTranslators[$node->getNodeName()], $node);
210+
return call_user_func($this->nodeTranslators[$node->getNodeName()], $node, $this);
211211
}
212212

213213
/**

0 commit comments

Comments
 (0)