forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
/**
 | 
						|
 * JS module implementation of setTimeout and clearTimeout.
 | 
						|
 */
 | 
						|
 | 
						|
// This gives us >=2^30 unique timer IDs, enough for 1 per ms for 12.4 days.
 | 
						|
var gNextId = 1; // setTimeout and setInterval must return a positive integer
 | 
						|
 | 
						|
var gTimerTable = new Map(); // int -> nsITimer or idleCallback
 | 
						|
 | 
						|
// Don't generate this for every timer.
 | 
						|
var setTimeout_timerCallbackQI = ChromeUtils.generateQI([
 | 
						|
  "nsITimerCallback",
 | 
						|
  "nsINamed",
 | 
						|
]);
 | 
						|
 | 
						|
function _setTimeoutOrIsInterval(
 | 
						|
  aCallback,
 | 
						|
  aMilliseconds,
 | 
						|
  aIsInterval,
 | 
						|
  aTarget,
 | 
						|
  aArgs
 | 
						|
) {
 | 
						|
  if (typeof aCallback !== "function") {
 | 
						|
    throw new Error(
 | 
						|
      `callback is not a function in ${
 | 
						|
        aIsInterval ? "setInterval" : "setTimeout"
 | 
						|
      }`
 | 
						|
    );
 | 
						|
  }
 | 
						|
  let id = gNextId++;
 | 
						|
  let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 | 
						|
 | 
						|
  if (aTarget) {
 | 
						|
    timer.target = aTarget;
 | 
						|
  }
 | 
						|
 | 
						|
  let callback = {
 | 
						|
    QueryInterface: setTimeout_timerCallbackQI,
 | 
						|
 | 
						|
    // nsITimerCallback
 | 
						|
    notify() {
 | 
						|
      if (!aIsInterval) {
 | 
						|
        gTimerTable.delete(id);
 | 
						|
      }
 | 
						|
      aCallback.apply(null, aArgs);
 | 
						|
    },
 | 
						|
 | 
						|
    // nsINamed
 | 
						|
    get name() {
 | 
						|
      return `${
 | 
						|
        aIsInterval ? "setInterval" : "setTimeout"
 | 
						|
      }() for ${Cu.getDebugName(aCallback)}`;
 | 
						|
    },
 | 
						|
  };
 | 
						|
 | 
						|
  timer.initWithCallback(
 | 
						|
    callback,
 | 
						|
    aMilliseconds,
 | 
						|
    aIsInterval ? timer.TYPE_REPEATING_SLACK : timer.TYPE_ONE_SHOT
 | 
						|
  );
 | 
						|
 | 
						|
  gTimerTable.set(id, timer);
 | 
						|
  return id;
 | 
						|
}
 | 
						|
 | 
						|
export function setTimeout(aCallback, aMilliseconds, ...aArgs) {
 | 
						|
  return _setTimeoutOrIsInterval(aCallback, aMilliseconds, false, null, aArgs);
 | 
						|
}
 | 
						|
 | 
						|
export function setTimeoutWithTarget(
 | 
						|
  aCallback,
 | 
						|
  aMilliseconds,
 | 
						|
  aTarget,
 | 
						|
  ...aArgs
 | 
						|
) {
 | 
						|
  return _setTimeoutOrIsInterval(
 | 
						|
    aCallback,
 | 
						|
    aMilliseconds,
 | 
						|
    false,
 | 
						|
    aTarget,
 | 
						|
    aArgs
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
export function setInterval(aCallback, aMilliseconds, ...aArgs) {
 | 
						|
  return _setTimeoutOrIsInterval(aCallback, aMilliseconds, true, null, aArgs);
 | 
						|
}
 | 
						|
 | 
						|
export function setIntervalWithTarget(
 | 
						|
  aCallback,
 | 
						|
  aMilliseconds,
 | 
						|
  aTarget,
 | 
						|
  ...aArgs
 | 
						|
) {
 | 
						|
  return _setTimeoutOrIsInterval(
 | 
						|
    aCallback,
 | 
						|
    aMilliseconds,
 | 
						|
    true,
 | 
						|
    aTarget,
 | 
						|
    aArgs
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
function clear(aId) {
 | 
						|
  if (gTimerTable.has(aId)) {
 | 
						|
    gTimerTable.get(aId).cancel();
 | 
						|
    gTimerTable.delete(aId);
 | 
						|
  }
 | 
						|
}
 | 
						|
export var clearInterval = clear;
 | 
						|
export var clearTimeout = clear;
 | 
						|
 | 
						|
export function requestIdleCallback(aCallback, aOptions) {
 | 
						|
  if (typeof aCallback !== "function") {
 | 
						|
    throw new Error("callback is not a function in requestIdleCallback");
 | 
						|
  }
 | 
						|
  let id = gNextId++;
 | 
						|
 | 
						|
  let callback = (...aArgs) => {
 | 
						|
    if (gTimerTable.has(id)) {
 | 
						|
      gTimerTable.delete(id);
 | 
						|
      aCallback(...aArgs);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  ChromeUtils.idleDispatch(callback, aOptions);
 | 
						|
  gTimerTable.set(id, callback);
 | 
						|
  return id;
 | 
						|
}
 | 
						|
 | 
						|
export function cancelIdleCallback(aId) {
 | 
						|
  if (gTimerTable.has(aId)) {
 | 
						|
    gTimerTable.delete(aId);
 | 
						|
  }
 | 
						|
}
 |