📄 domnode.java
字号:
if (event == null) { event = getMutationEvent(); } if (event != null) { doFree = true; } else { event = new DomEvent.DomMutationEvent(null); } event.initMutationEvent("DOMNodeRemoved", true /* bubbles */, false /* nocancel */, this /* related */, null, null, null, (short) 0); target.dispatchEvent(event); // XXX should really visit every descendant of 'target' // and sent a DOMNodeRemovedFromDocument event to it... // bleech, there's no way to keep that acceptably fast. event.target = null; event.relatedNode = null; event.currentNode = null; if (doFree) { eventDataLock = false; } // else we created more work for the GC } // // Avoid creating lots of memory management work, by using a simple // allocation strategy for the mutation event objects that get used // at least once per tree modification. We can't use stack allocation, // so we do the next simplest thing -- more or less, static allocation. // Concurrent notifications should be rare, anyway. // // Returns the preallocated object, which needs to be carefully freed, // or null to indicate the caller needs to allocate their own. // static private DomEvent.DomMutationEvent getMutationEvent() { synchronized (lockNode) { if (eventDataLock) { return null; } eventDataLock = true; return mutationEvent; } } // NOTE: this is manually inlined in the insertion // and removal event methods above; change in sync. static private void freeMutationEvent() { // clear fields to enable GC mutationEvent.clear(); eventDataLock = false; } void setDepth(int depth) { this.depth = depth; for (DomNode ctx = first; ctx != null; ctx = ctx.next) { ctx.setDepth(depth + 1); } } /** * <b>DOM L1</b> * Appends the specified node to this node's list of children. * Document subclasses must override this to enforce the restrictions * that there be only one element and document type child. * * <p> Causes a DOMNodeInserted mutation event to be reported. * Will first cause a DOMNodeRemoved event to be reported if the * parameter already has a parent. If the new child is a document * fragment node, both events will be reported for each child of * the fragment; the order in which children are removed and * inserted is implementation-specific. * * <p> If this DOM has been compiled without mutation event support, * these events will not be reported. */ public Node appendChild(Node newChild) { try { DomNode child = (DomNode) newChild; if (child.nodeType == DOCUMENT_FRAGMENT_NODE) { // Append all nodes in the fragment to this node for (DomNode ctx = child.first; ctx != null; ctx = ctx.next) { checkMisc(ctx); } for (DomNode ctx = child.first; ctx != null; ) { DomNode ctxNext = ctx.next; appendChild(ctx); ctx = ctxNext; } } else { checkMisc(child); if (child.parent != null) { child.parent.removeChild(child); } child.parent = this; child.index = length++; child.setDepth(depth + 1); child.next = null; if (last == null) { first = child; child.previous = null; } else { last.next = child; child.previous = last; } last = child; if (reportMutations) { insertionEvent(null, child); } } return child; } catch (ClassCastException e) { throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR, null, newChild, 0); } } /** * <b>DOM L1</b> * Inserts the specified node in this node's list of children. * Document subclasses must override this to enforce the restrictions * that there be only one element and document type child. * * <p> Causes a DOMNodeInserted mutation event to be reported. Will * first cause a DOMNodeRemoved event to be reported if the newChild * parameter already has a parent. If the new child is a document * fragment node, both events will be reported for each child of * the fragment; the order in which children are removed and inserted * is implementation-specific. * * <p> If this DOM has been compiled without mutation event support, * these events will not be reported. */ public Node insertBefore(Node newChild, Node refChild) { if (refChild == null) { return appendChild(newChild); } try { DomNode child = (DomNode) newChild; DomNode ref = (DomNode) refChild; if (child.nodeType == DOCUMENT_FRAGMENT_NODE) { // Append all nodes in the fragment to this node for (DomNode ctx = child.first; ctx != null; ctx = ctx.next) { checkMisc(ctx); } for (DomNode ctx = child.first; ctx != null; ) { DomNode ctxNext = ctx.next; insertBefore(ctx, ref); ctx = ctxNext; } } else { checkMisc(child); if (ref == null || ref.parent != this) { throw new DomDOMException(DOMException.NOT_FOUND_ERR, null, ref, 0); } if (ref == child) { throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR, "can't insert node before itself", ref, 0); } if (child.parent != null) { child.parent.removeChild(child); } child.parent = this; int i = ref.index; child.setDepth(depth + 1); child.next = ref; if (ref.previous != null) { ref.previous.next = child; } child.previous = ref.previous; ref.previous = child; if (first == ref) { first = child; } // index renumbering for (DomNode ctx = child; ctx != null; ctx = ctx.next) { ctx.index = i++; } if (reportMutations) { insertionEvent(null, child); } } return child; } catch (ClassCastException e) { throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR, null, newChild, 0); } } /** * <b>DOM L1</b> * Replaces the specified node in this node's list of children. * Document subclasses must override this to test the restrictions * that there be only one element and document type child. * * <p> Causes DOMNodeRemoved and DOMNodeInserted mutation event to be * reported. Will cause another DOMNodeRemoved event to be reported if * the newChild parameter already has a parent. These events may be * delivered in any order, except that the event reporting removal * from such an existing parent will always be delivered before the * event reporting its re-insertion as a child of some other node. * The order in which children are removed and inserted is implementation * specific. * * <p> If your application needs to depend on the in which those removal * and insertion events are delivered, don't use this API. Instead, * invoke the removeChild and insertBefore methods directly, to guarantee * a specific delivery order. Similarly, don't use document fragments, * Otherwise your application code may not work on a DOM which implements * this method differently. * * <p> If this DOM has been compiled without mutation event support, * these events will not be reported. */ public Node replaceChild(Node newChild, Node refChild) { try { DomNode child = (DomNode) newChild; DomNode ref = (DomNode) refChild; DomEvent.DomMutationEvent event = getMutationEvent(); boolean doFree = (event != null); if (child.nodeType == DOCUMENT_FRAGMENT_NODE) { // Append all nodes in the fragment to this node for (DomNode ctx = child.first; ctx != null; ctx = ctx.next) { checkMisc(ctx); } if (ref == null || ref.parent != this) { throw new DomDOMException(DOMException.NOT_FOUND_ERR, null, ref, 0); } if (reportMutations) { removalEvent(event, ref); } length--; length += child.length; if (child.length == 0) { // Removal if (ref.previous != null) { ref.previous.next = ref.next; } if (ref.next != null) { ref.next.previous = ref.previous; } if (first == ref) { first = ref.next; } if (last == ref) { last = ref.previous; } } else { int i = ref.index; for (DomNode ctx = child.first; ctx != null; ctx = ctx.next) { // Insertion ctx.parent = this; ctx.index = i++; ctx.setDepth(ref.depth); if (ctx == child.first) { ctx.previous = ref.previous; } if (ctx == child.last) { ctx.next = ref.next; } } if (first == ref) { first = child.first; } if (last == ref) { last = child.last; } } } else { checkMisc(child); if (ref == null || ref.parent != this) { throw new DomDOMException(DOMException.NOT_FOUND_ERR, null, ref, 0); } if (reportMutations) { removalEvent(event, ref); } if (child.parent != null) { child.parent.removeChild(child); } child.parent = this; child.index = ref.index; child.setDepth(ref.depth); if (ref.previous != null) { ref.previous.next = child; } child.previous = ref.previous; if (ref.next != null) { ref.next.previous = child; } child.next = ref.next; if (first == ref) { first = child; } if (last == ref) { last = child; } if (reportMutations) { insertionEvent(event, child); } if (doFree) { freeMutationEvent(); } } ref.parent = null; ref.index = 0; ref.setDepth(0); ref.previous = null; ref.next = null; return ref; } catch (ClassCastException e) { throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR, null, newChild, 0); } } /** * <b>DOM L1</b> * Removes the specified child from this node's list of children, * or else reports an exception. * * <p> Causes a DOMNodeRemoved mutation event to be reported. * * <p> If this DOM has been compiled without mutation event support, * these events will not be reported. */ public Node removeChild(Node refChild) { try { DomNode ref = (DomNode) refChild; if (ref == null || ref.parent != this) { throw new DomDOMException(DOMException.NOT_FOUND_ERR, null, ref, 0); } if (readonly && !owner.building) { throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, null, this, 0); } for (DomNode child = first; child != null; child = child.next) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -