diff --git a/CHANGELOG.md b/CHANGELOG.md index c8d2e42..16820f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * Handle null/undefined/negative values in `CharacterData` interface methods * More spec-correctness fixes for `DOMTokenList` * Fix `[src=...]` selectors +* Spec-correctness fixes for `Document#createElement()` and + `Document#createElementNS()` # domino 2.0.3 (12 Jul 2018) * Define `blur()`, `focus()` and `forceSpellCheck()` on `HTMLElement` (#125) diff --git a/lib/Document.js b/lib/Document.js index 0c627d1..4bd61e5 100644 --- a/lib/Document.js +++ b/lib/Document.js @@ -146,35 +146,54 @@ Document.prototype = Object.create(ContainerNode.prototype, { }}, createElement: { value: function(localName) { + localName = String(localName); if (!xml.isValidName(localName)) utils.InvalidCharacterError(); - if (this.isHTML) localName = utils.toASCIILowerCase(localName); - return html.createElement(this, localName, null); + // Per spec, namespace should be HTML namespace if "context object is + // an HTML document or context object's content type is + // "application/xhtml+xml", and null otherwise. + // XXX we don't track "context object's content type" + if (this.isHTML) { + localName = utils.toASCIILowerCase(localName); + return html.createElement(this, localName, null); + } else { + return new Element(this, localName, null, null); + } }, writable: isApiWritable }, createElementNS: { value: function(namespace, qualifiedName) { - if (!xml.isValidName(qualifiedName)) utils.InvalidCharacterError(); - if (!xml.isValidQName(qualifiedName)) utils.NamespaceError(); - var pos, prefix, localName; - if ((pos = qualifiedName.indexOf(':')) !== -1) { + // Convert parameter types according to WebIDL + namespace = + (namespace === null || namespace === undefined || namespace === '') ? null : + String(namespace); + qualifiedName = String(qualifiedName); + // See https://github.com/whatwg/dom/issues/671 + // and https://github.com/whatwg/dom/issues/319 + if (!xml.isValidQName(qualifiedName)) { + utils.InvalidCharacterError(); + } + + prefix = null; + localName = qualifiedName; + + pos = qualifiedName.indexOf(':'); + if (pos >= 0) { prefix = qualifiedName.substring(0, pos); localName = qualifiedName.substring(pos+1); - - if (namespace === '' || - (prefix === 'xml' && namespace !== NAMESPACE.XML)) - utils.NamespaceError(); } - else { - prefix = null; - localName = qualifiedName; + if (prefix !== null && namespace === null) { + utils.NamespaceError(); } - - if (((qualifiedName === 'xmlns' || prefix === 'xmlns') && - namespace !== NAMESPACE.XMLNS) || - (namespace === NAMESPACE.XMLNS && - qualifiedName !== 'xmlns' && - prefix !== 'xmlns')) + if (prefix === 'xml' && namespace !== NAMESPACE.XML) { + utils.NamespaceError(); + } + if ((prefix === 'xmlns' || qualifiedName === 'xmlns') && + namespace !== NAMESPACE.XMLNS) { utils.NamespaceError(); + } + if (namespace === NAMESPACE.XMLNS && !(prefix==='xmlns' || qualifiedName==='xmlns')) { + utils.NamespaceError(); + } if (namespace === NAMESPACE.HTML) { return html.createElement(this, localName, prefix);