Implement HTMLTemplateElement
authorrafaelw@chromium.org <rafaelw@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Dec 2012 03:09:49 +0000 (03:09 +0000)
committerrafaelw@chromium.org <rafaelw@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Dec 2012 03:09:49 +0000 (03:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=86031

Reviewed by Adam Barth.

Source/WebCore:

Initial implementation. This patch includes the parser changes, new IDL and element implementation for <template>.

Spec: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html

Tests: fast/dom/HTMLTemplateElement/cloneNode.html
       fast/dom/HTMLTemplateElement/inertContents.html
       fast/dom/HTMLTemplateElement/innerHTML.html
       fast/dom/HTMLTemplateElement/ownerDocument.html
       html5lib/run-template.html

* WebCore.gypi:
* css/html.css:
(template):
* dom/Document.cpp:
(WebCore):
(WebCore::Document::templateContentsOwnerDocument):
* dom/Document.h:
(Document):
* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::serializeNodesWithNamespaces):
* html/HTMLElement.h:
(HTMLElement):
* html/HTMLElementsAllInOne.cpp:
* html/HTMLTagNames.in:
* html/HTMLTemplateElement.cpp: Added.
(WebCore):
(WebCore::HTMLTemplateElement::HTMLTemplateElement):
(WebCore::HTMLTemplateElement::setInnerHTML):
(WebCore::HTMLTemplateElement::~HTMLTemplateElement):
(WebCore::HTMLTemplateElement::create):
(WebCore::HTMLTemplateElement::content):
(WebCore::HTMLTemplateElement::setContent):
(WebCore::toHTMLTemplateElement):
* html/HTMLTemplateElement.h: Added.
(WebCore):
(HTMLTemplateElement):
(WebCore::toHTMLTemplateElement):
* html/HTMLTemplateElement.idl: Added.
* html/parser/HTMLConstructionSite.cpp:
(WebCore::executeTask):
(WebCore::HTMLConstructionSite::insertComment):
(WebCore::HTMLConstructionSite::insertTextNode):
(WebCore::HTMLConstructionSite::createElement):
(WebCore::HTMLConstructionSite::ownerDocumentForCurrentNode):
(WebCore):
(WebCore::HTMLConstructionSite::createHTMLElement):
(WebCore::HTMLConstructionSite::findFosterSite):
* html/parser/HTMLConstructionSite.h:
(HTMLConstructionSite):
* html/parser/HTMLElementStack.cpp:
(WebCore):
(WebCore::HTMLElementStack::hasTemplateInHTMLScope):
* html/parser/HTMLElementStack.h:
(HTMLElementStack):
* html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::constructTreeFromToken):
(WebCore::HTMLTreeBuilder::processStartTagForInBody):
(WebCore):
(WebCore::HTMLTreeBuilder::processTemplateEndTag):
(WebCore::HTMLTreeBuilder::processStartTagForInTable):
(WebCore::HTMLTreeBuilder::processStartTag):
(WebCore::HTMLTreeBuilder::processHtmlStartTagForInBody):
(WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately):
(WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
(WebCore::HTMLTreeBuilder::processEndTagForInRow):
(WebCore::HTMLTreeBuilder::processEndTagForInCell):
(WebCore::HTMLTreeBuilder::processEndTagForInBody):
(WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
(WebCore::HTMLTreeBuilder::processTableEndTagForInTable):
(WebCore::HTMLTreeBuilder::processEndTag):
(WebCore::HTMLTreeBuilder::processCharacterBuffer):
(WebCore::HTMLTreeBuilder::processEndOfFile):
(WebCore::HTMLTreeBuilder::processStartTagForInHead):
* html/parser/HTMLTreeBuilder.h:
(HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::isParsingTemplateContents):
(WebCore::HTMLTreeBuilder::isParsingFragmentOrTemplateContents):
* page/DOMWindow.idl:

Source/WebKit/chromium:

Turning on HTMLTemplateElement for chromium port.

* features.gypi:

LayoutTests:

* fast/dom/HTMLTemplateElement/cloneNode-expected.txt: Added.
* fast/dom/HTMLTemplateElement/cloneNode.html: Added.
* fast/dom/HTMLTemplateElement/inertContents-expected.txt: Added.
* fast/dom/HTMLTemplateElement/inertContents.html: Added.
* fast/dom/HTMLTemplateElement/innerHTML-expected.txt: Added.
* fast/dom/HTMLTemplateElement/innerHTML.html: Added.
* fast/dom/HTMLTemplateElement/ownerDocument-expected.txt: Added.
* fast/dom/HTMLTemplateElement/ownerDocument.html: Added.
* html5lib/resources/template.dat: Added.
* html5lib/run-template-expected.txt: Added.
* html5lib/run-template.html: Added.
* resources/dump-as-markup.js:
(Markup._get):
(Markup._getSelectionFromNode):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@136467 268f45cc-cd09-0410-ab3c-d52691b4dbfc

50 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/HTMLTemplateElement/cloneNode-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/cloneNode.html [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/inertContents-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/inertContents.html [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/innerHTML-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/innerHTML.html [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/ownerDocument-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/ownerDocument.html [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML.xhtml [new file with mode: 0644]
LayoutTests/html5lib/resources/template.dat [new file with mode: 0644]
LayoutTests/html5lib/run-template-expected.txt [new file with mode: 0644]
LayoutTests/html5lib/run-template.html [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/qt/TestExpectations
LayoutTests/platform/win/TestExpectations
LayoutTests/platform/wincairo/TestExpectations
LayoutTests/resources/dump-as-markup.js
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources.make
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/html.css
Source/WebCore/dom/ContainerNode.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/editing/MarkupAccumulator.cpp
Source/WebCore/html/HTMLElement.cpp
Source/WebCore/html/HTMLElementsAllInOne.cpp
Source/WebCore/html/HTMLTagNames.in
Source/WebCore/html/HTMLTemplateElement.cpp [new file with mode: 0644]
Source/WebCore/html/HTMLTemplateElement.h [new file with mode: 0644]
Source/WebCore/html/HTMLTemplateElement.idl [new file with mode: 0644]
Source/WebCore/html/parser/HTMLConstructionSite.cpp
Source/WebCore/html/parser/HTMLConstructionSite.h
Source/WebCore/html/parser/HTMLElementStack.cpp
Source/WebCore/html/parser/HTMLElementStack.h
Source/WebCore/html/parser/HTMLTreeBuilder.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.h
Source/WebCore/page/DOMWindow.idl
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/features.gypi
Tools/Scripts/webkitperl/FeatureList.pm

index a365663..ba14bb9 100644 (file)
@@ -1,3 +1,25 @@
+2012-12-03  Rafael Weinstein  <rafaelw@chromium.org>
+
+        Implement HTMLTemplateElement
+        https://bugs.webkit.org/show_bug.cgi?id=86031
+
+        Reviewed by Adam Barth.
+
+        * fast/dom/HTMLTemplateElement/cloneNode-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/cloneNode.html: Added.
+        * fast/dom/HTMLTemplateElement/inertContents-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/inertContents.html: Added.
+        * fast/dom/HTMLTemplateElement/innerHTML-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/innerHTML.html: Added.
+        * fast/dom/HTMLTemplateElement/ownerDocument-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/ownerDocument.html: Added.
+        * html5lib/resources/template.dat: Added.
+        * html5lib/run-template-expected.txt: Added.
+        * html5lib/run-template.html: Added.
+        * resources/dump-as-markup.js:
+        (Markup._get):
+        (Markup._getSelectionFromNode):
+
 2012-12-03  Julien Chaffraix  <jchaffraix@webkit.org>
 
         [CSS Grid Layout] Support percentage paddings and margins on grid items
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/cloneNode-expected.txt b/LayoutTests/fast/dom/HTMLTemplateElement/cloneNode-expected.txt
new file mode 100644 (file)
index 0000000..8bb61cd
--- /dev/null
@@ -0,0 +1,8 @@
+Test that template contents are not cloned when the template element is cloned
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS template.content.childNodes.length is 1
+PASS clone.content.childNodes.length is 0
+
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/cloneNode.html b/LayoutTests/fast/dom/HTMLTemplateElement/cloneNode.html
new file mode 100644 (file)
index 0000000..eda5f75
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<template id="template">Contents</template>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script>
+
+description('Test that template contents are not cloned when the template element is cloned');
+
+if (!window.HTMLTemplateElement)
+    testFailed('This test requires ENABLE(TEMPLATE_ELEMENT)');
+
+var template = document.getElementById('template');
+shouldBe('template.content.childNodes.length', '1');
+var clone = template.cloneNode(true);
+shouldBe('clone.content.childNodes.length', '0');
+
+</script>
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/inertContents-expected.txt b/LayoutTests/fast/dom/HTMLTemplateElement/inertContents-expected.txt
new file mode 100644 (file)
index 0000000..45ff115
--- /dev/null
@@ -0,0 +1,7 @@
+http://baz.com/bat.jpg - willSendRequest <NSURLRequest URL http://baz.com/bat.jpg, main document URL inertContents.html, http method GET> redirectResponse (null)
+Blocked access to external URL http://baz.com/bat.jpg
+http://baz.com/bat.jpg - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -999, failing URL "(null)">
+The test asserts that elements within template contents are "inert", e.g. resources do not fetch, script does not run.
+
+pass!
+
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/inertContents.html b/LayoutTests/fast/dom/HTMLTemplateElement/inertContents.html
new file mode 100644 (file)
index 0000000..c3c05ec
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+var testVal = 1;
+
+window.onload = function() {
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.dumpResourceLoadCallbacks();
+    }
+
+    if (testVal != 1)
+        return;
+
+    var templateContent = document.getElementById('template').content;
+    var img = templateContent.childNodes[1];
+    img.src = "http://baz.com/bat.jpg";
+    document.body.appendChild(templateContent);
+
+    if (testVal != 2)
+        return;
+
+    document.getElementById('output').innerText = 'pass!';
+}
+</script>
+</head>
+<body>
+<p>The test asserts that elements within template contents are "inert", e.g. resources do not fetch, script does not run.</p>
+<template id="template"><script>window.testVal = 2;</script><img src="http://foo.com/bar.jpg">
+</template>
+<div id="output">
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/innerHTML-expected.txt b/LayoutTests/fast/dom/HTMLTemplateElement/innerHTML-expected.txt
new file mode 100644 (file)
index 0000000..5f97270
--- /dev/null
@@ -0,0 +1,5 @@
+The test asserts that template contents are serialized with innerHTML and its children are ignored.
+
+<div>Contents 1
+<template>Contents 2</template>
+</div>
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/innerHTML.html b/LayoutTests/fast/dom/HTMLTemplateElement/innerHTML.html
new file mode 100644 (file)
index 0000000..c762ca3
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+window.onload = function() {
+    if (window.testRunner)
+        testRunner.dumpAsText();
+
+    var template = document.getElementById('template');
+    template.appendChild(document.createElement('span')).innerText = 'should not serialize';
+    var innerTemplate = template.content.firstChild.firstElementChild;
+    innerTemplate.appendChild(document.createElement('span')).innerText = 'should not serialize either';
+
+    template.innerHTML = template.innerHTML;
+    if (template.childNodes.length != 1) // The only child should be the span that was added above.
+        return;
+
+    document.getElementById('output').innerText = template.innerHTML;
+    var template2 = document.createElement('template');
+    template2.innerHTML = '<template></template>';
+}
+</script>
+</head>
+<body>
+<p>The test asserts that template contents are serialized with innerHTML and its children are ignored.</p>
+<template id="template"><div>Contents 1
+  <template>Contents 2</template>
+</div></template>
+<div id="output">
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocument-expected.txt b/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocument-expected.txt
new file mode 100644 (file)
index 0000000..b702aea
--- /dev/null
@@ -0,0 +1,28 @@
+Test HTMLTemplateElement content ownerDocument
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS template.ownerDocument is document
+PASS templateContentOwnerDocument instanceof HTMLDocument is true
+PASS document is not templateContentOwnerDocument
+PASS template.content.firstChild.ownerDocument is templateContentOwnerDocument
+PASS innerTemplate.ownerDocument is templateContentOwnerDocument
+PASS innerTemplate.content.ownerDocument is templateContentOwnerDocument
+PASS innerTemplate.ownerDocument instanceof HTMLDocument is true
+PASS template2.ownerDocument is document
+PASS template2.content.ownerDocument is templateContentOwnerDocument
+PASS df.ownerDocument is document
+PASS span.ownerDocument is document
+PASS df.ownerDocument is templateContentOwnerDocument
+PASS span.ownerDocument is templateContentOwnerDocument
+PASS template.content = document.createElement("span"); threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS template.content = document.createTextNode("text"); threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS template.content = new WebKitShadowRoot(div) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS template3.ownerDocument is document
+PASS template3.content.ownerDocument is templateContentOwnerDocument
+PASS template3.content.firstChild.ownerDocument is templateContentOwnerDocument
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocument.html b/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocument.html
new file mode 100644 (file)
index 0000000..d45192b
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<template id="template"><span><template></template></span></template>
+<template id="template2"><span></span></template>
+<template id="template3"><svg></svg></template>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script>
+
+description('Test HTMLTemplateElement content ownerDocument');
+
+if (!window.HTMLTemplateElement)
+    testFailed('This test requires ENABLE(TEMPLATE_ELEMENT)');
+
+var template = document.getElementById('template');
+shouldBe('template.ownerDocument', 'document');
+
+var templateContentOwnerDocument = template.content.ownerDocument;
+shouldBeTrue('templateContentOwnerDocument instanceof HTMLDocument');
+shouldNotBe('document', 'templateContentOwnerDocument');
+shouldBe('template.content.firstChild.ownerDocument', 'templateContentOwnerDocument');
+
+var innerTemplate = template.content.firstChild.firstChild;
+shouldBe('innerTemplate.ownerDocument', 'templateContentOwnerDocument');
+shouldBe('innerTemplate.content.ownerDocument', 'templateContentOwnerDocument');
+shouldBeTrue('innerTemplate.ownerDocument instanceof HTMLDocument');
+
+var template2 = document.getElementById('template2');
+shouldBe('template2.ownerDocument', 'document');
+shouldBe('template2.content.ownerDocument', 'templateContentOwnerDocument');
+
+var df = document.createDocumentFragment();
+var span = df.appendChild(document.createElement('span'));
+shouldBe('df.ownerDocument', 'document');
+shouldBe('span.ownerDocument', 'document');
+
+template.content = df;
+shouldBe('df.ownerDocument', 'templateContentOwnerDocument');
+shouldBe('span.ownerDocument', 'templateContentOwnerDocument');
+
+shouldThrow('template.content = document.createElement("span");');
+shouldThrow('template.content = document.createTextNode("text");');
+if (window.WebKitShadowRoot) {
+    var div = document.createElement('div');
+    shouldThrow('template.content = new WebKitShadowRoot(div)');
+}
+
+var template3 = document.getElementById('template2');
+shouldBe('template3.ownerDocument', 'document');
+shouldBe('template3.content.ownerDocument', 'templateContentOwnerDocument');
+shouldBe('template3.content.firstChild.ownerDocument', 'templateContentOwnerDocument');
+
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML-expected.txt b/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML-expected.txt
new file mode 100644 (file)
index 0000000..bf69bff
--- /dev/null
@@ -0,0 +1,12 @@
+Test HTMLTemplateElement content ownerDocument in XHTML Document
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document instanceof HTMLDocument is false
+PASS document is not templateContentOwnerDocument
+PASS templateContentOwnerDocument instanceof HTMLDocument is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML.xhtml b/LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML.xhtml
new file mode 100644 (file)
index 0000000..b85838a
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="../../js/resources/js-test-pre.js"></script>
+<script>
+
+description('Test HTMLTemplateElement content ownerDocument in XHTML Document');
+
+if (!window.HTMLTemplateElement)
+    testFailed('This test requires ENABLE(TEMPLATE_ELEMENT)');
+
+shouldBeFalse('document instanceof HTMLDocument');
+var template4 = document.createElement('template');
+var templateContentOwnerDocument = template4.content.ownerDocument;
+shouldNotBe('document', 'templateContentOwnerDocument');
+shouldBeFalse('templateContentOwnerDocument instanceof HTMLDocument');
+
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/html5lib/resources/template.dat b/LayoutTests/html5lib/resources/template.dat
new file mode 100644 (file)
index 0000000..1bae81e
--- /dev/null
@@ -0,0 +1,843 @@
+#data
+<body><template>Hello</template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         "Hello"
+
+#data
+<template>Hello</template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|         "Hello"
+|   <body>
+
+#data
+<template></template><div></div>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|   <body>
+|     <div>
+
+#data
+<html><template>Hello</template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|         "Hello"
+|   <body>
+
+#data
+<head><template><div></div></template></head>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|         <div>
+|   <body>
+
+#data
+<div><template><div><span></template><b>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         #document-fragment
+|           <div>
+|             <span>
+|       <b>
+
+#data
+<div><template></div>Hello
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         #document-fragment
+|           "Hello"
+
+#data
+<div></template></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+
+#data
+<table><template></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+
+#data
+<table><template></template></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+
+#data
+<table><div><template></template></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       <template>
+|         #document-fragment
+|     <table>
+
+#data
+<table><template></template><div></div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|     <table>
+|       <template>
+|         #document-fragment
+
+#data
+<table>   <template></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       "   "
+|       <template>
+|         #document-fragment
+
+#data
+<table><tbody><template></template></tbody>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <template>
+|           #document-fragment
+
+#data
+<table><tbody><template></tbody></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <template>
+|           #document-fragment
+
+#data
+<table><tbody><template></template></tbody></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <template>
+|           #document-fragment
+
+#data
+<table><thead><template></template></thead>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <thead>
+|         <template>
+|           #document-fragment
+
+#data
+<table><tfoot><template></template></tfoot>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tfoot>
+|         <template>
+|           #document-fragment
+
+#data
+<select><template></template></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         #document-fragment
+
+#data
+<select><template><option></option></template></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         #document-fragment
+|           <option>
+
+#data
+<template><option></option></select><option></option></template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|         <option>
+|         <option>
+|   <body>
+
+#data
+<select><template></template><option></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         #document-fragment
+|       <option>
+
+#data
+<select><option><template></template></select>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <option>
+|         <template>
+|           #document-fragment
+
+#data
+<select><template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <template>
+|         #document-fragment
+
+#data
+<select><option></option><template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <option>
+|       <template>
+|         #document-fragment
+
+#data
+<select><option></option><template><option>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <select>
+|       <option>
+|       <template>
+|         #document-fragment
+|           <option>
+
+#data
+<table><thead><template><td></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <thead>
+|         <template>
+|           #document-fragment
+|             <td>
+
+#data
+<table><template><thead></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <thead>
+
+#data
+<body><table><template><td></tr><div></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <td>
+|             <div>
+
+#data
+<table><template><thead></template></thead></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <thead>
+
+#data
+<table><thead><template><tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <thead>
+|         <template>
+|           #document-fragment
+|             <tr>
+
+#data
+<table><template><tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <tr>
+
+#data
+<table><tr><template><td>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <template>
+|             #document-fragment
+|               <td>
+
+#data
+<table><template><tr><template><td></template></tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <tr>
+|             <template>
+|               #document-fragment
+|                 <td>
+
+#data
+<table><template><tr><template><td></td></template></tr></template></table>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <tr>
+|             <template>
+|               #document-fragment
+|                 <td>
+
+#data
+<table><template><td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <template>
+|         #document-fragment
+|           <td>
+
+#data
+<body><template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <template>
+|           #document-fragment
+|             <tr>
+|         <td>
+
+#data
+<table><colgroup><template><col>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <colgroup>
+|         <template>
+|           #document-fragment
+|             <col>
+
+#data
+<frameset><template><frame></frame></template></frameset>
+#errors
+#document
+| <html>
+|   <head>
+|   <frameset>
+|     <template>
+|       #document-fragment
+|         <frame>
+
+#data
+<template><frame></frame></frameset><frame></frame></template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|         <frame>
+|         <frame>
+|   <body>
+
+#data
+<template><div><frameset><span></span></div><span></span></template>
+#errors
+#document
+| <html>
+|   <head>
+|     <template>
+|       #document-fragment
+|         <div>
+|           <span>
+|         <span>
+|   <body>
+
+#data
+<body><template><div><frameset><span></span></div><span></span></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <div>
+|           <span>
+|         <span>
+
+#data
+<body><template><script>var i = 1;</script><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <script>
+|           "var i = 1;"
+|         <td>
+
+#data
+<body><template><tr><div></div></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <tr>
+|         <div>
+
+#data
+<body><template><tr></tr><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <tr>
+|         <tr>
+|           <td>
+
+#data
+<body><template><td></td></tr><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <td>
+|         <td>
+
+
+#data
+<body><template><td></td><tbody><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td><caption></caption><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td><colgroup></caption><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <td>
+|         <td>
+
+#data
+<body><template><td></td></table><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <td>
+|         <td>
+
+#data
+<body><template><tr></tr><tbody><tr></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <tr>
+|         <tr>
+
+#data
+<body><template><tr></tr><caption><tr></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <tr>
+|         <tr>
+
+#data
+<body><template><tr></tr></table><tr></tr></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <tr>
+|         <tr>
+
+#data
+<body><template><thead></thead><caption></caption><tbody></tbody></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <thead>
+|         <caption>
+|         <tbody>
+
+#data
+<body><template><thead></thead></table><tbody></tbody></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <thead>
+|         <tbody>
+
+#data
+<body><template><div><tr></tr></div></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <div>
+
+#data
+<body><template><em>Hello</em></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <em>
+|           "Hello"
+
+#data
+<body><template><!--comment--></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <!-- comment -->
+
+#data
+<body><template><style></style><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <style>
+|         <td>
+
+#data
+<body><template><meta><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <meta>
+|         <td>
+
+#data
+<body><template><link><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <link>
+|         <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <template>
+|           #document-fragment
+|             <tr>
+|         <td>
+
+#data
+<body><table><colgroup><template><col></col></template></colgroup></table></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <colgroup>
+|         <template>
+|           #document-fragment
+|             <col>
+
+#data
+<body a=b><template><div></div><body c=d><div></div></body></template></body>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     a="b"
+|     <template>
+|       #document-fragment
+|         <div>
+|         <div>
+
+#data
+<html a=b><template><div><html b=c><span></template>
+#errors
+#document
+| <html>
+|   a="b"
+|   <head>
+|     <template>
+|       #document-fragment
+|         <div>
+|           <span>
+|   <body>
+
+#data
+<html a=b><template><col></col><html b=c><col></col></template>
+#errors
+#document
+| <html>
+|   a="b"
+|   <head>
+|     <template>
+|       #document-fragment
+|         <col>
+|         <col>
+|   <body>
+
+#data
+<html a=b><template><frame></frame><html b=c><frame></frame></template>
+#errors
+#document
+| <html>
+|   a="b"
+|   <head>
+|     <template>
+|       #document-fragment
+|         <frame>
+|         <frame>
+|   <body>
+
+#data
+<body><template><tr></tr><template></template><td></td></template>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <template>
+|       #document-fragment
+|         <tr>
+|         <template>
+|           #document-fragment
+|         <td>
diff --git a/LayoutTests/html5lib/run-template-expected.txt b/LayoutTests/html5lib/run-template-expected.txt
new file mode 100644 (file)
index 0000000..9efe324
--- /dev/null
@@ -0,0 +1 @@
+resources/template.dat: PASS
diff --git a/LayoutTests/html5lib/run-template.html b/LayoutTests/html5lib/run-template.html
new file mode 100644 (file)
index 0000000..f81129a
--- /dev/null
@@ -0,0 +1,8 @@
+<!doctype html>
+<script>
+var test_files = [
+  'resources/template.dat',
+]
+</script>
+<script src="../resources/dump-as-markup.js"></script>
+<script src="resources/runner.js"></script>
\ No newline at end of file
index 5513708..5023c8a 100644 (file)
@@ -310,6 +310,10 @@ fast/text/unicode-variation-selector.html
 fast/forms/file/input-file-entries.html
 http/tests/security/contentSecurityPolicy/filesystem-urls-match-self.html
 
+# ENABLE(TEMPLATE_ELEMENT) is disabled.
+fast/dom/HTMLTemplateElement
+html5lib/run-template.html
+
 # Transparent image being produced
 fast/frames/transparent-scrollbar.html
 
index b8aabbf..4ce54f9 100644 (file)
@@ -77,6 +77,10 @@ http/tests/xmlhttprequest/default-content-type-dashboard.html [ WontFix ]
 # ENABLE(DRAGGABLE_REGION) is disabled
 fast/css/draggable-region-parser.html [ WontFix ]
 
+# ENABLE(TEMPLATE_ELEMENT) is disabled.
+webkit.org/b/10357 fast/dom/HTMLTemplateElement [ Skip ]
+webkit.org/b/10357 html5lib/run-template.html [ Skip ]
+
 # These test -apple- and -khtml- prefixed CSS properties, which we don't support.
 inspector/styles/vendor-prefixes.html [ WontFix ]
 fast/css/apple-prefix.html [ WontFix ]
index e8c3e05..9892e72 100644 (file)
@@ -432,6 +432,10 @@ fast/dom/shadow
 editing/shadow
 inspector/elements/update-shadowdom.html
 
+# ENABLE(TEMPLATE_ELEMENT) is disabled.
+fast/dom/HTMLTemplateElement
+html5lib/run-template.html
+
 # JSC does not support setIsolatedWorldSecurityOrigin (http://webkit.org/b/61540)
 http/tests/security/isolatedWorld/cross-origin-xhr.html
 
index 4bba4a1..8cd575f 100644 (file)
@@ -188,6 +188,10 @@ fast/dom/shadow
 fast/frames/detached-shadow-frame.html
 inspector/elements/update-shadowdom.html
 
+# ENABLE(TEMPLATE_ELEMENT) is disabled.
+fast/dom/HTMLTemplateElement
+html5lib/run-template.html
+
 # Fail until SUBPIXEL_LAYOUT is enabled
 # https://bugs.webkit.org/show_bug.cgi?id=85532
 fast/sub-pixel
index ba818d6..a9022a9 100644 (file)
@@ -1527,6 +1527,10 @@ fast/regions/style-scoped-in-flow.html
 editing/shadow
 fast/dom/shadow
 
+# ENABLE(TEMPLATE_ELEMENT) is disabled.
+fast/dom/HTMLTemplateElement
+html5lib/run-template.html
+
 # CSS Regions support not yet enabled. http://webkit.org/b/57312
 fast/regions
 
index 3a7c20e..b12adb5 100644 (file)
@@ -2062,6 +2062,10 @@ fast/regions/style-scoped-in-flow.html
 editing/shadow
 fast/dom/shadow
 
+# ENABLE(TEMPLATE_ELEMENT) is disabled.
+fast/dom/HTMLTemplateElement
+html5lib/run-template.html
+
 # CSS Regions support not yet enabled. http://webkit.org/b/57312
 fast/regions
 
index 53a001f..c7fdf17 100644 (file)
@@ -220,16 +220,24 @@ Markup._get = function(node, depth)
     case Node.DOCUMENT_FRAGMENT_NODE:
         if (node.nodeName == "#shadow-root")
           str += "<shadow:root>";
+        else
+          str += "#document-fragment";
     }
-
-    for (var i = 0, len = node.childNodes.length; i < len; i++) {
-        var selection = Markup._getSelectionMarker(node, i);
-        if (selection)
-            str += Markup._indent(depth + 1) + selection;
-
-        str += Markup._get(node.childNodes[i], depth + 1);
+    
+    
+    // HTML Template elements serialize their content DocumentFragment, and NOT their children.
+    if (node.namespaceURI = 'http://www.w3.org/1999/xhtml' && node.tagName == 'TEMPLATE') {
+        str += Markup._get(node.content, depth + 1);
+    } else {
+        for (var i = 0, len = node.childNodes.length; i < len; i++) {
+            var selection = Markup._getSelectionMarker(node, i);
+            if (selection)
+                str += Markup._indent(depth + 1) + selection;
+    
+            str += Markup._get(node.childNodes[i], depth + 1);
+        }
     }
-
+    
     str += Markup._getShadowHostIfPossible(node, depth);
     
     var selection = Markup._getSelectionMarker(node, i);
@@ -284,7 +292,7 @@ Markup._NAMESPACE_URI_MAP = {
 
 Markup._getSelectionFromNode = function(node)
 {
-    return node.ownerDocument.defaultView.getSelection();
+    return node.ownerDocument.defaultView ? node.ownerDocument.defaultView.getSelection() : null;
 }
 
 Markup._SELECTION_FOCUS = '<#selection-focus>';
index 9d10dc4..950a360 100644 (file)
@@ -488,6 +488,7 @@ SET(WebCore_IDL_FILES
     html/HTMLTableElement.idl
     html/HTMLTableRowElement.idl
     html/HTMLTableSectionElement.idl
+    html/HTMLTemplateElement.idl
     html/HTMLTextAreaElement.idl
     html/HTMLTitleElement.idl
     html/HTMLTrackElement.idl
@@ -1431,6 +1432,7 @@ SET(WebCore_SOURCES
     html/HTMLTableRowElement.cpp
     html/HTMLTableRowsCollection.cpp
     html/HTMLTableSectionElement.cpp
+    html/HTMLTemplateElement.cpp
     html/HTMLTextAreaElement.cpp
     html/HTMLTextFormControlElement.cpp
     html/HTMLTitleElement.cpp
index 29e340b..596d743 100644 (file)
@@ -1,3 +1,89 @@
+2012-12-03  Rafael Weinstein  <rafaelw@chromium.org>
+
+        Implement HTMLTemplateElement
+        https://bugs.webkit.org/show_bug.cgi?id=86031
+
+        Reviewed by Adam Barth.
+
+        Initial implementation. This patch includes the parser changes, new IDL and element implementation for <template>.
+
+        Spec: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html
+
+        Tests: fast/dom/HTMLTemplateElement/cloneNode.html
+               fast/dom/HTMLTemplateElement/inertContents.html
+               fast/dom/HTMLTemplateElement/innerHTML.html
+               fast/dom/HTMLTemplateElement/ownerDocument.html
+               html5lib/run-template.html
+
+        * WebCore.gypi:
+        * css/html.css:
+        (template):
+        * dom/Document.cpp:
+        (WebCore):
+        (WebCore::Document::templateContentsOwnerDocument):
+        * dom/Document.h:
+        (Document):
+        * editing/MarkupAccumulator.cpp:
+        (WebCore::MarkupAccumulator::serializeNodesWithNamespaces):
+        * html/HTMLElement.h:
+        (HTMLElement):
+        * html/HTMLElementsAllInOne.cpp:
+        * html/HTMLTagNames.in:
+        * html/HTMLTemplateElement.cpp: Added.
+        (WebCore):
+        (WebCore::HTMLTemplateElement::HTMLTemplateElement):
+        (WebCore::HTMLTemplateElement::setInnerHTML):
+        (WebCore::HTMLTemplateElement::~HTMLTemplateElement):
+        (WebCore::HTMLTemplateElement::create):
+        (WebCore::HTMLTemplateElement::content):
+        (WebCore::HTMLTemplateElement::setContent):
+        (WebCore::toHTMLTemplateElement):
+        * html/HTMLTemplateElement.h: Added.
+        (WebCore):
+        (HTMLTemplateElement):
+        (WebCore::toHTMLTemplateElement):
+        * html/HTMLTemplateElement.idl: Added.
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::executeTask):
+        (WebCore::HTMLConstructionSite::insertComment):
+        (WebCore::HTMLConstructionSite::insertTextNode):
+        (WebCore::HTMLConstructionSite::createElement):
+        (WebCore::HTMLConstructionSite::ownerDocumentForCurrentNode):
+        (WebCore):
+        (WebCore::HTMLConstructionSite::createHTMLElement):
+        (WebCore::HTMLConstructionSite::findFosterSite):
+        * html/parser/HTMLConstructionSite.h:
+        (HTMLConstructionSite):
+        * html/parser/HTMLElementStack.cpp:
+        (WebCore):
+        (WebCore::HTMLElementStack::hasTemplateInHTMLScope):
+        * html/parser/HTMLElementStack.h:
+        (HTMLElementStack):
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::HTMLTreeBuilder::constructTreeFromToken):
+        (WebCore::HTMLTreeBuilder::processStartTagForInBody):
+        (WebCore):
+        (WebCore::HTMLTreeBuilder::processTemplateEndTag):
+        (WebCore::HTMLTreeBuilder::processStartTagForInTable):
+        (WebCore::HTMLTreeBuilder::processStartTag):
+        (WebCore::HTMLTreeBuilder::processHtmlStartTagForInBody):
+        (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately):
+        (WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
+        (WebCore::HTMLTreeBuilder::processEndTagForInRow):
+        (WebCore::HTMLTreeBuilder::processEndTagForInCell):
+        (WebCore::HTMLTreeBuilder::processEndTagForInBody):
+        (WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
+        (WebCore::HTMLTreeBuilder::processTableEndTagForInTable):
+        (WebCore::HTMLTreeBuilder::processEndTag):
+        (WebCore::HTMLTreeBuilder::processCharacterBuffer):
+        (WebCore::HTMLTreeBuilder::processEndOfFile):
+        (WebCore::HTMLTreeBuilder::processStartTagForInHead):
+        * html/parser/HTMLTreeBuilder.h:
+        (HTMLTreeBuilder):
+        (WebCore::HTMLTreeBuilder::isParsingTemplateContents):
+        (WebCore::HTMLTreeBuilder::isParsingFragmentOrTemplateContents):
+        * page/DOMWindow.idl:
+
 2012-12-03  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r136460.
index e536fd1..7baa5f8 100644 (file)
@@ -348,6 +348,7 @@ BINDING_IDLS = \
     $(WebCore)/html/HTMLTableElement.idl \
     $(WebCore)/html/HTMLTableRowElement.idl \
     $(WebCore)/html/HTMLTableSectionElement.idl \
+    $(WebCore)/html/HTMLTemplateElement.idl \
     $(WebCore)/html/HTMLTextAreaElement.idl \
     $(WebCore)/html/HTMLTitleElement.idl \
     $(WebCore)/html/HTMLTrackElement.idl \
index f17f846..5af7ef5 100644 (file)
@@ -431,6 +431,8 @@ webcore_built_sources += \
        DerivedSources/WebCore/JSHTMLTableRowElement.h \
        DerivedSources/WebCore/JSHTMLTableSectionElement.cpp \
        DerivedSources/WebCore/JSHTMLTableSectionElement.h \
+       DerivedSources/WebCore/JSHTMLTemplateElement.cpp \
+       DerivedSources/WebCore/JSHTMLTemplateElement.h \
        DerivedSources/WebCore/JSHTMLTextAreaElement.cpp \
        DerivedSources/WebCore/JSHTMLTextAreaElement.h \
        DerivedSources/WebCore/JSHTMLTitleElement.cpp \
@@ -1489,6 +1491,7 @@ dom_binding_idls += \
        $(WebCore)/html/HTMLTableElement.idl \
        $(WebCore)/html/HTMLTableRowElement.idl \
        $(WebCore)/html/HTMLTableSectionElement.idl \
+       $(WebCore)/html/HTMLTemplateElement.idl \
        $(WebCore)/html/HTMLTextAreaElement.idl \
        $(WebCore)/html/HTMLTitleElement.idl \
        $(WebCore)/html/HTMLTrackElement.idl \
@@ -3437,6 +3440,8 @@ webcore_sources += \
        Source/WebCore/html/HTMLTableRowsCollection.h \
        Source/WebCore/html/HTMLTableSectionElement.cpp \
        Source/WebCore/html/HTMLTableSectionElement.h \
+       Source/WebCore/html/HTMLTemplateElement.cpp \
+       Source/WebCore/html/HTMLTemplateElement.h \
        Source/WebCore/html/HTMLTextAreaElement.cpp \
        Source/WebCore/html/HTMLTextAreaElement.h \
        Source/WebCore/html/HTMLTextFormControlElement.cpp \
index 79bbdf9..299021c 100644 (file)
@@ -659,6 +659,7 @@ SOURCES += \
     html/HTMLTableRowElement.cpp \
     html/HTMLTableRowsCollection.cpp \
     html/HTMLTableSectionElement.cpp \
+    html/HTMLTemplateElement.cpp \
     html/HTMLTextAreaElement.cpp \
     html/HTMLTextFormControlElement.cpp \
     html/HTMLTitleElement.cpp \
@@ -1825,6 +1826,7 @@ HEADERS += \
     html/HTMLTableRowElement.h \
     html/HTMLTableRowsCollection.h \
     html/HTMLTableSectionElement.h \
+    html/HTMLTemplateElement.h \
     html/HTMLTextAreaElement.h \
     html/HTMLTextFormControlElement.h \
     html/HTMLTitleElement.h \
index 128f87c..dbffa54 100644 (file)
             'html/HTMLTableRowElement.idl',
             'html/HTMLTableSectionElement.idl',
             'html/HTMLTextAreaElement.idl',
+            'html/HTMLTemplateElement.idl',
             'html/HTMLTitleElement.idl',
             'html/HTMLTrackElement.idl',
             'html/HTMLUListElement.idl',
             'html/HTMLTableRowsCollection.h',
             'html/HTMLTableSectionElement.cpp',
             'html/HTMLTableSectionElement.h',
+            'html/HTMLTemplateElement.cpp',
+            'html/HTMLTemplateElement.h',
             'html/HTMLTextAreaElement.cpp',
             'html/HTMLTextFormControlElement.cpp',
             'html/HTMLTitleElement.cpp',
index 95dbddf..e99480c 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="$(ConfigurationBuildDir)\obj\$(ProjectName)\DerivedSources\JSHTMLTemplateElement.cpp"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_All|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Production|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="$(ConfigurationBuildDir)\obj\$(ProjectName)\DerivedSources\JSHTMLTemplateElement.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="$(ConfigurationBuildDir)\obj\$(ProjectName)\DerivedSources\JSHTMLTextAreaElement.cpp"
                                >
                                <FileConfiguration
                                >
                        </File>
                        <File
+                               RelativePath="..\html\HTMLTemplateElement.cpp"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_All|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Production|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\html\HTMLTemplateElement.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\html\HTMLTextAreaElement.cpp"
                                >
                                <FileConfiguration
index edc4624..70fe378 100644 (file)
                D6E276AE14637455001D280A /* MutationObserverRegistration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutationObserverRegistration.h; sourceTree = "<group>"; };
                D6E528A1149A926D00EFE1F3 /* MutationObserverInterestGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MutationObserverInterestGroup.cpp; sourceTree = "<group>"; };
                D6E528A2149A926D00EFE1F3 /* MutationObserverInterestGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutationObserverInterestGroup.h; sourceTree = "<group>"; };
+               D6EFC0BB1666DF7A003D291E /* HTMLTemplateElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLTemplateElement.cpp; sourceTree = "<group>"; };
+               D6EFC0BC1666DF7A003D291E /* HTMLTemplateElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTemplateElement.h; sourceTree = "<group>"; };
+               D6EFC0BD1666DF7A003D291E /* HTMLTemplateElement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLTemplateElement.idl; sourceTree = "<group>"; };
                D6FDAEF2149C06190037B1E1 /* HistogramSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HistogramSupport.cpp; sourceTree = "<group>"; };
                D6FDAEF2149C06190037B1E2 /* StatsCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StatsCounter.cpp; sourceTree = "<group>"; };
                D6FDAEF2149C06190037B1E3 /* MemoryUsageSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryUsageSupport.cpp; sourceTree = "<group>"; };
                                A871DB170A150BD600B12A68 /* HTMLTableSectionElement.h */,
                                8555425C0AA48B1E00BA89F2 /* HTMLTableSectionElement.idl */,
                                519FE0A20DAD446E00A08F21 /* HTMLTagNames.in */,
+                               D6EFC0BB1666DF7A003D291E /* HTMLTemplateElement.cpp */,
+                               D6EFC0BC1666DF7A003D291E /* HTMLTemplateElement.h */,
+                               D6EFC0BD1666DF7A003D291E /* HTMLTemplateElement.idl */,
                                A81369BB097374F500D74463 /* HTMLTextAreaElement.cpp */,
                                A81369BA097374F500D74463 /* HTMLTextAreaElement.h */,
                                A80E7E160A1A7CCB007FB8C5 /* HTMLTextAreaElement.idl */,
index 4a1e335..fea7c87 100644 (file)
@@ -1262,6 +1262,12 @@ summary::-webkit-details-marker {
     margin-right: 0.4em;
 }
 
+#if defined(ENABLE_TEMPLATE_ELEMENT) && ENABLE_TEMPLATE_ELEMENT
+template {
+    display: none
+}
+#endif
+
 bdi, output {
     unicode-bidi: -webkit-isolate;
 }
index a40e81d..b6b91ba 100644 (file)
@@ -310,6 +310,7 @@ void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChil
     ASSERT(newChild);
     ASSERT(nextChild);
     ASSERT(nextChild->parentNode() == this);
+    ASSERT(document() == newChild->document());
 
     NodeVector targets;
     collectTargetNodes(newChild.get(), targets);
@@ -695,6 +696,7 @@ void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild)
 {
     ASSERT(newChild);
     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
+    ASSERT(document() == newChild->document());
 
     Node* last = m_lastChild;
     {
index 3fb6ec4..ca2a24e 100644 (file)
@@ -5888,4 +5888,22 @@ Locale& Document::getCachedLocale(const AtomicString& locale)
     return *(result.iterator->value);
 }
 
+#if ENABLE(TEMPLATE_ELEMENT)
+Document* Document::templateContentsOwnerDocument()
+{
+    // If DOCUMENT does not have a browsing context, Let TEMPLATE CONTENTS OWNER be DOCUMENT and abort these steps.
+    if (!m_frame)
+        return this;
+
+    if (!m_templateContentsOwnerDocument) {
+        if (isHTMLDocument())
+            m_templateContentsOwnerDocument = HTMLDocument::create(0, blankURL());
+        else
+            m_templateContentsOwnerDocument = Document::create(0, blankURL());
+    }
+
+    return m_templateContentsOwnerDocument.get();
+}
+#endif
+
 } // namespace WebCore
index 27ec3cf..f5b8ccd 100644 (file)
@@ -1172,6 +1172,10 @@ public:
     const Vector<RefPtr<Element> >& topLayerElements() const { return m_topLayerElements; }
 #endif
 
+#if ENABLE(TEMPLATE_ELEMENT)
+    Document* templateContentsOwnerDocument();
+#endif
+
 protected:
     Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
 
@@ -1527,6 +1531,10 @@ private:
 
     typedef HashMap<AtomicString, OwnPtr<Locale> > LocaleIdentifierToLocaleMap;
     LocaleIdentifierToLocaleMap m_localeCache;
+
+#if ENABLE(TEMPLATE_ELEMENT)
+    RefPtr<Document> m_templateContentsOwnerDocument;
+#endif
 };
 
 inline void Document::notifyRemovePendingSheetIfNeeded()
index beb832f..c766fff 100644 (file)
@@ -34,6 +34,7 @@
 #include "Editor.h"
 #include "HTMLElement.h"
 #include "HTMLNames.h"
+#include "HTMLTemplateElement.h"
 #include "KURL.h"
 #include "ProcessingInstruction.h"
 #include "XLinkNames.h"
@@ -141,7 +142,12 @@ void MarkupAccumulator::serializeNodesWithNamespaces(Node* targetNode, Node* nod
         appendStartTag(targetNode, &namespaceHash);
 
     if (!(targetNode->document()->isHTMLDocument() && elementCannotHaveEndTag(targetNode))) {
-        for (Node* current = targetNode->firstChild(); current; current = current->nextSibling())
+#if ENABLE(TEMPLATE_ELEMENT)
+        Node* current = targetNode->hasTagName(templateTag) ? toHTMLTemplateElement(targetNode)->content()->firstChild() : targetNode->firstChild();
+#else
+        Node* current = targetNode->firstChild();
+#endif
+        for ( ; current; current = current->nextSibling())
             serializeNodesWithNamespaces(current, nodeToSkip, IncludeNode, &namespaceHash, tagNamesToSkip);
     }
 
index 87b7e26..bcd4f1d 100644 (file)
@@ -44,6 +44,7 @@
 #include "HTMLFormElement.h"
 #include "HTMLNames.h"
 #include "HTMLParserIdioms.h"
+#include "HTMLTemplateElement.h"
 #include "HTMLTextFormControlElement.h"
 #include "RenderWordBreak.h"
 #include "ScriptEventListener.h"
@@ -343,8 +344,14 @@ String HTMLElement::outerHTML() const
 
 void HTMLElement::setInnerHTML(const String& html, ExceptionCode& ec)
 {
-    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, this, AllowScriptingContent, ec))
-        replaceChildrenWithFragment(this, fragment.release(), ec);
+    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, this, AllowScriptingContent, ec)) {
+        ContainerNode* container = this;
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (hasLocalName(templateTag))
+            container = toHTMLTemplateElement(this)->content();
+#endif
+        replaceChildrenWithFragment(container, fragment.release(), ec);
+    }
 }
 
 static void mergeWithNextTextNode(PassRefPtr<Node> node, ExceptionCode& ec)
index d517c84..7f3b3f4 100644 (file)
 #include "HTMLTablePartElement.cpp"
 #include "HTMLTableRowElement.cpp"
 #include "HTMLTableSectionElement.cpp"
+#include "HTMLTemplateElement.cpp"
 #include "HTMLTextAreaElement.cpp"
 #include "HTMLTextFormControlElement.cpp"
 #include "HTMLTitleElement.cpp"
index 85a1e61..d623dd9 100644 (file)
@@ -124,6 +124,7 @@ sup interfaceName=HTMLElement
 table
 tbody interfaceName=HTMLTableSectionElement
 td interfaceName=HTMLTableCellElement
+template conditional=TEMPLATE_ELEMENT
 textarea interfaceName=HTMLTextAreaElement, constructorNeedsFormElement
 tfoot interfaceName=HTMLTableSectionElement
 th interfaceName=HTMLTableCellElement
diff --git a/Source/WebCore/html/HTMLTemplateElement.cpp b/Source/WebCore/html/HTMLTemplateElement.cpp
new file mode 100644 (file)
index 0000000..afd329e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 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"
+
+#if ENABLE(TEMPLATE_ELEMENT)
+
+#include "HTMLTemplateElement.h"
+
+#include "DOMImplementation.h"
+#include "DocumentFragment.h"
+#include "HTMLDocument.h"
+#include "markup.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+inline HTMLTemplateElement::HTMLTemplateElement(const QualifiedName& tagName, Document* document)
+    : HTMLElement(tagName, document)
+{
+}
+
+HTMLTemplateElement::~HTMLTemplateElement()
+{
+}
+
+PassRefPtr<HTMLTemplateElement> HTMLTemplateElement::create(const QualifiedName& tagName, Document* document)
+{
+    return adoptRef(new HTMLTemplateElement(tagName, document));
+}
+
+DocumentFragment* HTMLTemplateElement::content() const
+{
+    if (!m_content)
+        m_content = DocumentFragment::create(ownerDocument()->templateContentsOwnerDocument());
+
+    return m_content.get();
+}
+
+// FIXME: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20127 (prevent DOM hierarchy cycles).
+// FIXME: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20129 (extended adoptNode to consider template.content).
+void HTMLTemplateElement::setContent(PassRefPtr<DocumentFragment> prpContent, ExceptionCode& ec)
+{
+    RefPtr<DocumentFragment> content = prpContent;
+
+    if (!content || content->isShadowRoot()) {
+        ec = TYPE_MISMATCH_ERR;
+        return;
+    }
+
+    if (m_content.get() == content.get())
+        return;
+
+    if (content->ownerDocument() != ownerDocument()->templateContentsOwnerDocument())
+        ownerDocument()->templateContentsOwnerDocument()->adoptNode(content, ASSERT_NO_EXCEPTION);
+
+    m_content = content;
+}
+
+#ifndef NDEBUG
+const HTMLTemplateElement* toHTMLTemplateElement(const Node* node)
+{
+    ASSERT(!node || (node->isHTMLElement() && node->hasTagName(templateTag)));
+    return static_cast<const HTMLTemplateElement*>(node);
+}
+#endif
+
+} // namespace WebCore
+
+#endif // ENABLE(TEMPLATE_ELEMENT)
diff --git a/Source/WebCore/html/HTMLTemplateElement.h b/Source/WebCore/html/HTMLTemplateElement.h
new file mode 100644 (file)
index 0000000..6ef913e
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#ifndef HTMLTemplateElement_h
+#define HTMLTemplateElement_h
+
+#if ENABLE(TEMPLATE_ELEMENT)
+
+#include "DocumentFragment.h"
+#include "HTMLElement.h"
+
+namespace WebCore {
+
+class HTMLTemplateElement : public HTMLElement {
+public:
+    static PassRefPtr<HTMLTemplateElement> create(const QualifiedName&, Document*);
+    virtual ~HTMLTemplateElement();
+
+    DocumentFragment* content() const;
+
+    void setContent(PassRefPtr<DocumentFragment>, ExceptionCode&);
+
+private:
+    HTMLTemplateElement(const QualifiedName&, Document*);
+
+    mutable RefPtr<DocumentFragment> m_content;
+};
+
+const HTMLTemplateElement* toHTMLTemplateElement(const Node*);
+
+inline HTMLTemplateElement* toHTMLTemplateElement(Node* node)
+{
+    return const_cast<HTMLTemplateElement*>(toHTMLTemplateElement(static_cast<const Node*>(node)));
+}
+
+#ifdef NDEBUG
+
+// The debug version of this, with assertions, is not inlined.
+inline const HTMLTemplateElement* toHTMLTemplateElement(const Node* node)
+{
+    return static_cast<const HTMLTemplateElement*>(node);
+}
+#endif // NDEBUG
+
+} // namespace WebCore
+
+#endif // ENABLE(TEMPLATE_ELEMENT)
+
+#endif // HTMLTemplateElement_h
diff --git a/Source/WebCore/html/HTMLTemplateElement.idl b/Source/WebCore/html/HTMLTemplateElement.idl
new file mode 100644 (file)
index 0000000..7a5836d
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+[
+    Conditional=TEMPLATE_ELEMENT
+] interface HTMLTemplateElement : HTMLElement {
+    attribute DocumentFragment content setter raises (DOMException);
+};
+
index 9c182ba..62269de 100644 (file)
@@ -40,6 +40,7 @@
 #include "HTMLParserIdioms.h"
 #include "HTMLScriptElement.h"
 #include "HTMLStackItem.h"
+#include "HTMLTemplateElement.h"
 #include "HTMLToken.h"
 #include "HTMLTokenizer.h"
 #include "LocalizedStrings.h"
@@ -77,6 +78,11 @@ static inline bool isAllWhitespace(const String& string)
 
 static inline void executeTask(HTMLConstructionSiteTask& task)
 {
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (task.parent->hasTagName(templateTag))
+        task.parent = toHTMLTemplateElement(task.parent.get())->content();
+#endif
+
     if (task.nextChild)
         task.parent->parserInsertBefore(task.child.get(), task.nextChild.get());
     else
@@ -247,7 +253,7 @@ void HTMLConstructionSite::insertDoctype(AtomicHTMLToken* token)
 void HTMLConstructionSite::insertComment(AtomicHTMLToken* token)
 {
     ASSERT(token->type() == HTMLTokenTypes::Comment);
-    attachLater(currentNode(), Comment::create(currentNode()->document(), token->comment()));
+    attachLater(currentNode(), Comment::create(ownerDocumentForCurrentNode(), token->comment()));
 }
 
 void HTMLConstructionSite::insertCommentOnDocument(AtomicHTMLToken* token)
@@ -325,7 +331,7 @@ void HTMLConstructionSite::insertScriptElement(AtomicHTMLToken* token)
     // those flags or effects thereof.
     const bool parserInserted = m_fragmentScriptingPermission != AllowScriptingContentAndDoNotMarkAlreadyStarted;
     const bool alreadyStarted = m_isParsingFragment && parserInserted;
-    RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, currentNode()->document(), parserInserted, alreadyStarted);
+    RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, ownerDocumentForCurrentNode(), parserInserted, alreadyStarted);
     if (m_fragmentScriptingPermission != DisallowScriptingContent)
         element->parserSetAttributes(token->attributes(), m_fragmentScriptingPermission);
     attachLater(currentNode(), element);
@@ -351,6 +357,11 @@ void HTMLConstructionSite::insertTextNode(const String& characters, WhitespaceMo
     if (shouldFosterParent())
         findFosterSite(task);
 
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (task.parent->hasTagName(templateTag))
+        task.parent = toHTMLTemplateElement(task.parent.get())->content();
+#endif
+
     // Strings composed entirely of whitespace are likely to be repeated.
     // Turn them into AtomicString so we share a single string for each.
     bool shouldUseAtomicString = whitespaceMode == AllWhitespace
@@ -387,18 +398,27 @@ void HTMLConstructionSite::insertTextNode(const String& characters, WhitespaceMo
 PassRefPtr<Element> HTMLConstructionSite::createElement(AtomicHTMLToken* token, const AtomicString& namespaceURI)
 {
     QualifiedName tagName(nullAtom, token->name(), namespaceURI);
-    RefPtr<Element> element = currentNode()->document()->createElement(tagName, true);
+    RefPtr<Element> element = ownerDocumentForCurrentNode()->createElement(tagName, true);
     element->parserSetAttributes(token->attributes(), m_fragmentScriptingPermission);
     return element.release();
 }
 
+inline Document* HTMLConstructionSite::ownerDocumentForCurrentNode()
+{
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (currentNode()->hasTagName(templateTag))
+        return toHTMLTemplateElement(currentElement())->content()->document();
+#endif
+    return currentNode()->document();
+}
+
 PassRefPtr<Element> HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token)
 {
     QualifiedName tagName(nullAtom, token->name(), xhtmlNamespaceURI);
     // FIXME: This can't use HTMLConstructionSite::createElement because we
     // have to pass the current form element.  We should rework form association
     // to occur after construction to allow better code sharing here.
-    RefPtr<Element> element = HTMLElementFactory::createHTMLElement(tagName, currentNode()->document(), form(), true);
+    RefPtr<Element> element = HTMLElementFactory::createHTMLElement(tagName, ownerDocumentForCurrentNode(), form(), true);
     element->parserSetAttributes(token->attributes(), m_fragmentScriptingPermission);
     ASSERT(element->isHTMLElement());
     return element.release();
@@ -462,6 +482,15 @@ void HTMLConstructionSite::generateImpliedEndTags()
 
 void HTMLConstructionSite::findFosterSite(HTMLConstructionSiteTask& task)
 {
+#if ENABLE(TEMPLATE_ELEMENT)
+    // When a node is to be foster parented, the last template element with no table element is below it in the stack of open elements is the foster parent element (NOT the template's parent!)
+    HTMLElementStack::ElementRecord* lastTemplateElement = m_openElements.topmost(templateTag.localName());
+    if (lastTemplateElement && !m_openElements.inTableScope(tableTag)) {
+        task.parent = lastTemplateElement->element();
+        return;
+    }
+#endif
+
     HTMLElementStack::ElementRecord* lastTableElementRecord = m_openElements.topmost(tableTag.localName());
     if (lastTableElementRecord) {
         Element* lastTableElement = lastTableElementRecord->element();
index 60572bd..df32590 100644 (file)
@@ -114,9 +114,10 @@ public:
     ContainerNode* currentNode() const { return m_openElements.topNode(); }
     HTMLStackItem* currentStackItem() const { return m_openElements.topStackItem(); }
     HTMLStackItem* oneBelowTop() const { return m_openElements.oneBelowTop(); }
-
+    Document* ownerDocumentForCurrentNode();
     HTMLElementStack* openElements() const { return &m_openElements; }
     HTMLFormattingElementList* activeFormattingElements() const { return &m_activeFormattingElements; }
+    bool currentIsRootNode() { return m_openElements.topNode() == m_openElements.rootNode(); }
 
     Element* head() const { return m_head->element(); }
     HTMLStackItem* headStackItem() const { return m_head.get(); }
index 6c220c9..b804677 100644 (file)
@@ -38,14 +38,15 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-static inline bool isRootNode(HTMLStackItem* item)
+
+namespace {
+
+inline bool isRootNode(HTMLStackItem* item)
 {
     return item->isDocumentFragmentNode()
         || item->hasTagName(htmlTag);
 }
 
-namespace {
-
 inline bool isScopeMarker(HTMLStackItem* item)
 {
     return item->hasTagName(appletTag)
@@ -64,6 +65,9 @@ inline bool isScopeMarker(HTMLStackItem* item)
         || item->hasTagName(SVGNames::foreignObjectTag)
         || item->hasTagName(SVGNames::descTag)
         || item->hasTagName(SVGNames::titleTag)
+#if ENABLE(TEMPLATE_ELEMENT)
+        || item->hasTagName(templateTag)
+#endif
         || isRootNode(item);
 }
 
@@ -77,6 +81,9 @@ inline bool isListItemScopeMarker(HTMLStackItem* item)
 inline bool isTableScopeMarker(HTMLStackItem* item)
 {
     return item->hasTagName(tableTag)
+#if ENABLE(TEMPLATE_ELEMENT)
+        || item->hasTagName(templateTag)
+#endif
         || isRootNode(item);
 }
 
@@ -85,12 +92,18 @@ inline bool isTableBodyScopeMarker(HTMLStackItem* item)
     return item->hasTagName(tbodyTag)
         || item->hasTagName(tfootTag)
         || item->hasTagName(theadTag)
+#if ENABLE(TEMPLATE_ELEMENT)
+        || item->hasTagName(templateTag)
+#endif
         || isRootNode(item);
 }
 
 inline bool isTableRowScopeMarker(HTMLStackItem* item)
 {
     return item->hasTagName(trTag)
+#if ENABLE(TEMPLATE_ELEMENT)
+        || item->hasTagName(templateTag)
+#endif
         || isRootNode(item);
 }
 
@@ -527,6 +540,13 @@ bool HTMLElementStack::inSelectScope(const QualifiedName& tagName) const
     return inSelectScope(tagName.localName());
 }
 
+#if ENABLE(TEMPLATE_ELEMENT)
+bool HTMLElementStack::hasTemplateInHTMLScope() const
+{
+    return inScopeCommon<isRootNode>(m_top.get(), templateTag.localName());
+}
+#endif
+
 Element* HTMLElementStack::htmlElement() const
 {
     ASSERT(m_rootNode);
index 873cbde..2c0db13 100644 (file)
@@ -150,7 +150,9 @@ public:
 
     bool hasOnlyOneElement() const;
     bool secondElementIsHTMLBodyElement() const;
-
+#if ENABLE(TEMPLATE_ELEMENT)
+    bool hasTemplateInHTMLScope() const;
+#endif
     Element* htmlElement() const;
     Element* headElement() const;
     Element* bodyElement() const;
index c78562b..6974c64 100644 (file)
@@ -41,6 +41,7 @@
 #include "HTMLParserIdioms.h"
 #include "HTMLScriptElement.h"
 #include "HTMLStackItem.h"
+#include "HTMLTemplateElement.h"
 #include "HTMLToken.h"
 #include "HTMLTokenizer.h"
 #include "LocalizedStrings.h"
@@ -360,7 +361,7 @@ void HTMLTreeBuilder::constructTreeFromToken(HTMLToken& rawToken)
     // synchronously re-enters the parser. We don't clear the token immedately
     // for Character tokens because the AtomicHTMLToken avoids copying the
     // characters by keeping a pointer to the underlying buffer in the
-    // HTMLToken. Fortuantely, Character tokens can't cause use to re-enter
+    // HTMLToken. Fortunately, Character tokens can't cause use to re-enter
     // the parser.
     //
     // FIXME: Stop clearing the rawToken once we start running the parser off
@@ -672,8 +673,12 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
     }
     if (token->name() == bodyTag) {
         parseError(token);
-        if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
-            ASSERT(isParsingFragment());
+        bool fragmentOrTemplateCase = !m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement();
+#if ENABLE(TEMPLATE_ELEMENT)
+        fragmentOrTemplateCase = fragmentOrTemplateCase || m_tree.openElements()->hasTemplateInHTMLScope();
+#endif
+        if (fragmentOrTemplateCase) {
+            ASSERT(isParsingFragmentOrTemplateContents());
             return;
         }
         m_framesetOk = false;
@@ -683,7 +688,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
     if (token->name() == framesetTag) {
         parseError(token);
         if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
-            ASSERT(isParsingFragment());
+            ASSERT(isParsingFragmentOrTemplateContents());
             return;
         }
         if (!m_framesetOk)
@@ -944,13 +949,43 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
         parseError(token);
         return;
     }
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (token->name() == templateTag) {
+        processTemplateStartTag(token);
+        return;
+    }
+#endif
     m_tree.reconstructTheActiveFormattingElements();
     m_tree.insertHTMLElement(token);
 }
 
+#if ENABLE(TEMPLATE_ELEMENT)
+
+void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken* token)
+{
+    m_tree.activeFormattingElements()->appendMarker();
+    m_tree.insertHTMLElement(token);
+    setInsertionMode(TemplateContentsMode);
+}
+
+void HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken* token)
+{
+    if (!m_tree.openElements()->inScope(token->name())) {
+        parseError(token);
+        return;
+    }
+    m_tree.generateImpliedEndTags();
+    if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        parseError(token);
+    m_tree.openElements()->popUntilPopped(token->name());
+    m_tree.activeFormattingElements()->clearToLastMarker();
+    resetInsertionModeAppropriately();
+}
+#endif
+
 bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
 {
-    if (m_tree.currentNode() == m_tree.openElements()->rootNode()) {
+    if (m_tree.currentIsRootNode()) {
         ASSERT(isParsingFragment());
         // FIXME: parse error
         return false;
@@ -1012,7 +1047,7 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken* token)
     if (token->name() == tableTag) {
         parseError(token);
         if (!processTableEndTagForInTable()) {
-            ASSERT(isParsingFragment());
+            ASSERT(isParsingFragmentOrTemplateContents());
             return;
         }
         processStartTag(token);
@@ -1039,6 +1074,12 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken* token)
         m_tree.openElements()->pop();
         return;
     }
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (token->name() == templateTag) {
+        processTemplateStartTag(token);
+        return;
+    }
+#endif
     parseError(token);
     HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
     processStartTagForInBody(token);
@@ -1153,6 +1194,12 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             m_tree.insertSelfClosingHTMLElement(token);
             return;
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateStartTag(token);
+            return;
+        }
+#endif
         if (!processColgroupEndTagForInColumnGroup()) {
             ASSERT(isParsingFragment());
             return;
@@ -1177,7 +1224,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name())) {
             // FIXME: This is slow.
             if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
-                ASSERT(isParsingFragment());
+                ASSERT(isParsingFragmentOrTemplateContents());
                 parseError(token);
                 return;
             }
@@ -1202,7 +1249,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             || isCaptionColOrColgroupTag(token->name())
             || isTableBodyContextTag(token->name())) {
             if (!processTrEndTagForInRow()) {
-                ASSERT(isParsingFragment());
+                ASSERT(isParsingFragmentOrTemplateContents());
                 return;
             }
             ASSERT(insertionMode() == InTableBodyMode);
@@ -1280,6 +1327,12 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             processStartTagForInHead(token);
             return;
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateStartTag(token);
+            return;
+        }
+#endif
         parseError(token);
         break;
     case AfterFramesetMode:
@@ -1359,6 +1412,12 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             ASSERT_UNUSED(didProcess, didProcess);
             return;
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateStartTag(token);
+            return;
+        }
+#endif
         break;
     case InTableTextMode:
         defaultForInTableText();
@@ -1367,12 +1426,51 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
     case TextMode:
         ASSERT_NOT_REACHED();
         break;
+    case TemplateContentsMode:
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateStartTag(token);
+            return;
+        }
+
+        if (token->name() == linkTag
+            || token->name() == scriptTag
+            || token->name() == styleTag
+            || token->name() == metaTag) {
+            processStartTagForInHead(token);
+            return;
+        }
+
+        if (token->name() == frameTag)
+            setInsertionMode(InFramesetMode);
+        else if (token->name() == colTag)
+            setInsertionMode(InColumnGroupMode);
+        else if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name()))
+            setInsertionMode(InTableMode);
+        else if (token->name() == trTag)
+            setInsertionMode(InTableBodyMode);
+        else if (isTableCellContextTag(token->name()))
+            setInsertionMode(InRowMode);
+        else
+            setInsertionMode(InBodyMode);
+
+        processStartTag(token);
+#else
+        ASSERT_NOT_REACHED();
+#endif
+        break;
     }
 }
 
 void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken* token)
 {
     parseError(token);
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (m_tree.openElements()->hasTemplateInHTMLScope()) {
+        ASSERT(isParsingTemplateContents());
+        return;
+    }
+#endif
     m_tree.insertHTMLHtmlStartTagInBody(token);
 }
 
@@ -1542,8 +1640,12 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
             last = true;
             item = HTMLStackItem::create(m_fragmentContext.contextElement(), HTMLStackItem::ItemForContextElement);
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        // FIXME: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20130 (should <template> clear the "implied context element".
+        if (item->hasTagName(templateTag))
+            return setInsertionMode(TemplateContentsMode);
+#endif
         if (item->hasTagName(selectTag)) {
-            ASSERT(isParsingFragment());
             return setInsertionMode(InSelectMode);
         }
         if (item->hasTagName(tdTag) || item->hasTagName(thTag))
@@ -1555,19 +1657,20 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
         if (item->hasTagName(captionTag))
             return setInsertionMode(InCaptionMode);
         if (item->hasTagName(colgroupTag)) {
-            ASSERT(isParsingFragment());
             return setInsertionMode(InColumnGroupMode);
         }
         if (item->hasTagName(tableTag))
             return setInsertionMode(InTableMode);
         if (item->hasTagName(headTag)) {
-            ASSERT(isParsingFragment());
+#if ENABLE(TEMPLATE_ELEMENT)
+            if (!m_fragmentContext.fragment() || m_fragmentContext.contextElement() != item->node())
+                return setInsertionMode(InHeadMode);
+#endif
             return setInsertionMode(InBodyMode);
         }
         if (item->hasTagName(bodyTag))
             return setInsertionMode(InBodyMode);
         if (item->hasTagName(framesetTag)) {
-            ASSERT(isParsingFragment());
             return setInsertionMode(InFramesetMode);
         }
         if (item->hasTagName(htmlTag)) {
@@ -1598,7 +1701,7 @@ void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken* token)
     if (token->name() == tableTag) {
         // FIXME: This is slow.
         if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
-            ASSERT(isParsingFragment());
+            ASSERT(isParsingFragmentOrTemplateContents());
             parseError(token);
             return;
         }
@@ -1628,7 +1731,7 @@ void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken* token)
     }
     if (token->name() == tableTag) {
         if (!processTrEndTagForInRow()) {
-            ASSERT(isParsingFragment());
+            ASSERT(isParsingFragmentOrTemplateContents());
             return;
         }
         ASSERT(insertionMode() == InTableBodyMode);
@@ -1681,7 +1784,11 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
         || token->name() == trTag
         || isTableBodyContextTag(token->name())) {
         if (!m_tree.openElements()->inTableScope(token->name())) {
+#if ENABLE(TEMPLATE_ELEMENT)
+            ASSERT(isTableBodyContextTag(token->name()) || m_tree.openElements()->inTableScope(templateTag) || isParsingFragment());
+#else
             ASSERT(isTableBodyContextTag(token->name()) || isParsingFragment());
+#endif
             parseError(token);
             return;
         }
@@ -1821,6 +1928,12 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
         processFakeStartTag(brTag);
         return;
     }
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (token->name() == templateTag) {
+        processTemplateEndTag(token);
+        return;
+    }
+#endif
     processAnyOtherEndTagForInBody(token);
 }
 
@@ -1842,7 +1955,7 @@ bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
 bool HTMLTreeBuilder::processTrEndTagForInRow()
 {
     if (!m_tree.openElements()->inTableScope(trTag.localName())) {
-        ASSERT(isParsingFragment());
+        ASSERT(isParsingFragmentOrTemplateContents());
         // FIXME: parse error
         return false;
     }
@@ -1856,7 +1969,7 @@ bool HTMLTreeBuilder::processTrEndTagForInRow()
 bool HTMLTreeBuilder::processTableEndTagForInTable()
 {
     if (!m_tree.openElements()->inTableScope(tableTag)) {
-        ASSERT(isParsingFragment());
+        ASSERT(isParsingFragmentOrTemplateContents());
         // FIXME: parse error.
         return false;
     }
@@ -1913,6 +2026,15 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
         // Fall through.
     case InHeadMode:
         ASSERT(insertionMode() == InHeadMode);
+        // FIXME: This case should be broken out into processEndTagForInHead,
+        // because other end tag cases now refer to it ("process the token for using the rules of the "in head" insertion mode").
+        // but because the logic falls through to AfterHeadMode, that gets a little messy.
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateEndTag(token);
+            return;
+        }
+#endif
         if (token->name() == headTag) {
             m_tree.openElements()->popHTMLHeadElement();
             setInsertionMode(AfterHeadMode);
@@ -1977,6 +2099,12 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             parseError(token);
             return;
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateEndTag(token);
+            return;
+        }
+#endif
         if (!processColgroupEndTagForInColumnGroup()) {
             ASSERT(isParsingFragment());
             return;
@@ -2052,7 +2180,12 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
     case InFramesetMode:
         ASSERT(insertionMode() == InFramesetMode);
         if (token->name() == framesetTag) {
-            if (m_tree.currentNode() == m_tree.openElements()->rootNode()) {
+            bool ignoreFramesetForFragmentParsing  = m_tree.currentIsRootNode();
+#if ENABLE(TEMPLATE_ELEMENT)
+            ignoreFramesetForFragmentParsing = ignoreFramesetForFragmentParsing || m_tree.openElements()->hasTemplateInHTMLScope();
+#endif
+            if (ignoreFramesetForFragmentParsing) {
+                ASSERT(isParsingFragmentOrTemplateContents());
                 parseError(token);
                 return;
             }
@@ -2061,6 +2194,12 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
                 setInsertionMode(AfterFramesetMode);
             return;
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateEndTag(token);
+            return;
+        }
+#endif
         break;
     case AfterFramesetMode:
         ASSERT(insertionMode() == AfterFramesetMode);
@@ -2119,11 +2258,32 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             resetInsertionModeAppropriately();
             return;
         }
+#if ENABLE(TEMPLATE_ELEMENT)
+        if (token->name() == templateTag) {
+            processTemplateEndTag(token);
+            return;
+        }
+#endif
         break;
     case InTableTextMode:
         defaultForInTableText();
         processEndTag(token);
         break;
+    case TemplateContentsMode:
+#if ENABLE(TEMPLATE_ELEMENT)
+        // FIXME: https://www.w3.org/Bugs/Public/show_bug.cgi?id=19966
+        if (token->name() == templateTag) {
+            ASSERT(m_tree.currentStackItem()->hasTagName(templateTag));
+            m_tree.openElements()->pop();
+            resetInsertionModeAppropriately();
+            return;
+        }
+        setInsertionMode(InBodyMode);
+        processEndTag(token);
+#else
+        ASSERT_NOT_REACHED();
+#endif
+        break;
     }
 }
 
@@ -2224,8 +2384,14 @@ ReprocessBuffer:
     }
     case InBodyMode:
     case InCaptionMode:
+    case TemplateContentsMode:
     case InCellMode: {
+#if ENABLE(TEMPLATE_ELEMENT)
+        ASSERT(insertionMode() == InBodyMode || insertionMode() == InCaptionMode || insertionMode() == InCellMode || insertionMode() == TemplateContentsMode);
+#else
+        ASSERT(insertionMode() != TemplateContentsMode);
         ASSERT(insertionMode() == InBodyMode || insertionMode() == InCaptionMode || insertionMode() == InCellMode);
+#endif
         processCharacterBufferForInBody(buffer);
         break;
     }
@@ -2360,7 +2526,12 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
     case InCellMode:
     case InCaptionMode:
     case InRowMode:
+#if ENABLE(TEMPLATE_ELEMENT)
+        ASSERT(insertionMode() == InBodyMode || insertionMode() == InCellMode || insertionMode() == InCaptionMode || insertionMode() == InRowMode || insertionMode() == TemplateContentsMode);
+#else
+        ASSERT(insertionMode() != TemplateContentsMode);
         ASSERT(insertionMode() == InBodyMode || insertionMode() == InCellMode || insertionMode() == InCaptionMode || insertionMode() == InRowMode);
+#endif
         notImplemented(); // Emit parse error based on what elements are still open.
         break;
     case AfterBodyMode:
@@ -2386,7 +2557,7 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
             parseError(token);
         break;
     case InColumnGroupMode:
-        if (m_tree.currentNode() == m_tree.openElements()->rootNode()) {
+        if (m_tree.currentIsRootNode()) {
             ASSERT(isParsingFragment());
             return; // FIXME: Should we break here instead of returning?
         }
@@ -2409,6 +2580,16 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
         setInsertionMode(m_originalInsertionMode);
         processEndOfFile(token);
         return;
+    case TemplateContentsMode:
+        if (m_tree.currentIsRootNode()) {
+            ASSERT(isParsingFragment());
+            break;
+        }
+        parseError(token);
+        m_tree.openElements()->pop();
+        resetInsertionModeAppropriately();
+        processEndOfFile(token);
+        return;
     }
     ASSERT(m_tree.currentNode());
     m_tree.openElements()->popAll();
@@ -2512,6 +2693,12 @@ bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken* token)
             processFakeEndTag(scriptTag);
         return true;
     }
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (token->name() == templateTag) {
+        processTemplateStartTag(token);
+        return true;
+    }
+#endif
     if (token->name() == headTag) {
         parseError(token);
         return true;
index 8ff0f58..213e7e0 100644 (file)
@@ -67,6 +67,12 @@ public:
     ~HTMLTreeBuilder();
 
     bool isParsingFragment() const { return !!m_fragmentContext.fragment(); }
+#if ENABLE(TEMPLATE_ELEMENT)
+    bool isParsingTemplateContents() const { return m_tree.openElements()->hasTemplateInHTMLScope(); }
+    bool isParsingFragmentOrTemplateContents() const { return isParsingFragment() || isParsingTemplateContents(); }
+#else
+    bool isParsingFragmentOrTemplateContents() const { return isParsingFragment(); }
+#endif
 
     void detach();
 
@@ -97,6 +103,7 @@ private:
         InHeadMode,
         InHeadNoscriptMode,
         AfterHeadMode,
+        TemplateContentsMode,
         InBodyMode,
         TextMode,
         InTableMode,
@@ -190,6 +197,11 @@ private:
 
     void resetInsertionModeAppropriately();
 
+#if ENABLE(TEMPLATE_ELEMENT)
+    void processTemplateStartTag(AtomicHTMLToken*);
+    void processTemplateEndTag(AtomicHTMLToken*);
+#endif
+
     class FragmentParsingContext {
         WTF_MAKE_NONCOPYABLE(FragmentParsingContext);
     public:
index 4a3a5f4..918f480 100644 (file)
     attribute HTMLTableElementConstructor HTMLTableElement;
     attribute HTMLTableRowElementConstructor HTMLTableRowElement;
     attribute HTMLTableSectionElementConstructor HTMLTableSectionElement;
+    attribute [Conditional=TEMPLATE_ELEMENT] HTMLTemplateElementConstructor HTMLTemplateElement;
     attribute HTMLTextAreaElementConstructor HTMLTextAreaElement;
     attribute HTMLTitleElementConstructor HTMLTitleElement;
     attribute HTMLUListElementConstructor HTMLUListElement;
index 01431c6..5a36a79 100644 (file)
@@ -1,3 +1,14 @@
+2012-12-03  Rafael Weinstein  <rafaelw@chromium.org>
+
+        Implement HTMLTemplateElement
+        https://bugs.webkit.org/show_bug.cgi?id=86031
+
+        Reviewed by Adam Barth.
+
+        Turning on HTMLTemplateElement for chromium port.
+
+        * features.gypi:
+
 2012-12-03  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r136460.
index 621d4ce..20fb8d1 100644 (file)
       'ENABLE_STYLE_SCOPED=1',
       'ENABLE_SVG=<(enable_svg)',
       'ENABLE_SVG_FONTS=<(enable_svg)',
-      'ENABLE_TEMPLATE_ELEMENT=0',
+      'ENABLE_TEMPLATE_ELEMENT=1',
       'ENABLE_TEXT_AUTOSIZING=1',
       'ENABLE_TOUCH_ADJUSTMENT=1',
       'ENABLE_TOUCH_EVENTS=<(enable_touch_events)',
index 68d673c..7730cbb 100644 (file)
@@ -395,7 +395,7 @@ my @features = (
       define => "USE_SYSTEM_MALLOC", default => isWinCE(), value => \$systemMallocSupport },
 
     { option => "template-tag", desc => "Toggle Templates Tag support",
-      define => "ENABLE_TEMPLATE_ELEMENT", default => !isAppleWinWebKit(), value => \$templateTagSupport },
+      define => "ENABLE_TEMPLATE_ELEMENT", default => 0, value => \$templateTagSupport },
 
     { option => "text-autosizing", desc => "Toggle Text Autosizing support",
       define => "ENABLE_TEXT_AUTOSIZING", default => 0, value => \$textAutosizingSupport },