Skip to content

Commit 9250229

Browse files
authored
Merge pull request #188 from rails/flavorjones-minimize-operations
performance: eliminate operations on removed nodes
2 parents 12859b1 + b4efdad commit 9250229

File tree

2 files changed

+63
-5
lines changed

2 files changed

+63
-5
lines changed

Diff for: lib/rails/html/scrubbers.rb

+7-3
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,11 @@ def scrub(node)
7272
return CONTINUE if skip_node?(node)
7373

7474
unless (node.element? || node.comment?) && keep_node?(node)
75-
return STOP if scrub_node(node) == STOP
75+
return STOP unless scrub_node(node) == CONTINUE
7676
end
7777

7878
scrub_attributes(node)
79+
CONTINUE
7980
end
8081

8182
protected
@@ -107,8 +108,11 @@ def scrub_node(node)
107108
def scrub_attributes(node)
108109
if @attributes
109110
node.attribute_nodes.each do |attr|
110-
attr.remove if scrub_attribute?(attr.name)
111-
scrub_attribute(node, attr)
111+
if scrub_attribute?(attr.name)
112+
attr.remove
113+
else
114+
scrub_attribute(node, attr)
115+
end
112116
end
113117

114118
scrub_css_attribute(node)

Diff for: test/scrubbers_test.rb

+56-2
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,65 @@ def scrub_node(node)
207207
end
208208
end
209209

210-
def setup
211-
@scrubber = ScrubStopper.new
210+
class ScrubContinuer < Rails::HTML::PermitScrubber
211+
def scrub_node(node)
212+
Loofah::Scrubber::CONTINUE
213+
end
212214
end
213215

214216
def test_returns_stop_from_scrub_if_scrub_node_does
217+
@scrubber = ScrubStopper.new
215218
assert_scrub_stopped "<script>remove me</script>"
216219
end
220+
221+
def test_returns_continue_from_scrub_if_scrub_node_does
222+
@scrubber = ScrubContinuer.new
223+
assert_node_skipped "<script>keep me</script>"
224+
end
225+
end
226+
227+
class PermitScrubberMinimalOperationsTest < ScrubberTest
228+
class TestPermitScrubber < Rails::HTML::PermitScrubber
229+
def initialize
230+
@scrub_attribute_args = []
231+
@scrub_attributes_args = []
232+
233+
super
234+
235+
self.tags = ["div"]
236+
self.attributes = ["class"]
237+
end
238+
239+
def scrub_attributes(node)
240+
@scrub_attributes_args << node.name
241+
242+
super
243+
end
244+
245+
def scrub_attribute(node, attr)
246+
@scrub_attribute_args << [node.name, attr.name]
247+
248+
super
249+
end
250+
end
251+
252+
def test_does_not_scrub_removed_attributes
253+
@scrubber = TestPermitScrubber.new
254+
255+
input = "<div class='foo' href='bar'></div>"
256+
frag = scrub_fragment(input)
257+
assert_equal("<div class=\"foo\"></div>", frag)
258+
259+
assert_equal([["div", "class"]], @scrubber.instance_variable_get(:@scrub_attribute_args))
260+
end
261+
262+
def test_does_not_scrub_attributes_of_a_removed_node
263+
@scrubber = TestPermitScrubber.new
264+
265+
input = "<div class='foo' href='bar'><svg xlink:href='asdf'><set></set></svg></div>"
266+
frag = scrub_fragment(input)
267+
assert_equal("<div class=\"foo\"></div>", frag)
268+
269+
assert_equal(["div"], @scrubber.instance_variable_get(:@scrub_attributes_args))
270+
end
217271
end

0 commit comments

Comments
 (0)