@@ -1,5 +1,6 @@
"use strict";

const idlUtils = require("../generated/utils");
const NodeImpl = require("./Node-impl").implementation;

const DOMException = require("../../web-idl/DOMException");
@@ -85,7 +86,7 @@ class CharacterDataImpl extends NodeImpl {
this._ownerDocument.implementation._hasFeature("MutationEvents")) {
const ev = this._ownerDocument.createEvent("MutationEvents");
ev.initMutationEvent("DOMCharacterDataModified", true, false, this, oldData, newData, null, null);
this.dispatchEvent(ev);
this.dispatchEvent(idlUtils.implForWrapper(ev));
}
}
}
@@ -1,10 +1,10 @@
"use strict";

const NodeImpl = require("./Node-impl").implementation;
const CharacterDataImpl = require("./CharacterData-impl").implementation;

const NODE_TYPE = require("../node-type");

class CommentImpl extends NodeImpl {
class CommentImpl extends CharacterDataImpl {
constructor(args, privateData) {
super(args, privateData);

@@ -27,6 +27,7 @@ const Comment = require("../generated/Comment");
const ProcessingInstruction = require("../generated/ProcessingInstruction");
const Text = require("../generated/Text");
const DocumentFragment = require("../generated/DocumentFragment");
const ParentNodeImpl = require("./ParentNode-impl").implementation;

function clearChildNodes(node) {
for (let child = domSymbolTree.firstChild(node); child; child = domSymbolTree.firstChild(node)) {
@@ -302,10 +303,10 @@ class DocumentImpl extends NodeImpl {
}

_createElementWithCorrectElementInterface(name, namespace) {
const wrapper = idlUtils.wrapperForImpl(this);
// https://dom.spec.whatwg.org/#concept-element-interface
// TODO: eventually we should re-write the element-builder system to be namespace aware, but for now it is not.
return (this._elementBuilders[name.toLowerCase()] || this._defaultElementBuilder.bind(this))(wrapper, name, namespace);
const elem = (this._elementBuilders[name.toLowerCase()] || this._defaultElementBuilder.bind(this))(this, name, namespace);
return idlUtils.implForWrapper(elem);
}

appendChild(/* Node */ arg) {
@@ -525,7 +526,7 @@ class DocumentImpl extends NodeImpl {
"Processing instruction data cannot contain the string \"?>\"");
}

return ProcessingInstruction.create([], {
return ProcessingInstruction.createImpl([], {
core: this._core,
ownerDocument: this,
target,
@@ -534,17 +535,17 @@ class DocumentImpl extends NodeImpl {
}

createTextNode(data) {
return Text.create([], {
return Text.createImpl([], {
core: this._core,
ownerDocument: idlUtils.wrapperForImpl(this),
ownerDocument: this,
data
});
}

createComment(data) {
return Comment.create([], {
return Comment.createImpl([], {
core: this._core,
ownerDocument: idlUtils.wrapperForImpl(this),
ownerDocument: this,
data
});
}
@@ -576,7 +577,7 @@ class DocumentImpl extends NodeImpl {
}

createDocumentFragment() {
return DocumentFragment.create([], { ownerDocument: idlUtils.wrapperForImpl(this) });
return DocumentFragment.createImpl([], { ownerDocument: this });
}

createAttribute(localName) {
@@ -586,7 +587,7 @@ class DocumentImpl extends NodeImpl {
localName = localName.toLowerCase();
}

return generatedAttr.create([], { localName });
return generatedAttr.createImpl([], { localName });
}

createAttributeNS(namespace, name) {
@@ -596,7 +597,7 @@ class DocumentImpl extends NodeImpl {
namespace = namespace !== null ? String(namespace) : namespace;

const extracted = validateAndExtract(namespace, name);
return generatedAttr.create([], {
return generatedAttr.createImpl([], {
namespace: extracted.namespace,
namespacePrefix: extracted.prefix,
localName: extracted.localName
@@ -628,6 +629,8 @@ class DocumentImpl extends NodeImpl {
}
}

idlUtils.mixin(DocumentImpl.prototype, ParentNodeImpl.prototype);

DocumentImpl._removingSteps = [];

DocumentImpl.prototype._elementBuilders = Object.create(null);
@@ -1,6 +1,8 @@
"use strict";

const idlUtils = require("../generated/utils");
const NodeImpl = require("./Node-impl").implementation;
const ParentNodeImpl = require("./ParentNode-impl").implementation;

const NODE_TYPE = require("../node-type");

@@ -12,6 +14,8 @@ class DocumentFragmentImpl extends NodeImpl {
}
}

idlUtils.mixin(DocumentFragmentImpl.prototype, ParentNodeImpl.prototype);

module.exports = {
implementation: DocumentFragmentImpl
};
@@ -1,6 +1,8 @@
"use strict";

const idlUtils = require("../generated/utils");
const NodeImpl = require("./Node-impl").implementation;
const ParentNodeImpl = require("./ParentNode-impl").implementation;
const attributes = require("../attributes");
const NODE_TYPE = require("../node-type");
const domToHtml = require("../../browser/domtohtml").domToHtml;
@@ -194,7 +196,7 @@ class ElementImpl extends NodeImpl {
const attribute = attributes.getAttributeByName(this, name);

if (attribute === null) {
const newAttr = attrGenerated.create([], { localName: name, value });
const newAttr = attrGenerated.createImpl([], { localName: name, value });
attributes.appendAttribute(this, newAttr);
return;
}
@@ -265,23 +267,23 @@ class ElementImpl extends NodeImpl {
}

setAttributeNode(attr) {
if (!attrGenerated.is(attr)) {
if (!attrGenerated.isImpl(attr)) {
throw new TypeError("First argument to Element.prototype.setAttributeNode must be an Attr");
}

return attributes.setAttribute(this, attr);
}

setAttributeNodeNS(attr) {
if (!attrGenerated.is(attr)) {
if (!attrGenerated.isImpl(attr)) {
throw new TypeError("First argument to Element.prototype.setAttributeNodeNS must be an Attr");
}

return attributes.setAttribute(this, attr);
}

removeAttributeNode(attr) {
if (!attrGenerated.is(attr)) {
if (!attrGenerated.isImpl(attr)) {
throw new TypeError("First argument to Element.prototype.removeAttributeNode must be an Attr");
}

@@ -295,6 +297,8 @@ class ElementImpl extends NodeImpl {
}
}

idlUtils.mixin(ElementImpl.prototype, ParentNodeImpl.prototype);

/* returns NodeList */
ElementImpl.prototype.getElementsByTagName = memoizeQuery(function (name) {
name = name.toLowerCase();
@@ -203,19 +203,16 @@ class NodeImpl extends EventTargetImpl {
return domSymbolTree.previousSibling(this);
}

insertBefore(newChild, refChild) {
if (refChild === undefined) {
refChild = null;
insertBefore(newChildImpl, refChildImpl) {
if (refChildImpl === undefined) {
refChildImpl = null;
}

const newChildImpl = idlUtils.implForWrapper(newChild);
const refChildImpl = refChild ? idlUtils.implForWrapper(refChild) : null;

// TODO branding
if (!newChild || !("nodeType" in newChild)) {
if (!newChildImpl || !(newChildImpl instanceof NodeImpl)) {
throw new TypeError("First argument to Node.prototype.insertBefore must be a Node");
}
if (refChild !== null && !("nodeType" in refChild)) {
if (refChildImpl !== null && !(refChildImpl instanceof NodeImpl)) {
throw new TypeError("Second argument to Node.prototype.insertBefore must be a Node or null or undefined");
}

@@ -224,16 +221,16 @@ class NodeImpl extends EventTargetImpl {
}

// DocumentType must be implicitly adopted
if (newChild.nodeType === NODE_TYPE.DOCUMENT_TYPE_NODE) {
newChild._ownerDocument = this._ownerDocument;
if (newChildImpl.nodeType === NODE_TYPE.DOCUMENT_TYPE_NODE) {
newChildImpl._ownerDocument = this._ownerDocument;
}

// TODO - if (!newChild) then?
if (this.nodeName !== "#document" && idlUtils.implForWrapper(newChild)._ownerDocument !== this._ownerDocument) {
if (this.nodeName !== "#document" && newChildImpl._ownerDocument !== this._ownerDocument) {
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR);
}

if (newChild.nodeType && newChild.nodeType === NODE_TYPE.ATTRIBUTE_NODE) {
if (newChildImpl.nodeType && newChildImpl.nodeType === NODE_TYPE.ATTRIBUTE_NODE) {
throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR);
}

@@ -245,22 +242,22 @@ class NodeImpl extends EventTargetImpl {
}

// fragments are merged into the element (except parser-created fragments in <template>)
if (newChild.nodeType === NODE_TYPE.DOCUMENT_FRAGMENT_NODE) {
let grandChild;
while ((grandChild = domSymbolTree.firstChild(newChildImpl))) {
newChild.removeChild(idlUtils.wrapperForImpl(grandChild));
this.insertBefore(idlUtils.wrapperForImpl(grandChild), refChild);
if (newChildImpl.nodeType === NODE_TYPE.DOCUMENT_FRAGMENT_NODE) {
let grandChildImpl;
while ((grandChildImpl = domSymbolTree.firstChild(newChildImpl))) {
newChildImpl.removeChild(grandChildImpl);
this.insertBefore(grandChildImpl, refChildImpl);
}
} else if (newChild === refChild) {
return newChild;
} else if (newChildImpl === refChildImpl) {
return newChildImpl;
} else {
const oldParent = domSymbolTree.parent(newChildImpl);
const oldParentImpl = domSymbolTree.parent(newChildImpl);
// if the newChild is already in the tree elsewhere, remove it first
if (oldParent) {
oldParent.removeChild(newChild);
if (oldParentImpl) {
oldParentImpl.removeChild(newChildImpl);
}

if (refChild === null) {
if (refChildImpl === null) {
domSymbolTree.appendChild(this, newChildImpl);
} else {
if (domSymbolTree.parent(refChildImpl) !== this) {
@@ -272,26 +269,29 @@ class NodeImpl extends EventTargetImpl {

this._modified();

if (this._attached && newChild._attach) {
newChild._attach();
if (this._attached && newChildImpl._attach) {
newChildImpl._attach();
}

this._descendantAdded(this, newChild);
this._descendantAdded(this, newChildImpl);
}

if (mutationEventsEnabled(this)) {
const doc = getDocument(this);
let ev = doc.createEvent("MutationEvents");
let ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));
if (ev === undefined) {
console.log(this)
}

ev.initMutationEvent("DOMNodeInserted", true, false, this, null, null, null, null);
newChild.dispatchEvent(ev);
newChildImpl.dispatchEvent(ev);

ev = doc.createEvent("MutationEvents");
ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));
ev.initMutationEvent("DOMSubtreeModified", true, false, this, null, null, null, null);
this.dispatchEvent(ev);

if (this.nodeType === NODE_TYPE.DOCUMENT_NODE || this._attachedToDocument) {
ev = doc.createEvent("MutationEvents");
ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));
ev.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);

for (const el of domSymbolTree.treeIterator(newChildImpl)) {
@@ -303,7 +303,7 @@ class NodeImpl extends EventTargetImpl {
}
}

return newChild;
return newChildImpl;
} // raises(DOMException);

_modified() {
@@ -422,7 +422,7 @@ class NodeImpl extends EventTargetImpl {
// TODO remove MutationEvents completely at some point
if (value !== oldValue && this._ownerDocument &&
this._ownerDocument.implementation._hasFeature("MutationEvents")) {
const ev = this._ownerDocument.createEvent("MutationEvents");
const ev = idlUtils.implForWrapper(this._ownerDocument.createEvent("MutationEvents"));

let attrChange = MutationEvent.MODIFICATION;
if (value === null) {
@@ -443,7 +443,7 @@ class NodeImpl extends EventTargetImpl {

if (mutationEventsEnabled(this) && value !== oldValue) {
const doc = getDocument(this);
const ev = doc.createEvent("MutationEvents");
const ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));

ev.initMutationEvent("DOMSubtreeModified", true, false, this, null, null, null, null);
this.dispatchEvent(ev);
@@ -455,10 +455,10 @@ class NodeImpl extends EventTargetImpl {
throw new TypeError("Not enough arguments to Node.prototype.replaceChild");
}
// TODO branding
if (!node || !("nodeType" in node)) {
if (!node || !(node instanceof NodeImpl)) {
throw new TypeError("First argument to Node.prototype.replaceChild must be a Node");
}
if (!child || !("nodeType" in child)) {
if (!child || !(child instanceof NodeImpl)) {
throw new TypeError("Second argument to Node.prototype.replaceChild must be a Node");
}

@@ -497,46 +497,45 @@ class NodeImpl extends EventTargetImpl {
}
}

removeChild(/* Node */ oldChild) {
removeChild(/* Node */ oldChildImpl) {
if (this._readonly === true) {
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
}

const oldChildImpl = idlUtils.implForWrapper(oldChild);
if (!oldChild || domSymbolTree.parent(oldChildImpl) !== this) {
if (!oldChildImpl || domSymbolTree.parent(oldChildImpl) !== this) {
throw new DOMException(DOMException.NOT_FOUND_ERR);
}

if (mutationEventsEnabled(this)) {
const doc = getDocument(this);
let ev = doc.createEvent("MutationEvents");
let ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));

ev.initMutationEvent("DOMNodeRemoved", true, false, this, null, null, null, null);
oldChild.dispatchEvent(ev);
oldChildImpl.dispatchEvent(ev);

ev = doc.createEvent("MutationEvents");
ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));
ev.initMutationEvent("DOMSubtreeModified", true, false, this, null, null, null, null);
this.dispatchEvent(ev);

ev = doc.createEvent("MutationEvents");
ev = idlUtils.implForWrapper(doc.createEvent("MutationEvents"));
ev.initMutationEvent("DOMNodeRemovedFromDocument", false, false, null, null, null, null, null);
for (const el of domSymbolTree.treeIterator(oldChild)) {
for (const el of domSymbolTree.treeIterator(oldChildImpl)) {
if (el.nodeType === NODE_TYPE.ELEMENT_NODE) {
el.dispatchEvent(ev);
el._attachedToDocument = false;
}
}
}

const oldPreviousSibling = oldChild.previousSibling;
const oldPreviousSibling = oldChildImpl.previousSibling;
domSymbolTree.remove(oldChildImpl);
this._modified();
oldChild._detach();
this._descendantRemoved(this, oldChild);
oldChildImpl._detach();
this._descendantRemoved(this, oldChildImpl);
if (this._ownerDocument) {
this._ownerDocument._runRemovingSteps(oldChild, this, oldPreviousSibling);
this._ownerDocument._runRemovingSteps(oldChildImpl, this, oldPreviousSibling);
}
return oldChild;
return oldChildImpl;
} // raises(DOMException);

appendChild(newChild) {
@@ -560,7 +559,7 @@ class NodeImpl extends EventTargetImpl {

// Level2/core clean off empty nodes
if (child.nodeValue === "") {
this.removeChild(idlUtils.wrapperForImpl(child));
this.removeChild(child);
continue;
}

@@ -569,7 +568,7 @@ class NodeImpl extends EventTargetImpl {
if (prevChild && prevChild.nodeType === NODE_TYPE.TEXT_NODE && child.nodeType === NODE_TYPE.TEXT_NODE) {
// merge text nodes
prevChild.appendData(child.nodeValue);
this.removeChild(idlUtils.wrapperForImpl(child));
this.removeChild(child);
}
}
}
@@ -597,20 +596,19 @@ class NodeImpl extends EventTargetImpl {
return documentBaseURL(this._ownerDocument);
}

compareDocumentPosition(other) {
compareDocumentPosition(otherImpl) {
// Let reference be the context object.
const reference = this;
const otherImpl = idlUtils.implForWrapper(other);

if (!(otherImpl instanceof NodeImpl)) {
throw new Error("Comparing position against non-Node values is not allowed");
}

if (isObsoleteNodeType(reference) || isObsoleteNodeType(other)) {
if (isObsoleteNodeType(reference) || isObsoleteNodeType(otherImpl)) {
throw new Error("Obsolete node type");
}

const result = domSymbolTree.compareTreePosition(reference, other);
const result = domSymbolTree.compareTreePosition(reference, otherImpl);

// “If other and reference are not in the same tree, return the result of adding DOCUMENT_POSITION_DISCONNECTED,
// DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, and either DOCUMENT_POSITION_PRECEDING or
@@ -626,7 +624,7 @@ class NodeImpl extends EventTargetImpl {
}

contains(other) {
return Boolean(idlUtils.implForWrapper(other) instanceof NodeImpl &&
return Boolean(other instanceof NodeImpl &&
(this === other || this.compareDocumentPosition(other) & NODE_DOCUMENT_POSITION.DOCUMENT_POSITION_CONTAINED_BY));
}

@@ -0,0 +1,14 @@
"use strict";

const domSymbolTree = require("../helpers/internal-constants").domSymbolTree;

const createHTMLCollection = require("../html-collection").create;
const updateHTMLCollection = require("../html-collection").update;

class NonElementParentNodeImpl {

}

module.exports = {
implementation: NonElementParentNodeImpl
};
@@ -0,0 +1,7 @@
[NoInterfaceObject,
Exposed=Window]
interface NonElementParentNode {
Element? getElementById(DOMString elementId);
};
Document implements NonElementParentNode;
DocumentFragment implements NonElementParentNode;
@@ -1,6 +1,6 @@
"use strict";

const Text = require("./generated/Text");
const Text = require("./generated/Text").interface;

module.exports = function (core) {
core.Text = Text;