Diff
Modified: trunk/LayoutTests/ChangeLog (175027 => 175028)
--- trunk/LayoutTests/ChangeLog 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/LayoutTests/ChangeLog 2014-10-22 09:22:05 UTC (rev 175028)
@@ -1,3 +1,21 @@
+2014-10-22 Dhi Aurrahman <[email protected]>
+
+ Add relList to the anchor, area and link elements
+ https://bugs.webkit.org/show_bug.cgi?id=137860
+
+ Reviewed by Darin Adler and Chris Dumez.
+
+ Tests relList aspects for anchor, area and list elements.
+ Update dom static property for-in iteration test result to include relList.
+
+ * fast/dom/rel-list-expected.txt: Added.
+ * fast/dom/rel-list-gc-expected.txt: Added.
+ * fast/dom/rel-list-gc.html: Added.
+ * fast/dom/rel-list.html: Added.
+ * js/dom/dom-static-property-for-in-iteration-expected.txt: Updated results.
+ * perf/rel-list-remove-expected.txt: Added.
+ * perf/rel-list-remove.html: Added.
+
2014-10-21 Brent Fulgham <[email protected]>
[Win] More rebaselines.
Added: trunk/LayoutTests/fast/dom/rel-list-expected.txt (0 => 175028)
--- trunk/LayoutTests/fast/dom/rel-list-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/rel-list-expected.txt 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,378 @@
+Tests that relList works on anchor, area and link elements
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Tests relList for anchor element
+PASS element.relList == null is false
+PASS element.relList == undefined is false
+PASS element.relList instanceof DOMTokenList is true
+PASS element.relList.length is 3
+PASS element.relList.contains("a") is true
+PASS element.relList.contains("b") is true
+PASS element.relList.contains("c") is true
+PASS element.relList.contains("d") is false
+PASS element.relList.length is 3
+PASS element.relList.contains("foo") is true
+PASS element.relList.contains("bar") is true
+PASS element.relList.contains("chocolate") is true
+PASS element.relList.contains("orange") is false
+PASS element.relList.length is 0
+PASS element.relList.length is 0
+PASS element.relList.length is 2
+PASS element.relList.contains("marshmallow") is true
+PASS element.relList.contains("chips") is true
+PASS element.relList.contains("orange") is false
+PASS String(element.relList) is "x"
+PASS element.relList.length is 0
+PASS element.relList.length is 1
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.rel is "x"
+PASS element.rel is "x"
+PASS element.rel is "x x"
+PASS element.rel is "y x"
+PASS element.rel is ""
+PASS element.rel is ""
+PASS element.rel is " y y "
+PASS element.rel is "y"
+Ensure that we can handle empty rel correctly
+PASS element.relList.toggle('x') is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x') is false
+PASS element.rel is ""
+PASS element.relList.contains("x") is false
+PASS element.relList[1] is undefined.
+PASS element.relList.contains("x") is false
+PASS element.relList.contains("x") is true
+Test toggle with force argument
+PASS element.relList.toggle('x', true) is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x', true) is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x', false) is false
+PASS element.rel is ""
+PASS element.relList.toggle('x', false) is false
+PASS element.rel is ""
+PASS element.relList.toggle("", true) threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.toggle("x y", false) threw exception Error: InvalidCharacterError: DOM Exception 5.
+Testing add in presence of trailing white spaces.
+PASS element.rel is "x y"
+PASS element.rel is "x\ty"
+PASS element.rel is " y"
+Test invalid tokens
+PASS element.relList.contains("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.contains("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.add("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.add("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.remove("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.remove("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.toggle("") threw exception Error: SyntaxError: DOM Exception 12.
+Indexing
+PASS element.relList[0] is "x"
+PASS element.relList.item(0) is "x"
+PASS element.relList[1] is "x"
+PASS element.relList.item(1) is "x"
+PASS element.relList[1] is "y"
+PASS element.relList.item(1) is "y"
+PASS element.relList[0] is undefined.
+PASS element.relList.item(0) is null
+PASS element.relList[4] is undefined.
+PASS element.relList.item(4) is null
+PASS element.relList[-1] is undefined.
+PASS element.relList.item(-1) is null
+PASS element.relList.item() threw exception TypeError: Not enough arguments.
+Test case since DOMTokenList is case sensitive
+PASS element.relList.contains("x") is true
+PASS element.relList.contains("X") is false
+PASS element.relList[0] is "x"
+PASS element.relList.contains() threw exception TypeError: Not enough arguments.
+PASS element.relList.contains("X") is true
+PASS element.relList.contains("x") is false
+PASS element.relList[0] is "X"
+Testing whitespace
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+DOMTokenList presence and type
+PASS 'undefined' != typeof DOMTokenList is true
+PASS typeof DOMTokenList.prototype is "object"
+PASS typeof element.relList is "object"
+PASS element.relList.constructor is DOMTokenList
+PASS element.relList === element.relList is true
+Variadic calls
+PASS element.rel is "a b"
+PASS element.rel is "a b c"
+PASS element.rel is "a b c null d undefined 0 false"
+PASS element.rel is "a b"
+PASS element.relList.add("a", "b", "") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.rel is ""
+PASS element.relList.add("a", "b", "c d") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.rel is ""
+PASS element.relList.add("a", {toString: function() { throw new Error("user error"); }}, "b") threw exception Error: user error.
+PASS element.rel is ""
+PASS element.relList.add() did not throw exception.
+PASS observer.takeRecords().length is 1
+PASS element.rel is "b d "
+PASS element.rel is "d "
+PASS element.rel is "a b c"
+PASS element.relList.remove("a", "b", "") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.rel is "a b"
+PASS element.relList.remove("a", {toString: function() { throw new Error("user error"); }}, "b") threw exception Error: user error.
+PASS element.rel is "a b"
+PASS element.relList.remove("a", "b", "c d") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.rel is "a b"
+PASS element.relList.remove() did not throw exception.
+PASS observer.takeRecords().length is 1
+Tests relList for area element
+PASS element.relList == null is false
+PASS element.relList == undefined is false
+PASS element.relList instanceof DOMTokenList is true
+PASS element.relList.length is 3
+PASS element.relList.contains("a") is true
+PASS element.relList.contains("b") is true
+PASS element.relList.contains("c") is true
+PASS element.relList.contains("d") is false
+PASS element.relList.length is 3
+PASS element.relList.contains("foo") is true
+PASS element.relList.contains("bar") is true
+PASS element.relList.contains("chocolate") is true
+PASS element.relList.contains("orange") is false
+PASS element.relList.length is 0
+PASS element.relList.length is 0
+PASS element.relList.length is 2
+PASS element.relList.contains("marshmallow") is true
+PASS element.relList.contains("chips") is true
+PASS element.relList.contains("orange") is false
+PASS String(element.relList) is "x"
+PASS element.relList.length is 0
+PASS element.relList.length is 1
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.rel is "x"
+PASS element.rel is "x"
+PASS element.rel is "x x"
+PASS element.rel is "y x"
+PASS element.rel is ""
+PASS element.rel is ""
+PASS element.rel is " y y "
+PASS element.rel is "y"
+Ensure that we can handle empty rel correctly
+PASS element.relList.toggle('x') is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x') is false
+PASS element.rel is ""
+PASS element.relList.contains("x") is false
+PASS element.relList[1] is undefined.
+PASS element.relList.contains("x") is false
+PASS element.relList.contains("x") is true
+Test toggle with force argument
+PASS element.relList.toggle('x', true) is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x', true) is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x', false) is false
+PASS element.rel is ""
+PASS element.relList.toggle('x', false) is false
+PASS element.rel is ""
+PASS element.relList.toggle("", true) threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.toggle("x y", false) threw exception Error: InvalidCharacterError: DOM Exception 5.
+Testing add in presence of trailing white spaces.
+PASS element.rel is "x y"
+PASS element.rel is "x\ty"
+PASS element.rel is " y"
+Test invalid tokens
+PASS element.relList.contains("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.contains("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.add("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.add("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.remove("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.remove("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.toggle("") threw exception Error: SyntaxError: DOM Exception 12.
+Indexing
+PASS element.relList[0] is "x"
+PASS element.relList.item(0) is "x"
+PASS element.relList[1] is "x"
+PASS element.relList.item(1) is "x"
+PASS element.relList[1] is "y"
+PASS element.relList.item(1) is "y"
+PASS element.relList[0] is undefined.
+PASS element.relList.item(0) is null
+PASS element.relList[4] is undefined.
+PASS element.relList.item(4) is null
+PASS element.relList[-1] is undefined.
+PASS element.relList.item(-1) is null
+PASS element.relList.item() threw exception TypeError: Not enough arguments.
+Test case since DOMTokenList is case sensitive
+PASS element.relList.contains("x") is true
+PASS element.relList.contains("X") is false
+PASS element.relList[0] is "x"
+PASS element.relList.contains() threw exception TypeError: Not enough arguments.
+PASS element.relList.contains("X") is true
+PASS element.relList.contains("x") is false
+PASS element.relList[0] is "X"
+Testing whitespace
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+DOMTokenList presence and type
+PASS 'undefined' != typeof DOMTokenList is true
+PASS typeof DOMTokenList.prototype is "object"
+PASS typeof element.relList is "object"
+PASS element.relList.constructor is DOMTokenList
+PASS element.relList === element.relList is true
+Variadic calls
+PASS element.rel is "a b"
+PASS element.rel is "a b c"
+PASS element.rel is "a b c null d undefined 0 false"
+PASS element.rel is "a b"
+PASS element.relList.add("a", "b", "") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.rel is ""
+PASS element.relList.add("a", "b", "c d") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.rel is ""
+PASS element.relList.add("a", {toString: function() { throw new Error("user error"); }}, "b") threw exception Error: user error.
+PASS element.rel is ""
+PASS element.relList.add() did not throw exception.
+PASS observer.takeRecords().length is 1
+PASS element.rel is "b d "
+PASS element.rel is "d "
+PASS element.rel is "a b c"
+PASS element.relList.remove("a", "b", "") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.rel is "a b"
+PASS element.relList.remove("a", {toString: function() { throw new Error("user error"); }}, "b") threw exception Error: user error.
+PASS element.rel is "a b"
+PASS element.relList.remove("a", "b", "c d") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.rel is "a b"
+PASS element.relList.remove() did not throw exception.
+PASS observer.takeRecords().length is 1
+Tests relList for link element
+PASS element.relList == null is false
+PASS element.relList == undefined is false
+PASS element.relList instanceof DOMTokenList is true
+PASS element.relList.length is 3
+PASS element.relList.contains("a") is true
+PASS element.relList.contains("b") is true
+PASS element.relList.contains("c") is true
+PASS element.relList.contains("d") is false
+PASS element.relList.length is 3
+PASS element.relList.contains("foo") is true
+PASS element.relList.contains("bar") is true
+PASS element.relList.contains("chocolate") is true
+PASS element.relList.contains("orange") is false
+PASS element.relList.length is 0
+PASS element.relList.length is 0
+PASS element.relList.length is 2
+PASS element.relList.contains("marshmallow") is true
+PASS element.relList.contains("chips") is true
+PASS element.relList.contains("orange") is false
+PASS String(element.relList) is "x"
+PASS element.relList.length is 0
+PASS element.relList.length is 1
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.rel is "x"
+PASS element.rel is "x"
+PASS element.rel is "x x"
+PASS element.rel is "y x"
+PASS element.rel is ""
+PASS element.rel is ""
+PASS element.rel is " y y "
+PASS element.rel is "y"
+Ensure that we can handle empty rel correctly
+PASS element.relList.toggle('x') is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x') is false
+PASS element.rel is ""
+PASS element.relList.contains("x") is false
+PASS element.relList[1] is undefined.
+PASS element.relList.contains("x") is false
+PASS element.relList.contains("x") is true
+Test toggle with force argument
+PASS element.relList.toggle('x', true) is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x', true) is true
+PASS element.rel is "x"
+PASS element.relList.toggle('x', false) is false
+PASS element.rel is ""
+PASS element.relList.toggle('x', false) is false
+PASS element.rel is ""
+PASS element.relList.toggle("", true) threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.toggle("x y", false) threw exception Error: InvalidCharacterError: DOM Exception 5.
+Testing add in presence of trailing white spaces.
+PASS element.rel is "x y"
+PASS element.rel is "x\ty"
+PASS element.rel is " y"
+Test invalid tokens
+PASS element.relList.contains("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.contains("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.add("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.add("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.remove("") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.relList.remove("x y") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.relList.toggle("") threw exception Error: SyntaxError: DOM Exception 12.
+Indexing
+PASS element.relList[0] is "x"
+PASS element.relList.item(0) is "x"
+PASS element.relList[1] is "x"
+PASS element.relList.item(1) is "x"
+PASS element.relList[1] is "y"
+PASS element.relList.item(1) is "y"
+PASS element.relList[0] is undefined.
+PASS element.relList.item(0) is null
+PASS element.relList[4] is undefined.
+PASS element.relList.item(4) is null
+PASS element.relList[-1] is undefined.
+PASS element.relList.item(-1) is null
+PASS element.relList.item() threw exception TypeError: Not enough arguments.
+Test case since DOMTokenList is case sensitive
+PASS element.relList.contains("x") is true
+PASS element.relList.contains("X") is false
+PASS element.relList[0] is "x"
+PASS element.relList.contains() threw exception TypeError: Not enough arguments.
+PASS element.relList.contains("X") is true
+PASS element.relList.contains("x") is false
+PASS element.relList[0] is "X"
+Testing whitespace
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+PASS element.relList.length is 2
+DOMTokenList presence and type
+PASS 'undefined' != typeof DOMTokenList is true
+PASS typeof DOMTokenList.prototype is "object"
+PASS typeof element.relList is "object"
+PASS element.relList.constructor is DOMTokenList
+PASS element.relList === element.relList is true
+Variadic calls
+PASS element.rel is "a b"
+PASS element.rel is "a b c"
+PASS element.rel is "a b c null d undefined 0 false"
+PASS element.rel is "a b"
+PASS element.relList.add("a", "b", "") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.rel is ""
+PASS element.relList.add("a", "b", "c d") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.rel is ""
+PASS element.relList.add("a", {toString: function() { throw new Error("user error"); }}, "b") threw exception Error: user error.
+PASS element.rel is ""
+PASS element.relList.add() did not throw exception.
+PASS observer.takeRecords().length is 1
+PASS element.rel is "b d "
+PASS element.rel is "d "
+PASS element.rel is "a b c"
+PASS element.relList.remove("a", "b", "") threw exception Error: SyntaxError: DOM Exception 12.
+PASS element.rel is "a b"
+PASS element.relList.remove("a", {toString: function() { throw new Error("user error"); }}, "b") threw exception Error: user error.
+PASS element.rel is "a b"
+PASS element.relList.remove("a", "b", "c d") threw exception Error: InvalidCharacterError: DOM Exception 5.
+PASS element.rel is "a b"
+PASS element.relList.remove() did not throw exception.
+PASS observer.takeRecords().length is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/rel-list-gc-expected.txt (0 => 175028)
--- trunk/LayoutTests/fast/dom/rel-list-gc-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/rel-list-gc-expected.txt 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,13 @@
+Tests relList gc for anchor element
+PASS element.relList.life is 42
+PASS element.relList.life is 42
+Tests relList gc for area element
+PASS element.relList.life is 42
+PASS element.relList.life is 42
+Tests relList gc for link element
+PASS element.relList.life is 42
+PASS element.relList.life is 42
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/rel-list-gc.html (0 => 175028)
--- trunk/LayoutTests/fast/dom/rel-list-gc.html (rev 0)
+++ trunk/LayoutTests/fast/dom/rel-list-gc.html 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<script>
+var element;
+
+function test(type)
+{
+ element = document.createElement(type);
+ var relList = element.relList;
+ element.relList.life = 42;
+ shouldEvaluateTo('element.relList.life', 42);
+ relList = null;
+ gc();
+ shouldEvaluateTo('element.relList.life', 42);
+}
+
+debug('Tests relList gc for anchor element');
+test('a');
+debug('Tests relList gc for area element');
+test('area');
+debug('Tests relList gc for link element');
+test('link');
+
+</script>
+<script src=""
+</body>
+</html>
\ No newline at end of file
Added: trunk/LayoutTests/fast/dom/rel-list.html (0 => 175028)
--- trunk/LayoutTests/fast/dom/rel-list.html (rev 0)
+++ trunk/LayoutTests/fast/dom/rel-list.html 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,303 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<a id="a" rel="a b c"></a>
+<area id="area" rel="a b c"></area>
+<link id="link" rel="a b c">
+<script>
+description('Tests that relList works on anchor, area and link elements');
+
+var element;
+var type;
+var observer;
+
+function createElement(rel)
+{
+ element = document.createElement(type);
+ element.rel = rel;
+}
+
+function test()
+{
+ element = document.getElementById(type);
+ shouldBeFalse('element.relList == null');
+ shouldBeFalse('element.relList == undefined');
+ shouldBeTrue('element.relList instanceof DOMTokenList');
+ shouldBe('element.relList.length', '3');
+ shouldBeTrue('element.relList.contains("a")');
+ shouldBeTrue('element.relList.contains("b")');
+ shouldBeTrue('element.relList.contains("c")');
+ shouldBeFalse('element.relList.contains("d")');
+
+ createElement("foo bar chocolate");
+ shouldBe('element.relList.length', '3');
+ shouldBeTrue('element.relList.contains("foo")');
+ shouldBeTrue('element.relList.contains("bar")');
+ shouldBeTrue('element.relList.contains("chocolate")');
+ shouldBeFalse('element.relList.contains("orange")');
+
+ element.removeAttribute('rel');
+ shouldBe('element.relList.length', '0');
+
+ element.setAttribute('rel', '');
+ shouldBe('element.relList.length', '0');
+
+ element.setAttribute('rel', 'marshmallow chips');
+ shouldBe('element.relList.length', '2');
+ shouldBeTrue('element.relList.contains("marshmallow")');
+ shouldBeTrue('element.relList.contains("chips")');
+ shouldBeFalse('element.relList.contains("orange")');
+
+ createElement('x');
+ element.relList = 'y';
+ shouldBeEqualToString('String(element.relList)', 'x');
+
+ createElement('');
+ shouldEvaluateTo('element.relList.length', 0);
+
+ createElement('x');
+ shouldEvaluateTo('element.relList.length', 1);
+
+ createElement('x x');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ createElement('x y');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ createElement('');
+ element.relList.add('x');
+ shouldBeEqualToString('element.rel', 'x');
+
+ createElement('x');
+ element.relList.add('x');
+ shouldBeEqualToString('element.rel', 'x');
+
+ createElement('x x');
+ element.relList.add('x');
+ shouldBeEqualToString('element.rel', 'x x');
+
+ createElement('y');
+ element.relList.add('x');
+ shouldBeEqualToString('element.rel', 'y x');
+
+ createElement('');
+ element.relList.remove('x');
+ shouldBeEqualToString('element.rel', '');
+
+ createElement('x');
+ element.relList.remove('x');
+ shouldBeEqualToString('element.rel', '');
+
+ createElement(' y x y ');
+ element.relList.remove('x');
+ shouldBeEqualToString('element.rel', ' y y ');
+
+ createElement(' x y x ');
+ element.relList.remove('x');
+ shouldBeEqualToString('element.rel', 'y');
+
+ debug('Ensure that we can handle empty rel correctly');
+ element = document.createElement(type);
+ shouldBeTrue("element.relList.toggle('x')");
+ shouldBeEqualToString('element.rel', 'x');
+ shouldBeFalse("element.relList.toggle('x')");
+ shouldBeEqualToString('element.rel', '');
+
+ element = document.createElement(type);
+ shouldBeFalse('element.relList.contains("x")');
+ shouldBeUndefined('element.relList[1]');
+ element.relList.remove('x');
+ shouldBeFalse('element.relList.contains("x")');
+ element.relList.add('x');
+ shouldBeTrue('element.relList.contains("x")');
+
+ debug('Test toggle with force argument');
+ createElement('');
+ shouldBeTrue("element.relList.toggle('x', true)");
+ shouldBeEqualToString('element.rel', 'x');
+ shouldBeTrue("element.relList.toggle('x', true)");
+ shouldBeEqualToString('element.rel', 'x');
+ shouldBeFalse("element.relList.toggle('x', false)");
+ shouldBeEqualToString('element.rel', '');
+ shouldBeFalse("element.relList.toggle('x', false)");
+ shouldBeEqualToString('element.rel', '');
+ shouldThrow('element.relList.toggle("", true)');
+ shouldThrow('element.relList.toggle("x y", false)');
+
+ debug('Testing add in presence of trailing white spaces.');
+ createElement('x ');
+ element.relList.add('y');
+ shouldBeEqualToString('element.rel', 'x y');
+
+ createElement('x\t');
+ element.relList.add('y');
+ shouldBeEqualToString('element.rel', 'x\ty');
+
+ createElement(' ');
+ element.relList.add('y');
+ shouldBeEqualToString('element.rel', ' y');
+
+ debug('Test invalid tokens');
+
+ createElement('x');
+ shouldThrow('element.relList.contains("")');
+
+ createElement('x y');
+ shouldThrow('element.relList.contains("x y")');
+
+ createElement('');
+ shouldThrow('element.relList.add("")');
+
+ createElement('');
+ shouldThrow('element.relList.add("x y")');
+
+ createElement('');
+ shouldThrow('element.relList.remove("")');
+
+ createElement('');
+ shouldThrow('element.relList.remove("x y")');
+
+ createElement('');
+ shouldThrow('element.relList.toggle("")');
+
+ debug('Indexing');
+ createElement('x');
+ shouldBeEqualToString('element.relList[0]', 'x');
+ shouldBeEqualToString('element.relList.item(0)', 'x');
+
+ createElement('x x');
+ shouldBeEqualToString('element.relList[1]', 'x');
+ shouldBeEqualToString('element.relList.item(1)', 'x');
+
+ createElement('x y');
+ shouldBeEqualToString('element.relList[1]', 'y');
+ shouldBeEqualToString('element.relList.item(1)', 'y');
+
+ createElement('');
+ shouldBeUndefined('element.relList[0]');
+ shouldBeNull('element.relList.item(0)');
+
+ createElement('x y z');
+ shouldBeUndefined('element.relList[4]');
+ shouldBeNull('element.relList.item(4)');
+ shouldBeUndefined('element.relList[-1]');
+ shouldBeNull('element.relList.item(-1)');
+ shouldThrow('element.relList.item()');
+
+ debug('Test case since DOMTokenList is case sensitive');
+ createElement('x');
+ shouldBeTrue('element.relList.contains("x")');
+ shouldBeFalse('element.relList.contains("X")');
+ shouldBeEqualToString('element.relList[0]', 'x');
+ shouldThrow('element.relList.contains()');
+
+ createElement('X');
+ shouldBeTrue('element.relList.contains("X")');
+ shouldBeFalse('element.relList.contains("x")');
+ shouldBeEqualToString('element.relList[0]', 'X');
+
+ debug('Testing whitespace');
+ createElement('x\u0020y');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ createElement('x\u0009y');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ createElement('x\u000Ay');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ createElement('x\u000Cy');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ createElement('x\u000Dy');
+ shouldEvaluateTo('element.relList.length', 2);
+
+ debug('DOMTokenList presence and type');
+ shouldBeTrue('\'undefined\' != typeof DOMTokenList');
+
+ shouldBeEqualToString('typeof DOMTokenList.prototype', 'object');
+
+ createElement('x');
+ shouldBeEqualToString('typeof element.relList', 'object');
+ shouldEvaluateTo('element.relList.constructor', 'DOMTokenList');
+ shouldBeTrue('element.relList === element.relList');
+
+ debug('Variadic calls');
+
+ createElement('');
+ element.relList.add('a', 'b');
+ shouldBeEqualToString('element.rel', 'a b');
+
+ element.relList.add('a', 'b', 'c');
+ shouldBeEqualToString('element.rel', 'a b c');
+
+ element.relList.add(null, {toString: function() { return 'd' }}, undefined, 0, false);
+ shouldBeEqualToString('element.rel', 'a b c null d undefined 0 false');
+
+ createElement('');
+ element.relList.add('a', 'b', 'a');
+ shouldBeEqualToString('element.rel', 'a b');
+
+ createElement('');
+ shouldThrow('element.relList.add("a", "b", "")');
+ shouldBeEqualToString('element.rel', '');
+ shouldThrow('element.relList.add("a", "b", "c d")');
+ shouldBeEqualToString('element.rel', '');
+ shouldThrow('element.relList.add("a", {toString: function() { throw new Error("user error"); }}, "b")', '"Error: user error"');
+ shouldBeEqualToString('element.rel', '');
+
+ createElement('');
+ shouldNotThrow('element.relList.add()');
+
+ createElement('');
+ observer = new WebKitMutationObserver(function() {});
+ observer.observe(element, {attributes: true});
+ element.relList.add('a', 'c');
+ shouldBe('observer.takeRecords().length', '1');
+
+ createElement('a b c d ');
+ element.relList.remove('a', 'c');
+ shouldBeEqualToString('element.rel', 'b d ');
+
+ element.relList.remove('b', 'b');
+ shouldBeEqualToString('element.rel', 'd ');
+
+ createElement('a b c null d undefined 0 false');
+ element.relList.remove(null, {toString: function() { return 'd' }}, undefined, 0, false);
+ shouldBeEqualToString('element.rel', 'a b c');
+
+ createElement('a b');
+ shouldThrow('element.relList.remove("a", "b", "")');
+
+ shouldBeEqualToString('element.rel', 'a b');
+ shouldThrow('element.relList.remove("a", {toString: function() { throw new Error("user error"); }}, "b")', '"Error: user error"');
+ shouldBeEqualToString('element.rel', 'a b');
+
+ shouldThrow('element.relList.remove("a", "b", "c d")');
+ shouldBeEqualToString('element.rel', 'a b');
+ shouldNotThrow('element.relList.remove()');
+
+ createElement('a b c');
+ observer = new WebKitMutationObserver(function() {});
+ observer.observe(element, {attributes: true});
+ element.relList.remove('a', 'c');
+ shouldBe('observer.takeRecords().length', '1');
+}
+
+debug('Tests relList for anchor element');
+type = 'a';
+test();
+debug('Tests relList for area element');
+type = 'area';
+test();
+debug('Tests relList for link element');
+type = 'link';
+test();
+
+</script>
+<script src=""
+</body>
+</html>
\ No newline at end of file
Modified: trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt (175027 => 175028)
--- trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt 2014-10-22 09:22:05 UTC (rev 175028)
@@ -27,6 +27,7 @@
PASS a["search"] is
PASS a["origin"] is file://
PASS a["text"] is nerget
+PASS a["relList"] is
PASS a["title"] is
PASS a["lang"] is
PASS a["translate"] is true
@@ -49,7 +50,7 @@
PASS a["style"] is [object CSSStyleDeclaration]
PASS a["id"] is foo
PASS a["offsetLeft"] is 8
-PASS a["offsetTop"] is 774
+PASS a["offsetTop"] is 789
PASS a["offsetWidth"] is 39
PASS a["offsetHeight"] is 18
PASS a["clientLeft"] is 0
Added: trunk/LayoutTests/perf/rel-list-remove-expected.txt (0 => 175028)
--- trunk/LayoutTests/perf/rel-list-remove-expected.txt (rev 0)
+++ trunk/LayoutTests/perf/rel-list-remove-expected.txt 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,8 @@
+Tests that relList remove is linear.
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
Added: trunk/LayoutTests/perf/rel-list-remove.html (0 => 175028)
--- trunk/LayoutTests/perf/rel-list-remove.html (rev 0)
+++ trunk/LayoutTests/perf/rel-list-remove.html 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,42 @@
+<script src=""
+<script>
+
+var element, rel, relToRemove, type;
+
+// Test 1 tests that remove is linear when there are N rels.
+
+function setupFunction1(magnitude)
+{
+ element = document.createElement(type);
+ relToRemove = 'b';
+ rel = Array(magnitude).join('a ') + relToRemove;
+}
+
+// Test 2 tests that remove is linear when the length of the rel is N.
+
+function setupFunction2(magnitude)
+{
+ element = document.createElement(type);
+ relToRemove = Array(magnitude + 1).join('a');
+ rel = relToRemove;
+}
+
+function test(magnitude)
+{
+ element.rel = rel;
+ element.relList.remove(relToRemove);
+}
+
+Magnitude.description('Tests that relList remove is linear.');
+type = 'a'
+Magnitude.run(setupFunction1, test, Magnitude.LINEAR);
+Magnitude.run(setupFunction2, test, Magnitude.LINEAR);
+type = 'area'
+Magnitude.run(setupFunction1, test, Magnitude.LINEAR);
+Magnitude.run(setupFunction2, test, Magnitude.LINEAR);
+type = 'link'
+Magnitude.run(setupFunction1, test, Magnitude.LINEAR);
+Magnitude.run(setupFunction2, test, Magnitude.LINEAR);
+
+</script>
+</body>
Modified: trunk/Source/WebCore/CMakeLists.txt (175027 => 175028)
--- trunk/Source/WebCore/CMakeLists.txt 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/CMakeLists.txt 2014-10-22 09:22:05 UTC (rev 175028)
@@ -1647,6 +1647,7 @@
html/RadioInputType.cpp
html/RadioNodeList.cpp
html/RangeInputType.cpp
+ html/RelList.cpp
html/ResetInputType.cpp
html/SearchInputType.cpp
html/StepRange.cpp
Modified: trunk/Source/WebCore/ChangeLog (175027 => 175028)
--- trunk/Source/WebCore/ChangeLog 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/ChangeLog 2014-10-22 09:22:05 UTC (rev 175028)
@@ -1,3 +1,52 @@
+2014-10-22 Dhi Aurrahman <[email protected]>
+
+ Add relList to the anchor, area and link elements
+ https://bugs.webkit.org/show_bug.cgi?id=137860
+
+ Reviewed by Darin Adler and Chris Dumez.
+
+ Add relList to reflect the rel content attribute for anchor[1],
+ area[2] and link[3] elements.
+
+ [1] https://html.spec.whatwg.org/multipage/semantics.html#dom-a-rellist
+ [2] https://html.spec.whatwg.org/multipage/embedded-content.html#dom-area-rellist
+ [3] https://html.spec.whatwg.org/multipage/semantics.html#dom-link-rellist
+
+ Tests: fast/dom/rel-list-gc.html
+ fast/dom/rel-list.html
+ perf/rel-list-remove.html
+
+ * CMakeLists.txt:
+ * WebCore.vcxproj/WebCore.vcxproj:
+ * WebCore.vcxproj/WebCore.vcxproj.filters:
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/SpaceSplitString.cpp:
+ (WebCore::SpaceSplitString::set):
+ * html/HTMLAnchorElement.cpp:
+ (WebCore::HTMLAnchorElement::parseAttribute):
+ (WebCore::HTMLAnchorElement::relList):
+ (WebCore::HTMLAnchorElement::setRel): Deleted.
+ * html/HTMLAnchorElement.h:
+ * html/HTMLAnchorElement.idl:
+ * html/HTMLAreaElement.idl:
+ * html/HTMLLinkElement.cpp:
+ (WebCore::HTMLLinkElement::parseAttribute):
+ (WebCore::HTMLLinkElement::relList):
+ * html/HTMLLinkElement.h:
+ * html/HTMLLinkElement.idl:
+ * html/RelList.cpp: Added.
+ (WebCore::RelList::RelList):
+ (WebCore::RelList::ref):
+ (WebCore::RelList::deref):
+ (WebCore::RelList::length):
+ (WebCore::RelList::item):
+ (WebCore::RelList::element):
+ (WebCore::RelList::updateRelAttribute):
+ (WebCore::RelList::containsInternal):
+ (WebCore::RelList::value):
+ (WebCore::RelList::setValue):
+ * html/RelList.h: Added.
+
2014-10-21 Andy Estes <[email protected]>
One more iOS build fix after r175013.
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (175027 => 175028)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2014-10-22 09:22:05 UTC (rev 175028)
@@ -16059,6 +16059,7 @@
<ClCompile Include="..\html\RadioInputType.cpp" />
<ClCompile Include="..\html\RadioNodeList.cpp" />
<ClCompile Include="..\html\RangeInputType.cpp" />
+ <ClCompile Include="..\html\RelList.cpp" />
<ClCompile Include="..\html\ResetInputType.cpp" />
<ClCompile Include="..\html\SearchInputType.cpp" />
<ClCompile Include="..\html\StepRange.cpp" />
@@ -20836,6 +20837,7 @@
<ClInclude Include="..\html\RadioInputType.h" />
<ClInclude Include="..\html\RadioNodeList.h" />
<ClInclude Include="..\html\RangeInputType.h" />
+ <ClInclude Include="..\html\RelList.h" />
<ClInclude Include="..\html\ResetInputType.h" />
<ClInclude Include="..\html\SearchInputType.h" />
<ClInclude Include="..\html\StepRange.h" />
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (175027 => 175028)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2014-10-22 09:22:05 UTC (rev 175028)
@@ -4053,6 +4053,9 @@
<ClCompile Include="..\html\RangeInputType.cpp">
<Filter>html</Filter>
</ClCompile>
+ <ClCompile Include="..\html\RelList.cpp">
+ <Filter>html</Filter>
+ </ClCompile>
<ClCompile Include="..\html\ResetInputType.cpp">
<Filter>html</Filter>
</ClCompile>
@@ -11208,6 +11211,9 @@
<ClInclude Include="..\html\RangeInputType.h">
<Filter>html</Filter>
</ClInclude>
+ <ClInclude Include="..\html\RelList.h">
+ <Filter>html</Filter>
+ </ClInclude>
<ClInclude Include="..\html\ResetInputType.h">
<Filter>html</Filter>
</ClInclude>
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (175027 => 175028)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2014-10-22 09:22:05 UTC (rev 175028)
@@ -4691,6 +4691,8 @@
B2ED97710B1F55CE00257D0F /* GraphicsContextCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2ED97700B1F55CE00257D0F /* GraphicsContextCG.cpp */; };
B2F34FE60E82F81400F627CD /* DNS.h in Headers */ = {isa = PBXBuildFile; fileRef = B2F34FE50E82F81400F627CD /* DNS.h */; settings = {ATTRIBUTES = (Private, ); }; };
B2F34FE90E82F82700F627CD /* DNSCFNet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2F34FE80E82F82700F627CD /* DNSCFNet.cpp */; };
+ B2F78CFD19F2F02D0049696C /* RelList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2F78CFB19F2F02D0049696C /* RelList.cpp */; };
+ B2F78CFE19F2F02D0049696C /* RelList.h in Headers */ = {isa = PBXBuildFile; fileRef = B2F78CFC19F2F02D0049696C /* RelList.h */; };
B2FA3D360AB75A6F000E5AC4 /* JSSVGAnimateColorElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2FA3C4E0AB75A6E000E5AC4 /* JSSVGAnimateColorElement.cpp */; };
B2FA3D370AB75A6F000E5AC4 /* JSSVGAnimateColorElement.h in Headers */ = {isa = PBXBuildFile; fileRef = B2FA3C4F0AB75A6E000E5AC4 /* JSSVGAnimateColorElement.h */; };
B2FA3D380AB75A6F000E5AC4 /* JSSVGAnimatedAngle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2FA3C500AB75A6E000E5AC4 /* JSSVGAnimatedAngle.cpp */; };
@@ -12061,6 +12063,8 @@
B2ED97700B1F55CE00257D0F /* GraphicsContextCG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContextCG.cpp; sourceTree = "<group>"; };
B2F34FE50E82F81400F627CD /* DNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNS.h; sourceTree = "<group>"; };
B2F34FE80E82F82700F627CD /* DNSCFNet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNSCFNet.cpp; sourceTree = "<group>"; };
+ B2F78CFB19F2F02D0049696C /* RelList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RelList.cpp; sourceTree = "<group>"; };
+ B2F78CFC19F2F02D0049696C /* RelList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RelList.h; sourceTree = "<group>"; };
B2FA3C4E0AB75A6E000E5AC4 /* JSSVGAnimateColorElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGAnimateColorElement.cpp; sourceTree = "<group>"; };
B2FA3C4F0AB75A6E000E5AC4 /* JSSVGAnimateColorElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSSVGAnimateColorElement.h; sourceTree = "<group>"; };
B2FA3C500AB75A6E000E5AC4 /* JSSVGAnimatedAngle.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGAnimatedAngle.cpp; sourceTree = "<group>"; };
@@ -17914,6 +17918,8 @@
B658FFA41522EFAA00DD5595 /* RadioNodeList.h */,
F55B3D991251F12D003EF269 /* RangeInputType.cpp */,
F55B3D9A1251F12D003EF269 /* RangeInputType.h */,
+ B2F78CFB19F2F02D0049696C /* RelList.cpp */,
+ B2F78CFC19F2F02D0049696C /* RelList.h */,
F55B3D9B1251F12D003EF269 /* ResetInputType.cpp */,
F55B3D9C1251F12D003EF269 /* ResetInputType.h */,
F55B3D9D1251F12D003EF269 /* SearchInputType.cpp */,
@@ -24670,6 +24676,7 @@
E157A8F118185425009F821D /* JSCryptoAlgorithmBuilder.h in Headers */,
E1C657131815F9DD00256CDD /* JSCryptoAlgorithmDictionary.h in Headers */,
E157A8E11817331C009F821D /* JSCryptoKey.h in Headers */,
+ B2F78CFE19F2F02D0049696C /* RelList.h in Headers */,
E1F80B8E183172B5007885C3 /* JSCryptoKeyPair.h in Headers */,
E125F85218283A5600D84CD9 /* JSCryptoKeySerializationJWK.h in Headers */,
E125F83E182411E700D84CD9 /* JSCryptoOperationData.h in Headers */,
@@ -27402,6 +27409,7 @@
CECADFC6153778FF00E37068 /* DictationAlternative.cpp in Sources */,
CECADFC8153778FF00E37068 /* DictationCommand.cpp in Sources */,
D0BD4F5C1408850F006839B6 /* DictationCommandIOS.cpp in Sources */,
+ B2F78CFD19F2F02D0049696C /* RelList.cpp in Sources */,
312D67B11535691F00563D0D /* Dictionary.cpp in Sources */,
FDAF19981513D131008DB0C3 /* DirectConvolver.cpp in Sources */,
49FC7A501444AF5F00A5D864 /* DisplayRefreshMonitor.cpp in Sources */,
Modified: trunk/Source/WebCore/dom/SpaceSplitString.cpp (175027 => 175028)
--- trunk/Source/WebCore/dom/SpaceSplitString.cpp 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/dom/SpaceSplitString.cpp 2014-10-22 09:22:05 UTC (rev 175028)
@@ -94,6 +94,10 @@
void SpaceSplitString::set(const AtomicString& inputString, bool shouldFoldCase)
{
+ if (inputString.isNull()) {
+ clear();
+ return;
+ }
m_data = SpaceSplitStringData::create(shouldFoldCase ? inputString.convertToASCIILowercase() : inputString);
}
Modified: trunk/Source/WebCore/html/HTMLAnchorElement.cpp (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLAnchorElement.cpp 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLAnchorElement.cpp 2014-10-22 09:22:05 UTC (rev 175028)
@@ -41,6 +41,7 @@
#include "MouseEvent.h"
#include "PingLoader.h"
#include "PlatformMouseEvent.h"
+#include "RelList.h"
#include "RenderImage.h"
#include "ResourceRequest.h"
#include "SVGImage.h"
@@ -261,8 +262,12 @@
invalidateCachedVisitedLinkHash();
} else if (name == nameAttr || name == titleAttr) {
// Do nothing.
- } else if (name == relAttr)
- setRel(value);
+ } else if (name == relAttr) {
+ if (SpaceSplitString::spaceSplitStringContainsValue(value, "noreferrer", true))
+ m_linkRelations |= RelationNoReferrer;
+ if (m_relList)
+ m_relList->updateRelAttribute(value);
+ }
else
HTMLElement::parseAttribute(name, value);
}
@@ -310,10 +315,11 @@
return m_linkRelations & relation;
}
-void HTMLAnchorElement::setRel(const String& value)
+DOMTokenList& HTMLAnchorElement::relList()
{
- if (SpaceSplitString::spaceSplitStringContainsValue(value, "noreferrer", true))
- m_linkRelations |= RelationNoReferrer;
+ if (!m_relList)
+ m_relList = std::make_unique<RelList>(*this);
+ return *m_relList;
}
const AtomicString& HTMLAnchorElement::name() const
Modified: trunk/Source/WebCore/html/HTMLAnchorElement.h (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLAnchorElement.h 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLAnchorElement.h 2014-10-22 09:22:05 UTC (rev 175028)
@@ -30,6 +30,8 @@
namespace WebCore {
+class RelList;
+
// Link relation bitmask values.
// FIXME: Uncomment as the various link relations are implemented.
enum {
@@ -97,11 +99,12 @@
virtual bool willRespondToMouseClickEvents() override;
bool hasRel(uint32_t relation) const;
- void setRel(const String&);
LinkHash visitedLinkHash() const;
void invalidateCachedVisitedLinkHash() { m_cachedVisitedLinkHash = 0; }
+ DOMTokenList& relList();
+
protected:
HTMLAnchorElement(const QualifiedName&, Document&);
@@ -140,6 +143,8 @@
bool m_wasShiftKeyDownOnMouseDown : 1;
uint32_t m_linkRelations : 30;
mutable LinkHash m_cachedVisitedLinkHash;
+
+ std::unique_ptr<RelList> m_relList;
};
inline LinkHash HTMLAnchorElement::visitedLinkHash() const
Modified: trunk/Source/WebCore/html/HTMLAnchorElement.idl (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLAnchorElement.idl 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLAnchorElement.idl 2014-10-22 09:22:05 UTC (rev 175028)
@@ -66,5 +66,7 @@
// Objective-C extension:
readonly attribute URL absoluteLinkURL;
#endif
+
+ readonly attribute DOMTokenList relList;
};
Modified: trunk/Source/WebCore/html/HTMLAreaElement.idl (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLAreaElement.idl 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLAreaElement.idl 2014-10-22 09:22:05 UTC (rev 175028)
@@ -24,6 +24,7 @@
[Reflect, URL] attribute DOMString href;
[Reflect] attribute boolean noHref;
[Reflect] attribute DOMString ping;
+ [Reflect] attribute DOMString rel;
[Reflect] attribute DOMString shape;
[Reflect] attribute DOMString target;
@@ -43,5 +44,7 @@
// Objective-C extension:
readonly attribute URL absoluteLinkURL;
#endif
+
+ readonly attribute DOMTokenList relList;
};
Modified: trunk/Source/WebCore/html/HTMLLinkElement.cpp (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLLinkElement.cpp 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLLinkElement.cpp 2014-10-22 09:22:05 UTC (rev 175028)
@@ -46,6 +46,7 @@
#include "MediaQueryEvaluator.h"
#include "MouseEvent.h"
#include "Page.h"
+#include "RelList.h"
#include "RenderStyle.h"
#include "SecurityOrigin.h"
#include "Settings.h"
@@ -139,6 +140,8 @@
{
if (name == relAttr) {
m_relAttribute = LinkRelAttribute(value);
+ if (m_relList)
+ m_relList->updateRelAttribute(value);
process();
} else if (name == hrefAttr) {
bool wasLink = isLink();
@@ -381,6 +384,13 @@
linkLoadingErrored();
}
+DOMTokenList& HTMLLinkElement::relList()
+{
+ if (!m_relList)
+ m_relList = std::make_unique<RelList>(*this);
+ return *m_relList;
+}
+
void HTMLLinkElement::notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred)
{
if (m_firedLoad)
Modified: trunk/Source/WebCore/html/HTMLLinkElement.h (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLLinkElement.h 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLLinkElement.h 2014-10-22 09:22:05 UTC (rev 175028)
@@ -37,6 +37,7 @@
namespace WebCore {
class HTMLLinkElement;
+class RelList;
class URL;
template<typename T> class EventSender;
@@ -71,6 +72,8 @@
void dispatchPendingEvent(LinkEventSender*);
static void dispatchPendingLoadEvents();
+ DOMTokenList& relList();
+
private:
virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
@@ -100,7 +103,6 @@
virtual void defaultEventHandler(Event*) override;
void handleClick(Event&);
-private:
HTMLLinkElement(const QualifiedName&, Document&, bool createdByParser);
virtual void addSubresourceAttributeURLs(ListHashSet<URL>&) const override;
@@ -138,6 +140,8 @@
bool m_loadedSheet;
PendingSheetType m_pendingSheetType;
+
+ std::unique_ptr<RelList> m_relList;
};
} //namespace
Modified: trunk/Source/WebCore/html/HTMLLinkElement.idl (175027 => 175028)
--- trunk/Source/WebCore/html/HTMLLinkElement.idl 2014-10-22 07:29:26 UTC (rev 175027)
+++ trunk/Source/WebCore/html/HTMLLinkElement.idl 2014-10-22 09:22:05 UTC (rev 175028)
@@ -40,5 +40,7 @@
// Objective-C extension:
readonly attribute URL absoluteLinkURL;
#endif
+
+ readonly attribute DOMTokenList relList;
};
Added: trunk/Source/WebCore/html/RelList.cpp (0 => 175028)
--- trunk/Source/WebCore/html/RelList.cpp (rev 0)
+++ trunk/Source/WebCore/html/RelList.cpp 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Dhi Aurrahman <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RelList.h"
+
+#include "Element.h"
+#include "HTMLNames.h"
+
+namespace WebCore {
+
+RelList::RelList(Element& element)
+ : m_element(element)
+ , m_relAttributeValue(SpaceSplitString(element.fastGetAttribute(HTMLNames::relAttr), false))
+{
+}
+
+void RelList::ref()
+{
+ m_element.ref();
+}
+
+void RelList::deref()
+{
+ m_element.deref();
+}
+
+unsigned RelList::length() const
+{
+ return m_relAttributeValue.size();
+}
+
+const AtomicString RelList::item(unsigned index) const
+{
+ if (index >= length())
+ return nullAtom;
+ return m_relAttributeValue[index];
+}
+
+Element* RelList::element() const
+{
+ return &m_element;
+}
+
+void RelList::updateRelAttribute(const AtomicString& value)
+{
+ m_relAttributeValue.set(value, false);
+}
+
+bool RelList::containsInternal(const AtomicString& token) const
+{
+ return m_relAttributeValue.contains(token);
+}
+
+AtomicString RelList::value() const
+{
+ return m_element.fastGetAttribute(HTMLNames::relAttr);
+}
+
+void RelList::setValue(const AtomicString& value)
+{
+ m_element.setAttribute(HTMLNames::relAttr, value);
+}
+
+} // namespace WebCore
+
Added: trunk/Source/WebCore/html/RelList.h (0 => 175028)
--- trunk/Source/WebCore/html/RelList.h (rev 0)
+++ trunk/Source/WebCore/html/RelList.h 2014-10-22 09:22:05 UTC (rev 175028)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 Dhi Aurrahman <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RelList_h
+#define RelList_h
+
+#include "DOMTokenList.h"
+#include "SpaceSplitString.h"
+
+namespace WebCore {
+
+class Element;
+
+class RelList final : public DOMTokenList {
+public:
+ RelList(Element&);
+ void updateRelAttribute(const AtomicString&);
+
+private:
+ virtual void ref() override;
+ virtual void deref() override;
+ virtual unsigned length() const override;
+ virtual const AtomicString item(unsigned index) const override;
+ virtual Element* element() const override;
+ virtual bool containsInternal(const AtomicString&) const override;
+ virtual AtomicString value() const override;
+ virtual void setValue(const AtomicString&) override;
+
+ Element& m_element;
+ mutable SpaceSplitString m_relAttributeValue;
+};
+
+} // namespace WebCore
+
+#endif // RelList_h
+