[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc
arv at chromium.org
arv at chromium.org
Wed Dec 22 13:49:30 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit e4f1cb58af44e3cf3e3eff5e378ab4cc360da08f
Author: arv at chromium.org <arv at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Sep 27 23:12:11 2010 +0000
2010-09-27 Erik Arvidsson <arv at chromium.org>
Reviewed by Darin Adler.
Implement HTML 5's HTMLElement.classList property
https://bugs.webkit.org/show_bug.cgi?id=20709
* fast/dom/HTMLElement/class-list-expected.txt: Added.
* fast/dom/HTMLElement/class-list-gc-expected.txt: Added.
* fast/dom/HTMLElement/class-list-gc.html: Added.
* fast/dom/HTMLElement/class-list-quirks-expected.txt: Added.
* fast/dom/HTMLElement/class-list-quirks.html: Added.
* fast/dom/HTMLElement/class-list.html: Added.
* fast/dom/HTMLElement/script-tests/class-list-gc.js: Added.
(gc):
* fast/dom/HTMLElement/script-tests/class-list.js: Added.
(createElement):
* fast/dom/Window/window-properties-expected.txt:
* fast/dom/Window/window-property-descriptors-expected.txt:
* fast/dom/prototype-inheritance-2-expected.txt:
* fast/dom/prototype-inheritance-expected.txt:
* fast/js/global-constructors-expected.txt:
* perf/class-list-remove-expected.txt: Added.
* perf/class-list-remove.html: Added.
2010-09-27 Erik Arvidsson <arv at chromium.org>
Reviewed by Darin Adler.
Implement HTML 5's HTMLElement.classList property
https://bugs.webkit.org/show_bug.cgi?id=20709
This adds a DOMTokenList class that is used for the classList property. DOMTokenList uses a SpaceSplitString for fast
contains check. In standards mode the existing classNames is used but in quirks mode we use an internal SpaceSplitString
because classList is always case sensitive.
Tests: fast/dom/HTMLElement/class-list-gc.html
fast/dom/HTMLElement/class-list-quirks.html
fast/dom/HTMLElement/class-list.html
perf/class-list-remove.html
* Android.derived.jscbindings.mk:
* Android.derived.v8bindings.mk:
* Android.jscbindings.mk:
* CMakeLists.txt:
* DerivedSources.cpp:
* DerivedSources.make:
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pri:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* bindings/gobject/GNUmakefile.am:
* bindings/js/JSElementCustom.cpp:
(WebCore::JSElement::markChildren): Make sure that we keep the wrapper while the element is alive.
* bindings/scripts/CodeGeneratorJS.pm: DOMTokenList has a string indexed getter.
* bindings/scripts/CodeGeneratorV8.pm:
* bindings/v8/custom/V8DOMTokenListCustom.cpp: Added.
(WebCore::toV8):
* dom/Element.cpp:
(WebCore::Element::classList):
(WebCore::Element::optionalClassList):
* dom/Element.h:
* dom/ElementRareData.h: This now has an OwnPtr to a ClassList if the Element::classList is ever called.
* dom/SpaceSplitString.h:
(WebCore::SpaceSplitString::isNull):
* dom/StyledElement.cpp:
(WebCore::StyledElement::classAttributeChanged): Update the classList if it exists.
* dom/StyledElement.h:
* html/DOMTokenList.cpp: Added.
(WebCore::validateToken):
(WebCore::DOMTokenList::DOMTokenList):
(WebCore::DOMTokenList::ref):
(WebCore::DOMTokenList::deref):
(WebCore::DOMTokenList::length):
(WebCore::DOMTokenList::item):
(WebCore::DOMTokenList::contains):
(WebCore::DOMTokenList::containsInternal): The internal methods do no validation of the token.
(WebCore::DOMTokenList::add):
(WebCore::DOMTokenList::addInternal):
(WebCore::DOMTokenList::remove):
(WebCore::DOMTokenList::removeInternal):
(WebCore::DOMTokenList::toggle):
(WebCore::DOMTokenList::toString):
(WebCore::DOMTokenList::reset):
(WebCore::DOMTokenList::classNames):
* html/DOMTokenList.h: Added.
(WebCore::DOMTokenList::create):
(WebCore::DOMTokenList::element):
* html/DOMTokenList.idl: Added.
* html/HTMLElement.idl:
* page/DOMWindow.cpp:
* page/DOMWindow.idl:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68440 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 3c691c4..1f36135 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,28 @@
+2010-09-27 Erik Arvidsson <arv at chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Implement HTML 5's HTMLElement.classList property
+ https://bugs.webkit.org/show_bug.cgi?id=20709
+
+ * fast/dom/HTMLElement/class-list-expected.txt: Added.
+ * fast/dom/HTMLElement/class-list-gc-expected.txt: Added.
+ * fast/dom/HTMLElement/class-list-gc.html: Added.
+ * fast/dom/HTMLElement/class-list-quirks-expected.txt: Added.
+ * fast/dom/HTMLElement/class-list-quirks.html: Added.
+ * fast/dom/HTMLElement/class-list.html: Added.
+ * fast/dom/HTMLElement/script-tests/class-list-gc.js: Added.
+ (gc):
+ * fast/dom/HTMLElement/script-tests/class-list.js: Added.
+ (createElement):
+ * fast/dom/Window/window-properties-expected.txt:
+ * fast/dom/Window/window-property-descriptors-expected.txt:
+ * fast/dom/prototype-inheritance-2-expected.txt:
+ * fast/dom/prototype-inheritance-expected.txt:
+ * fast/js/global-constructors-expected.txt:
+ * perf/class-list-remove-expected.txt: Added.
+ * perf/class-list-remove.html: Added.
+
2010-09-27 David Hyatt <hyatt at apple.com>
Reviewed by Sam Weinig.
diff --git a/LayoutTests/fast/dom/HTMLElement/class-list-expected.txt b/LayoutTests/fast/dom/HTMLElement/class-list-expected.txt
new file mode 100644
index 0000000..bd0e8a4
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/class-list-expected.txt
@@ -0,0 +1,68 @@
+Tests the classList attribute and its properties.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Tests from http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/
+PASS String(element.classList) is "x"
+PASS element.classList.length is 0
+PASS element.classList.length is 1
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.className is "x"
+PASS element.className is "x"
+PASS element.className is "x x"
+PASS element.className is "y x"
+PASS element.className is ""
+PASS element.className is ""
+PASS element.className is " y y "
+PASS element.className is "y"
+Testing add in presence of trailing white spaces.
+PASS element.className is "x y"
+PASS element.className is "x y"
+PASS element.className is " y"
+Test invalid tokens
+PASS element.classList.contains('') threw expected DOMException with code 12
+PASS element.classList.contains('x y') threw expected DOMException with code 5
+PASS element.classList.add('') threw expected DOMException with code 12
+PASS element.classList.add('x y') threw expected DOMException with code 5
+PASS element.classList.remove('') threw expected DOMException with code 12
+PASS element.classList.remove('x y') threw expected DOMException with code 5
+PASS element.classList.toggle('') threw expected DOMException with code 12
+PASS element.classList.toggle('x y') threw expected DOMException with code 5
+Indexing
+PASS element.classList[0] is "x"
+PASS element.classList.item(0) is "x"
+PASS element.classList[1] is "x"
+PASS element.classList.item(1) is "x"
+PASS element.classList[1] is "y"
+PASS element.classList.item(1) is "y"
+PASS element.classList[0] is null
+PASS element.classList.item(0) is null
+PASS element.classList[4] is null
+PASS element.classList.item(4) is null
+PASS element.classList[-1] is undefined.
+PASS element.classList.item(-1) is null
+Test case since DOMTokenList is case sensitive
+PASS element.classList.contains('x') is true
+PASS element.classList.contains('X') is false
+PASS element.classList[0] is "x"
+PASS element.classList.contains('X') is true
+PASS element.classList.contains('x') is false
+PASS element.classList[0] is "X"
+Testing whitespace
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+DOMTokenList presence and type
+PASS 'undefined' != typeof DOMTokenList is true
+PASS typeof DOMTokenList.prototype is "object"
+PASS typeof element.classList is "object"
+PASS element.classList.constructor is DOMTokenList
+PASS element.classList === element.classList is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLElement/class-list-gc-expected.txt b/LayoutTests/fast/dom/HTMLElement/class-list-gc-expected.txt
new file mode 100644
index 0000000..e1c25fb
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/class-list-gc-expected.txt
@@ -0,0 +1,11 @@
+This tests that properties on the classList persists GC.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS d.classList.life is 42
+PASS d.classList.life is 42
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLElement/class-list-gc.html b/LayoutTests/fast/dom/HTMLElement/class-list-gc.html
new file mode 100644
index 0000000..4c5efad
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/class-list-gc.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/class-list-gc.js"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/HTMLElement/class-list-quirks-expected.txt b/LayoutTests/fast/dom/HTMLElement/class-list-quirks-expected.txt
new file mode 100644
index 0000000..bd0e8a4
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/class-list-quirks-expected.txt
@@ -0,0 +1,68 @@
+Tests the classList attribute and its properties.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Tests from http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/
+PASS String(element.classList) is "x"
+PASS element.classList.length is 0
+PASS element.classList.length is 1
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.className is "x"
+PASS element.className is "x"
+PASS element.className is "x x"
+PASS element.className is "y x"
+PASS element.className is ""
+PASS element.className is ""
+PASS element.className is " y y "
+PASS element.className is "y"
+Testing add in presence of trailing white spaces.
+PASS element.className is "x y"
+PASS element.className is "x y"
+PASS element.className is " y"
+Test invalid tokens
+PASS element.classList.contains('') threw expected DOMException with code 12
+PASS element.classList.contains('x y') threw expected DOMException with code 5
+PASS element.classList.add('') threw expected DOMException with code 12
+PASS element.classList.add('x y') threw expected DOMException with code 5
+PASS element.classList.remove('') threw expected DOMException with code 12
+PASS element.classList.remove('x y') threw expected DOMException with code 5
+PASS element.classList.toggle('') threw expected DOMException with code 12
+PASS element.classList.toggle('x y') threw expected DOMException with code 5
+Indexing
+PASS element.classList[0] is "x"
+PASS element.classList.item(0) is "x"
+PASS element.classList[1] is "x"
+PASS element.classList.item(1) is "x"
+PASS element.classList[1] is "y"
+PASS element.classList.item(1) is "y"
+PASS element.classList[0] is null
+PASS element.classList.item(0) is null
+PASS element.classList[4] is null
+PASS element.classList.item(4) is null
+PASS element.classList[-1] is undefined.
+PASS element.classList.item(-1) is null
+Test case since DOMTokenList is case sensitive
+PASS element.classList.contains('x') is true
+PASS element.classList.contains('X') is false
+PASS element.classList[0] is "x"
+PASS element.classList.contains('X') is true
+PASS element.classList.contains('x') is false
+PASS element.classList[0] is "X"
+Testing whitespace
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+PASS element.classList.length is 2
+DOMTokenList presence and type
+PASS 'undefined' != typeof DOMTokenList is true
+PASS typeof DOMTokenList.prototype is "object"
+PASS typeof element.classList is "object"
+PASS element.classList.constructor is DOMTokenList
+PASS element.classList === element.classList is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLElement/class-list-quirks.html b/LayoutTests/fast/dom/HTMLElement/class-list-quirks.html
new file mode 100644
index 0000000..fd876a1
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/class-list-quirks.html
@@ -0,0 +1,13 @@
+<!-- Quirks Mode -->
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/class-list.js"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/HTMLElement/class-list.html b/LayoutTests/fast/dom/HTMLElement/class-list.html
new file mode 100644
index 0000000..61df243
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/class-list.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/class-list.js"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/HTMLElement/script-tests/class-list-gc.js b/LayoutTests/fast/dom/HTMLElement/script-tests/class-list-gc.js
new file mode 100644
index 0000000..0e3161a
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/script-tests/class-list-gc.js
@@ -0,0 +1,30 @@
+description('This tests that properties on the classList persists GC.');
+
+function gc()
+{
+ if (window.GCController)
+ return GCController.collect();
+
+ for (var i = 0; i < 10000; i++) {
+ var s = new String;
+ }
+}
+
+var d = document.createElement('div');
+
+// Ensure the classList is created.
+var classList = d.classList;
+
+// Set a custom property.
+d.classList.life = 42;
+shouldEvaluateTo('d.classList.life', 42);
+
+// Null out reference to the dataset.
+classList = null;
+
+gc();
+
+// Test that the classList wrapper persisted the GC and still has the custom property.
+shouldEvaluateTo('d.classList.life', 42);
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/dom/HTMLElement/script-tests/class-list.js b/LayoutTests/fast/dom/HTMLElement/script-tests/class-list.js
new file mode 100644
index 0000000..2a34dfa
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLElement/script-tests/class-list.js
@@ -0,0 +1,238 @@
+description('Tests the classList attribute and its properties.');
+
+var element;
+
+function createElement(className)
+{
+ element = document.createElement('p');
+ element.className = className;
+}
+
+debug('Tests from http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/setting/001.htm
+// Firefox throws here but WebKit does not throw on setting readonly idl
+// attributes.
+createElement('x');
+try {
+ element.classList = 'y';
+ shouldBeEqualToString('String(element.classList)', 'x');
+} catch (ex) {
+ testPassed('Throwing on set is acceptable');
+}
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/001.htm
+createElement('');
+shouldEvaluateTo('element.classList.length', 0);
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/002.htm
+createElement('x');
+shouldEvaluateTo('element.classList.length', 1);
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/003.htm
+createElement('x x');
+shouldEvaluateTo('element.classList.length', 2);
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/004.htm
+createElement('x y');
+shouldEvaluateTo('element.classList.length', 2);
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/005.htm
+createElement('');
+element.classList.add('x');
+shouldBeEqualToString('element.className', 'x');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/006.htm
+createElement('x');
+element.classList.add('x');
+shouldBeEqualToString('element.className', 'x');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/007.htm
+createElement('x x');
+element.classList.add('x');
+shouldBeEqualToString('element.className', 'x x');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/008.htm
+createElement('y');
+element.classList.add('x');
+shouldBeEqualToString('element.className', 'y x');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/009.htm
+createElement('');
+element.classList.remove('x');
+shouldBeEqualToString('element.className', '');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/010.htm
+createElement('x');
+element.classList.remove('x');
+shouldBeEqualToString('element.className', '');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/011.htm
+createElement(' y x y ');
+element.classList.remove('x');
+shouldBeEqualToString('element.className', ' y y ');
+
+// http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/012.htm
+createElement(' x y x ');
+element.classList.remove('x');
+shouldBeEqualToString('element.className', 'y');
+
+debug('Testing add in presence of trailing white spaces.');
+
+createElement('x ');
+element.classList.add('y');
+shouldBeEqualToString('element.className', 'x y');
+
+createElement('x\t');
+element.classList.add('y');
+shouldBeEqualToString('element.className', 'x\t y');
+
+createElement(' ');
+element.classList.add('y');
+shouldBeEqualToString('element.className', ' y');
+
+
+debug('Test invalid tokens');
+
+// Testing exception due to invalid token
+
+// shouldThrow from js-test-pre.js is not sufficient.
+function shouldThrowDOMException(f, ec)
+{
+ try {
+ f();
+ testFailed('Expected an exception');
+ } catch (ex) {
+ if (!(ex instanceof DOMException)) {
+ testFailed('Exception is not an instance of DOMException, found: ' +
+ Object.toString.call(ex));
+ return;
+ }
+ if (ec !== ex.code) {
+ testFailed('Wrong exception code: ' + ex.code);
+ return;
+ }
+ }
+ var formattedFunction = String(f).replace(/^function.+\{\s*/m, '').
+ replace(/;?\s+\}/m, '');
+ testPassed(formattedFunction + ' threw expected DOMException with code ' + ec);
+}
+
+createElement('x');
+shouldThrowDOMException(function() {
+ element.classList.contains('');
+}, DOMException.SYNTAX_ERR);
+
+createElement('x y');
+shouldThrowDOMException(function() {
+ element.classList.contains('x y');
+}, DOMException.INVALID_CHARACTER_ERR);
+
+createElement('');
+shouldThrowDOMException(function() {
+ element.classList.add('');
+}, DOMException.SYNTAX_ERR);
+
+createElement('');
+shouldThrowDOMException(function() {
+ element.classList.add('x y');
+}, DOMException.INVALID_CHARACTER_ERR);
+
+createElement('');
+shouldThrowDOMException(function() {
+ element.classList.remove('');
+}, DOMException.SYNTAX_ERR);
+
+createElement('');
+shouldThrowDOMException(function() {
+ element.classList.remove('x y');
+}, DOMException.INVALID_CHARACTER_ERR);
+
+createElement('');
+shouldThrowDOMException(function() {
+ element.classList.toggle('');
+}, DOMException.SYNTAX_ERR);
+
+createElement('x y');
+shouldThrowDOMException(function() {
+ element.classList.toggle('x y');
+}, DOMException.INVALID_CHARACTER_ERR);
+
+
+debug('Indexing');
+
+createElement('x');
+shouldBeEqualToString('element.classList[0]', 'x');
+shouldBeEqualToString('element.classList.item(0)', 'x');
+
+createElement('x x');
+shouldBeEqualToString('element.classList[1]', 'x');
+shouldBeEqualToString('element.classList.item(1)', 'x');
+
+createElement('x y');
+shouldBeEqualToString('element.classList[1]', 'y');
+shouldBeEqualToString('element.classList.item(1)', 'y');
+
+createElement('');
+shouldBeNull('element.classList[0]');
+shouldBeNull('element.classList.item(0)');
+
+createElement('x y z');
+shouldBeNull('element.classList[4]');
+shouldBeNull('element.classList.item(4)');
+shouldBeUndefined('element.classList[-1]'); // Not a valid index so should not trigger item().
+shouldBeNull('element.classList.item(-1)');
+
+debug('Test case since DOMTokenList is case sensitive');
+
+createElement('x');
+shouldBeTrue('element.classList.contains(\'x\')');
+shouldBeFalse('element.classList.contains(\'X\')');
+shouldBeEqualToString('element.classList[0]', 'x');
+
+createElement('X');
+shouldBeTrue('element.classList.contains(\'X\')');
+shouldBeFalse('element.classList.contains(\'x\')');
+shouldBeEqualToString('element.classList[0]', 'X');
+
+
+debug('Testing whitespace');
+// U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF),
+// U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN (CR)
+
+createElement('x\u0020y');
+shouldEvaluateTo('element.classList.length', 2);
+
+createElement('x\u0009y');
+shouldEvaluateTo('element.classList.length', 2);
+
+createElement('x\u000Ay');
+shouldEvaluateTo('element.classList.length', 2);
+
+createElement('x\u000Cy');
+shouldEvaluateTo('element.classList.length', 2);
+
+createElement('x\u000Dy');
+shouldEvaluateTo('element.classList.length', 2);
+
+
+debug('DOMTokenList presence and type');
+
+
+// Safari returns object
+// Firefox returns object
+// IE8 returns object
+// Chrome returns function
+// assertEquals('object', typeof DOMTokenList);
+shouldBeTrue('\'undefined\' != typeof DOMTokenList');
+
+shouldBeEqualToString('typeof DOMTokenList.prototype', 'object');
+
+createElement('x');
+shouldBeEqualToString('typeof element.classList', 'object');
+
+shouldEvaluateTo('element.classList.constructor', 'DOMTokenList');
+
+shouldBeTrue('element.classList === element.classList');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/dom/Window/window-properties-expected.txt b/LayoutTests/fast/dom/Window/window-properties-expected.txt
index b5455de..cc1d0be 100644
--- a/LayoutTests/fast/dom/Window/window-properties-expected.txt
+++ b/LayoutTests/fast/dom/Window/window-properties-expected.txt
@@ -561,6 +561,14 @@ window.DOMStringList.prototype.contains [function]
window.DOMStringList.prototype.item [function]
window.DOMStringMap [object DOMStringMapConstructor]
window.DOMStringMap.prototype [object DOMStringMapPrototype]
+window.DOMTokenList [object DOMTokenListConstructor]
+window.DOMTokenList.prototype [object DOMTokenListPrototype]
+window.DOMTokenList.prototype.add [function]
+window.DOMTokenList.prototype.contains [function]
+window.DOMTokenList.prototype.item [function]
+window.DOMTokenList.prototype.remove [function]
+window.DOMTokenList.prototype.toString [function]
+window.DOMTokenList.prototype.toggle [function]
window.Date [function]
window.Document [object DocumentConstructor]
window.Document.prototype [object DocumentPrototype]
diff --git a/LayoutTests/fast/dom/Window/window-property-descriptors-expected.txt b/LayoutTests/fast/dom/Window/window-property-descriptors-expected.txt
index 08d6664..f5e763f 100644
--- a/LayoutTests/fast/dom/Window/window-property-descriptors-expected.txt
+++ b/LayoutTests/fast/dom/Window/window-property-descriptors-expected.txt
@@ -40,6 +40,7 @@ PASS typeof Object.getOwnPropertyDescriptor(window, 'DOMImplementation') is 'obj
PASS typeof Object.getOwnPropertyDescriptor(window, 'DOMParser') is 'object'
PASS typeof Object.getOwnPropertyDescriptor(window, 'DOMStringList') is 'object'
PASS typeof Object.getOwnPropertyDescriptor(window, 'DOMStringMap') is 'object'
+PASS typeof Object.getOwnPropertyDescriptor(window, 'DOMTokenList') is 'object'
PASS typeof Object.getOwnPropertyDescriptor(window, 'Date') is 'object'
PASS typeof Object.getOwnPropertyDescriptor(window, 'Document') is 'object'
PASS typeof Object.getOwnPropertyDescriptor(window, 'DocumentFragment') is 'object'
diff --git a/LayoutTests/fast/dom/prototype-inheritance-2-expected.txt b/LayoutTests/fast/dom/prototype-inheritance-2-expected.txt
index 1d1f5c5..3451d16 100644
--- a/LayoutTests/fast/dom/prototype-inheritance-2-expected.txt
+++ b/LayoutTests/fast/dom/prototype-inheritance-2-expected.txt
@@ -77,6 +77,9 @@ PASS DOMImplementationPrototype from inner.document.forms.testForm.0.ownerDocume
PASS DOMStringMap from inner.document.forms.testForm.0.dataset
PASS DOMStringMapConstructor from inner.document.forms.testForm.0.dataset.constructor
PASS DOMStringMapPrototype from inner.document.forms.testForm.0.dataset.__proto__
+PASS DOMTokenList from inner.document.forms.testForm.0.0.classList
+PASS DOMTokenListConstructor from inner.document.forms.testForm.0.classList.constructor
+PASS DOMTokenListPrototype from inner.document.forms.testForm.0.0.classList.__proto__
PASS DOMWindow from inner
PASS DOMWindowPrototype from inner.document.forms.testForm.0.ownerDocument.defaultView.__proto__
PASS DocumentPrototype from inner.document.forms.testForm.0.ownerDocument.__proto__.__proto__
diff --git a/LayoutTests/fast/dom/prototype-inheritance-expected.txt b/LayoutTests/fast/dom/prototype-inheritance-expected.txt
index 3b45ce8..fa6476a 100644
--- a/LayoutTests/fast/dom/prototype-inheritance-expected.txt
+++ b/LayoutTests/fast/dom/prototype-inheritance-expected.txt
@@ -77,6 +77,8 @@ PASS inner.DOMStringList.isInner is true
PASS inner.DOMStringList.constructor.isInner is true
PASS inner.DOMStringMap.isInner is true
PASS inner.DOMStringMap.constructor.isInner is true
+PASS inner.DOMTokenList.isInner is true
+PASS inner.DOMTokenList.constructor.isInner is true
PASS inner.Date.isInner is true
PASS inner.Date.constructor.isInner is true
PASS inner.Document.isInner is true
diff --git a/LayoutTests/fast/js/global-constructors-expected.txt b/LayoutTests/fast/js/global-constructors-expected.txt
index 97893da..2143b86 100644
--- a/LayoutTests/fast/js/global-constructors-expected.txt
+++ b/LayoutTests/fast/js/global-constructors-expected.txt
@@ -38,6 +38,7 @@ PASS DOMImplementation.toString() is '[object DOMImplementationConstructor]'
PASS DOMParser.toString() is '[object DOMParserConstructor]'
PASS DOMStringList.toString() is '[object DOMStringListConstructor]'
PASS DOMStringMap.toString() is '[object DOMStringMapConstructor]'
+PASS DOMTokenList.toString() is '[object DOMTokenListConstructor]'
PASS Document.toString() is '[object DocumentConstructor]'
PASS DocumentFragment.toString() is '[object DocumentFragmentConstructor]'
PASS DocumentType.toString() is '[object DocumentTypeConstructor]'
diff --git a/LayoutTests/perf/class-list-remove-expected.txt b/LayoutTests/perf/class-list-remove-expected.txt
new file mode 100644
index 0000000..2e38133
--- /dev/null
+++ b/LayoutTests/perf/class-list-remove-expected.txt
@@ -0,0 +1,4 @@
+Tests that classList remove is linear.
+PASS
+PASS
+
diff --git a/LayoutTests/perf/class-list-remove.html b/LayoutTests/perf/class-list-remove.html
new file mode 100644
index 0000000..f03e9ba
--- /dev/null
+++ b/LayoutTests/perf/class-list-remove.html
@@ -0,0 +1,39 @@
+<script src="../resources/magnitude-perf.js"></script>
+<script>
+
+var element, s;
+
+// Test 1 tests that remove is linear when there are N class names.
+
+function setupFunction1(magnitude)
+{
+ s = 'b';
+ element = document.createElement('div');
+ element.className = Array(magnitude).join('a ') + s;
+}
+
+function test1(magnitude)
+{
+ element.classList.remove(s);
+}
+
+// Test 2 tests that remove is linear when the length of the class name is N.
+
+function setupFunction2(magnitude)
+{
+ element = document.createElement('div');
+}
+
+function test2(magnitude)
+{
+ var s = Array(magnitude + 1).join('a');
+ element.className = s;
+ element.classList.remove(s);
+}
+
+Magnitude.description('Tests that classList remove is linear.');
+Magnitude.run(setupFunction1, test1, Magnitude.LINEAR);
+Magnitude.run(setupFunction2, test2, Magnitude.LINEAR);
+
+</script>
+</body>
diff --git a/WebCore/Android.derived.jscbindings.mk b/WebCore/Android.derived.jscbindings.mk
index 486d8cd..a927f11 100644
--- a/WebCore/Android.derived.jscbindings.mk
+++ b/WebCore/Android.derived.jscbindings.mk
@@ -159,6 +159,7 @@ GEN := \
$(intermediates)/html/JSBlob.h \
$(intermediates)/html/JSBlobBuilder.h \
$(intermediates)/html/JSDOMFormData.h \
+ $(intermediates)/html/JSDOMTokenList.h \
$(intermediates)/html/JSDataGridColumn.h \
$(intermediates)/html/JSDataGridColumnList.h \
$(intermediates)/html/JSFile.h \
diff --git a/WebCore/Android.derived.v8bindings.mk b/WebCore/Android.derived.v8bindings.mk
index 9b8f22c..a73157d 100644
--- a/WebCore/Android.derived.v8bindings.mk
+++ b/WebCore/Android.derived.v8bindings.mk
@@ -140,6 +140,7 @@ $(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/bindings/%.cpp : $(intermediates)
GEN := \
$(intermediates)/bindings/V8Blob.h \
$(intermediates)/bindings/V8BlobBuilder.h \
+ $(intermediates)/bindings/V8DOMTokenList.h \
$(intermediates)/bindings/V8DataGridColumn.h \
$(intermediates)/bindings/V8DataGridColumnList.h \
$(intermediates)/bindings/V8File.h \
diff --git a/WebCore/Android.jscbindings.mk b/WebCore/Android.jscbindings.mk
index e07ed1e..0816113 100644
--- a/WebCore/Android.jscbindings.mk
+++ b/WebCore/Android.jscbindings.mk
@@ -83,6 +83,7 @@ LOCAL_SRC_FILES += \
bindings/js/JSDOMBinding.cpp \
bindings/js/JSDOMFormDataCustom.cpp \
bindings/js/JSDOMGlobalObject.cpp \
+ bindings/js/JSDOMTokenList.cpp \
bindings/js/JSDOMWindowBase.cpp \
bindings/js/JSDOMWindowCustom.cpp \
bindings/js/JSDOMWindowShell.cpp \
diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
index faed8ee..50f64cf 100644
--- a/WebCore/CMakeLists.txt
+++ b/WebCore/CMakeLists.txt
@@ -205,6 +205,7 @@ SET(WebCore_IDL_FILES
html/DataGridColumn.idl
html/DataGridColumnList.idl
html/DOMFormData.idl
+ html/DOMTokenList.idl
html/HTMLAllCollection.idl
html/HTMLAnchorElement.idl
html/HTMLAppletElement.idl
@@ -942,6 +943,7 @@ SET(WebCore_SOURCES
html/CollectionCache.cpp
html/DOMDataGridDataSource.cpp
html/DOMFormData.cpp
+ html/DOMTokenList.cpp
html/DataGridColumn.cpp
html/DataGridColumnList.cpp
html/DateComponents.cpp
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 26eb4b5..ac75c44 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,73 @@
+2010-09-27 Erik Arvidsson <arv at chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Implement HTML 5's HTMLElement.classList property
+ https://bugs.webkit.org/show_bug.cgi?id=20709
+
+ This adds a DOMTokenList class that is used for the classList property. DOMTokenList uses a SpaceSplitString for fast
+ contains check. In standards mode the existing classNames is used but in quirks mode we use an internal SpaceSplitString
+ because classList is always case sensitive.
+
+ Tests: fast/dom/HTMLElement/class-list-gc.html
+ fast/dom/HTMLElement/class-list-quirks.html
+ fast/dom/HTMLElement/class-list.html
+ perf/class-list-remove.html
+
+ * Android.derived.jscbindings.mk:
+ * Android.derived.v8bindings.mk:
+ * Android.jscbindings.mk:
+ * CMakeLists.txt:
+ * DerivedSources.cpp:
+ * DerivedSources.make:
+ * GNUmakefile.am:
+ * WebCore.gypi:
+ * WebCore.pri:
+ * WebCore.pro:
+ * WebCore.vcproj/WebCore.vcproj:
+ * WebCore.xcodeproj/project.pbxproj:
+ * bindings/gobject/GNUmakefile.am:
+ * bindings/js/JSElementCustom.cpp:
+ (WebCore::JSElement::markChildren): Make sure that we keep the wrapper while the element is alive.
+ * bindings/scripts/CodeGeneratorJS.pm: DOMTokenList has a string indexed getter.
+ * bindings/scripts/CodeGeneratorV8.pm:
+ * bindings/v8/custom/V8DOMTokenListCustom.cpp: Added.
+ (WebCore::toV8):
+ * dom/Element.cpp:
+ (WebCore::Element::classList):
+ (WebCore::Element::optionalClassList):
+ * dom/Element.h:
+ * dom/ElementRareData.h: This now has an OwnPtr to a ClassList if the Element::classList is ever called.
+ * dom/SpaceSplitString.h:
+ (WebCore::SpaceSplitString::isNull):
+ * dom/StyledElement.cpp:
+ (WebCore::StyledElement::classAttributeChanged): Update the classList if it exists.
+ * dom/StyledElement.h:
+ * html/DOMTokenList.cpp: Added.
+ (WebCore::validateToken):
+ (WebCore::DOMTokenList::DOMTokenList):
+ (WebCore::DOMTokenList::ref):
+ (WebCore::DOMTokenList::deref):
+ (WebCore::DOMTokenList::length):
+ (WebCore::DOMTokenList::item):
+ (WebCore::DOMTokenList::contains):
+ (WebCore::DOMTokenList::containsInternal): The internal methods do no validation of the token.
+ (WebCore::DOMTokenList::add):
+ (WebCore::DOMTokenList::addInternal):
+ (WebCore::DOMTokenList::remove):
+ (WebCore::DOMTokenList::removeInternal):
+ (WebCore::DOMTokenList::toggle):
+ (WebCore::DOMTokenList::toString):
+ (WebCore::DOMTokenList::reset):
+ (WebCore::DOMTokenList::classNames):
+ * html/DOMTokenList.h: Added.
+ (WebCore::DOMTokenList::create):
+ (WebCore::DOMTokenList::element):
+ * html/DOMTokenList.idl: Added.
+ * html/HTMLElement.idl:
+ * page/DOMWindow.cpp:
+ * page/DOMWindow.idl:
+
2010-09-27 Kenneth Russell <kbr at google.com>
Reviewed by James Robinson.
diff --git a/WebCore/DerivedSources.cpp b/WebCore/DerivedSources.cpp
index bab8109..898da5c 100644
--- a/WebCore/DerivedSources.cpp
+++ b/WebCore/DerivedSources.cpp
@@ -91,6 +91,7 @@
#include "JSDOMSelection.cpp"
#include "JSDOMStringList.cpp"
#include "JSDOMStringMap.cpp"
+#include "JSDOMTokenList.cpp"
#include "JSDOMWindow.cpp"
#include "JSElement.cpp"
#include "JSEntity.cpp"
diff --git a/WebCore/DerivedSources.make b/WebCore/DerivedSources.make
index adbd30c..2fda5e9 100644
--- a/WebCore/DerivedSources.make
+++ b/WebCore/DerivedSources.make
@@ -124,6 +124,7 @@ DOM_CLASSES = \
DOMSelection \
DOMStringList \
DOMStringMap \
+ DOMTokenList \
DOMWindow \
Database \
DatabaseCallback \
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index 44c71b5..882ca7c 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -216,6 +216,8 @@ webcore_built_sources += \
DerivedSources/WebCore/JSDOMStringList.h \
DerivedSources/WebCore/JSDOMStringMap.cpp \
DerivedSources/WebCore/JSDOMStringMap.h \
+ DerivedSources/WebCore/JSDOMTokenList.cpp \
+ DerivedSources/WebCore/JSDOMTokenList.h \
DerivedSources/WebCore/JSDOMWindow.cpp \
DerivedSources/WebCore/JSDOMWindow.h \
DerivedSources/WebCore/JSElement.cpp \
@@ -1433,6 +1435,8 @@ webcore_sources += \
WebCore/html/canvas/CanvasRenderingContext.h \
WebCore/html/canvas/CanvasStyle.cpp \
WebCore/html/canvas/CanvasStyle.h \
+ WebCore/html/DOMTokenList.cpp \
+ WebCore/html/DOMTokenList.h \
WebCore/html/CollectionCache.cpp \
WebCore/html/CollectionCache.h \
WebCore/html/CollectionType.h \
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index ca655d5..ee65f47 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -111,6 +111,7 @@
'fileapi/Metadata.idl',
'fileapi/MetadataCallback.idl',
'html/DOMFormData.idl',
+ 'html/DOMTokenList.idl',
'html/DataGridColumn.idl',
'html/DataGridColumnList.idl',
'html/HTMLAllCollection.idl',
@@ -766,6 +767,7 @@
'bindings/v8/custom/V8DocumentLocationCustom.cpp',
'bindings/v8/custom/V8DOMFormDataCustom.cpp',
'bindings/v8/custom/V8DOMStringMapCustom.cpp',
+ 'bindings/v8/custom/V8DOMTokenListCustom.cpp',
'bindings/v8/custom/V8DOMWindowCustom.cpp',
'bindings/v8/custom/V8DocumentCustom.cpp',
'bindings/v8/custom/V8ElementCustom.cpp',
@@ -1517,6 +1519,8 @@
'html/DOMDataGridDataSource.h',
'html/DOMFormData.cpp',
'html/DOMFormData.h',
+ 'html/DOMTokenList.cpp',
+ 'html/DOMTokenList.h',
'html/DataGridColumn.cpp',
'html/DataGridColumn.h',
'html/DataGridColumnList.cpp',
diff --git a/WebCore/WebCore.pri b/WebCore/WebCore.pri
index 67b5fdb..d15c343 100644
--- a/WebCore/WebCore.pri
+++ b/WebCore/WebCore.pri
@@ -201,6 +201,7 @@ IDL_BINDINGS += \
html/DataGridColumn.idl \
html/DataGridColumnList.idl \
html/DOMFormData.idl \
+ html/DOMTokenList.idl \
html/HTMLAllCollection.idl \
html/HTMLAudioElement.idl \
html/HTMLAnchorElement.idl \
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 93076d6..337d227 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -403,7 +403,8 @@ v8 {
bindings/v8/custom/V8InjectedScriptHostCustom.cpp \
bindings/v8/custom/V8InspectorFrontendHostCustom.cpp \
bindings/v8/custom/V8CustomEventListener.cpp \
- bindings/v8/custom/V8DOMStringMapCustom.cpp
+ bindings/v8/custom/V8DOMStringMapCustom.cpp \
+ bindings/v8/custom/V8DOMTokenListCustom.cpp
SOURCES += \
bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp \
@@ -838,6 +839,7 @@ SOURCES += \
html/CollectionCache.cpp \
html/DOMDataGridDataSource.cpp \
html/DOMFormData.cpp \
+ html/DOMTokenList.cpp \
html/DataGridColumn.cpp \
html/DataGridColumnList.cpp \
html/DateComponents.cpp \
@@ -1716,6 +1718,7 @@ HEADERS += \
html/DateComponents.h \
html/DOMDataGridDataSource.h \
html/DOMFormData.h \
+ html/DOMTokenList.h \
html/FormDataList.h \
html/FTPDirectoryDocument.h \
html/HTMLAllCollection.h \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 6e84f7c..83ca957 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -4033,6 +4033,14 @@
>
</File>
<File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSDOMTokenList.cpp"
+ >
+ </File>
+ <File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSDOMTokenList.h"
+ >
+ </File>
+ <File
RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSDOMWindow.cpp"
>
<FileConfiguration
@@ -37845,6 +37853,18 @@
>
</File>
<File
+ RelativePath="..\html\DOMTokenList.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\html\DOMTokenList.h"
+ >
+ </File>
+ <File
+ RelativePath="..\html\FormDataList.cpp"
+ >
+ </File>
+ <File
RelativePath="..\html\FTPDirectoryDocument.h"
>
</File>
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index dd4a8b6..5dbf13e 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -1412,12 +1412,18 @@
7693BAD3106C2DCA007B0823 /* PluginHalter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7693BACF106C2DCA007B0823 /* PluginHalter.cpp */; };
7693BAD4106C2DCA007B0823 /* PluginHalter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7693BAD0106C2DCA007B0823 /* PluginHalter.h */; };
7693BAD5106C2DCA007B0823 /* PluginHalterClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 7693BAD1106C2DCA007B0823 /* PluginHalterClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 7694563C1214D97C0007CBAE /* JSDOMTokenList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7694563A1214D97C0007CBAE /* JSDOMTokenList.cpp */; };
+ 7694563D1214D97C0007CBAE /* JSDOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 7694563B1214D97C0007CBAE /* JSDOMTokenList.h */; };
+ 7694565B1214DB630007CBAE /* DOMDOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 769456591214DB630007CBAE /* DOMDOMTokenList.h */; };
+ 7694565C1214DB630007CBAE /* DOMDOMTokenList.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7694565A1214DB630007CBAE /* DOMDOMTokenList.mm */; };
76CDD2F21103DA6600680521 /* AccessibilityMenuList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76CDD2EC1103DA6600680521 /* AccessibilityMenuList.cpp */; };
76CDD2F31103DA6600680521 /* AccessibilityMenuList.h in Headers */ = {isa = PBXBuildFile; fileRef = 76CDD2ED1103DA6600680521 /* AccessibilityMenuList.h */; };
76CDD2F41103DA6600680521 /* AccessibilityMenuListPopup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76CDD2EE1103DA6600680521 /* AccessibilityMenuListPopup.cpp */; };
76CDD2F51103DA6600680521 /* AccessibilityMenuListPopup.h in Headers */ = {isa = PBXBuildFile; fileRef = 76CDD2EF1103DA6600680521 /* AccessibilityMenuListPopup.h */; };
76CDD2F61103DA6600680521 /* AccessibilityMenuListOption.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76CDD2F01103DA6600680521 /* AccessibilityMenuListOption.cpp */; };
76CDD2F71103DA6600680521 /* AccessibilityMenuListOption.h in Headers */ = {isa = PBXBuildFile; fileRef = 76CDD2F11103DA6600680521 /* AccessibilityMenuListOption.h */; };
+ 76FC2B0B12370DA0006A991A /* DOMTokenList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76FC2B0812370DA0006A991A /* DOMTokenList.cpp */; };
+ 76FC2B0C12370DA0006A991A /* DOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 76FC2B0912370DA0006A991A /* DOMTokenList.h */; };
76FF17E311235673001D61B5 /* PluginViewNone.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76FF17E211235673001D61B5 /* PluginViewNone.cpp */; };
79AC9218109945C80021266E /* JSCompositionEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79AC9216109945C80021266E /* JSCompositionEvent.cpp */; };
79AC9219109945C80021266E /* JSCompositionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 79AC9217109945C80021266E /* JSCompositionEvent.h */; };
@@ -2777,7 +2783,6 @@
973E325610883B7C005BC493 /* ResourceLoadNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */; };
973E325710883B7C005BC493 /* ResourceLoadNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 973E325510883B7C005BC493 /* ResourceLoadNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
976D6C77122B8A3D001FD1F7 /* AsyncFileWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C58122B8A3D001FD1F7 /* AsyncFileWriter.h */; };
- 976D6C93122B8A3D001FD1F7 /* AsyncFileWriterClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C74122B8A3D001FD1F7 /* AsyncFileWriterClient.h */; };
976D6C78122B8A3D001FD1F7 /* Blob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976D6C59122B8A3D001FD1F7 /* Blob.cpp */; };
976D6C79122B8A3D001FD1F7 /* Blob.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C5A122B8A3D001FD1F7 /* Blob.h */; };
976D6C7B122B8A3D001FD1F7 /* BlobBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976D6C5C122B8A3D001FD1F7 /* BlobBuilder.cpp */; };
@@ -2798,6 +2803,7 @@
976D6C8F122B8A3D001FD1F7 /* FileThreadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C70122B8A3D001FD1F7 /* FileThreadTask.h */; };
976D6C90122B8A3D001FD1F7 /* FileWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976D6C71122B8A3D001FD1F7 /* FileWriter.cpp */; };
976D6C91122B8A3D001FD1F7 /* FileWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C72122B8A3D001FD1F7 /* FileWriter.h */; };
+ 976D6C93122B8A3D001FD1F7 /* AsyncFileWriterClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C74122B8A3D001FD1F7 /* AsyncFileWriterClient.h */; };
976D6C94122B8A3D001FD1F7 /* ThreadableBlobRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976D6C75122B8A3D001FD1F7 /* ThreadableBlobRegistry.cpp */; };
976D6C95122B8A3D001FD1F7 /* ThreadableBlobRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C76122B8A3D001FD1F7 /* ThreadableBlobRegistry.h */; };
977B37231228721700B81FF8 /* HTMLElementStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977B371F1228721700B81FF8 /* HTMLElementStack.cpp */; };
@@ -7370,12 +7376,19 @@
7693BACF106C2DCA007B0823 /* PluginHalter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginHalter.cpp; sourceTree = "<group>"; };
7693BAD0106C2DCA007B0823 /* PluginHalter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginHalter.h; sourceTree = "<group>"; };
7693BAD1106C2DCA007B0823 /* PluginHalterClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginHalterClient.h; sourceTree = "<group>"; };
+ 7694563A1214D97C0007CBAE /* JSDOMTokenList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMTokenList.cpp; sourceTree = "<group>"; };
+ 7694563B1214D97C0007CBAE /* JSDOMTokenList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMTokenList.h; sourceTree = "<group>"; };
+ 769456591214DB630007CBAE /* DOMDOMTokenList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMDOMTokenList.h; sourceTree = "<group>"; };
+ 7694565A1214DB630007CBAE /* DOMDOMTokenList.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMDOMTokenList.mm; sourceTree = "<group>"; };
76CDD2EC1103DA6600680521 /* AccessibilityMenuList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityMenuList.cpp; sourceTree = "<group>"; };
76CDD2ED1103DA6600680521 /* AccessibilityMenuList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMenuList.h; sourceTree = "<group>"; };
76CDD2EE1103DA6600680521 /* AccessibilityMenuListPopup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityMenuListPopup.cpp; sourceTree = "<group>"; };
76CDD2EF1103DA6600680521 /* AccessibilityMenuListPopup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMenuListPopup.h; sourceTree = "<group>"; };
76CDD2F01103DA6600680521 /* AccessibilityMenuListOption.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityMenuListOption.cpp; sourceTree = "<group>"; };
76CDD2F11103DA6600680521 /* AccessibilityMenuListOption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMenuListOption.h; sourceTree = "<group>"; };
+ 76FC2B0812370DA0006A991A /* DOMTokenList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMTokenList.cpp; sourceTree = "<group>"; };
+ 76FC2B0912370DA0006A991A /* DOMTokenList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMTokenList.h; sourceTree = "<group>"; };
+ 76FC2B0A12370DA0006A991A /* DOMTokenList.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DOMTokenList.idl; sourceTree = "<group>"; };
76FF17E211235673001D61B5 /* PluginViewNone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginViewNone.cpp; sourceTree = "<group>"; };
79AC9216109945C80021266E /* JSCompositionEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCompositionEvent.cpp; sourceTree = "<group>"; };
79AC9217109945C80021266E /* JSCompositionEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCompositionEvent.h; sourceTree = "<group>"; };
@@ -8677,7 +8690,6 @@
973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadNotifier.cpp; sourceTree = "<group>"; };
973E325510883B7C005BC493 /* ResourceLoadNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadNotifier.h; sourceTree = "<group>"; };
976D6C58122B8A3D001FD1F7 /* AsyncFileWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AsyncFileWriter.h; path = fileapi/AsyncFileWriter.h; sourceTree = "<group>"; };
- 976D6C74122B8A3D001FD1F7 /* AsyncFileWriterClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AsyncFileWriterClient.h; path = fileapi/AsyncFileWriterClient.h; sourceTree = "<group>"; };
976D6C59122B8A3D001FD1F7 /* Blob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Blob.cpp; path = fileapi/Blob.cpp; sourceTree = "<group>"; };
976D6C5A122B8A3D001FD1F7 /* Blob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Blob.h; path = fileapi/Blob.h; sourceTree = "<group>"; };
976D6C5C122B8A3D001FD1F7 /* BlobBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlobBuilder.cpp; path = fileapi/BlobBuilder.cpp; sourceTree = "<group>"; };
@@ -8698,6 +8710,7 @@
976D6C70122B8A3D001FD1F7 /* FileThreadTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileThreadTask.h; path = fileapi/FileThreadTask.h; sourceTree = "<group>"; };
976D6C71122B8A3D001FD1F7 /* FileWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileWriter.cpp; path = fileapi/FileWriter.cpp; sourceTree = "<group>"; };
976D6C72122B8A3D001FD1F7 /* FileWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileWriter.h; path = fileapi/FileWriter.h; sourceTree = "<group>"; };
+ 976D6C74122B8A3D001FD1F7 /* AsyncFileWriterClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AsyncFileWriterClient.h; path = fileapi/AsyncFileWriterClient.h; sourceTree = "<group>"; };
976D6C75122B8A3D001FD1F7 /* ThreadableBlobRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadableBlobRegistry.cpp; path = fileapi/ThreadableBlobRegistry.cpp; sourceTree = "<group>"; };
976D6C76122B8A3D001FD1F7 /* ThreadableBlobRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadableBlobRegistry.h; path = fileapi/ThreadableBlobRegistry.h; sourceTree = "<group>"; };
977B371F1228721700B81FF8 /* HTMLElementStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLElementStack.cpp; path = parser/HTMLElementStack.cpp; sourceTree = "<group>"; };
@@ -13520,6 +13533,8 @@
children = (
2E2D99E510E2BC1C00496337 /* DOMBlob.h */,
2E2D99E610E2BC1C00496337 /* DOMBlob.mm */,
+ 769456591214DB630007CBAE /* DOMDOMTokenList.h */,
+ 7694565A1214DB630007CBAE /* DOMDOMTokenList.mm */,
BC00EFFE0E0A185500FD04E3 /* DOMFile.h */,
BC00EFFF0E0A185500FD04E3 /* DOMFile.mm */,
2E3BC106117D479800B9409A /* DOMFileError.h */,
@@ -14143,6 +14158,9 @@
2ED609BA1145B07100C8684E /* DOMFormData.cpp */,
2ED609BB1145B07100C8684E /* DOMFormData.h */,
2E0888C3114883A900AF4265 /* DOMFormData.idl */,
+ 76FC2B0812370DA0006A991A /* DOMTokenList.cpp */,
+ 76FC2B0912370DA0006A991A /* DOMTokenList.h */,
+ 76FC2B0A12370DA0006A991A /* DOMTokenList.idl */,
A8136D370973A8E700D74463 /* FormDataList.cpp */,
A8136D360973A8E700D74463 /* FormDataList.h */,
97205AAD123928CA00B17380 /* FTPDirectoryDocument.cpp */,
@@ -14634,6 +14652,8 @@
BC77D1680FF19F550070887B /* JSDataGridColumnList.h */,
2E0888D21148848A00AF4265 /* JSDOMFormData.cpp */,
2E0888D31148848A00AF4265 /* JSDOMFormData.h */,
+ 7694563A1214D97C0007CBAE /* JSDOMTokenList.cpp */,
+ 7694563B1214D97C0007CBAE /* JSDOMTokenList.h */,
49EECEF4105070C400099FAB /* JSFloat32Array.cpp */,
49EECEF5105070C400099FAB /* JSFloat32Array.h */,
BC97E410109154FA0010D361 /* JSHTMLAllCollection.cpp */,
@@ -20582,6 +20602,9 @@
84730D911248F0B300D3A9C9 /* LightSource.h in Headers */,
84730D921248F0B300D3A9C9 /* PointLightSource.h in Headers */,
84730D931248F0B300D3A9C9 /* SpotLightSource.h in Headers */,
+ 7694563D1214D97C0007CBAE /* JSDOMTokenList.h in Headers */,
+ 7694565B1214DB630007CBAE /* DOMDOMTokenList.h in Headers */,
+ 76FC2B0C12370DA0006A991A /* DOMTokenList.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -23061,6 +23084,9 @@
84730D8A1248F0B300D3A9C9 /* FETile.cpp in Sources */,
84730D8C1248F0B300D3A9C9 /* FETurbulence.cpp in Sources */,
84730D901248F0B300D3A9C9 /* LightSource.cpp in Sources */,
+ 7694563C1214D97C0007CBAE /* JSDOMTokenList.cpp in Sources */,
+ 7694565C1214DB630007CBAE /* DOMDOMTokenList.mm in Sources */,
+ 76FC2B0B12370DA0006A991A /* DOMTokenList.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/WebCore/bindings/gobject/GNUmakefile.am b/WebCore/bindings/gobject/GNUmakefile.am
index 12835cc..d808e18 100644
--- a/WebCore/bindings/gobject/GNUmakefile.am
+++ b/WebCore/bindings/gobject/GNUmakefile.am
@@ -49,6 +49,8 @@ webkitgtk_gdom_built_sources += \
DerivedSources/webkit/WebKitDOMDOMStringListPrivate.h \
DerivedSources/webkit/WebKitDOMDOMStringMap.cpp \
DerivedSources/webkit/WebKitDOMDOMStringMapPrivate.h \
+ DerivedSources/webkit/WebKitDOMDOMTokenList.cpp \
+ DerivedSources/webkit/WebKitDOMDOMTokenListPrivate.h \
DerivedSources/webkit/WebKitDOMDOMWindow.cpp \
DerivedSources/webkit/WebKitDOMDOMWindowPrivate.h \
DerivedSources/webkit/WebKitDOMElement.cpp \
@@ -263,6 +265,7 @@ webkitgtk_built_h_api += \
DerivedSources/webkit/WebKitDOMDOMImplementation.h \
DerivedSources/webkit/WebKitDOMDOMStringList.h \
DerivedSources/webkit/WebKitDOMDOMStringMap.h \
+ DerivedSources/webkit/WebKitDOMDOMTokenList.h \
DerivedSources/webkit/WebKitDOMElement.h \
DerivedSources/webkit/WebKitDOMEntityReference.h \
DerivedSources/webkit/WebKitDOMEvent.h \
diff --git a/WebCore/bindings/js/JSElementCustom.cpp b/WebCore/bindings/js/JSElementCustom.cpp
index 8a1df5c..f691620 100644
--- a/WebCore/bindings/js/JSElementCustom.cpp
+++ b/WebCore/bindings/js/JSElementCustom.cpp
@@ -60,6 +60,7 @@ void JSElement::markChildren(MarkStack& markStack)
JSGlobalData& globalData = *Heap::heap(this)->globalData();
markDOMObjectWrapper(markStack, globalData, element->attributeMap());
+ markDOMObjectWrapper(markStack, globalData, element->optionalClassList());
markDOMObjectWrapper(markStack, globalData, element->optionalDataset());
if (element->isStyledElement())
diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm
index 1a114a4..803542e 100644
--- a/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -240,7 +240,7 @@ sub IndexGetterReturnsStrings
{
my $type = shift;
- return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration" or $type eq "DOMStringList";
+ return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration" or $type eq "DOMStringList" or $type eq "DOMTokenList";
return 0;
}
diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm
index f74f2b1..3353f0f 100644
--- a/WebCore/bindings/scripts/CodeGeneratorV8.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm
@@ -2510,6 +2510,7 @@ sub HasCustomToV8Implementation {
return 1 if $interfaceName eq "CanvasPixelArray";
return 1 if $interfaceName eq "DOMStringMap";
return 1 if $interfaceName eq "DOMWindow";
+ return 1 if $interfaceName eq "DOMTokenList";
return 1 if $interfaceName eq "Element";
return 1 if $interfaceName eq "HTMLDocument";
return 1 if $interfaceName eq "HTMLElement";
diff --git a/WebCore/bindings/v8/custom/V8DOMTokenListCustom.cpp b/WebCore/bindings/v8/custom/V8DOMTokenListCustom.cpp
new file mode 100644
index 0000000..171ff5c
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8DOMTokenListCustom.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 "V8DOMTokenList.h"
+
+#include "DOMTokenList.h"
+#include "V8Binding.h"
+#include "V8DOMWrapper.h"
+#include "V8Element.h"
+
+namespace WebCore {
+
+v8::Handle<v8::Value> toV8(DOMTokenList* impl)
+{
+ if (!impl)
+ return v8::Null();
+ v8::Handle<v8::Object> wrapper = V8DOMTokenList::wrap(impl);
+ // Add a hidden reference from the element to the DOMTokenList.
+ Element* element = impl->element();
+ if (!wrapper.IsEmpty() && element) {
+ v8::Handle<v8::Value> elementValue = toV8(element);
+ if (!elementValue.IsEmpty() && elementValue->IsObject())
+ V8DOMWrapper::setHiddenReference(elementValue.As<v8::Object>(), wrapper);
+ }
+ return wrapper;
+}
+
+} // namespace WebCore
diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp
index 5c4e82b..c408790 100644
--- a/WebCore/dom/Element.cpp
+++ b/WebCore/dom/Element.cpp
@@ -33,6 +33,7 @@
#include "CSSStyleSelector.h"
#include "ClientRect.h"
#include "ClientRectList.h"
+#include "DOMTokenList.h"
#include "DatasetDOMStringMap.h"
#include "Document.h"
#include "DocumentFragment.h"
@@ -1573,6 +1574,21 @@ bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
return false;
}
+DOMTokenList* Element::classList()
+{
+ ElementRareData* data = ensureRareData();
+ if (!data->m_classList)
+ data->m_classList = DOMTokenList::create(this);
+ return data->m_classList.get();
+}
+
+DOMTokenList* Element::optionalClassList() const
+{
+ if (!hasRareData())
+ return 0;
+ return rareData()->m_classList.get();
+}
+
DOMStringMap* Element::dataset()
{
ElementRareData* data = ensureRareData();
diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h
index d9a5085..b51e750 100644
--- a/WebCore/dom/Element.h
+++ b/WebCore/dom/Element.h
@@ -36,6 +36,7 @@ class Attribute;
class ClientRect;
class ClientRectList;
class DOMStringMap;
+class DOMTokenList;
class ElementRareData;
class IntSize;
@@ -269,6 +270,9 @@ public:
bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
+ DOMTokenList* classList();
+ DOMTokenList* optionalClassList() const;
+
DOMStringMap* dataset();
DOMStringMap* optionalDataset() const;
diff --git a/WebCore/dom/ElementRareData.h b/WebCore/dom/ElementRareData.h
index 8e338ab..f1e6334 100644
--- a/WebCore/dom/ElementRareData.h
+++ b/WebCore/dom/ElementRareData.h
@@ -22,6 +22,7 @@
#ifndef ElementRareData_h
#define ElementRareData_h
+#include "DOMTokenList.h"
#include "DatasetDOMStringMap.h"
#include "Element.h"
#include "NodeRareData.h"
@@ -42,6 +43,7 @@ public:
RefPtr<RenderStyle> m_computedStyle;
OwnPtr<DatasetDOMStringMap> m_datasetDOMStringMap;
+ OwnPtr<DOMTokenList> m_classList;
};
inline IntSize defaultMinimumSizeForResizing()
diff --git a/WebCore/dom/SpaceSplitString.h b/WebCore/dom/SpaceSplitString.h
index f49670b..0d3650e 100644
--- a/WebCore/dom/SpaceSplitString.h
+++ b/WebCore/dom/SpaceSplitString.h
@@ -74,6 +74,7 @@ namespace WebCore {
bool containsAll(const SpaceSplitString& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); }
size_t size() const { return m_data ? m_data->size() : 0; }
+ bool isNull() const { return !m_data; }
const AtomicString& operator[](size_t i) const { ASSERT(i < size()); return (*m_data)[i]; }
private:
diff --git a/WebCore/dom/StyledElement.cpp b/WebCore/dom/StyledElement.cpp
index a158e2e..f07fda9 100644
--- a/WebCore/dom/StyledElement.cpp
+++ b/WebCore/dom/StyledElement.cpp
@@ -28,6 +28,7 @@
#include "CSSStyleSelector.h"
#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
+#include "DOMTokenList.h"
#include "Document.h"
#include "HTMLNames.h"
#include <wtf/HashFunctions.h>
@@ -217,12 +218,12 @@ void StyledElement::classAttributeChanged(const AtomicString& newClassString)
}
bool hasClass = i < length;
setHasClass(hasClass);
- if (hasClass)
+ if (hasClass) {
attributes()->setClass(newClassString);
- else {
- if (attributeMap())
- attributeMap()->clearClass();
- }
+ if (DOMTokenList* classList = optionalClassList())
+ classList->reset(newClassString);
+ } else if (attributeMap())
+ attributeMap()->clearClass();
setNeedsStyleRecalc();
dispatchSubtreeModifiedEvent();
}
diff --git a/WebCore/dom/StyledElement.h b/WebCore/dom/StyledElement.h
index 8040dbf..4b62388 100644
--- a/WebCore/dom/StyledElement.h
+++ b/WebCore/dom/StyledElement.h
@@ -32,6 +32,7 @@
namespace WebCore {
class Attribute;
+class ClassList;
class CSSMappedAttributeDeclaration;
class StyledElement : public Element {
diff --git a/WebCore/html/DOMTokenList.cpp b/WebCore/html/DOMTokenList.cpp
new file mode 100644
index 0000000..8ee45a2
--- /dev/null
+++ b/WebCore/html/DOMTokenList.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * 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 "DOMTokenList.h"
+
+#include "Element.h"
+#include "HTMLNames.h"
+#include "SpaceSplitString.h"
+#include "StringBuilder.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static bool validateToken(const AtomicString& token, ExceptionCode& ec)
+{
+ if (token.isEmpty()) {
+ ec = SYNTAX_ERR;
+ return false;
+ }
+
+ unsigned length = token.length();
+ for (unsigned i = 0; i < length; ++i) {
+ if (isClassWhitespace(token[i])) {
+ ec = INVALID_CHARACTER_ERR;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+DOMTokenList::DOMTokenList(Element* element)
+ : m_element(element)
+{
+ if (m_element->document()->inQuirksMode())
+ m_classNamesForQuirksMode.set(m_element->fastGetAttribute(classAttr), false);
+}
+
+void DOMTokenList::ref()
+{
+ m_element->ref();
+}
+
+void DOMTokenList::deref()
+{
+ m_element->deref();
+}
+
+unsigned DOMTokenList::length() const
+{
+ return classNames().size();
+}
+
+const AtomicString DOMTokenList::item(unsigned index) const
+{
+ if (index >= length())
+ return AtomicString();
+ return classNames()[index];
+}
+
+bool DOMTokenList::contains(const AtomicString& token, ExceptionCode& ec) const
+{
+ if (!validateToken(token, ec))
+ return false;
+ return containsInternal(token);
+}
+
+bool DOMTokenList::containsInternal(const AtomicString& token) const
+{
+ return classNames().contains(token);
+}
+
+void DOMTokenList::add(const AtomicString& token, ExceptionCode& ec)
+{
+ if (!validateToken(token, ec))
+ return;
+ addInternal(token);
+}
+
+void DOMTokenList::addInternal(const AtomicString& token) const
+{
+ const AtomicString& oldClassName(m_element->fastGetAttribute(classAttr));
+ if (oldClassName.isEmpty())
+ m_element->setAttribute(classAttr, token);
+ else if (!containsInternal(token)) {
+ StringBuilder builder;
+ builder.append(oldClassName);
+ if (oldClassName[oldClassName.length() - 1] != ' ')
+ builder.append(' ');
+ builder.append(token);
+ m_element->setAttribute(classAttr, builder.toString());
+ }
+}
+
+void DOMTokenList::remove(const AtomicString& token, ExceptionCode& ec)
+{
+ if (!validateToken(token, ec))
+ return;
+ removeInternal(token);
+}
+
+void DOMTokenList::removeInternal(const AtomicString& token) const
+{
+ // Check using contains first since it uses AtomicString comparisons instead
+ // of character by character testing.
+ if (!containsInternal(token))
+ return;
+
+ // Algorithm defined at http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#remove-a-token-from-a-string
+
+ const AtomicString& input = m_element->fastGetAttribute(classAttr);
+ unsigned inputLength = input.length();
+ Vector<UChar> output; // 3
+ output.reserveCapacity(inputLength);
+ unsigned position = 0; // 4
+
+ // Step 5
+ while (position < inputLength) {
+ if (isClassWhitespace(input[position])) { // 6
+ output.append(input[position++]); // 6.1, 6.2
+ continue; // 6.3
+ }
+
+ // Step 7
+ Vector<UChar> s;
+ while (position < inputLength && !isClassWhitespace(input[position]))
+ s.append(input[position++]);
+
+ // Step 8
+ if (s == token) {
+ // Step 8.1
+ while (position < inputLength && isClassWhitespace(input[position]))
+ ++position;
+
+ // Step 8.2
+ size_t j = output.size();
+ while (j > 0 && isClassWhitespace(output[j - 1]))
+ --j;
+ output.resize(j);
+
+ // Step 8.3
+ if (position < inputLength && !output.isEmpty())
+ output.append(' ');
+ } else
+ output.append(s); // Step 9
+ }
+
+ output.shrinkToFit();
+ m_element->setAttribute(classAttr, String::adopt(output));
+}
+
+bool DOMTokenList::toggle(const AtomicString& token, ExceptionCode& ec)
+{
+ if (!validateToken(token, ec))
+ return false;
+
+ if (containsInternal(token)) {
+ removeInternal(token);
+ return false;
+ }
+ addInternal(token);
+ return true;
+}
+
+String DOMTokenList::toString() const
+{
+ return m_element->fastGetAttribute(classAttr);
+}
+
+void DOMTokenList::reset(const String& newClassName)
+{
+ if (!m_classNamesForQuirksMode.isNull())
+ m_classNamesForQuirksMode.set(newClassName, false);
+}
+
+const SpaceSplitString& DOMTokenList::classNames() const
+{
+ if (!m_classNamesForQuirksMode.isNull())
+ return m_classNamesForQuirksMode;
+ return m_element->attributeMap()->classNames();
+}
+
+} // namespace WebCore
diff --git a/WebCore/html/DOMTokenList.h b/WebCore/html/DOMTokenList.h
new file mode 100644
index 0000000..fad69ca
--- /dev/null
+++ b/WebCore/html/DOMTokenList.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * 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 DOMTokenList_h
+#define DOMTokenList_h
+
+#include "ExceptionCode.h"
+#include "SpaceSplitString.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Element;
+
+class DOMTokenList : public Noncopyable {
+public:
+ static PassOwnPtr<DOMTokenList> create(Element* element)
+ {
+ return adoptPtr(new DOMTokenList(element));
+ }
+
+ void ref();
+ void deref();
+
+ unsigned length() const;
+ const AtomicString item(unsigned index) const;
+ bool contains(const AtomicString&, ExceptionCode&) const;
+ void add(const AtomicString&, ExceptionCode&);
+ void remove(const AtomicString&, ExceptionCode&);
+ bool toggle(const AtomicString&, ExceptionCode&);
+ String toString() const;
+
+ void reset(const String&);
+
+ Element* element() { return m_element; }
+
+private:
+ DOMTokenList(Element*);
+
+ void addInternal(const AtomicString&) const;
+ bool containsInternal(const AtomicString&) const;
+ void removeInternal(const AtomicString&) const;
+
+ const SpaceSplitString& classNames() const;
+
+ Element* m_element;
+ SpaceSplitString m_classNamesForQuirksMode;
+};
+
+} // namespace WebCore
+
+#endif // DOMTokenList_h
diff --git a/WebCore/html/DOMTokenList.idl b/WebCore/html/DOMTokenList.idl
new file mode 100644
index 0000000..a46900e
--- /dev/null
+++ b/WebCore/html/DOMTokenList.idl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+module core {
+
+ interface [
+ GenerateConstructor,
+ HasIndexGetter
+ ] DOMTokenList {
+ readonly attribute unsigned long length;
+ [ConvertNullStringTo=Null] DOMString item(in unsigned long index);
+ boolean contains(in DOMString token) raises(DOMException);
+ void add(in DOMString token) raises(DOMException);
+ void remove(in DOMString token) raises(DOMException);
+ boolean toggle(in DOMString token) raises(DOMException);
+
+#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
+ [DontEnum] DOMString toString();
+#endif
+ };
+
+}
diff --git a/WebCore/html/HTMLElement.idl b/WebCore/html/HTMLElement.idl
index 863f28c..b127c51 100644
--- a/WebCore/html/HTMLElement.idl
+++ b/WebCore/html/HTMLElement.idl
@@ -31,6 +31,7 @@ module html {
attribute [Reflect] DOMString lang;
attribute [Reflect] DOMString dir;
attribute [Reflect=class] DOMString className;
+ readonly attribute DOMTokenList classList;
attribute long tabIndex;
attribute boolean draggable;
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp
index 5efaea7..343ca2c 100644
--- a/WebCore/page/DOMWindow.cpp
+++ b/WebCore/page/DOMWindow.cpp
@@ -40,6 +40,7 @@
#include "DOMSelection.h"
#include "DOMStringList.h"
#include "DOMTimer.h"
+#include "DOMTokenList.h"
#include "Database.h"
#include "DatabaseCallback.h"
#include "DeviceMotionController.h"
diff --git a/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl
index 72ca36a..8cac879 100644
--- a/WebCore/page/DOMWindow.idl
+++ b/WebCore/page/DOMWindow.idl
@@ -379,6 +379,7 @@ module window {
// attribute DOMImplementationListConstructor DOMImplementationList;
// attribute DOMImplementationSourceConstructor DOMImplementationSource;
attribute DOMImplementationConstructor DOMImplementation;
+ attribute DOMTokenListConstructor DOMTokenList;
attribute DocumentFragmentConstructor DocumentFragment;
attribute DocumentConstructor Document;
attribute NodeConstructor Node;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list