Handle XHTML self-closing void tag behavior

Also wrap createDocument correctly for handling doctypes.

Fixes #278 ShadowDOM.js causing unclosed img tags in XHTML
This commit is contained in:
Daniel Freedman
2015-04-10 12:24:59 -07:00
parent 9e5c7b527d
commit ffba906cf2
4 changed files with 43 additions and 6 deletions

View File

@@ -332,6 +332,12 @@
setWrapper(impl, this);
}
var originalCreateDocument = document.implementation.createDocument;
DOMImplementation.prototype.createDocument = function() {
arguments[2] = unwrap(arguments[2]);
return wrap(originalCreateDocument.apply(unsafeUnwrap(this), arguments));
};
function wrapImplMethod(constructor, name) {
var original = document.implementation[name];
constructor.prototype[name] = function() {
@@ -347,7 +353,6 @@
}
wrapImplMethod(DOMImplementation, 'createDocumentType');
wrapImplMethod(DOMImplementation, 'createDocument');
wrapImplMethod(DOMImplementation, 'createHTMLDocument');
forwardImplMethod(DOMImplementation, 'hasFeature');
@@ -356,8 +361,8 @@
forwardMethodsToWrapper([
window.DOMImplementation,
], [
'createDocumentType',
'createDocument',
'createDocumentType',
'createHTMLDocument',
'hasFeature',
]);

View File

@@ -93,6 +93,20 @@
'noscript'
]);
var XHTML_NS = 'http://www.w3.org/1999/xhtml';
function needsSelfClosingSlash(node) {
// if the namespace is not XHTML_NS, this is probably an XML or SVG Document
// and will need a closing slash on void elements
if (node.namespaceURI !== XHTML_NS)
return true;
var doctype = node.ownerDocument.doctype;
// doctype is null for quirksmode documents
// publicId and systemId are required for XHTML, and are null for HTML5
return doctype && doctype.publicId && doctype.systemId;
}
function getOuterHTML(node, parentNode) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
@@ -102,11 +116,14 @@
for (var i = 0, attr; attr = attrs[i]; i++) {
s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
}
s += '>';
if (voidElements[tagName])
return s;
return s + getInnerHTML(node) + '</' + tagName + '>';
if (voidElements[tagName]) {
if (needsSelfClosingSlash(node))
s += '/';
return s + '>';
}
return s + '>' + getInnerHTML(node) + '</' + tagName + '>';
case Node.TEXT_NODE:
var data = node.data;

View File

@@ -33,6 +33,13 @@ htmlSuite('Document', function() {
assert.equal(doc2.lastElementChild.tagName, 'HTML');
});
test('Create XHTML Document', function() {
var docType = wrap(document).implementation.createDocumentType('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd');
var doc = wrap(document).implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', docType);
assert(doc);
});
test('document.documentElement', function() {
var doc = wrap(document);
assert.equal(doc.documentElement.ownerDocument, doc);

View File

@@ -114,4 +114,12 @@ suite('HTMLElement', function() {
div.hidden = false;
assert.isFalse(div.hasAttribute('hidden'));
});
test('img outerHTML in XHTML documents', function() {
var docType = document.implementation.createDocumentType('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd');
var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', docType);
var img = doc.createElement('img');
assert.equal(img.outerHTML, '<img/>');
});
});