can-dom-mutate
Advanced tools
Comparing version 2.0.2 to 2.0.3
12
-util.js
@@ -10,9 +10,11 @@ "use strict"; | ||
} | ||
function addToSet(items, set) { | ||
for(var i =0, length = items.length; i < length; i++) { | ||
set.add(items[i]); | ||
function wasNotInSet(item, set) { | ||
var inSet = set.has(item); | ||
if(inSet === false) { | ||
set.add(item); | ||
} | ||
return !inSet; | ||
} | ||
function contains(parent, child){ | ||
@@ -164,4 +166,4 @@ if(parent.contains) { | ||
subscription: subscription, | ||
addToSet: addToSet, | ||
wasNotInSet: wasNotInSet, | ||
contains: contains | ||
}; |
@@ -7,3 +7,2 @@ 'use strict'; | ||
var DOCUMENT = require("can-globals/document/document"); | ||
var canReflect = require("can-reflect"); | ||
@@ -16,5 +15,17 @@ var util = require('./-util'); | ||
var domMutate, dispatchInsertion, dispatchRemoval, dispatchAttributeChange; | ||
var domMutate, | ||
dispatchNodeInserted, | ||
dispatchNodeConnected, | ||
dispatchGlobalConnected, | ||
dispatchNodeRemoved, | ||
dispatchNodeDisconnected, | ||
dispatchGlobalDisconnected, | ||
dispatchAttributeChange, | ||
dispatchGlobalAttributeChange; | ||
var dataStore = new WeakMap(); | ||
var isConnected = require("./-is-connected"); | ||
var queue; | ||
function getRelatedData(node, key) { | ||
@@ -41,5 +52,9 @@ var data = dataStore.get(node); | ||
function toMutationEvent(node, mutation) { | ||
return {target: node, sourceMutation: mutation}; | ||
} | ||
/* | ||
function toMutationEvents (nodes) { | ||
var events = []; | ||
for (var i = 0; i < nodes.length; i++) { | ||
for (var i = 0, length = nodes.length; i < length; i++) { | ||
events.push({target: nodes[i]}); | ||
@@ -49,14 +64,8 @@ } | ||
} | ||
*/ | ||
function batch(processBatchItems) { | ||
return function batchAdd(items, callback, dispatchConnected, flush) { | ||
processBatchItems(items, dispatchConnected, flush); | ||
if(callback){ | ||
callback(); | ||
} | ||
}; | ||
} | ||
function getDocumentListeners (target, key) { | ||
// TODO: it's odd these functions read DOCUMENT() instead of | ||
// target.ownerDocument. To change to ownerDocument, we might need a "is document" | ||
// check. | ||
var doc = DOCUMENT(); | ||
@@ -118,3 +127,3 @@ var data = getRelatedData(doc, key); | ||
var recordsAndCallbacks = null; | ||
//var recordsAndCallbacks = null; | ||
@@ -128,3 +137,3 @@ function flushCallbacks(callbacks, arg){ | ||
} | ||
/* | ||
function flushRecords(){ | ||
@@ -153,42 +162,16 @@ if(recordsAndCallbacks === null) { | ||
} | ||
*/ | ||
function dispatch(getListeners, targetKey) { | ||
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); | ||
return function dispatchEvents(event) { | ||
if (targetListeners) { | ||
flush(targetListeners, event); | ||
} | ||
var targetListeners = getListeners(event.target, targetKey); | ||
if(!dispatchConnected) { | ||
continue; | ||
} | ||
if (targetListeners) { | ||
flushCallbacks(targetListeners, event); | ||
} | ||
var connectedListeners; | ||
if(connectedKey){ | ||
connectedListeners = getTargetListeners(target, connectedKey); | ||
} | ||
if (connectedListeners) { | ||
flush(connectedListeners, event); | ||
} | ||
if (!documentDataKey) { | ||
continue; | ||
} | ||
var documentListeners = getDocumentListeners(target, documentDataKey); | ||
if (documentListeners) { | ||
flush(documentListeners, event); | ||
} | ||
} | ||
}; | ||
} | ||
var count = 0; | ||
@@ -244,3 +227,3 @@ | ||
} | ||
/* | ||
function handleTreeMutations(mutations) { | ||
@@ -254,21 +237,33 @@ // in IE11, if the document is being removed | ||
if(this.flushing === true) { | ||
this.mutations.push.apply(this.mutations, mutations); | ||
return; | ||
} | ||
this.flushing = true; | ||
this.mutations = [].slice.call(mutations); | ||
var mutation; | ||
var mutationCount = mutations.length; | ||
var added = new Set(), removed = new Set(); | ||
for (var m = 0; m < mutationCount; m++) { | ||
var mutation = mutations[m]; | ||
while(mutation = this.mutations.shift()) { | ||
var removedCount = mutation.removedNodes.length; | ||
for (var r = 0; r < removedCount; r++) { | ||
// get what already isn't in `removed` | ||
var newRemoved = util.addToSet( getAllNodes(mutation.removedNodes[r]), removed); | ||
dispatchRemoval( newRemoved.map(toMutationEvent), null, true, flushCallbacks ); | ||
} | ||
var addedCount = mutation.addedNodes.length; | ||
for (var a = 0; a < addedCount; a++) { | ||
util.addToSet( getAllNodes(mutation.addedNodes[a]), added); | ||
var newAdded = util.addToSet( getAllNodes(mutation.addedNodes[a]), added); | ||
dispatchInsertion( newAdded.map(toMutationEvent), null, true, flushCallbacks ); | ||
} | ||
var removedCount = mutation.removedNodes.length; | ||
for (var r = 0; r < removedCount; r++) { | ||
util.addToSet( getAllNodes(mutation.removedNodes[r]), removed); | ||
} | ||
} | ||
dispatchRemoval( toMutationEvents( canReflect.toArray(removed) ), null, true, flushCallbacks ); | ||
dispatchInsertion( toMutationEvents( canReflect.toArray(added) ), null, true, flushCallbacks ); | ||
this.flushing = false; | ||
//dispatchRemoval( toMutationEvents( canReflect.toArray(removed) ), null, true, flushCallbacks ); | ||
//dispatchInsertion( toMutationEvents( canReflect.toArray(added) ), null, true, flushCallbacks ); | ||
} | ||
@@ -292,3 +287,7 @@ | ||
} | ||
*/ | ||
var treeMutationConfig = { | ||
@@ -317,5 +316,5 @@ subtree: true, | ||
if (isAttributes) { | ||
stopObserving = observeMutations(target, observerKey, attributeMutationConfig, handleAttributeMutations); | ||
stopObserving = observeMutations(target, observerKey, attributeMutationConfig, queue.enqueueAndFlushMutations); | ||
} else { | ||
stopObserving = observeMutations(DOCUMENT(), observerKey, treeMutationConfig, handleTreeMutations); | ||
stopObserving = observeMutations(DOCUMENT(), observerKey, treeMutationConfig, queue.enqueueAndFlushMutations); | ||
} | ||
@@ -391,6 +390,13 @@ | ||
dispatchInsertion = batch(dispatch(insertedDataKey, connectedDataKey, documentConnectedDataKey)); | ||
dispatchRemoval = batch(dispatch(removedDataKey, disconnectedDataKey, documentDisconnectedDataKey)); | ||
dispatchAttributeChange = batch(dispatch(attributeChangeDataKey, null , documentAttributeChangeDataKey)); | ||
dispatchNodeInserted = dispatch(getTargetListeners, insertedDataKey); | ||
dispatchNodeConnected = dispatch(getTargetListeners, connectedDataKey); | ||
dispatchGlobalConnected = dispatch(getDocumentListeners, documentConnectedDataKey); | ||
dispatchNodeRemoved = dispatch(getTargetListeners, removedDataKey); | ||
dispatchNodeDisconnected = dispatch(getTargetListeners, disconnectedDataKey); | ||
dispatchGlobalDisconnected = dispatch(getDocumentListeners, documentDisconnectedDataKey); | ||
dispatchAttributeChange = dispatch(getTargetListeners, attributeChangeDataKey); | ||
dispatchGlobalAttributeChange = dispatch(getDocumentListeners, documentAttributeChangeDataKey); | ||
// node listeners | ||
@@ -417,3 +423,125 @@ var addNodeConnectedListener = addNodeListener(connectedDataKey, treeDataKey); | ||
// ========================================== | ||
function dispatchTreeMutation(mutation, processedState) { | ||
// was the mutation connected | ||
var wasConnected = mutation.isConnected === true || mutation.isConnected === undefined; | ||
// there are | ||
// - the global connected | ||
// - individual connected | ||
// - individual inserted | ||
var removedCount = mutation.removedNodes.length; | ||
for (var r = 0; r < removedCount; r++) { | ||
// get what already isn't in `removed` | ||
// see if "removed" | ||
// if wasConnected .. dispatch disconnected | ||
var removedNodes = getAllNodes(mutation.removedNodes[r]); | ||
removedNodes.forEach(function(node){ | ||
var event = toMutationEvent(node, mutation); | ||
if( util.wasNotInSet(node, processedState.removed) ) { | ||
dispatchNodeRemoved( event ); | ||
} | ||
if(wasConnected && util.wasNotInSet(node, processedState.disconnected) ) { | ||
dispatchNodeDisconnected( event ); | ||
dispatchGlobalDisconnected( event ); | ||
} | ||
}); | ||
} | ||
var addedCount = mutation.addedNodes.length; | ||
for (var a = 0; a < addedCount; a++) { | ||
var insertedNodes = getAllNodes(mutation.addedNodes[a]); | ||
insertedNodes.forEach(function(node){ | ||
var event = toMutationEvent(node, mutation); | ||
if(util.wasNotInSet(node, processedState.inserted)) { | ||
dispatchNodeInserted( event ); | ||
} | ||
if(wasConnected && util.wasNotInSet(node, processedState.connected) ) { | ||
dispatchNodeConnected( event ); | ||
dispatchGlobalConnected( event ); | ||
} | ||
}); | ||
} | ||
// run mutation | ||
} | ||
var FLUSHING_MUTATIONS = []; | ||
var IS_FLUSHING = false; | ||
var IS_FLUSH_PENDING = false; | ||
var ENQUEUED_MUTATIONS = []; | ||
queue = { | ||
// This is used to dispatch mutations immediately. | ||
// This is usually called by the result of a mutation observer. | ||
enqueueAndFlushMutations: function(mutations) { | ||
if(IS_FLUSH_PENDING) { | ||
FLUSHING_MUTATIONS.push.apply(FLUSHING_MUTATIONS, ENQUEUED_MUTATIONS); | ||
IS_FLUSH_PENDING = false; | ||
ENQUEUED_MUTATIONS = []; | ||
} | ||
FLUSHING_MUTATIONS.push.apply(FLUSHING_MUTATIONS, mutations); | ||
if(IS_FLUSHING) { | ||
return; | ||
} | ||
IS_FLUSHING = true; | ||
var index = 0; | ||
var processedState = { | ||
connected: new Set(), | ||
disconnected: new Set(), | ||
inserted: new Set(), | ||
removed: new Set() | ||
}; | ||
while(index < FLUSHING_MUTATIONS.length) { | ||
var mutation = FLUSHING_MUTATIONS[index]; | ||
// process mutation | ||
if(mutation.type === "childList") { | ||
dispatchTreeMutation(mutation, processedState); | ||
} else if(mutation.type === "attributes") { | ||
dispatchAttributeChange(mutation); | ||
} | ||
index++; | ||
} | ||
FLUSHING_MUTATIONS = []; | ||
IS_FLUSHING = false; | ||
}, | ||
// called to dipatch later unless we are already dispatching. | ||
enqueueMutationsAndFlushAsync: function(mutations){ | ||
ENQUEUED_MUTATIONS.push.apply(ENQUEUED_MUTATIONS, mutations); | ||
// if there are currently dispatching mutations, this should happen sometime after | ||
if(!IS_FLUSH_PENDING) { | ||
IS_FLUSH_PENDING = true; | ||
nextTick(function(){ | ||
if(IS_FLUSH_PENDING) { | ||
IS_FLUSH_PENDING = false; | ||
var pending = ENQUEUED_MUTATIONS; | ||
ENQUEUED_MUTATIONS = []; | ||
queue.enqueueAndFlushMutations(pending); | ||
} else { | ||
// Someone called enqueueAndFlushMutations before this finished. | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
// ========================================== | ||
domMutate = { | ||
@@ -429,5 +557,14 @@ /** | ||
* @param {Node} node The node on which to dispatch an insertion mutation. | ||
* @param {function} callback The optional callback called after the mutation is dispatched. | ||
*/ | ||
dispatchNodeInsertion: function (node, callback, dispatchConnected) { | ||
dispatchNodeInsertion: function (node, target) { | ||
queue.enqueueMutationsAndFlushAsync( | ||
[{ | ||
type: "childList", | ||
target: target, | ||
addedNodes: [node], | ||
isConnected: isConnected.isConnected(target), | ||
removedNodes: [] | ||
}] | ||
); | ||
/* | ||
var nodes = new Set(); | ||
@@ -437,3 +574,3 @@ util.addToSet( getAllNodes(node), nodes); | ||
// this is basically an array of every single child of node including node | ||
dispatchInsertion(events, callback, dispatchConnected, flushAsync); | ||
dispatchInsertion(events, callback, dispatchConnected, flushAsync);*/ | ||
}, | ||
@@ -452,7 +589,17 @@ | ||
*/ | ||
dispatchNodeRemoval: function (node, callback, dispatchConnected) { | ||
dispatchNodeRemoval: function (node, target) { | ||
queue.enqueueMutationsAndFlushAsync( | ||
[{ | ||
type: "childList", | ||
target: target, | ||
addedNodes: [], | ||
removedNodes: [node], | ||
isConnected: isConnected.isConnected(target) | ||
}] | ||
); | ||
/* | ||
var nodes = new Set(); | ||
util.addToSet( getAllNodes(node), nodes); | ||
var events = toMutationEvents( canReflect.toArray(nodes) ); | ||
dispatchRemoval(events, callback, dispatchConnected, flushAsync); | ||
dispatchRemoval(events, callback, dispatchConnected, flushAsync);*/ | ||
}, | ||
@@ -478,10 +625,12 @@ | ||
* @param {String} oldValue The attribute value before the change. | ||
* @param {function} callback The optional callback called after the mutation is dispatched. | ||
*/ | ||
dispatchNodeAttributeChange: function (target, attributeName, oldValue, callback) { | ||
dispatchAttributeChange([{ | ||
target: target, | ||
attributeName: attributeName, | ||
oldValue: oldValue | ||
}], callback, true, flushAsync); | ||
dispatchNodeAttributeChange: function (target, attributeName, oldValue) { | ||
queue.enqueueMutationsAndFlushAsync( | ||
[{ | ||
type: "attributes", | ||
target: target, | ||
attributeName: attributeName, | ||
oldValue: oldValue | ||
}] | ||
); | ||
}, | ||
@@ -585,13 +734,10 @@ | ||
doc = doc || DOCUMENT(); | ||
var data = dataStore.get(doc); | ||
var data = dataStore.get(doc), | ||
records = []; | ||
if(data) { | ||
if(data.domMutationTreeData && data.domMutationTreeData.observer) { | ||
var records = data.domMutationTreeData.observer.takeRecords(); | ||
handleTreeMutations(records); | ||
records = data.domMutationTreeData.observer.takeRecords(); | ||
} | ||
// flush any synthetic records | ||
flushRecords(); | ||
} | ||
queue.enqueueAndFlushMutations(records); | ||
}, | ||
@@ -598,0 +744,0 @@ onNodeInserted: addNodeInsertedListener, |
@@ -7,2 +7,3 @@ var unit = require('steal-qunit'); | ||
var makeSimpleDocument = require("can-vdom/make-document/make-document"); | ||
var isConnected = require("../-is-connected"); | ||
@@ -35,3 +36,3 @@ var test = unit.test; | ||
// IE 11 doesn't support isConnected, so both isConnected() calls will go through here | ||
assert.ok(true, "Native Node.prototype does not support isConnected"); | ||
assert.ok(true, "Native Node.prototype does not support isConnected"); | ||
} | ||
@@ -42,5 +43,5 @@ return null; | ||
assert.ok(node.isConnected(fakenode), "Real document connected"); | ||
assert.ok(isConnected.isConnected(fakenode), "Real document connected"); | ||
getDocument(makeSimpleDocument()); | ||
assert.ok(node.isConnected(fakenode), "SimpleDocument connected"); | ||
assert.ok(isConnected.isConnected(fakenode), "SimpleDocument connected"); | ||
getDocument(doc); | ||
@@ -156,5 +157,5 @@ }); | ||
var undo = mock(domMutate, 'dispatchNodeInsertion', function (node, callback) { | ||
var undo = mock(domMutate, 'dispatchNodeInsertion', function (node, parentNode) { | ||
assert.equal(node, child, 'Should pass the child being appended'); | ||
assert.equal(callback, undefined, 'Should not pass a callback'); | ||
assert.equal(parentNode , parent, 'Should pass the parent'); | ||
assert.ok(parent.contains(node), 'Node should be in parent before dispatch is called'); | ||
@@ -209,5 +210,5 @@ undo(); | ||
var undo = mock(domMutate, 'dispatchNodeInsertion', function (node, callback) { | ||
var undo = mock(domMutate, 'dispatchNodeInsertion', function (node, parentNode) { | ||
assert.equal(node, child, 'Should pass the child being appended'); | ||
assert.equal(callback, undefined, 'Should not pass a callback'); | ||
assert.equal(parentNode, parent, 'Should pass the parent node'); | ||
assert.ok(parent.contains(node), 'Node should be in parent before dispatch is called'); | ||
@@ -240,5 +241,5 @@ undo(); | ||
var undo = mock(domMutate, 'dispatchNodeRemoval', function (node, callback) { | ||
var undo = mock(domMutate, 'dispatchNodeRemoval', function (node, parentNode) { | ||
assert.equal(node, child, 'Should pass the child being removed'); | ||
assert.equal(callback, undefined, 'Should not pass a callback'); | ||
assert.equal(parent, parentNode, 'Should pass the parent node'); | ||
assert.ok(!parent.contains(node), 'Node should be removed before dispatch is called'); | ||
@@ -261,5 +262,5 @@ undo(); | ||
var undoRemoval = mock(domMutate, 'dispatchNodeRemoval', function (node, callback) { | ||
var undoRemoval = mock(domMutate, 'dispatchNodeRemoval', function (node, parentNode) { | ||
assert.equal(node, sibling, 'Should pass the sibling being removed'); | ||
assert.equal(callback, undefined, 'Should not pass a callback'); | ||
assert.equal(parent, parentNode, 'Should pass the parent'); | ||
assert.ok(!parent.contains(node), 'Node should be removed before dispatch is called'); | ||
@@ -270,6 +271,6 @@ undoRemoval(); | ||
var undoInsertion = mock(domMutate, 'dispatchNodeInsertion', function (node, callback) { | ||
var undoInsertion = mock(domMutate, 'dispatchNodeInsertion', function (node, parentNode) { | ||
assert.ok(isSiblingRemoved, 'Sibling should be removed before the child is inserted (as far as dispatch order is concerned)'); | ||
assert.equal(node, child, 'Should pass the child being inserted'); | ||
assert.equal(callback, undefined, 'Should not pass a callback'); | ||
assert.equal(parentNode, parent, 'Should not pass a callback'); | ||
assert.ok(parent.contains(node), 'Node should be inserted before dispatch is called'); | ||
@@ -339,2 +340,22 @@ undoInsertion(); | ||
}); | ||
QUnit.test("connected should be called if element is inserted to a disconnected element and then the parent is inserted )#64", function(assert){ | ||
var done = assert.async(); | ||
var fixture = testUtils.getFixture(); | ||
var parent = document.createElement('div'); | ||
var child = document.createElement('div'); | ||
var undo = domMutate.onNodeConnected(child, function() { | ||
assert.ok(true, 'this was called'); | ||
undo(); | ||
done(); | ||
}); | ||
node.appendChild.call(parent, child); | ||
node.appendChild.call(fixture, parent); | ||
}); | ||
}; | ||
@@ -359,3 +380,3 @@ moduleWithoutMutationObserver('can-dom-mutate/node with real document', getDocument(), withoutMutationObserverTests); | ||
QUnit.test('appendChild should not call dispatchNodeInsertion', function (assert) { | ||
QUnit.skip('appendChild should not call dispatchNodeInsertion', function (assert) { | ||
assert.expect(1); | ||
@@ -373,3 +394,3 @@ var doc = getDocument(); | ||
QUnit.test('insertBefore should not call dispatchNodeInsertion', function (assert) { | ||
QUnit.skip('insertBefore should not call dispatchNodeInsertion', function (assert) { | ||
assert.expect(1); | ||
@@ -390,3 +411,3 @@ var doc = getDocument(); | ||
QUnit.test('removeChild should not call dispatchNodeRemoval', function (assert) { | ||
QUnit.skip('removeChild should not call dispatchNodeRemoval', function (assert) { | ||
assert.expect(1); | ||
@@ -406,3 +427,3 @@ var doc = getDocument(); | ||
QUnit.test('replaceChild should not call dispatchNodeRemoval+Insertion', function (assert) { | ||
QUnit.skip('replaceChild should not call dispatchNodeRemoval+Insertion', function (assert) { | ||
assert.expect(2); | ||
@@ -432,4 +453,6 @@ var doc = getDocument(); | ||
getDocument(doc1); | ||
var undo = domMutate.onNodeDisconnected(doc1.documentElement, function() { | ||
assert.ok(true, 'this was called'); | ||
getDocument(doc); | ||
undo(); | ||
@@ -441,3 +464,3 @@ done(); | ||
node.removeChild.call(doc1, doc1.documentElement); | ||
getDocument(doc); | ||
}); | ||
@@ -444,0 +467,0 @@ } |
@@ -10,27 +10,5 @@ 'use strict'; | ||
var contains = util.contains; | ||
var isConnected = require("../-is-connected"); | ||
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); | ||
var compat = { | ||
@@ -40,5 +18,5 @@ replaceChild: function (newChild, oldChild) { | ||
var result = this.replaceChild(newChild, oldChild); | ||
domMutate.dispatchNodeRemoval(oldChild, null, isConnected(this) && !isConnected(oldChild)); | ||
domMutate.dispatchNodeRemoval(oldChild, this); | ||
for (var i = 0; i < newChildren.length; i++) { | ||
domMutate.dispatchNodeInsertion(newChildren[i], null, isConnected(this)); | ||
domMutate.dispatchNodeInsertion(newChildren[i], this); | ||
} | ||
@@ -78,3 +56,3 @@ return result; | ||
for (var i = 0; i < nodes.length; i++) { | ||
domMutate[dispatchMethod](nodes[i], null, isConnected(this) && (pair[1] === 'Removal' ? !isConnected(nodes[i]) : true)); | ||
domMutate[dispatchMethod](nodes[i], this); | ||
} | ||
@@ -89,3 +67,3 @@ return result; | ||
normal[methodName] = function () { | ||
if(isConnected(this)) { | ||
if(isConnected.isConnected(this)) { | ||
return this[methodName].apply(this, arguments); | ||
@@ -208,4 +186,4 @@ } else { | ||
mutate.isConnected = isConnected; | ||
//mutate.isConnected = isConnected; | ||
module.exports = namespace.domMutateNode = domMutate.node = mutate; |
{ | ||
"name": "can-dom-mutate", | ||
"description": "Dispatch and listen for DOM mutations", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"author": { | ||
@@ -25,3 +25,3 @@ "name": "DoneJS Team", | ||
"jshint": "^2.9.1", | ||
"steal": "^1.3.1", | ||
"steal": "^2.0.0", | ||
"steal-qunit": "^2.0.0", | ||
@@ -28,0 +28,0 @@ "steal-tools": "^1.2.0", |
@@ -209,8 +209,9 @@ var unit = require('steal-qunit'); | ||
var called = false; | ||
domMutate.onNodeConnected(wrapper, function () { | ||
var teardown = domMutate.onNodeConnected(wrapper, function () { | ||
teardown(); | ||
called = true; | ||
}); | ||
node.appendChild.call(parent, wrapper); | ||
domMutate.flushRecords(); | ||
@@ -221,2 +222,87 @@ assert.ok(called, "insertion run immediately"); | ||
test('onDisconnected after onConnected', function(assert){ | ||
var done = assert.async(); | ||
var doc = globals.getKeyValue('document'); | ||
var parent = testUtils.getFixture(); | ||
var wrapper = doc.createElement("div"); | ||
var called = false; | ||
var disconnectTeardown = domMutate.onNodeDisconnected(wrapper, function(){ | ||
assert.ok(called, "connected called before disconnected"); | ||
done(); | ||
disconnectTeardown(); | ||
}); | ||
var connectedTeardown = domMutate.onNodeConnected(wrapper, function () { | ||
called = true; | ||
assert.ok(true, "connected called"); | ||
connectedTeardown(); | ||
}); | ||
node.appendChild.call(parent, wrapper); // problem here is that it's removed | ||
node.removeChild.call(parent, wrapper); | ||
}); | ||
test('no double connected', function(assert){ | ||
assert.expect(1); | ||
var done = assert.async(); | ||
var doc = globals.getKeyValue('document'); | ||
var outer = doc.createElement("div"); | ||
var inner = doc.createElement("div"); | ||
var connectedTeardown = domMutate.onNodeConnected(inner, function () { | ||
assert.ok(true, "connected called"); | ||
setTimeout(function(){ | ||
connectedTeardown(); | ||
done(); | ||
},1); | ||
}); | ||
var parent = testUtils.getFixture(); | ||
node.appendChild.call(parent, outer); | ||
node.appendChild.call(outer, inner); | ||
}); | ||
test("flushRecords while processing records issues changes in order", function(assert){ | ||
var done = assert.async(); | ||
var doc = globals.getKeyValue('document'); | ||
var parent = testUtils.getFixture(); | ||
var firstDiv = doc.createElement("div"), | ||
secondDiv = doc.createElement("div"), | ||
thirdDiv = doc.createElement("div"); | ||
var order = []; | ||
var firstConnectedTeardown = domMutate.onNodeConnected(firstDiv, function () { | ||
order.push("first"); | ||
node.appendChild.call(parent, thirdDiv); | ||
domMutate.flushRecords(); | ||
firstConnectedTeardown(); | ||
}); | ||
var secondConnectedTeardown = domMutate.onNodeConnected(secondDiv, function () { | ||
order.push("second"); | ||
secondConnectedTeardown(); | ||
}); | ||
var thirdConnectedTeardown = domMutate.onNodeConnected(thirdDiv, function () { | ||
order.push("third"); | ||
assert.deepEqual(order, ["first","second","third"]); | ||
order.push("third"); | ||
thirdConnectedTeardown(); | ||
done(); | ||
}); | ||
node.appendChild.call(parent, firstDiv); | ||
node.appendChild.call(parent, secondDiv); | ||
}); | ||
} | ||
@@ -250,2 +336,1 @@ | ||
moduleMutationObserver('can-dom-mutate with SimpleDocument', makeSimpleDocument(), mutationObserverTests); | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
0
1
1
78221
23
1823