text: /**
  Some credit for this helper goes to http://github.com/YuzuJS/setImmediate
  */
  import { root } from './root'
  export class ImmediateDefinition {
    constructor (root) {
      this.root = root
      if (root.setImmediate && typeof root.setImmediate === 'function') {
        this.setImmediate = root.setImmediate.bind(root)
        this.clearImmediate = root.clearImmediate.bind(root)
      } else {
        this.nextHandle = 1
        this.tasksByHandle = {}
        this.currentlyRunningATask = false
        // Don't get fooled by e.g. browserify environments.
        if (this.canUseProcessNextTick()) {
          // For Node.js before 0.9
          this.setImmediate = this.createProcessNextTickSetImmediate()
        } else if (this.canUsePostMessage()) {
          // For non-IE10 modern browsers
          this.setImmediate = this.createPostMessageSetImmediate()
        } else if (this.canUseMessageChannel()) {
          // For web workers, where supported
          this.setImmediate = this.createMessageChannelSetImmediate()
        } else if (this.canUseReadyStateChange()) {
          // For IE 6–8
          this.setImmediate = this.createReadyStateChangeSetImmediate()
        } else {
          // For older browsers
          this.setImmediate = this.createSetTimeoutSetImmediate()
        }
        let ci = function clearImmediate (handle) {
          delete clearImmediate.instance.tasksByHandle[handle]
        }
        ci.instance = this
        this.clearImmediate = ci
      }
    }
    identify (o) {
      return this.root.Object.prototype.toString.call(o)
    }
    canUseProcessNextTick () {
      return this.identify(this.root.process) === '[object process]'
    }
    canUseMessageChannel () {
      return Boolean(this.root.MessageChannel)
    }
    canUseReadyStateChange () {
      const document = this.root.document
      return Boolean(document && 'onreadystatechange' in document.createElement('script'))
    }
    canUsePostMessage () {
      const root = this.root
      // The test against `importScripts` prevents this implementation from being installed inside a web worker,
      // where `root.postMessage` means something completely different and can't be used for this purpose.
      if (root.postMessage && !root.importScripts) {
        let postMessageIsAsynchronous = true
        let oldOnMessage = root.onmessage
        root.onmessage = function () {
          postMessageIsAsynchronous = false
        }
        root.postMessage('', '*')
        root.onmessage = oldOnMessage
        return postMessageIsAsynchronous
      }
      return false
    }
    // This function accepts the same arguments as setImmediate, but
    // returns a function that requires no arguments.
    partiallyApplied (handler, ...args) {
      let fn = function result () {
        const { handler, args } = result
        if (typeof handler === 'function') {
          handler.apply(undefined, args)
        } else {
          (new Function('' + handler))()
        }
      }
      fn.handler = handler
      fn.args = args
      return fn
    }
    addFromSetImmediateArguments (args) {
      this.tasksByHandle[this.nextHandle] = this.partiallyApplied.apply(undefined, args)
      return this.nextHandle++
    }
    createProcessNextTickSetImmediate () {
      let fn = function setImmediate () {
        const { instance } = setImmediate
        let handle = instance.addFromSetImmediateArguments(arguments)
        instance.root.process.nextTick(instance.partiallyApplied(instance.runIfPresent, handle))
        return handle
      }
      fn.instance = this
      return fn
    }
    createPostMessageSetImmediate () {
      // Installs an event handler on `global` for the `message` event: see
      // * https://developer.mozilla.org/en/DOM/window.postMessage
      // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
      const root = this.root
      let messagePrefix = 'setImmediate$' + root.Math.random() + '$'
      let onGlobalMessage = function globalMessageHandler (event) {
        const instance = globalMessageHandler.instance
        if (event.source === root &&
                  typeof event.data === 'string' &&
                  event.data.indexOf(messagePrefix) === 0) {
          instance.runIfPresent(+event.data.slice(messagePrefix.length))
        }
      }
      onGlobalMessage.instance = this
      root.addEventListener('message', onGlobalMessage, false)
      let fn = function setImmediate () {
        const { messagePrefix, instance } = setImmediate
        let handle = instance.addFromSetImmediateArguments(arguments)
        instance.root.postMessage(messagePrefix + handle, '*')
        return handle
      }
      fn.instance = this
      fn.messagePrefix = messagePrefix
      return fn
    }
    runIfPresent (handle) {
      // From the spec: 'Wait until any invocations of this algorithm started before this one have completed.'
      // So if we're currently running a task, we'll need to delay this invocation.
      if (this.currentlyRunningATask) {
        // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
        // 'too much recursion' error.
        this.root.setTimeout(this.partiallyApplied(this.runIfPresent, handle), 0)
      } else {
        let task = this.tasksByHandle[handle]
        if (task) {
          this.currentlyRunningATask = true
          try {
            task()
          } finally {
            this.clearImmediate(handle)
            this.currentlyRunningATask = false
          }
        }
      }
    }
    createMessageChannelSetImmediate () {
      let channel = new this.root.MessageChannel()
      channel.port1.onmessage = (event) => {
        let handle = event.data
        this.runIfPresent(handle)
      }
      let fn = function setImmediate () {
        const { channel, instance } = setImmediate
        let handle = instance.addFromSetImmediateArguments(arguments)
        channel.port2.postMessage(handle)
        return handle
      }
      fn.channel = channel
      fn.instance = this
      return fn
    }
    createReadyStateChangeSetImmediate () {
      let fn = function setImmediate () {
        const instance = setImmediate.instance
        const root = instance.root
        const doc = root.document
        const html = doc.documentElement
        let handle = instance.addFromSetImmediateArguments(arguments)
        // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
        // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
        let script = doc.createElement('script')
        script.onreadystatechange = () => {
          instance.runIfPresent(handle)
          script.onreadystatechange = null
          html.removeChild(script)
          script = null
        }
        html.appendChild(script)
        return handle
      }
      fn.instance = this
      return fn
    }
    createSetTimeoutSetImmediate () {
      let fn = function setImmediate () {
        const instance = setImmediate.instance
        let handle = instance.addFromSetImmediateArguments(arguments)
        instance.root.setTimeout(instance.partiallyApplied(instance.runIfPresent, handle), 0)
        return handle
      }
      fn.instance = this
      return fn
    }
  }
  export const Immediate = new ImmediateDefinition(root)
  // # sourceMappingURL=Immediate.js.map
  