While the performance difference between the old and new approach is
pretty much negligible, it's simply not needed to use #shift/#unshift
here.
Thanks to Mon_Ouie from the #ruby IRC channel for suggesting this.
Without this the following could happen:
1. Thread A acquires the lock and sets the ownership to A.
2. Thread A yields and returns
3. Thread B tries to acquire the lock
4. At this exact moment Thread A calls the "synchronize" method again
and sees that the "owner" variable is still set to Thread A
5. Both thread A and B can now access the underlying data in parallel,
possibly leading to corrupted objects
This can be demonstrated using the following script:
require 'oga'
lru = Oga::LRU.new(64)
threads = 50.times.map do
Thread.new do
loop do
number = rand(100)
lru[number] = number
end
end
end
threads.each(&:join)
Run this for a while on either JRuby or Rubinius and you'll end up with
errors such as "ConcurrencyError: Detected invalid array contents due to
unsynchronized modifications with concurrent users" on JRuby or
"ArgumentError: negative array size" on Rubinius.
Resetting the owner variable ensures the above can never happen. Thanks
to @chrisseaton for bringing this up earlier today.
Prevents a superfluous end tag of a self-closing HTML tag from
closing its parent element prematurely, for example:
```html
<object><param></param><param></param></object>
```
(note <param> is self closing) being turned into:
```html
<object><param/></object><param/>
```
This is a Nokogiri extension (as far as I'm aware) but it's useful
enough to also include in Oga. Selectors such as "foo:nth(2)" are simply
compiled to XPath "descendant::foo[position() = 2]".
Fixes#123
```
element = Oga::XML::Element.new(:name => 'div')
some_node.replace(element)
```
You can also pass a `String` to `replace` and it will be replaced with
a `Oga::XML::Text` node
```
some_node.replace('this will replace the current node with a text node')
```
closes#115
Currently this only disabled the automatic insertion of closing tags, in
the future this may also disable other features if deemed worth the
effort.
Fixes#107
This ensures that entities such as "½" are decoded properly.
Previously this would be ignored as the regular expression used for this
only matched [a-zA-Z].
This was adapted from PR #111.
Previous HTML such as this would be lexed incorrectly:
<div>
<ul>
<li>foo
</ul>
inside div
</div>
outside div
The lexer would see this as the following instead:
<div>
<ul>
<li>foo</li>
inside div
</ul>
outside div
</div>
This commit exposes the name of the closing tag to
XML::Lexer#on_element_end (omitted for self closing tags). This can be
used to automatically close nested tags that were left open, ensuring
the above HTML is lexer correctly.
The new setup ignores namespace prefixes as these are not used in HTML,
XML in turn won't even run the code to begin with since it doesn't allow
one to leave out closing tags.
By encoding single/double quotes we can potentially break input, so lets
stop doing this. This now ensures that this:
<foo>a"b</foo>
Is actually serialized back into the exact same instead of being
serialized into:
<foo>a"b</foo>
This allows for more fine grained control over when to close certain
elements. For example, an unclosed <tr> element should be closed first
when bumping into any element other than <td> or <th>. Using the old
NodeNameSet this would mean having to list every possible HTML element
out there. Using this new setup one can just create a whitelist of the
<td> and <th> elements.
When closing certain HTML elements the lexer should also close whatever
parent elements remain. For example, consider the following HTML:
<table>
<thead>
<tr>
<th>Foo
<th>Bar
<tbody>
...
</tbody>
</table>
Here the "<tbody>" element shouldn't only close the "<th>Bar" element
but also the parent "<tr>" and "<thead>" elements. This ensures we'd end
up with the following HTML:
<table>
<thead>
<tr>
<th>Foo</th>
<th>Bar</th>
</tr>
</thead>
<tbody>
...
</tbody>
</table>
Instead of garbage along the lines of this:
<table>
<thead>
<tr>
<th>Foo</th>
<th>Bar</th>
<tbody>
...
</tbody>
</table></tr></thead>
Fixes#99 (hopefully for good this time)
By using AST::Node#children directly with a splat we save ourselves an
extra method call. This in turn speeds up both the
xpath/evaluator/big_xml_average_bench.rb and
xpath/evaluator/node_matches_bench.rb benchmarks a little bit.
Using the benchmark xpath/evaluator/node_matches_bench.rb the results
prior to this commit were as following for 3 cases:
name only: 737633 i/s
namespace wildcard: 612196 i/s
name wildcard: 516030 i/s
With this commit said numbers have changed to the following:
name only: 746086 i/s
namespace wildcard: 1097168 i/s
name wildcard: 1151255 i/s
This results in the following increase of performance for each case:
name only: 1,011x (insignificant)
namespace wildcard: 1,79x
name wildcard: 2,23x
In the benchmark xpath/evaluator/big_xml_average_bench.rb the difference
isn't really noticable as said benchmark only queries elements by names,
of which the performance hasn't really improved.
This ensures that HTML such as this:
<li>foo
<li>bar
is parsed as this:
<li>foo</li>
<li>bar</li>
and not as this:
<li>
foo
<li>bar</li>
</li>
Fixes#97