import Ember from 'ember';

let cachedRequireEntries;
let cachedScriptTags;
let cachedLinkTags;

/**
 * Determines whether an array contains the provided item.
 *
 * @param {Array} array
 * @param {Any} item
 * @return {Boolean}
 */
function has(array, item) {
  return array.indexOf(item) !== -1;
}

/**
 * Determines if the function already called.
 *
 * @return {Boolean}
 */
function canOnlyFireOnce() {
  let executed = false;
  return () => {
    if (!executed) {
      executed = true;
    }
    return executed;
  };
}

/**
 * Removes a DOM Node from the document.
 *
 * @param {Node} node
 * @return {Void}
 */
function removeNode(node) {
  node.parentNode.removeChild(node);
}

/**
 * Converts an iterable object into an actual Array.
 *
 * @param {Iterable} iterable
 * @return {Array}
 */
function toArray(iterable) {
  return Array.prototype.slice.call(iterable);
}

/**
 * Returns all of the HTML Elements matching a given selector as an array.
 *
 * @param {String} selector
 * @return {Array<HTMLElement>}
 */
function getAll(selector) {
  const htmlCollection = document.querySelectorAll(selector);
  return toArray(htmlCollection);
}

/**
 * Deletes an entry from require's list of modules.
 *
 * @param {String} entry
 * @return {Void}
 */
function resetRequireEntry(entry) {
  delete self.requirejs.entries[entry];
}

/**
 * Compares two arrays, if they're different, invokes a callback for each
 * entry that does not appear in the initial array.
 *
 * @param {Array} initial
 * @param {Array} current
 * @param {Function} diffHandler
 * @return {Void}
 */
function compareAndIterate(initial, current, diffHandler) {
  if (initial.length < current.length) {
    for (let i = 0; i < current.length; i++) {
      let entry = current[i];
      if (!has(initial, entry)) {
        diffHandler(entry);
      }
    }
  }
}

/**
 * Gets the current loaded asset state including scripts, links, and require
 * modules.
 *
 * @return {Object}
 */
export function getLoadedAssetState() {
  return {
    requireEntries: Object.keys(self.requirejs.entries),
    scripts: getAll('script'),
    links: getAll('link')
  };
}

/**
 * Caches the current loaded asset state with regards to links, scripts, and JS
 * modules currently present.
 *
 * @return {Void}
 */
export function cacheLoadedAssetState() {
  ({
    requireEntries: cachedRequireEntries,
    scripts: cachedScriptTags,
    links: cachedLinkTags
  } = getLoadedAssetState());
}

/**
 * Restores the loaded asset state to the previous cached value with regards to
 * links, scripts, and JS modules.
 *
 * @return {Void}
 */
export function resetLoadedAssetState() {
  if (canOnlyFireOnce()) {
    Ember.Logger.info('Resetting loaded asset state. This will attempt to restore the state of loaded assets to the last cached value. If an asset modified some global state, we cannot guarantee it will be reset. For more information see: https://github.com/trentmwillis/ember-asset-loader#resetting-test-state');
  }

  const {
    requireEntries: currentRequireEntries,
    scripts: currentScriptTags,
    links: currentLinkTags
  } = getLoadedAssetState();

  compareAndIterate(cachedRequireEntries, currentRequireEntries, resetRequireEntry);
  compareAndIterate(cachedScriptTags, currentScriptTags, removeNode);
  compareAndIterate(cachedLinkTags, currentLinkTags, removeNode);
}

@@ -305,146 +305,151 @@
 %0A * 
-Determines if the function already called.%0A *%0A * @return %7BBoolean%7D%0A */%0Afunction canOnlyFireOnce() %7B%0A  let executed = false;%0A  retur
+Returns a function which you only want to run once%0A *%0A * @return %7BBoolean%7D%0A */%0Afunction once(fn, context) %7B%0A  var result;%0A%0A  return functio
 n ()
- =%3E
  %7B%0A 
@@ -459,17 +459,10 @@
 if (
-!executed
+fn
 ) %7B%0A
@@ -471,23 +471,70 @@
     
-executed = true
+result = fn.apply(context %7C%7C this, arguments);%0A      fn = null
 ;%0A  
@@ -552,16 +552,14 @@
 urn 
-executed
+result
 ;%0A  
@@ -2678,30 +2678,41 @@
 %7B%0A  
-if (
+const 
 canOnly
-FireOnce())
+LogOnce = once(() =%3E
  %7B%0A 
@@ -3027,16 +3027,38 @@
 e');%0A  %7D
+);%0A  canOnlyLogOnce();
 %0A%0A  cons

Fix once function