diff --git a/src/MutationObserver/MutationObserver.js b/src/MutationObserver/MutationObserver.js index be7dda9..833ac53 100644 --- a/src/MutationObserver/MutationObserver.js +++ b/src/MutationObserver/MutationObserver.js @@ -8,11 +8,30 @@ var registrationsTable = new WeakMap(); - // We use setImmediate or postMessage for our future callback. - var setImmediate = window.msSetImmediate; + var setImmediate; - // Use post message to emulate setImmediate. - if (!setImmediate) { + // As much as we would like to use the native implementation, IE + // (all versions) suffers a rather annoying bug where it will drop or defer + // callbacks when heavy DOM operations are being performed concurrently. + // + // For a thorough discussion on this, see: + // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/ + if (/Trident/.test(navigator.userAgent)) { + // Sadly, this bug also affects postMessage and MessageQueues. + // + // We would like to use the onreadystatechange hack for IE <= 10, but it is + // dangerous in the polyfilled environment due to requiring that the + // observed script element be in the document. + setImmediate = setTimeout; + + // If some other browser ever implements it, let's prefer their native + // implementation: + } else if (window.setImmediate) { + setImmediate = window.setImmediate; + + // Otherwise, we fall back to postMessage as a means of emulating the next + // task semantics of setImmediate. + } else { var setImmediateQueue = []; var sentinel = String(Math.random()); window.addEventListener('message', function(e) { diff --git a/src/ShadowDOM/microtask.js b/src/ShadowDOM/microtask.js index c0e35b7..11ad4de 100644 --- a/src/ShadowDOM/microtask.js +++ b/src/ShadowDOM/microtask.js @@ -33,7 +33,7 @@ }; } else { - timerFunc = window.setImmediate || window.setTimeout; + timerFunc = window.setTimeout; } function setEndOfMicrotask(func) { diff --git a/workbench/ie10-task-flaking.html b/workbench/ie10-task-flaking.html new file mode 100644 index 0000000..b723d2b --- /dev/null +++ b/workbench/ie10-task-flaking.html @@ -0,0 +1,62 @@ + + + +
+Clicking start will schedule two self-restarting functions:
++After starting the test, move your mouse so that it is hovering over the top line of output. +
+ +
+If the browser is behaving, you should see runSetTimeout calls interleaved with runMutation calls (either 2:1 or 1:1, depending). +
+ ++On IE10, if our MutationObserver polyfill uses setImmediate, postMessage, or MessageQueue, the runMutation line will become erratic, and eventually not fire at all. +
+ + + + + + + +