Adding mapbox-gl branch

This commit is contained in:
Andreas Hocevar
2015-03-16 18:50:27 +01:00
parent 7985f030fa
commit 57ee7f52fd
3109 changed files with 943365 additions and 0 deletions
@@ -0,0 +1,329 @@
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview A timer class to which other classes and objects can
* listen on. This is only an abstraction above setInterval.
*
* @see ../demos/timers.html
*/
goog.provide('goog.Timer');
goog.require('goog.Promise');
goog.require('goog.events.EventTarget');
/**
* Class for handling timing events.
*
* @param {number=} opt_interval Number of ms between ticks (Default: 1ms).
* @param {Object=} opt_timerObject An object that has setTimeout, setInterval,
* clearTimeout and clearInterval (eg Window).
* @constructor
* @extends {goog.events.EventTarget}
*/
goog.Timer = function(opt_interval, opt_timerObject) {
goog.events.EventTarget.call(this);
/**
* Number of ms between ticks
* @type {number}
* @private
*/
this.interval_ = opt_interval || 1;
/**
* An object that implements setTimeout, setInterval, clearTimeout and
* clearInterval. We default to the window object. Changing this on
* goog.Timer.prototype changes the object for all timer instances which can
* be useful if your environment has some other implementation of timers than
* the window object.
* @type {Object}
* @private
*/
this.timerObject_ = opt_timerObject || goog.Timer.defaultTimerObject;
/**
* Cached tick_ bound to the object for later use in the timer.
* @type {Function}
* @private
*/
this.boundTick_ = goog.bind(this.tick_, this);
/**
* Firefox browser often fires the timer event sooner
* (sometimes MUCH sooner) than the requested timeout. So we
* compare the time to when the event was last fired, and
* reschedule if appropriate. See also goog.Timer.intervalScale
* @type {number}
* @private
*/
this.last_ = goog.now();
};
goog.inherits(goog.Timer, goog.events.EventTarget);
/**
* Maximum timeout value.
*
* Timeout values too big to fit into a signed 32-bit integer may cause
* overflow in FF, Safari, and Chrome, resulting in the timeout being
* scheduled immediately. It makes more sense simply not to schedule these
* timeouts, since 24.8 days is beyond a reasonable expectation for the
* browser to stay open.
*
* @type {number}
* @private
*/
goog.Timer.MAX_TIMEOUT_ = 2147483647;
/**
* A timer ID that cannot be returned by any known implmentation of
* Window.setTimeout. Passing this value to window.clearTimeout should
* therefore be a no-op.
*
* @const {number}
* @private
*/
goog.Timer.INVALID_TIMEOUT_ID_ = -1;
/**
* Whether this timer is enabled
* @type {boolean}
*/
goog.Timer.prototype.enabled = false;
/**
* An object that implements setTimout, setInterval, clearTimeout and
* clearInterval. We default to the global object. Changing
* goog.Timer.defaultTimerObject changes the object for all timer instances
* which can be useful if your environment has some other implementation of
* timers you'd like to use.
* @type {Object}
*/
goog.Timer.defaultTimerObject = goog.global;
/**
* A variable that controls the timer error correction. If the
* timer is called before the requested interval times
* intervalScale, which often happens on mozilla, the timer is
* rescheduled. See also this.last_
* @type {number}
*/
goog.Timer.intervalScale = 0.8;
/**
* Variable for storing the result of setInterval
* @type {?number}
* @private
*/
goog.Timer.prototype.timer_ = null;
/**
* Gets the interval of the timer.
* @return {number} interval Number of ms between ticks.
*/
goog.Timer.prototype.getInterval = function() {
return this.interval_;
};
/**
* Sets the interval of the timer.
* @param {number} interval Number of ms between ticks.
*/
goog.Timer.prototype.setInterval = function(interval) {
this.interval_ = interval;
if (this.timer_ && this.enabled) {
// Stop and then start the timer to reset the interval.
this.stop();
this.start();
} else if (this.timer_) {
this.stop();
}
};
/**
* Callback for the setTimeout used by the timer
* @private
*/
goog.Timer.prototype.tick_ = function() {
if (this.enabled) {
var elapsed = goog.now() - this.last_;
if (elapsed > 0 &&
elapsed < this.interval_ * goog.Timer.intervalScale) {
this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
this.interval_ - elapsed);
return;
}
// Prevents setInterval from registering a duplicate timeout when called
// in the timer event handler.
if (this.timer_) {
this.timerObject_.clearTimeout(this.timer_);
this.timer_ = null;
}
this.dispatchTick();
// The timer could be stopped in the timer event handler.
if (this.enabled) {
this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
this.interval_);
this.last_ = goog.now();
}
}
};
/**
* Dispatches the TICK event. This is its own method so subclasses can override.
*/
goog.Timer.prototype.dispatchTick = function() {
this.dispatchEvent(goog.Timer.TICK);
};
/**
* Starts the timer.
*/
goog.Timer.prototype.start = function() {
this.enabled = true;
// If there is no interval already registered, start it now
if (!this.timer_) {
// IMPORTANT!
// window.setInterval in FireFox has a bug - it fires based on
// absolute time, rather than on relative time. What this means
// is that if a computer is sleeping/hibernating for 24 hours
// and the timer interval was configured to fire every 1000ms,
// then after the PC wakes up the timer will fire, in rapid
// succession, 3600*24 times.
// This bug is described here and is already fixed, but it will
// take time to propagate, so for now I am switching this over
// to setTimeout logic.
// https://bugzilla.mozilla.org/show_bug.cgi?id=376643
//
this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
this.interval_);
this.last_ = goog.now();
}
};
/**
* Stops the timer.
*/
goog.Timer.prototype.stop = function() {
this.enabled = false;
if (this.timer_) {
this.timerObject_.clearTimeout(this.timer_);
this.timer_ = null;
}
};
/** @override */
goog.Timer.prototype.disposeInternal = function() {
goog.Timer.superClass_.disposeInternal.call(this);
this.stop();
delete this.timerObject_;
};
/**
* Constant for the timer's event type
* @type {string}
*/
goog.Timer.TICK = 'tick';
/**
* Calls the given function once, after the optional pause.
*
* The function is always called asynchronously, even if the delay is 0. This
* is a common trick to schedule a function to run after a batch of browser
* event processing.
*
* @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function
* or object that has a handleEvent method.
* @param {number=} opt_delay Milliseconds to wait; default is 0.
* @param {SCOPE=} opt_handler Object in whose scope to call the listener.
* @return {number} A handle to the timer ID.
* @template SCOPE
*/
goog.Timer.callOnce = function(listener, opt_delay, opt_handler) {
if (goog.isFunction(listener)) {
if (opt_handler) {
listener = goog.bind(listener, opt_handler);
}
} else if (listener && typeof listener.handleEvent == 'function') {
// using typeof to prevent strict js warning
listener = goog.bind(listener.handleEvent, listener);
} else {
throw Error('Invalid listener argument');
}
if (opt_delay > goog.Timer.MAX_TIMEOUT_) {
// Timeouts greater than MAX_INT return immediately due to integer
// overflow in many browsers. Since MAX_INT is 24.8 days, just don't
// schedule anything at all.
return goog.Timer.INVALID_TIMEOUT_ID_;
} else {
return goog.Timer.defaultTimerObject.setTimeout(
listener, opt_delay || 0);
}
};
/**
* Clears a timeout initiated by callOnce
* @param {?number} timerId a timer ID.
*/
goog.Timer.clear = function(timerId) {
goog.Timer.defaultTimerObject.clearTimeout(timerId);
};
/**
* @param {number} delay Milliseconds to wait.
* @param {(RESULT|goog.Thenable<RESULT>|Thenable)=} opt_result The value
* with which the promise will be resolved.
* @return {!goog.Promise<RESULT>} A promise that will be resolved after
* the specified delay, unless it is canceled first.
* @template RESULT
*/
goog.Timer.promise = function(delay, opt_result) {
var timerKey = null;
return new goog.Promise(function(resolve, reject) {
timerKey = goog.Timer.callOnce(function() {
resolve(opt_result);
}, delay);
if (timerKey == goog.Timer.INVALID_TIMEOUT_ID_) {
reject(new Error('Failed to schedule timer.'));
}
}).thenCatch(function(error) {
// Clear the timer. The most likely reason is "cancel" signal.
goog.Timer.clear(timerKey);
throw error;
});
};
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2006 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.Timer
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.TimerTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,149 @@
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
goog.provide('goog.TimerTest');
goog.setTestOnly('goog.TimerTest');
goog.require('goog.Promise');
goog.require('goog.Timer');
goog.require('goog.events');
goog.require('goog.testing.MockClock');
goog.require('goog.testing.jsunit');
var intervalIds = {};
var intervalIdCounter = 0;
var mockClock;
var maxDuration = 60 * 1000; // 60s
function setUp() {
mockClock = new goog.testing.MockClock(true /* install */);
}
function tearDown() {
mockClock.dispose();
}
// Run a test for 60s and see how many counts we get
function runTest(string, ticks, number) {
var t = new goog.Timer(ticks);
var count = 0;
goog.events.listen(t, 'tick', function(evt) {
count++;
});
t.start();
mockClock.tick(maxDuration);
assertEquals(string, number, count);
t.stop();
goog.events.removeAll(t);
}
function test100msTicks() {
// Desc, interval in ms, expected ticks in 60s
runTest('10 ticks per second for 60 seconds', 100, 600);
}
function test500msTicks() {
runTest('2 ticks per second for 60 seconds', 500, 120);
}
function test1sTicks() {
runTest('1 tick per second for 60 seconds', 1000, 60);
}
function test2sTicks() {
runTest('1 tick every 2 seconds for 60 seconds', 2000, 30);
}
function test5sTicks() {
runTest('1 tick every 5 seconds for 60 seconds', 5000, 12);
}
function test10sTicks() {
runTest('1 tick every 10 seconds for 60 seconds', 10000, 6);
}
function test30sTicks() {
runTest('1 tick every 30 seconds for 60 seconds', 30000, 2);
}
function test60sTicks() {
runTest('1 tick every 60 seconds', 60000, 1);
}
function testCallOnce() {
var c = 0;
var actualTimeoutId = goog.Timer.callOnce(
function() {
if (c > 0) {
assertTrue('callOnce should only be called once', false);
}
c++;
});
assertEquals('callOnce should return the timeout ID',
mockClock.getTimeoutsMade(), actualTimeoutId);
var obj = {c: 0};
goog.Timer.callOnce(function() {
if (this.c > 0) {
assertTrue('callOnce should only be called once', false);
}
assertEquals(obj, this);
this.c++;
}, 1, obj);
mockClock.tick(maxDuration);
}
function testCallOnceIgnoresTimeoutsTooLarge() {
var failCallback = goog.partial(fail, 'Timeout should never be called');
assertEquals('Timeouts slightly too large should yield a timer ID of -1',
-1, goog.Timer.callOnce(failCallback, 2147483648));
assertEquals('Infinite timeouts should yield a timer ID of -1',
-1, goog.Timer.callOnce(failCallback, Infinity));
}
function testPromise() {
var c = 0;
goog.Timer.promise(1, 'A').then(function(result) {
c++;
assertEquals('promise should return resolved value', 'A', result);
});
mockClock.tick(10);
assertEquals('promise must be yielded once and only once', 1, c);
}
function testPromise_cancel() {
var c = 0;
goog.Timer.promise(1, 'A').then(function(result) {
fail('promise must not be resolved');
}, function(reason) {
c++;
assertTrue('promise must fail due to cancel signal',
reason instanceof goog.Promise.CancellationError);
}).cancel();
mockClock.tick(10);
assertEquals('promise must be canceled once and only once', 1, c);
}
function testPromise_timeoutTooLarge() {
var c = 0;
goog.Timer.promise(2147483648, 'A').then(function(result) {
fail('promise must not be resolved');
}, function(reason) {
c++;
assertTrue('promise must be rejected', reason instanceof Error);
});
mockClock.tick(10);
assertEquals('promise must be rejected once and only once', 1, c);
}