Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

can-dom-mutate

Package Overview
Dependencies
Maintainers
8
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

can-dom-mutate - npm Package Compare versions

Comparing version 1.3.7 to 2.0.0

dist/bundles/can-dom-mutate/test.css

15

-util.js

@@ -32,11 +32,2 @@ "use strict";

function isInDocument (node) {
var root = getDocument();
if (root === node) {
return true;
}
return contains(root, node);
}
function isDocumentElement (node) {

@@ -128,3 +119,3 @@ return getDocument().documentElement === node;

rootNode,
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,
treeWalkerFilter,

@@ -167,3 +158,2 @@ false

eliminate: eliminate,
isInDocument: isInDocument,
getDocument: getDocument,

@@ -176,3 +166,4 @@ isDocumentElement: isDocumentElement,

subscription: subscription,
addToSet: addToSet
addToSet: addToSet,
contains: contains
};

209

can-dom-mutate.js

@@ -16,5 +16,3 @@ 'use strict';

var slice = Array.prototype.slice;
var domMutate, dispatchInsertion, dispatchRemoval;
var domMutate, dispatchInsertion, dispatchRemoval, dispatchAttributeChange;
var dataStore = new WeakMap();

@@ -53,4 +51,4 @@

return function batchAdd(items, callback) {
processBatchItems(items);
return function batchAdd(items, callback, dispatchConnected, flush) {
processBatchItems(items, dispatchConnected, flush);
if(callback){

@@ -114,21 +112,69 @@ callback();

function fire (callbacks, arg) {
var safeCallbacks = slice.call(callbacks, 0);
var safeCallbackCount = safeCallbacks.length;
for (var i = 0; i < safeCallbackCount; i++) {
safeCallbacks[i](arg);
var promise = Promise.resolve();
function nextTick(handler) {
promise.then(handler);
}
var recordsAndCallbacks = null;
function flushCallbacks(callbacks, arg){
var callbacksCount = callbacks.length;
var safeCallbacks = callbacks.slice(0);
for(var c = 0; c < callbacksCount; c++){
safeCallbacks[c](arg);
}
}
function dispatch(listenerKey, documentDataKey) {
return function dispatchEvents(events) {
function flushRecords(){
if(recordsAndCallbacks === null) {
return;
}
var safeBatch = recordsAndCallbacks;
recordsAndCallbacks = null;
var batchCount = safeBatch.length;
for (var i = 0; i < batchCount; i++) {
var batchData = safeBatch[i];
flushCallbacks(batchData.callbacks, batchData.arg);
}
}
function flushAsync(callbacks, arg) {
if(recordsAndCallbacks === null) {
recordsAndCallbacks = [{arg: arg, callbacks: callbacks}];
nextTick(flushRecords);
} else {
recordsAndCallbacks.push({arg: arg, callbacks: callbacks});
}
}
function dispatch(targetKey, connectedKey, documentDataKey) {
return function dispatchEvents(events, dispatchConnected, flush) {
// we could check the first element and see if it's in the document
// if it is conditionally fire "connected" events
for (var e = 0; e < events.length; e++) {
var event = events[e];
var target = event.target;
// we need to check
//
var targetListeners = getTargetListeners(target, targetKey);
var targetListeners = getTargetListeners(target, listenerKey);
if (targetListeners) {
fire(targetListeners, event);
flush(targetListeners, event);
}
if(!dispatchConnected) {
continue;
}
var connectedListeners;
if(connectedKey){
connectedListeners = getTargetListeners(target, connectedKey);
}
if (connectedListeners) {
flush(connectedListeners, event);
}
if (!documentDataKey) {

@@ -140,3 +186,3 @@ continue;

if (documentListeners) {
fire(documentListeners, event);
flush(documentListeners, event);
}

@@ -224,4 +270,4 @@ }

dispatchRemoval( toMutationEvents( canReflect.toArray(removed) ) );
dispatchInsertion( toMutationEvents( canReflect.toArray(added) ) );
dispatchRemoval( toMutationEvents( canReflect.toArray(removed) ), null, true, flushCallbacks );
dispatchInsertion( toMutationEvents( canReflect.toArray(added) ), null, true, flushCallbacks );
}

@@ -237,3 +283,7 @@

var oldValue = mutation.oldValue;
domMutate.dispatchNodeAttributeChange(node, attributeName, oldValue);
dispatchAttributeChange([{
target: node,
attributeName: attributeName,
oldValue: oldValue
}], null, true, flushCallbacks);
}

@@ -273,3 +323,6 @@ }

return function removeNodeListener() {
stopObserving();
if(stopObserving) {
stopObserving();
}
removeTargetListener(target, listenerKey, listener);

@@ -322,9 +375,11 @@ };

// target listener keys
var insertionDataKey = domMutationPrefix + 'InsertionData';
var removalDataKey = domMutationPrefix + 'RemovalData';
var connectedDataKey = domMutationPrefix + 'ConnectedData';
var disconnectedDataKey = domMutationPrefix + 'DisconnectedData';
var insertedDataKey = domMutationPrefix + 'InsertedData';
var removedDataKey = domMutationPrefix + 'RemovedData';
var attributeChangeDataKey = domMutationPrefix + 'AttributeChangeData';
// document listener keys
var documentInsertionDataKey = domMutationPrefix + 'DocumentInsertionData';
var documentRemovalDataKey = domMutationPrefix + 'DocumentRemovalData';
var documentConnectedDataKey = domMutationPrefix + 'DocumentConnectedData';
var documentDisconnectedDataKey = domMutationPrefix + 'DocumentDisconnectedData';
var documentAttributeChangeDataKey = domMutationPrefix + 'DocumentAttributeChangeData';

@@ -336,19 +391,21 @@

dispatchInsertion = batch(dispatch(insertionDataKey, documentInsertionDataKey));
dispatchRemoval = batch(dispatch(removalDataKey, documentRemovalDataKey));
var dispatchAttributeChange = batch(dispatch(attributeChangeDataKey, documentAttributeChangeDataKey));
dispatchInsertion = batch(dispatch(insertedDataKey, connectedDataKey, documentConnectedDataKey));
dispatchRemoval = batch(dispatch(removedDataKey, disconnectedDataKey, documentDisconnectedDataKey));
dispatchAttributeChange = batch(dispatch(attributeChangeDataKey, null , documentAttributeChangeDataKey));
// node listeners
var addNodeInsertionListener = addNodeListener(insertionDataKey, treeDataKey);
var addNodeRemovalListener = addNodeListener(removalDataKey, treeDataKey);
var addNodeConnectedListener = addNodeListener(connectedDataKey, treeDataKey);
var addNodeDisconnectedListener = addNodeListener(disconnectedDataKey, treeDataKey);
var addNodeInsertedListener = addNodeListener(insertedDataKey, treeDataKey);
var addNodeRemovedListener = addNodeListener(removedDataKey, treeDataKey);
var addNodeAttributeChangeListener = addNodeListener(attributeChangeDataKey, attributeDataKey, true);
// global listeners
var addInsertionListener = addGlobalListener(
documentInsertionDataKey,
addNodeInsertionListener
var addConnectedListener = addGlobalListener(
documentConnectedDataKey,
addNodeConnectedListener
);
var addRemovalListener = addGlobalListener(
documentRemovalDataKey,
addNodeRemovalListener
var addDisconnectedListener = addGlobalListener(
documentDisconnectedDataKey,
addNodeDisconnectedListener
);

@@ -373,7 +430,8 @@ var addAttributeChangeListener = addGlobalListener(

*/
dispatchNodeInsertion: function (node, callback) {
dispatchNodeInsertion: function (node, callback, dispatchConnected) {
var nodes = new Set();
util.addToSet( getAllNodes(node), nodes);
var events = toMutationEvents( canReflect.toArray(nodes) );
dispatchInsertion(events, callback);
// this is basically an array of every single child of node including node
dispatchInsertion(events, callback, dispatchConnected, flushAsync);
},

@@ -392,7 +450,7 @@

*/
dispatchNodeRemoval: function (node, callback) {
dispatchNodeRemoval: function (node, callback, dispatchConnected) {
var nodes = new Set();
util.addToSet( getAllNodes(node), nodes);
var events = toMutationEvents( canReflect.toArray(nodes) );
dispatchRemoval(events, callback);
dispatchRemoval(events, callback, dispatchConnected, flushAsync);
},

@@ -425,11 +483,11 @@

oldValue: oldValue
}], callback);
}], callback, true, flushAsync);
},
/**
* @function can-dom-mutate.onNodeInsertion onNodeInsertion
* @function can-dom-mutate.onNodeConnected onNodeConnected
*
* Listen for insertion mutations on the given node.
*
* @signature `onNodeInsertion( node, callback )`
* @signature `onNodeConnected( node, callback )`
* @parent can-dom-mutate.static

@@ -440,10 +498,14 @@ * @param {Node} node The node on which to listen for insertion mutations.

*/
onNodeInsertion: addNodeInsertionListener,
onNodeConnected: addNodeConnectedListener,
onNodeInsertion: function(){
// TODO: remove in prod
console.warn("can-dom-mutate: Use onNodeConnected instead of onNodeInsertion");
return addNodeConnectedListener.apply(this, arguments);
},
/**
* @function can-dom-mutate.onNodeRemoval onNodeRemoval
* @function can-dom-mutate.onNodeDisconnected onNodeDisconnected
*
* Listen for removal mutations on the given node.
*
* @signature `onNodeRemoval( node, callback )`
* @signature `onNodeDisconnected( node, callback )`
* @parent can-dom-mutate.static

@@ -454,4 +516,8 @@ * @param {Node} node The node on which to listen for removal mutations.

*/
onNodeRemoval: addNodeRemovalListener,
onNodeDisconnected: addNodeDisconnectedListener,
onNodeRemoval: function(){
// TODO: remove in prod
console.warn("can-dom-mutate: Use onNodeDisconnected instead of onNodeRemoval");
return addNodeDisconnectedListener.apply(this, arguments);
},
/**

@@ -471,7 +537,7 @@ * @function can-dom-mutate.onNodeAttributeChange onNodeAttributeChange

/**
* @function can-dom-mutate.onRemoval onRemoval
* @function can-dom-mutate.onDisconnected onDisconnected
*
* Listen for removal mutations on any node within the documentElement.
*
* @signature `onRemoval( documentElement, callback )`
* @signature `onDisconnected( documentElement, callback )`
* @parent can-dom-mutate.static

@@ -482,10 +548,14 @@ * @param {Node} documentElement The documentElement on which to listen for removal mutations.

*/
onRemoval: addRemovalListener,
onDisconnected: addDisconnectedListener,
onRemoval: function(){
// TODO: remove in prod
console.warn("can-dom-mutate: Use onDisconnected instead of onRemoval");
return addDisconnectedListener.apply(this, arguments);
},
/**
* @function can-dom-mutate.onInsertion onInsertion
* @function can-dom-mutate.onConnected onConnected
*
* Listen for insertion mutations on any node within the documentElement.
*
* @signature `onInsertion( documentElement, callback )`
* @signature `onConnected( documentElement, callback )`
* @parent can-dom-mutate.static

@@ -496,4 +566,8 @@ * @param {Node} documentElement The documentElement on which to listen for removal mutations.

*/
onInsertion: addInsertionListener,
onConnected: addConnectedListener,
onInsertion: function(){
// TODO: remove in prod
console.warn("can-dom-mutate: Use onConnected instead of onInsertion");
return addConnectedListener.apply(this, arguments);
},
/**

@@ -510,5 +584,28 @@ * @function can-dom-mutate.onAttributeChange onAttributeChange

*/
onAttributeChange: addAttributeChangeListener
onAttributeChange: addAttributeChangeListener,
flushRecords: function(doc){
doc = doc || DOCUMENT();
var data = dataStore.get(doc);
if(data) {
if(data.domMutationTreeData && data.domMutationTreeData.observer) {
var records = data.domMutationTreeData.observer.takeRecords();
handleTreeMutations(records);
}
// flush any synthetic records
flushRecords();
}
},
onNodeInserted: addNodeInsertedListener,
onNodeRemoved: addNodeRemovedListener
};
//!steal-remove-start
if(process.env.NODE_ENV !== "production") {
domMutate.dataStore = dataStore;
}
//!steal-remove-end
module.exports = namespace.domMutate = domMutate;

@@ -21,7 +21,7 @@ @module {{}} can-dom-mutate

// onAttributeChange( documentElement, callback ),
// onInsertion( documentElement, callback ),
// onRemoval( documentElement, callback ),
// onConnected( documentElement, callback ),
// onDisconnected( documentElement, callback ),
// onNodeAttributeChange( node, callback ),
// onNodeInsertion( node, callback ),
// onNodeRemoval( node, callback )
// onNodeConnected( node, callback ),
// onNodeDisconnected( node, callback )
// }

@@ -57,3 +57,3 @@

var teardown = domMutate.onNodeInsertion(element, ()=>{
var teardown = domMutate.onNodeConnected(element, ()=>{
console.log("element inserted!");

@@ -60,0 +60,0 @@ });

@@ -12,2 +12,4 @@ var unit = require('steal-qunit');

QUnit.test('inserted', function (assert) {
// make sure QUnit writing out the page is fully finished.
domMutate.flushRecords();
var done = assert.async();

@@ -19,3 +21,3 @@ var fixture = testUtils.getFixture();

childInsertedHandler,
removeOnInsertionHandler;
removeonConnectedHandler;

@@ -30,4 +32,4 @@ // add inserted event to registry

// clean up handler added by onInsertion
removeOnInsertionHandler ();
// clean up handler added by onConnected
removeonConnectedHandler ();

@@ -52,5 +54,5 @@ // remove inserted event from registry

// listen for any element being inserted and run appropriate test
var onNodeInsertionCount = 0;
removeOnInsertionHandler = domMutate.onInsertion(document.documentElement, function () {
switch(onNodeInsertionCount) {
var onNodeConnectedCount = 0;
removeonConnectedHandler = domMutate.onConnected(document.documentElement, function (arg) {
switch(onNodeConnectedCount) {
case 0:

@@ -62,6 +64,6 @@ assert.equal(insertedEventCount, 1, 'inserted event should trigger for event.currentTarget');

assert.equal(insertedEventCount, 1, 'inserted event should NOT trigger for child of event.currentTarget');
setTimeout(cleanup, 50);
setTimeout(cleanup, 100);
break;
}
onNodeInsertionCount++;
onNodeConnectedCount++;
});

@@ -68,0 +70,0 @@

@@ -80,4 +80,4 @@ 'use strict';

attributes: makeMutationEvent('attributes', domMutate.onNodeAttributeChange),
inserted: makeMutationEvent('inserted', domMutate.onNodeInsertion, false),
removed: makeMutationEvent('removed', domMutate.onNodeRemoval)
inserted: makeMutationEvent('inserted', domMutate.onNodeConnected, false),
removed: makeMutationEvent('removed', domMutate.onNodeDisconnected)
};

@@ -6,2 +6,3 @@ var unit = require('steal-qunit');

var testUtils = require('../test/test-utils');
var makeSimpleDocument = require("can-vdom/make-document/make-document");

@@ -11,2 +12,3 @@ var test = unit.test;

var moduleWithoutMutationObserver = testUtils.moduleWithoutMutationObserver;
var moduleMutationObserver = testUtils.moduleMutationObserver;
var mock = testUtils.mock;

@@ -20,2 +22,48 @@

unit.module("can-dom-mutate/node document selector");
test("isConnected() uses isConnected where available", function(assert) {
assert.expect(4);
var doc = getDocument();
var fakenode = {
get isConnected() {
assert.strictEqual(doc.constructor, getDocument().constructor, "with real document")
return true;
},
get ownerDocument() {
if ('isConnected' in doc) {
assert.notStrictEqual(doc.constructor, getDocument().constructor, "with SimpleDocument")
} else {
// IE 11 doesn't support isConnected, so both isConnected() calls will go through here
assert.ok(true, "Native Node.prototype does not support isConnected");
}
return null;
}
};
assert.ok(node.isConnected(fakenode), "Real document connected");
getDocument(makeSimpleDocument());
assert.ok(node.isConnected(fakenode), "SimpleDocument connected");
getDocument(doc);
});
function onNodeRemovedTest(){
test('removeChild dispatches onNodeRemoved', function (assert) {
var done = assert.async();
var parent = testUtils.getFixture();
var child = document.createElement('div');
parent.appendChild(child);
var undo = domMutate.onNodeRemoved(child, function() {
assert.ok(true, 'this was called');
undo();
done();
});
node.removeChild.call(parent, child);
});
}
moduleMutationObserver('can-dom-mutate/node with real document', getDocument(), onNodeRemovedTest);
moduleMutationObserver('can-dom-mutate/node with SimpleDocument', makeSimpleDocument(), onNodeRemovedTest);
moduleWithMutationObserver('can-dom-mutate/node', function () {

@@ -75,4 +123,6 @@ QUnit.test('appendChild should not call domMutate.dispatchNodeInsertion', function (assert) {

QUnit.test('setAttribute should not call domMutate.dispatchNodeAttributeChange', function (assert) {
var parent = testUtils.getFixture();
var element = document.createElement('div');
var undo = neverCall(assert, domMutate, 'dispatchNodeAttributeChange');
parent.appendChild(element);

@@ -86,4 +136,6 @@ node.setAttribute.call(element, 'data-foo', 'bar');

QUnit.test('removeAttribute should not call domMutate.dispatchNodeAttributeChange', function (assert) {
var parent = testUtils.getFixture();
var element = document.createElement('div');
var undo = neverCall(assert, domMutate, 'dispatchNodeAttributeChange');
parent.appendChild(element);

@@ -99,7 +151,8 @@ node.removeAttribute.call(element, 'data-foo');

moduleWithoutMutationObserver('can-dom-mutate/node', function () {
function withoutMutationObserverTests () {
QUnit.test('appendChild should call domMutate.dispatchNodeInsertion', function (assert) {
var doc = getDocument();
var done = assert.async();
var parent = testUtils.getFixture();
var child = document.createElement('div');
var child = doc.createElement('div');

@@ -118,6 +171,7 @@ var undo = mock(domMutate, 'dispatchNodeInsertion', function (node, callback) {

function getFragmentInsertionTest () {
var fragment = document.createDocumentFragment();
var child1 = document.createElement('div');
var child2 = document.createElement('div');
var grandchild = document.createElement('div');
var doc = getDocument();
var fragment = doc.createDocumentFragment();
var child1 = doc.createElement('div');
var child2 = doc.createElement('div');
var grandchild = doc.createElement('div');
fragment.appendChild(child1);

@@ -153,5 +207,6 @@ fragment.appendChild(child2);

var done = assert.async();
var doc = getDocument();
var parent = testUtils.getFixture();
var sibling = document.createElement('span');
var child = document.createElement('div');
var sibling = doc.createElement('span');
var child = doc.createElement('div');

@@ -172,4 +227,5 @@ var undo = mock(domMutate, 'dispatchNodeInsertion', function (node, callback) {

assert.expect(2);
var doc = getDocument();
var parent = testUtils.getFixture();
var sibling = document.createElement('div');
var sibling = doc.createElement('div');
parent.appendChild(sibling);

@@ -184,4 +240,5 @@

var done = assert.async();
var doc = getDocument();
var parent = testUtils.getFixture();
var child = document.createElement('div');
var child = doc.createElement('div');

@@ -202,5 +259,6 @@ var undo = mock(domMutate, 'dispatchNodeRemoval', function (node, callback) {

var done = assert.async();
var doc = getDocument();
var parent = testUtils.getFixture();
var sibling = document.createElement('span');
var child = document.createElement('div');
var sibling = doc.createElement('span');
var child = doc.createElement('div');
var isSiblingRemoved = false;

@@ -231,4 +289,5 @@

assert.expect(3);
var doc = getDocument();
var parent = testUtils.getFixture();
var sibling = document.createElement('div');
var sibling = doc.createElement('div');
parent.appendChild(sibling);

@@ -249,3 +308,4 @@

var done = assert.async();
var element = document.createElement('div');
var doc = getDocument();
var element = doc.createElement('div');
element.setAttribute('data-foo', 'bar');

@@ -268,3 +328,4 @@

var done = assert.async();
var element = document.createElement('div');
var doc = getDocument();
var element = doc.createElement('div');
element.setAttribute('data-foo', 'bar');

@@ -284,5 +345,8 @@

});
});
};
moduleWithoutMutationObserver('can-dom-mutate/node with real document', getDocument(), withoutMutationObserverTests);
moduleWithoutMutationObserver('can-dom-mutate/node with SimpleDocument', makeSimpleDocument(), withoutMutationObserverTests);
moduleWithoutMutationObserver('can-dom-mutate/node (not in document)', function () {
function notInDocumentTests() {
/*

@@ -302,7 +366,8 @@ We do not want insertion events to dispatched when a node

QUnit.test('appendChild should not call dispatchNodeInsertion', function (assert) {
assert.expect(0);
var fragment = document.createDocumentFragment();
var child = document.createElement('div');
var undo = mock(domMutate, 'dispatchNodeInsertion', function () {
assert.ok(false, 'This should never be called');
assert.expect(1);
var doc = getDocument();
var fragment = doc.createDocumentFragment();
var child = doc.createElement('div');
var undo = mock(domMutate, 'dispatchNodeInsertion', function (el, callback, dispatchConnected) {
assert.equal(dispatchConnected, false, 'We should not dispatch connected things');
});

@@ -315,10 +380,11 @@

QUnit.test('insertBefore should not call dispatchNodeInsertion', function (assert) {
assert.expect(0);
var fragment = document.createDocumentFragment();
var child = document.createElement('div');
var reference = document.createElement('span');
assert.expect(1);
var doc = getDocument();
var fragment = doc.createDocumentFragment();
var child = doc.createElement('div');
var reference = doc.createElement('span');
fragment.appendChild(reference);
var undo = mock(domMutate, 'dispatchNodeInsertion', function () {
assert.ok(false, 'This should never be called');
var undo = mock(domMutate, 'dispatchNodeInsertion', function (el, callback, dispatchConnected) {
assert.equal(dispatchConnected, false, 'We should not dispatch connected things');
});

@@ -331,9 +397,10 @@

QUnit.test('removeChild should not call dispatchNodeRemoval', function (assert) {
assert.expect(0);
var fragment = document.createDocumentFragment();
var child = document.createElement('div');
assert.expect(1);
var doc = getDocument();
var fragment = doc.createDocumentFragment();
var child = doc.createElement('div');
fragment.appendChild(child);
var undo = mock(domMutate, 'dispatchNodeRemoval', function () {
assert.ok(false, 'This should never be called');
var undo = mock(domMutate, 'dispatchNodeRemoval', function (el, callback, dispatchConnected) {
assert.equal(dispatchConnected, false, 'We should not dispatch connected things');
});

@@ -346,13 +413,14 @@

QUnit.test('replaceChild should not call dispatchNodeRemoval+Insertion', function (assert) {
assert.expect(0);
var fragment = document.createDocumentFragment();
var child = document.createElement('div');
var oldChild = document.createElement('span');
assert.expect(2);
var doc = getDocument();
var fragment = doc.createDocumentFragment();
var child = doc.createElement('div');
var oldChild = doc.createElement('span');
fragment.appendChild(oldChild);
var undoRemoval = mock(domMutate, 'dispatchNodeRemoval', function () {
assert.ok(false, 'This should never be called');
var undoRemoval = mock(domMutate, 'dispatchNodeRemoval', function (el, callback, dispatchConnected) {
assert.equal(dispatchConnected, false, 'We should not dispatch connected things');
});
var undoInsertion = mock(domMutate, 'dispatchNodeInsertion', function () {
assert.ok(false, 'This should never be called');
var undoInsertion = mock(domMutate, 'dispatchNodeInsertion', function (el, callback, dispatchConnected) {
assert.equal(dispatchConnected, false, 'We should not dispatch connected things');
});

@@ -367,5 +435,6 @@

var done = assert.async();
var doc1 = document.implementation.createHTMLDocument('doc1');
var doc = getDocument();
var doc1 = doc.implementation.createHTMLDocument('doc1');
getDocument(doc1);
var undo = domMutate.onNodeRemoval(doc1.documentElement, function() {
var undo = domMutate.onNodeDisconnected(doc1.documentElement, function() {
assert.ok(true, 'this was called');

@@ -378,4 +447,6 @@ undo();

node.removeChild.call(doc1, doc1.documentElement);
getDocument(document);
getDocument(doc);
});
});
}
moduleWithoutMutationObserver('can-dom-mutate/node (not in real document)', getDocument(), notInDocumentTests);
moduleWithoutMutationObserver('can-dom-mutate/node (not in SimpleDocument)', makeSimpleDocument(), notInDocumentTests);

@@ -8,17 +8,28 @@ 'use strict';

var isInDocument = util.isInDocument;
var getParents = util.getParents;
var contains = util.contains;
var synthetic = {
dispatchNodeInsertion: function (container, node) {
if (isInDocument(node)) {
domMutate.dispatchNodeInsertion(node);
}
},
dispatchNodeRemoval: function (container, node) {
if (isInDocument(container) && !isInDocument(node)) {
domMutate.dispatchNodeRemoval(node);
}
var isConnected;
function getIsConnectedFromNode(node) {
return node.isConnected;
}
function getIsConnectedFromDocument(node) {
var doc = node.ownerDocument;
// if node *is* the document, ownerDocument is null
// However, CanSimpleDom implements this incorrectly, and a document's ownerDocument is itself,
// so make both checks
return doc === null || doc === node || contains(doc, node);
}
function setIsConnected(doc) {
var node = doc.createTextNode("");
isConnected = 'isConnected' in node.constructor.prototype ?
getIsConnectedFromNode :
getIsConnectedFromDocument;
if(mutate) {
mutate.isConnected = isConnected;
}
};
}
setIsConnected(globals.getKeyValue("document"));
globals.onKeyValue("document", setIsConnected);

@@ -29,5 +40,5 @@ var compat = {

var result = this.replaceChild(newChild, oldChild);
synthetic.dispatchNodeRemoval(this, oldChild);
domMutate.dispatchNodeRemoval(oldChild, null, isConnected(this) && !isConnected(oldChild));
for (var i = 0; i < newChildren.length; i++) {
synthetic.dispatchNodeInsertion(this, newChildren[i]);
domMutate.dispatchNodeInsertion(newChildren[i], null, isConnected(this));
}

@@ -67,3 +78,3 @@ return result;

for (var i = 0; i < nodes.length; i++) {
synthetic[dispatchMethod](this, nodes[i]);
domMutate[dispatchMethod](nodes[i], null, isConnected(this) && (pair[1] === 'Removal' ? !isConnected(nodes[i]) : true));
}

@@ -78,3 +89,7 @@ return result;

normal[methodName] = function () {
return this[methodName].apply(this, arguments);
if(isConnected(this)) {
return this[methodName].apply(this, arguments);
} else {
return compat[methodName].apply(this, arguments);
}
};

@@ -183,2 +198,3 @@ });

var strategy = observer ? normal : compat;
for (var key in strategy) {

@@ -193,2 +209,4 @@ mutate[key] = strategy[key];

mutate.isConnected = isConnected;
module.exports = namespace.domMutateNode = domMutate.node = mutate;
{
"name": "can-dom-mutate",
"description": "Dispatch and listen for DOM mutations",
"version": "1.3.7",
"version": "2.0.0",
"author": {

@@ -16,6 +16,9 @@ "name": "DoneJS Team",

"can-namespace": "1.0.0",
"can-reflect": "^1.17.6"
"can-reflect": "^1.17.6",
"can-symbol": "^1.6.4"
},
"devDependencies": {
"can-dom-events": "^1.3.0",
"can-simple-dom": "^1.6.2",
"can-vdom": "^4.4.1",
"fixpack": "^2.3.1",

@@ -22,0 +25,0 @@ "jshint": "^2.9.1",

@@ -8,2 +8,3 @@ var unit = require('steal-qunit');

var MUTATION_OBSERVER = require('can-globals/mutation-observer/mutation-observer');
var makeSimpleDocument = require("can-vdom/make-document/make-document");

@@ -13,9 +14,10 @@ var test = unit.test;

moduleMutationObserver('can-dom-mutate', function () {
test('onNodeInsertion should be called when that node is inserted', function (assert) {
function mutationObserverTests() {
test('onNodeConnected should be called when that node is inserted', function (assert) {
var done = assert.async();
var doc = globals.getKeyValue('document');
var parent = testUtils.getFixture();
var child = document.createElement('div');
var child = doc.createElement('div');
var undo = domMutate.onNodeInsertion(child, function (mutation) {
var undo = domMutate.onNodeConnected(child, function (mutation) {
var node = mutation.target;

@@ -32,8 +34,9 @@ assert.equal(node, child, 'Node should be the inserted child');

test('onNodeRemoval should be called when that node is removed', function (assert) {
test('onNodeDisconnected should be called when that node is removed', function (assert) {
var done = assert.async();
var doc = globals.getKeyValue('document');
var parent = testUtils.getFixture();
var child = document.createElement('div');
var child = doc.createElement('div');
var undo = domMutate.onNodeRemoval(child, function (mutation) {
var undo = domMutate.onNodeDisconnected(child, function (mutation) {
var node = mutation.target;

@@ -52,3 +55,4 @@ assert.equal(node, child, 'Node should be the removed child');

var done = assert.async();
var child = document.createElement('div');
var doc = globals.getKeyValue('document');
var child = doc.createElement('div');
var attributeName = 'foo';

@@ -69,12 +73,15 @@ child.setAttribute(attributeName, 'bar');

test('onInserted should be called when any node is inserted', function (assert) {
test('onConnected should be called when any node is inserted', function (assert) {
var done = assert.async();
var parent = testUtils.getFixture();
var child = document.createElement('div');
var doc = globals.getKeyValue('document');
var child = doc.createElement('div');
var undo = domMutate.onInsertion(document.documentElement, function (mutation) {
assert.equal(mutation.target, child, 'Node should be the inserted child');
var undo = domMutate.onConnected(doc.documentElement, function (mutation) {
if(mutation.target === child) {
assert.ok(true, 'Node should be the inserted child');
undo();
done();
undo();
done();
}
});

@@ -89,8 +96,9 @@

var parent = testUtils.getFixture();
var fragment = document.createDocumentFragment();
var child1 = document.createElement('div');
var doc = globals.getKeyValue('document');
var fragment = doc.createDocumentFragment();
var child1 = doc.createElement('div');
child1.id = 'child1';
var child2 = document.createElement('div');
var child2 = doc.createElement('div');
child2.id = 'child2';
var grandchild = document.createElement('div');
var grandchild = doc.createElement('div');
grandchild.id = 'grandchild';

@@ -103,3 +111,3 @@ fragment.appendChild(child1);

var nodes = [child1, child2, grandchild];
var undo = domMutate.onInsertion(document.documentElement, function (mutation) {
var undo = domMutate.onConnected(doc.documentElement, function (mutation) {
var target = mutation.target;

@@ -127,12 +135,15 @@ if (nodes.indexOf(target) !== -1) {

test('onRemoval should be called when any node is removed', function (assert) {
test('onDisconnected should be called when any node is removed', function (assert) {
var done = assert.async();
var doc = globals.getKeyValue('document');
var parent = testUtils.getFixture();
var child = document.createElement('div');
var child = doc.createElement('div');
var undo = domMutate.onRemoval(document.documentElement, function (mutation) {
assert.equal(mutation.target, child, 'Node should be the removed child');
var undo = domMutate.onDisconnected(doc.documentElement, function (mutation) {
if(mutation.target === child) {
assert.ok(true, 'Node should be the removed child');
undo();
done();
undo();
done();
}
});

@@ -144,10 +155,11 @@

test('onNodeInsertion should be called when that node is inserted into a different document', function(assert){
test('onNodeConnected should be called when that node is inserted into a different document', function(assert){
var done = assert.async();
var doc = globals.getKeyValue('document');
var parent = testUtils.getFixture();
var doc1 = document.implementation.createHTMLDocument('doc1');
var doc1 = doc.implementation.createHTMLDocument('doc1');
var child = doc1.createElement('div');
var undo = domMutate.onNodeInsertion(child, function (mutation) {
var undo = domMutate.onNodeConnected(child, function (mutation) {
var node = mutation.target;

@@ -163,4 +175,5 @@ assert.equal(node, child, 'Node should be the inserted child');

test('onNodeRemoval does not leak when given a document fragment', function(assert){
var doc1 = document.implementation.createHTMLDocument('doc1');
test('onNodeDisconnected does not leak when given a document fragment', function(assert){
var doc = globals.getKeyValue('document');
var doc1 = doc.implementation.createHTMLDocument('doc1');
var frag = doc1.createDocumentFragment();

@@ -174,4 +187,4 @@ frag.appendChild(doc1.createElement('div'));

DOCUMENT(doc1);
domMutate.onNodeRemoval(frag, function() {});
DOCUMENT(document);
domMutate.onNodeDisconnected(frag, function() {});
DOCUMENT(doc);

@@ -181,10 +194,11 @@ assert.equal(getListenerCount(), previousListenerCount, "No new listeners added for this fragment");

test('onNodeInsertion should be called when textNode is inserted within a parent', function (assert) {
test('onNodeConnected should be called when textNode is inserted within a parent', function (assert) {
var done = assert.async();
var doc = globals.getKeyValue('document');
var parent = testUtils.getFixture();
var child = document.createTextNode("Hello World");
var wrapper = document.createElement("div");
var child = doc.createTextNode("Hello World");
var wrapper = doc.createElement("div");
wrapper.appendChild(child);
var undo = domMutate.onNodeInsertion(child, function (mutation) {
var undo = domMutate.onNodeConnected(child, function (mutation) {
var node = mutation.target;

@@ -200,9 +214,32 @@ assert.equal(node, child, 'Node should be the inserted child');

test('flushRecords works', function(assert){
var done = assert.async();
var doc = globals.getKeyValue('document');
var parent = testUtils.getFixture();
var wrapper = doc.createElement("div");
var called = false;
domMutate.onNodeConnected(wrapper, function () {
called = true;
});
node.appendChild.call(parent, wrapper);
domMutate.flushRecords();
assert.ok(called, "insertion run immediately");
setTimeout(done, 1);
});
}
moduleMutationObserver('can-dom-mutate with real document', DOCUMENT(), mutationObserverTests);
testUtils.moduleWithMutationObserver('can-dom-mutate with real document', function() {
test('changing the MutationObserver tears down the mutation observer', function (assert) {
assert.expect(2);
var doc = globals.getKeyValue('document');
var done = assert.async();
var parent = testUtils.getFixture();
var wrapper = document.createElement("div");
var wrapper = doc.createElement("div");
var undoA = domMutate.onNodeInsertion(wrapper, function () {
var undoA = domMutate.onNodeConnected(wrapper, function () {
assert.ok(true, "this will still be called b/c it's on the document");

@@ -212,3 +249,3 @@ undoA();

MUTATION_OBSERVER(MUTATION_OBSERVER());
var undoB = domMutate.onNodeInsertion(wrapper, function (mutation) {
var undoB = domMutate.onNodeConnected(wrapper, function (mutation) {
var node = mutation.target;

@@ -224,1 +261,3 @@ assert.equal(node, wrapper, 'Node should be the inserted child');

});
moduleMutationObserver('can-dom-mutate with SimpleDocument', makeSimpleDocument(), mutationObserverTests);

@@ -14,9 +14,36 @@ var unit = require('steal-qunit');

function moduleWithoutMutationObserver (title, tests) {
function moduleWithoutMutationObserver (title, doc, tests) {
var hooks = {
beforeEach: function () {
globals.setKeyValue(mutationObserverKey, null);
globals.setKeyValue('document', doc);
if(doc === document) {
this.fixture = document.getElementById("qunit-fixture");
} else {
this.fixture = doc.createElement("div");
this.fixture.setAttribute("id", "qunit-fixture");
doc.body.appendChild(this.fixture);
}
},
afterEach: function () {
afterEach: function (assert) {
globals.deleteKeyValue(mutationObserverKey);
if(doc !== document) {
doc.body.removeChild(this.fixture);
}
var done = assert.async();
setTimeout(function() {
globals.deleteKeyValue('document');
var fixture = document.getElementById("qunit-fixture");
while (fixture && fixture.hasChildNodes()) {
fixture.removeChild(fixture.lastChild);
}
done();
}, 10);
}

@@ -28,5 +55,7 @@ };

function moduleMutationObserver (title, tests) {
moduleWithMutationObserver(title, tests);
moduleWithoutMutationObserver(title, tests);
function moduleMutationObserver (title, doc, tests) {
if (doc === document) {
moduleWithMutationObserver(title, tests);
}
moduleWithoutMutationObserver(title, doc, tests);
}

@@ -43,3 +72,3 @@

function getFixture () {
return document.getElementById('qunit-fixture');
return globals.getKeyValue('document').getElementById('qunit-fixture');
}

@@ -46,0 +75,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc