This commit is contained in:
2022-09-30 05:39:11 +00:00
parent 41ee9463ae
commit 4687fa49bc
11418 changed files with 1312504 additions and 0 deletions

1
buildfiles/app/node_modules/lastfm/.npmignore generated vendored Normal file
View File

@ -0,0 +1 @@
config.js

93
buildfiles/app/node_modules/lastfm/History.md generated vendored Normal file
View File

@ -0,0 +1,93 @@
# Changelog
## 0.8.4
* Added some user functions to list of signed methods (maxkueng)
* Added some library functions to list of write methods (maxkueng)
## 0.8.3
* Fix issue where undefined mbid in track object would cause scrobble
to fail. (maxkueng)
* Fix issue where all undefined and null parameters would cause signatures
to fail.
* Use http.request instead of deprecated http.createClient. (xhochy)
* lastfm-node now requires node v0.4.10 and above.
## 0.8.1
* Automatically set album parameter from track details when available.
* Experimental REPL.
## 0.8.0
### Breaking changes
* Removed old handler options which were deprecated in 0.6.0.
### New features
* Scrobble request which return error codes 11, 16 or 29 are automatically retried.
## 0.7.0
### Breaking changes
* The success event on `lastfm.request` now emits parsed JSON rather than raw text.
* `RecentTracksStream.isStreaming` has been removed in favour of `RecentTracksStream.isStreaming()`.
## 0.6.3
* Fixed bug where success/error handlers on lastfm.info and lastfm.update were being fired twice.
* Configurable user-agent string.
* LastFmUpdate can now accept any parameter. This will be passed through to Last.Fm. This allows artist/track info to be supplied without having to use the track object from RecentTrackStream.
## 0.6.2
Fixed path issue (regression)
## 0.6.1
* Reinstated LastFmSession.authorise() handler options which were accidentallly removed rather than deprecated. Thanks to Vytautas Jakutis for the spot.
* Fixed LastFmSession.authorise() documentation (Vytautas Jakutis)
## 0.6.0
### New features
* Added request() method. Provides low-level support for entire Last.Fm API.
* Event handler options on RecentTrackStream, LastFmUpdate and LastFmInfo have been deprecated and replaced with more generic `handlers` option. These will be removed soon.
## 0.5.1
* More accurate error reporting from RecentTrackParser
* v0.4.x support
## 0.5.0
* Renamed lastfm.readRequest/writeRequest to read/write.
* Replace response reader with LastFmRequest.
## 0.4.4
* Handles response errors (timeouts, etc) when communicating with Last.fm
* Fixed bug where unexpected data in LastFmInfo would crash application.
## 0.4.3
* Fixed bug where RecentTrackStream was working with null tracks.
## 0.4.2
* Added session.isAuthorised()
## 0.4.1
* Added slightly more descriptive errors to RecentTracksParser.
## 0.4.0
### Breaking changes
* `LastFmSession` is no longer responsible for sending update. Use `lastfm.update()` instead.
lastfm.update("nowplaying", session, { track: track });
### New Features
* Access getInfo API calls through `lastfm.info()`. See README for example.

19
buildfiles/app/node_modules/lastfm/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2011, James Scott and Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

304
buildfiles/app/node_modules/lastfm/README.md generated vendored Normal file
View File

@ -0,0 +1,304 @@
# lastfm-node
Read and write to users recent plays on Last.fm.
## Installation
npm install lastfm
## Usage
var LastFmNode = require('lastfm').LastFmNode;
var lastfm = new LastFmNode({
api_key: 'apikey', // sign-up for a key at http://www.last.fm/api
secret: 'secret',
useragent: 'appname/vX.X MyApp' // optional. defaults to lastfm-node.
});
## Documentation
### LastFmRequest
lastfm.request(method, options);
Returns a `LastFmRequest` instance.
Send request to Last.fm. Requests automatically include the API key and are signed and/or sent via POST as described in the Last.fm API documentation.
Methods:
Accepts any Last.fm API method name, eg "artist.getInfo".
Options:
All options are passed through to Last.fm with the exception of the following.
- *write*
Force request to act as a write method. Write methods are signed and sent via POST. Useful for new methods not yet recognised by lastfm-node.
- *signed*
Force request to be signed. See Last.fm API docs for signature details. Useful for new methods not yet recognised by lastfm-node.
- *handlers*
Default event handlers to attach to the request object on creation.
Events:
- *success(json)*
JSON response from Last.fm
- *error(error)*
Ruh-roh. Either a error returned by Last.fm or a transmission error.
### RecentTracksStream
lastfm.stream(username);
Returns: a `RecentTracksStream` instance
Methods:
- *start()*
Start streaming recent track info.
- *stop()*
Stop streaming recent track info.
- *isStreaming()*
Boolean. True is nowplaying/recent track data is being actively fetched.
- *on(event, listener)*
Adds a listener for the specified event.
- *removeListener(event, listener)*
Removes the listener for the specified event.
Options:
- *autostart*
Start streaming automatically. Defaults to false.
- *handlers*
Default event handlers to attach to the request object on creation.
Events:
- *lastPlayed(track)*
The user's last scrobbled track.
- *nowPlaying(track)*
Track the user is currently listening to.
- *scrobbled(track)*
Now playing track has been scrobbled.
- *stoppedPlaying(track)*
User stopped listening to current track.
- *error(error)*
Ruh-roh.
### LastFmSession
lastfm.session([user], [key]);
Returns: a `LastFmSession` instance.
If no key is supplied then the authorise() method must be used before the session can be used to make authenticated calls. See the last.fm API documentation for more info.
Public properties:
- *user*
The username of the Last.fm user associated with the session.
- *key*
The session key. Either passed in or generated using authorise().
Methods:
- *authorise(token, [options])*
Authorises user with Last.fm api. See last.fm documentation. Options argument has handlers property that has default event handlers to attach to the LastFmSession instance.
- *on(event, handler)*
Adds a listener for the specified event.
- *removeListener(event, handler)*
Removes the listener for the specified event.
- *isAuthorised()*
Returns true if the session has been authorised or a key was specified in the constructor.
Events:
- *authorised(session)*
Authorisation of session was successful.
Note: Only emitted after a call to authorise(). Keys supplied in the constructor are assumed to be valid.
- *error(track, error)*
Ruh-roh.
### LastFmUpdate
lastfm.update(method, session, options);
Returns a `LastFmUpdate` instance.
Valid methods are 'nowplaying' and 'scrobble'.
An authorised `LastFmSession` instance is required to make a successful update.
If a scrobble request receives an 11 (service offline), 16 (temporarily unavailable) or 29 (rate limit exceeded) error code from Last.fm then the request is automatically retried until it is permanently rejected or accepted. The first retry attempt is made after 10 seconds with subsequent requests delayed by 30 seconds, 1 minute, 5 minutes, 15 minutes and then every 30 minutes.
Options:
Accepts all parameters used by track.updateNowPlaying and user.scrobble (see Last.Fm API) as well as:
- *track*
Track for nowplaying and scrobble requests. Uses same format as returned by `RecentTracksStream` events.
- *timestamp*
Required for scrobble requests. Timestamp is in unix time (seconds since 01-01-1970 and is in UTC time).
- *handlers*
Default event handlers to attach to the request object on creation.
Events:
- *success(track)*
Update request was successful.
- *retrying(retry)*
Scrobble request was not successful but will be retried after a delay. Retry object contains the following properties:
`delay` - The time in milliseconds before the request will be retried.
`error` - The error code returned by the Last.fm API.
`message` - The error message returned by the Last.fm API.
- *error(track, error)*
Ruh-roh.
### LastFmInfo
lastfm.info(itemtype, [options]);
Returns: a `LastFmInfo` instance.
Gets extended info about specified item.
Public properties:
- *itemtype*
Any Last.fm item with a getInfo method. eg user, track, artist, etc.
Options:
- *handlers*
Event handlers to attach to object at creation.
- *various*
Params as specified in Last.fm API, eg user: "username"
Special cases:
When requesting track info the `track` param can be either the track name or a track object as returned by `RecentTracksStream`.
## Example
var LastFmNode = require('lastfm').LastFmNode;
var lastfm = new LastFmNode({
api_key: 'abc',
secret: 'secret'
});
var trackStream = lastfm.stream('username');
trackStream.on('lastPlayed', function(track) {
console.log('Last played: ' + track.name);
});
trackStream.on('nowPlaying', function(track) {
console.log('Now playing: ' + track.name);
});
trackStream.on('scrobbled', function(track) {
console.log('Scrobbled: ' + track.name);
});
trackStream.on('stoppedPlaying', function(track) {
console.log('Stopped playing: ' + track.name);
});
trackStream.on('error', function(error) {
console.log('Error: ' + error.message);
});
trackStream.start();
var session = lastfm.session();
session.authorise(token, {
handlers: {
authorised: function(session) {
lastfm.update('nowplaying', session, { track: track } );
lastfm.update('scrobble', session, { track: track, timestamp: 12345678 });
}
}
});
var request = lastfm.request("artist.getInfo", {
artist: "The Mae Shi",
handlers: {
success: function(data) {
console.log("Success: " + data);
},
error: function(error) {
console.log("Error: " + error.message);
}
}
});
## Influences
Heavily drawn from technoweenie's twitter-node
http://github.com/technoweenie/twitter-node
## Contributors
* Garret Wilkin (garrettwilkin) - http://geethink.com
* Uwe L. Korn (xhochy) - http://xhochy.com
* Max Kueng (maxkueng) - http://maxkueng.com

17
buildfiles/app/node_modules/lastfm/Roadmap.md generated vendored Normal file
View File

@ -0,0 +1,17 @@
# Roadmap
## 0.7.0 (complete)
* Responses from lastfm.request are automatically converted to JSON.
## 0.8.0
* Failed scrobbles are automatically retried when appropriate.
## 0.9.0
* Caching support. Memory and reddis with other datastores to follow.
## 1.0.0
* Finalise API.
* Tidy JSON responses.
## 1.1.0
* Radio API/playlist support.

4
buildfiles/app/node_modules/lastfm/config.example.js generated vendored Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
api_key: '',
secret: ''
};

5
buildfiles/app/node_modules/lastfm/config.james.sj generated vendored Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
api_key: '6b6bd821c1bb65fc92c2da020a66e930',
secret: '2c302d2f03a0803f064d48da88fbb095',
session: '22827f87877938a73ad5756d22696f40'
};

44
buildfiles/app/node_modules/lastfm/lastfm-repl.js generated vendored Normal file
View File

@ -0,0 +1,44 @@
var LastFmNode = require('./lib/lastfm').LastFmNode,
repl = require('repl'),
config = require('./config'),
_ = require('underscore');
var echoHandler = function() {
_(arguments).each(function(arg) {
console.log(arg);
});
};
var errorHandler = function(error) {
console.log('Error: ' + error.message);
};
var quietHandler = function() { };
var _echoHandlers = {
error: errorHandler,
success: echoHandler,
lastPlayed: echoHandler,
nowPlaying: echoHandler,
scrobbled: echoHandler,
stoppedPlaying: echoHandler
};
var _quietHandlers = {
error: errorHandler,
success: quietHandler,
lastPlayed: quietHandler,
nowPlaying: quietHandler,
scrobbled: quietHandler,
stoppedPlaying: quietHandler
}
var lastfm = new LastFmNode({
api_key: config.api_key,
secret: config.secret
});
var context = repl.start().context;
context.lastfm = lastfm;
context._echoHandlers = _echoHandlers;
context._quietHandlers = _quietHandlers;

35
buildfiles/app/node_modules/lastfm/lib/lastfm/index.js generated vendored Normal file
View File

@ -0,0 +1,35 @@
var RecentTracksStream = require("./recenttracks-stream"),
LastFmSession = require("./lastfm-session"),
LastFmUpdate = require("./lastfm-update"),
LastFmInfo = require("./lastfm-info"),
LastFmRequest = require("./lastfm-request");
var LastFmNode = exports.LastFmNode = function(options) {
options = options || {};
this.url = "/2.0";
this.host = "ws.audioscrobbler.com";
this.format = "json";
this.secret = options.secret;
this.api_key = options.api_key;
this.useragent = options.useragent || "lastfm-node";
};
LastFmNode.prototype.request = function(method, params) {
return new LastFmRequest(this, method, params);
};
LastFmNode.prototype.stream = function(user, options) {
return new RecentTracksStream(this, user, options);
};
LastFmNode.prototype.session = function(user, key) {
return new LastFmSession(this, user, key);
};
LastFmNode.prototype.info = function(type, options) {
return new LastFmInfo(this, type, options);
};
LastFmNode.prototype.update = function(method, session, options) {
return new LastFmUpdate(this, method, session, options);
};

View File

@ -0,0 +1,45 @@
var EventEmitter = require("events").EventEmitter
, _ = require("underscore");
var LastFmBase = function() {
EventEmitter.call(this);
};
LastFmBase.prototype = Object.create(EventEmitter.prototype);
LastFmBase.prototype.registerHandlers = function(handlers) {
if (typeof handlers !== "object") {
return;
}
var that = this;
_(handlers).each(function(value, key) {
that.on(key, value);
});
};
var defaultBlacklist = ["error", "success", "handlers"];
LastFmBase.prototype.filterParameters = function(parameters, blacklist) {
var filteredParams = {};
_(parameters).each(function(value, key) {
if (isBlackListed(key)) {
return;
}
filteredParams[key] = value;
});
return filteredParams;
function isBlackListed(name) {
return _(defaultBlacklist).include(name) || _(blacklist).include(name);
}
};
LastFmBase.prototype.scheduleCallback = function(callback, delay) {
return setTimeout(callback, delay);
};
LastFmBase.prototype.cancelCallback = function(identifier) {
clearTimeout(identifier);
};
module.exports = LastFmBase;

View File

@ -0,0 +1,43 @@
var LastFmBase = require("./lastfm-base");
var LastFmInfo = function(lastfm, type, options) {
var that = this;
options = options || {};
LastFmBase.call(this);
registerEventHandlers(options);
requestInfo(type, options);
function registerEventHandlers(options) {
that.registerHandlers(options.handlers);
}
function requestInfo(type, options) {
if (!type) {
that.emit("error", new Error("Item type not specified"));
return;
}
var params = that.filterParameters(options)
, method = type + ".getinfo"
, request = lastfm.request(method, params);
request.on("success", success);
request.on("error", error);
}
function success(response) {
if (response[type]) {
that.emit("success", response[type]);
return;
}
that.emit("error", new Error("Unexpected error"));
}
function error(error) {
that.emit("error", error);
}
};
LastFmInfo.prototype = Object.create(LastFmBase.prototype);
module.exports = LastFmInfo;

View File

@ -0,0 +1,144 @@
if (global.GENTLY_HIJACK) require = GENTLY_HIJACK.hijack(require);
var http = require("http")
, querystring = require('querystring')
, _ = require("underscore")
, crypto = require("crypto")
, LastFmBase = require("./lastfm-base");
var WRITE_METHODS = ["album.addtags", "album.removetag", "album.share",
"artist.addtags", "artist.removetag", "artist.share", "artist.shout",
"event.attend", "event.share", "event.shout",
"library.addalbum", "library.addartist", "library.addtrack",
"library.removealbum", "library.removeartist", "library.removetrack", "library.removescrobble",
"playlist.addtrack", "playlist.create",
"radio.tune",
"track.addtags", "track.ban", "track.love", "track.removetag",
"track.scrobble", "track.share", "track.unban", "track.unlove",
"track.updatenowplaying",
"user.shout"],
SIGNED_METHODS = ["auth.getmobilesession", "auth.getsession", "auth.gettoken",
"radio.getplaylist",
"user.getrecentstations", "user.getrecommendedartists", "user.getrecommendedevents"];
var LastFmRequest = module.exports = function(lastfm, method, params) {
var that = this;
LastFmBase.call(this);
params = params || {};
that.registerHandlers(params.handlers);
sendRequest(lastfm.host, lastfm.url, params);
function sendRequest(host, url, params) {
var httpVerb = isWriteRequest() ? "POST" : "GET"
var requestParams = buildRequestParams(params);
var data = querystring.stringify(requestParams);
if (httpVerb == "GET") {
url += "?" + data;
}
var options = {
host: host,
port: 80,
path: url,
method: httpVerb,
headers: requestHeaders(httpVerb, host, data)
};
var req = http.request(options, chunkedResponse);
req.on("error", function(error) {
that.emit("error", error);
});
if (httpVerb == "POST") {
req.write(data);
}
req.end()
}
function buildRequestParams(params) {
var requestParams = that.filterParameters(params, ["signed", "write"]);
requestParams.method = method;
requestParams.api_key = requestParams.api_key || lastfm.api_key;
requestParams.format = requestParams.format || lastfm.format;
if (params.track && typeof params.track === "object") {
requestParams.artist = params.track.artist["#text"];
requestParams.track = params.track.name;
if (params.track.mbid) {
requestParams.mbid = params.track.mbid;
}
if (params.track.album) {
requestParams.album = requestParams.album || params.track.album["#text"];
}
}
if (requiresSignature()) {
requestParams.api_sig = createSignature(requestParams, lastfm.secret);
}
return requestParams;
}
function requiresSignature() {
return params.signed || isWriteRequest() || isSignedMethod(method);
}
function isWriteRequest() {
return params.write || isWriteMethod(method);
}
function isSignedMethod(method) {
return method && _(SIGNED_METHODS).include(method.toLowerCase());
}
function isWriteMethod(method) {
return method && _(WRITE_METHODS).include(method.toLowerCase());
}
function requestHeaders(httpVerb, host, data) {
var headers = {
"User-Agent": lastfm.useragent
};
if (httpVerb == "POST") {
headers["Content-Length"] = data.length;
headers["Content-Type"] = "application/x-www-form-urlencoded";
}
return headers;
}
function chunkedResponse(response) {
var data = "";
response.on("data", function(chunk) {
data += chunk.toString("utf8");
});
response.on("end", function() {
if (lastfm.format !== "json") {
that.emit("success", data);
return;
}
try {
var json = JSON.parse(data);
if (json.error) {
that.emit("error", json);
return;
}
that.emit("success", json);
}
catch(e) {
that.emit("error", e)
}
});
}
function createSignature(params, secret) {
var sig = "";
Object.keys(params).sort().forEach(function(key) {
if (key != "format") {
var value = typeof params[key] !== "undefined" && params[key] !== null ? params[key] : "";
sig += key + value;
}
});
sig += secret;
return crypto.createHash("md5").update(sig, "utf8").digest("hex");
}
};
LastFmRequest.prototype = Object.create(LastFmBase.prototype);

View File

@ -0,0 +1,72 @@
var LastFmBase = require("./lastfm-base");
var LastFmSession = function(lastfm, user, key) {
var that = this;
LastFmBase.call(this);
user = user || "";
key = key || "";
this.user = user;
this.key = key;
this.authorise = function(token, options) {
authorise(token, options);
};
this.isAuthorised = function() {
return isAuthorised();
}
function authorise(token, options) {
options = options || { };
registerEventHandlers(options);
validateToken(token);
}
function registerEventHandlers(options) {
that.registerHandlers(options.handlers);
}
function validateToken(token) {
if (!token) {
that.emit("error", new Error("No token supplied"));
return;
}
var params = { token: token },
request = lastfm.request("auth.getsession", params);
request.on("success", authoriseSession);
request.on("error", bubbleError);
}
function isAuthorised() {
return that.key && that.key !== '';
}
function authoriseSession(result) {
if (!result.session) {
that.emit("error", new Error("Unexpected error"));
return;
}
setSessionDetails(result.session);
that.emit("authorised", that);
}
function setSessionDetails(session) {
that.user = session.name;
that.key = session.key;
}
function bubbleError(error) {
that.emit("error", error);
}
};
LastFmSession.prototype = Object.create(LastFmBase.prototype);
module.exports = LastFmSession;

View File

@ -0,0 +1,104 @@
var _ = require("underscore")
, LastFmBase = require("./lastfm-base")
, retryOnErrors = [
11, // Service offline
16, // Temporarily unavailable
29 // Rate limit exceeded
]
, retrySchedule = [
10 * 1000, // 10 seconds
30 * 1000, // 30 seconds
60 * 1000, // 1 minute
5 * 60 * 1000, // 5 minutes
15 * 60 * 1000, // 15 minutes
30 * 60 * 1000 // 30 minutes
];
var LastFmUpdate = function(lastfm, method, session, options) {
var that = this;
options = options || { };
LastFmBase.call(this);
registerEventHandlers(options);
if (!session.isAuthorised()) {
this.emit("error", {
error: 4,
message: "Authentication failed"
});
return;
}
if (method !== "scrobble" && method !== "nowplaying") {
return;
}
update(method, options);
function registerEventHandlers(options) {
that.registerHandlers(options.handlers);
}
function update(method, options) {
if (method == "scrobble" && !options.timestamp) {
that.emit("error", {
error: 6,
message: "Invalid parameters - Timestamp is required for scrobbling"
});
return;
}
var retryCount = 0
, params = buildRequestParams(options)
, requestMethod = method == "scrobble" ? "track.scrobble" : "track.updateNowPlaying";
makeRequest();
function makeRequest() {
var request = lastfm.request(requestMethod, params);
request.on("error", errorCallback);
request.on("success", successCallback);
}
function successCallback(response) {
if (response) {
that.emit("success", options.track);
}
}
function errorCallback(error) {
if (shouldBeRetried(error)) {
var delay = delayFor(retryCount++)
, retry = {
error: error.error,
message: error.message,
delay: delay
};
that.emit("retrying", retry);
that.scheduleCallback(makeRequest, delay);
return;
}
bubbleError(error);
}
function shouldBeRetried(error) {
return method == "scrobble" && _(retryOnErrors).include(error.error)
}
}
function bubbleError(error) {
that.emit("error", error);
}
function buildRequestParams(params) {
var requestParams = that.filterParameters(params);
requestParams.sk = session.key;
return requestParams;
}
function delayFor(retryCount) {
var index = Math.min(retryCount, retrySchedule.length - 1);
return retrySchedule[index];
}
}
LastFmUpdate.prototype = Object.create(LastFmBase.prototype);
module.exports = LastFmUpdate;

View File

@ -0,0 +1,111 @@
var LastFmBase = require("./lastfm-base");
var RecentTracksStream = module.exports = function(lastfm, user, options) {
var that = this;
LastFmBase.call(this);
options = options || {};
var rate = 10
, isStreaming = false
, timeout
, lastPlay = null
, nowPlaying = null;
registerEventHandlers(options);
if (options.autostart) {
start();
}
this.start = function() {
start();
}
this.stop = function() {
stop();
}
this.isStreaming = function() {
return isStreaming;
}
function registerEventHandlers(options) {
that.registerHandlers(options.handlers);
}
function start() {
isStreaming = true;
check();
function check() {
var request = lastfm.request("user.getrecenttracks", {
user: user,
limit: 1
});
request.on("success", handleSuccess);
request.on("error", bubbleError);
if (isStreaming) {
timeout = that.scheduleCallback(check, rate * 1000);
}
}
function handleSuccess(data) {
if (!data || !data.recenttracks || !data.recenttracks.track) {
that.emit("error", new Error("Unexpected response"));
return;
}
var tracks = data.recenttracks.track;
if (tracks instanceof Array) {
processNowPlaying(tracks[0]);
processLastPlay(tracks[1]);
return;
}
var track = tracks;
if (track["@attr"] && track["@attr"]["nowplaying"]) {
processNowPlaying(track);
return;
}
processLastPlay(track);
if (nowPlaying) {
that.emit("stoppedPlaying", nowPlaying);
nowPlaying = null;
}
}
function bubbleError(error) {
that.emit("error", error);
}
}
function processNowPlaying(track) {
var sameTrack = (nowPlaying && nowPlaying.name == track.name);
if (!sameTrack) {
nowPlaying = track;
that.emit("nowPlaying", track);
}
}
function processLastPlay(track) {
if (!lastPlay) {
lastPlay = track;
that.emit("lastPlayed", track);
return;
}
var sameTrack = (lastPlay.name == track.name);
if (!sameTrack) {
lastPlay = track;
that.emit("scrobbled", track);
}
}
function stop() {
that.cancelCallback(timeout);
isStreaming = false;
}
};
RecentTracksStream.prototype = Object.create(LastFmBase.prototype);

View File

@ -0,0 +1,23 @@
Copyright (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,28 @@
__
/\ \ __
__ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
\ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
\/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
\ \____/
\/___/
Underscore.js is a utility-belt library for JavaScript that provides
support for the usual functional suspects (each, map, reduce, filter...)
without extending any core JavaScript objects.
For Docs, License, Tests, and pre-packed downloads, see:
https://underscorejs.org
For support and questions, please use
[the gitter channel](https://gitter.im/jashkenas/underscore)
or [stackoverflow](https://stackoverflow.com/search?q=underscore.js)
Underscore is an open-sourced component of DocumentCloud:
https://github.com/documentcloud
Many thanks to our contributors:
https://github.com/jashkenas/underscore/contributors
This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.

View File

@ -0,0 +1,21 @@
define(['./isObject', './_setup'], function (isObject, _setup) {
// Create a naked function reference for surrogate-prototype-swapping.
function ctor() {
return function(){};
}
// An internal function for creating a new object that inherits from another.
function baseCreate(prototype) {
if (!isObject(prototype)) return {};
if (_setup.nativeCreate) return _setup.nativeCreate(prototype);
var Ctor = ctor();
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
}
return baseCreate;
});

View File

@ -0,0 +1,15 @@
define(['./isObject', './identity', './isFunction', './isArray', './matcher', './property', './_optimizeCb'], function (isObject, identity, isFunction, isArray, matcher, property, _optimizeCb) {
// An internal function to generate callbacks that can be applied to each
// element in a collection, returning the desired result — either `_.identity`,
// an arbitrary callback, a property matcher, or a property accessor.
function baseIteratee(value, context, argCount) {
if (value == null) return identity;
if (isFunction(value)) return _optimizeCb(value, context, argCount);
if (isObject(value) && !isArray(value)) return matcher(value);
return property(value);
}
return baseIteratee;
});

View File

@ -0,0 +1,12 @@
define(['./_baseIteratee', './underscore', './iteratee'], function (_baseIteratee, underscore, iteratee) {
// The function we call internally to generate a callback. It invokes
// `_.iteratee` if overridden, otherwise `baseIteratee`.
function cb(value, context, argCount) {
if (underscore.iteratee !== iteratee) return underscore.iteratee(value, context);
return _baseIteratee(value, context, argCount);
}
return cb;
});

View File

@ -0,0 +1,10 @@
define(['./underscore'], function (underscore) {
// Helper function to continue chaining intermediate results.
function chainResult(instance, obj) {
return instance._chain ? underscore(obj).chain() : obj;
}
return chainResult;
});

View File

@ -0,0 +1,42 @@
define(['./_setup', './isFunction', './_has'], function (_setup, isFunction, _has) {
// Internal helper to create a simple lookup structure.
// `collectNonEnumProps` used to depend on `_.contains`, but this led to
// circular imports. `emulatedSet` is a one-off solution that only works for
// arrays of strings.
function emulatedSet(keys) {
var hash = {};
for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true;
return {
contains: function(key) { return hash[key]; },
push: function(key) {
hash[key] = true;
return keys.push(key);
}
};
}
// Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't
// be iterated by `for key in ...` and thus missed. Extends `keys` in place if
// needed.
function collectNonEnumProps(obj, keys) {
keys = emulatedSet(keys);
var nonEnumIdx = _setup.nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = isFunction(constructor) && constructor.prototype || _setup.ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_has(obj, prop) && !keys.contains(prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = _setup.nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
keys.push(prop);
}
}
}
return collectNonEnumProps;
});

View File

@ -0,0 +1,24 @@
define(function () {
// An internal function for creating assigner functions.
function createAssigner(keysFunc, defaults) {
return function(obj) {
var length = arguments.length;
if (defaults) obj = Object(obj);
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!defaults || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
}
return createAssigner;
});

View File

@ -0,0 +1,21 @@
define(['./keys'], function (keys) {
// Internal helper to generate functions for escaping and unescaping strings
// to/from HTML interpolation.
function createEscaper(map) {
var escaper = function(match) {
return map[match];
};
// Regexes for identifying a key that needs to be escaped.
var source = '(?:' + keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
}
return createEscaper;
});

View File

@ -0,0 +1,30 @@
define(['./_setup', './_getLength', './isNaN'], function (_setup, _getLength, _isNaN) {
// Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions.
function createIndexFinder(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {
var i = 0, length = _getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(_setup.slice.call(array, i, length), _isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
}
return createIndexFinder;
});

View File

@ -0,0 +1,18 @@
define(['./_cb', './_getLength'], function (_cb, _getLength) {
// Internal function to generate `_.findIndex` and `_.findLastIndex`.
function createPredicateIndexFinder(dir) {
return function(array, predicate, context) {
predicate = _cb(predicate, context);
var length = _getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
return createPredicateIndexFinder;
});

View File

@ -0,0 +1,30 @@
define(['./keys', './_optimizeCb', './_isArrayLike'], function (keys, _optimizeCb, _isArrayLike) {
// Internal helper to create a reducing function, iterating left or right.
function createReduce(dir) {
// Wrap code that reassigns argument variables in a separate function than
// the one that accesses `arguments.length` to avoid a perf hit. (#1991)
var reducer = function(obj, iteratee, memo, initial) {
var _keys = !_isArrayLike(obj) && keys(obj),
length = (_keys || obj).length,
index = dir > 0 ? 0 : length - 1;
if (!initial) {
memo = obj[_keys ? _keys[index] : index];
index += dir;
}
for (; index >= 0 && index < length; index += dir) {
var currentKey = _keys ? _keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
return memo;
};
return function(obj, iteratee, memo, context) {
var initial = arguments.length >= 3;
return reducer(obj, _optimizeCb(iteratee, context, 4), memo, initial);
};
}
return createReduce;
});

View File

@ -0,0 +1,13 @@
define(['./_setup'], function (_setup) {
// Common internal logic for `isArrayLike` and `isBufferLike`.
function createSizePropertyCheck(getSizeProperty) {
return function(collection) {
var sizeProperty = getSizeProperty(collection);
return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= _setup.MAX_ARRAY_INDEX;
}
}
return createSizePropertyCheck;
});

View File

@ -0,0 +1,15 @@
define(function () {
// Internal function to obtain a nested property in `obj` along `path`.
function deepGet(obj, path) {
var length = path.length;
for (var i = 0; i < length; i++) {
if (obj == null) return void 0;
obj = obj[path[i]];
}
return length ? obj : void 0;
}
return deepGet;
});

View File

@ -0,0 +1,15 @@
define(function () {
// Internal list of HTML entities for escaping.
var escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'`': '&#x60;'
};
return escapeMap;
});

View File

@ -0,0 +1,16 @@
define(['./isObject', './_baseCreate'], function (isObject, _baseCreate) {
// Internal function to execute `sourceFunc` bound to `context` with optional
// `args`. Determines whether to execute a function as a constructor or as a
// normal function.
function executeBound(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = _baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (isObject(result)) return result;
return self;
}
return executeBound;
});

View File

@ -0,0 +1,32 @@
define(['./isArray', './_getLength', './_isArrayLike', './isArguments'], function (isArray, _getLength, _isArrayLike, isArguments) {
// Internal implementation of a recursive `flatten` function.
function flatten(input, depth, strict, output) {
output = output || [];
if (!depth && depth !== 0) {
depth = Infinity;
} else if (depth <= 0) {
return output.concat(input);
}
var idx = output.length;
for (var i = 0, length = _getLength(input); i < length; i++) {
var value = input[i];
if (_isArrayLike(value) && (isArray(value) || isArguments(value))) {
// Flatten current level of array or arguments object.
if (depth > 1) {
flatten(value, depth - 1, strict, output);
idx = output.length;
} else {
var j = 0, len = value.length;
while (j < len) output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
}
}
return output;
}
return flatten;
});

View File

@ -0,0 +1,8 @@
define(['./_shallowProperty'], function (_shallowProperty) {
// Internal helper to obtain the `byteLength` property of an object.
var getByteLength = _shallowProperty('byteLength');
return getByteLength;
});

View File

@ -0,0 +1,8 @@
define(['./_shallowProperty'], function (_shallowProperty) {
// Internal helper to obtain the `length` property of an object.
var getLength = _shallowProperty('length');
return getLength;
});

View File

@ -0,0 +1,18 @@
define(['./_cb', './each'], function (_cb, each) {
// An internal function used for aggregate "group by" operations.
function group(behavior, partition) {
return function(obj, iteratee, context) {
var result = partition ? [[], []] : {};
iteratee = _cb(iteratee, context);
each(obj, function(value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
}
return group;
});

View File

@ -0,0 +1,10 @@
define(['./_setup'], function (_setup) {
// Internal function to check whether `key` is an own property name of `obj`.
function has(obj, key) {
return obj != null && _setup.hasOwnProperty.call(obj, key);
}
return has;
});

View File

@ -0,0 +1,11 @@
define(['./_getLength', './_createSizePropertyCheck'], function (_getLength, _createSizePropertyCheck) {
// Internal helper for collection methods to determine whether a collection
// should be iterated as an array or as an object.
// Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
var isArrayLike = _createSizePropertyCheck(_getLength);
return isArrayLike;
});

View File

@ -0,0 +1,9 @@
define(['./_createSizePropertyCheck', './_getByteLength'], function (_createSizePropertyCheck, _getByteLength) {
// Internal helper to determine whether we should spend extensive checks against
// `ArrayBuffer` et al.
var isBufferLike = _createSizePropertyCheck(_getByteLength);
return isBufferLike;
});

View File

@ -0,0 +1,11 @@
define(function () {
// Internal `_.pick` helper function to determine whether `key` is an enumerable
// property name of `obj`.
function keyInObj(value, key, obj) {
return key in obj;
}
return keyInObj;
});

View File

@ -0,0 +1,27 @@
define(function () {
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
function optimizeCb(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
// The 2-argument case is omitted because were not using it.
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
}
return optimizeCb;
});

View File

@ -0,0 +1,68 @@
define(['exports'], function (exports) {
// Current version.
var VERSION = '1.11.0';
// Establish the root object, `window` (`self`) in the browser, `global`
// on the server, or `this` in some virtual machines. We use `self`
// instead of `window` for `WebWorker` support.
var root = typeof self == 'object' && self.self === self && self ||
typeof global == 'object' && global.global === global && global ||
Function('return this')() ||
{};
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
// Create quick reference variables for speed access to core prototypes.
var push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
// Modern feature detection.
var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined';
// All **ECMAScript 5+** native function implementations that we hope to use
// are declared here.
var nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeCreate = Object.create,
nativeIsView = supportsArrayBuffer && ArrayBuffer.isView;
// Create references to these builtin functions because we override them.
var _isNaN = isNaN,
_isFinite = isFinite;
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
// The largest integer that can be represented exactly.
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
exports.ArrayProto = ArrayProto;
exports.MAX_ARRAY_INDEX = MAX_ARRAY_INDEX;
exports.ObjProto = ObjProto;
exports.SymbolProto = SymbolProto;
exports.VERSION = VERSION;
exports._isFinite = _isFinite;
exports._isNaN = _isNaN;
exports.hasEnumBug = hasEnumBug;
exports.hasOwnProperty = hasOwnProperty;
exports.nativeCreate = nativeCreate;
exports.nativeIsArray = nativeIsArray;
exports.nativeIsView = nativeIsView;
exports.nativeKeys = nativeKeys;
exports.nonEnumerableProps = nonEnumerableProps;
exports.push = push;
exports.root = root;
exports.slice = slice;
exports.supportsArrayBuffer = supportsArrayBuffer;
exports.toString = toString;
Object.defineProperty(exports, '__esModule', { value: true });
});

View File

@ -0,0 +1,12 @@
define(function () {
// Internal helper to generate a function to obtain property `key` from `obj`.
function shallowProperty(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
}
return shallowProperty;
});

View File

@ -0,0 +1,12 @@
define(['./_setup'], function (_setup) {
// Internal function for creating a `toString`-based type tester.
function tagTester(name) {
return function(obj) {
return _setup.toString.call(obj) === '[object ' + name + ']';
};
}
return tagTester;
});

View File

@ -0,0 +1,8 @@
define(['./_escapeMap', './invert'], function (_escapeMap, invert) {
// Internal list of HTML entities for unescaping.
var unescapeMap = invert(_escapeMap);
return unescapeMap;
});

View File

@ -0,0 +1,14 @@
define(function () {
// Returns a function that will only be executed on and after the Nth call.
function after(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
}
return after;
});

View File

@ -0,0 +1,15 @@
define(['./isObject', './_setup', './_collectNonEnumProps'], function (isObject, _setup, _collectNonEnumProps) {
// Retrieve all the enumerable property names of an object.
function allKeys(obj) {
if (!isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (_setup.hasEnumBug) _collectNonEnumProps(obj, keys);
return keys;
}
return allKeys;
});

View File

@ -0,0 +1,18 @@
define(function () {
// Returns a function that will only be executed up to (but not including) the
// Nth call.
function before(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
}
return before;
});

View File

@ -0,0 +1,15 @@
define(['./isFunction', './_executeBound', './restArguments'], function (isFunction, _executeBound, restArguments) {
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally).
var bind = restArguments(function(func, context, args) {
if (!isFunction(func)) throw new TypeError('Bind must be called on a function');
var bound = restArguments(function(callArgs) {
return _executeBound(func, bound, context, this, args.concat(callArgs));
});
return bound;
});
return bind;
});

View File

@ -0,0 +1,19 @@
define(['./_flatten', './restArguments', './bind'], function (_flatten, restArguments, bind) {
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
var bindAll = restArguments(function(obj, keys) {
keys = _flatten(keys, false, false);
var index = keys.length;
if (index < 1) throw new Error('bindAll must be passed function names');
while (index--) {
var key = keys[index];
obj[key] = bind(obj[key], obj);
}
return obj;
});
return bindAll;
});

View File

@ -0,0 +1,12 @@
define(['./underscore'], function (underscore) {
// Start chaining a wrapped Underscore object.
function chain(obj) {
var instance = underscore(obj);
instance._chain = true;
return instance;
}
return chain;
});

View File

@ -0,0 +1,17 @@
define(['./_setup'], function (_setup) {
// Chunk a single array into multiple arrays, each containing `count` or fewer
// items.
function chunk(array, count) {
if (count == null || count < 1) return [];
var result = [];
var i = 0, length = array.length;
while (i < length) {
result.push(_setup.slice.call(array, i, i += count));
}
return result;
}
return chunk;
});

View File

@ -0,0 +1,11 @@
define(['./isObject', './isArray', './extend'], function (isObject, isArray, extend) {
// Create a (shallow-cloned) duplicate of an object.
function clone(obj) {
if (!isObject(obj)) return obj;
return isArray(obj) ? obj.slice() : extend({}, obj);
}
return clone;
});

View File

@ -0,0 +1,10 @@
define(['./filter'], function (filter) {
// Trim out all falsy values from an array.
function compact(array) {
return filter(array, Boolean);
}
return compact;
});

View File

@ -0,0 +1,18 @@
define(function () {
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
function compose() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
}
return compose;
});

View File

@ -0,0 +1,12 @@
define(function () {
// Predicate-generating function. Often useful outside of Underscore.
function constant(value) {
return function() {
return value;
};
}
return constant;
});

View File

@ -0,0 +1,12 @@
define(['./_isArrayLike', './values', './indexOf'], function (_isArrayLike, values, indexOf) {
// Determine if the array or object contains a given item (using `===`).
function contains(obj, item, fromIndex, guard) {
if (!_isArrayLike(obj)) obj = values(obj);
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
return indexOf(obj, item, fromIndex) >= 0;
}
return contains;
});

View File

@ -0,0 +1,12 @@
define(['./_has', './_group'], function (_has, _group) {
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
var countBy = _group(function(result, value, key) {
if (_has(result, key)) result[key]++; else result[key] = 1;
});
return countBy;
});

View File

@ -0,0 +1,14 @@
define(['./_baseCreate', './extendOwn'], function (_baseCreate, extendOwn) {
// Creates an object that inherits from the given prototype object.
// If additional properties are provided then they will be added to the
// created object.
function create(prototype, props) {
var result = _baseCreate(prototype);
if (props) extendOwn(result, props);
return result;
}
return create;
});

View File

@ -0,0 +1,38 @@
define(['./restArguments', './delay'], function (restArguments, delay) {
// When a sequence of calls of the returned function ends, the argument
// function is triggered. The end of a sequence is defined by the `wait`
// parameter. If `immediate` is passed, the argument function will be
// triggered at the beginning of the sequence instead of at the end.
function debounce(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArguments(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
}
return debounce;
});

View File

@ -0,0 +1,8 @@
define(['./_createAssigner', './allKeys'], function (_createAssigner, allKeys) {
// Fill in a given object with default properties.
var defaults = _createAssigner(allKeys, true);
return defaults;
});

View File

@ -0,0 +1,9 @@
define(['./underscore', './delay', './partial'], function (underscore, delay, partial) {
// Defers a function, scheduling it to run after the current call stack has
// cleared.
var defer = partial(delay, underscore, 1);
return defer;
});

View File

@ -0,0 +1,13 @@
define(['./restArguments'], function (restArguments) {
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
var delay = restArguments(function(func, wait, args) {
return setTimeout(function() {
return func.apply(null, args);
}, wait);
});
return delay;
});

View File

@ -0,0 +1,14 @@
define(['./_flatten', './restArguments', './filter', './contains'], function (_flatten, restArguments, filter, contains) {
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
var difference = restArguments(function(array, rest) {
rest = _flatten(rest, true, true);
return filter(array, function(value){
return !contains(rest, value);
});
});
return difference;
});

View File

@ -0,0 +1,25 @@
define(['./keys', './_optimizeCb', './_isArrayLike'], function (keys, _optimizeCb, _isArrayLike) {
// The cornerstone for collection functions, an `each`
// implementation, aka `forEach`.
// Handles raw objects in addition to array-likes. Treats all
// sparse array-likes as if they were dense.
function each(obj, iteratee, context) {
iteratee = _optimizeCb(iteratee, context);
var i, length;
if (_isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var _keys = keys(obj);
for (i = 0, length = _keys.length; i < length; i++) {
iteratee(obj[_keys[i]], _keys[i], obj);
}
}
return obj;
}
return each;
});

View File

@ -0,0 +1,8 @@
define(['./_createEscaper', './_escapeMap'], function (_createEscaper, _escapeMap) {
// Function for escaping strings to HTML interpolation.
var _escape = _createEscaper(_escapeMap);
return _escape;
});

View File

@ -0,0 +1,17 @@
define(['./keys', './_cb', './_isArrayLike'], function (keys, _cb, _isArrayLike) {
// Determine whether all of the elements pass a truth test.
function every(obj, predicate, context) {
predicate = _cb(predicate, context);
var _keys = !_isArrayLike(obj) && keys(obj),
length = (_keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = _keys ? _keys[index] : index;
if (!predicate(obj[currentKey], currentKey, obj)) return false;
}
return true;
}
return every;
});

View File

@ -0,0 +1,8 @@
define(['./_createAssigner', './allKeys'], function (_createAssigner, allKeys) {
// Extend a given object with all the properties in passed-in object(s).
var extend = _createAssigner(allKeys);
return extend;
});

View File

@ -0,0 +1,10 @@
define(['./_createAssigner', './keys'], function (_createAssigner, keys) {
// Assigns a given object with all the own properties in the passed-in
// object(s).
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
var extendOwn = _createAssigner(keys);
return extendOwn;
});

View File

@ -0,0 +1,15 @@
define(['./_cb', './each'], function (_cb, each) {
// Return all the elements that pass a truth test.
function filter(obj, predicate, context) {
var results = [];
predicate = _cb(predicate, context);
each(obj, function(value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
return results;
}
return filter;
});

View File

@ -0,0 +1,12 @@
define(['./_isArrayLike', './findIndex', './findKey'], function (_isArrayLike, findIndex, findKey) {
// Return the first value which passes a truth test.
function find(obj, predicate, context) {
var keyFinder = _isArrayLike(obj) ? findIndex : findKey;
var key = keyFinder(obj, predicate, context);
if (key !== void 0 && key !== -1) return obj[key];
}
return find;
});

View File

@ -0,0 +1,8 @@
define(['./_createPredicateIndexFinder'], function (_createPredicateIndexFinder) {
// Returns the first index on an array-like that passes a truth test.
var findIndex = _createPredicateIndexFinder(1);
return findIndex;
});

View File

@ -0,0 +1,15 @@
define(['./keys', './_cb'], function (keys, _cb) {
// Returns the first key on an object that passes a truth test.
function findKey(obj, predicate, context) {
predicate = _cb(predicate, context);
var _keys = keys(obj), key;
for (var i = 0, length = _keys.length; i < length; i++) {
key = _keys[i];
if (predicate(obj[key], key, obj)) return key;
}
}
return findKey;
});

View File

@ -0,0 +1,8 @@
define(['./_createPredicateIndexFinder'], function (_createPredicateIndexFinder) {
// Returns the last index on an array-like that passes a truth test.
var findLastIndex = _createPredicateIndexFinder(-1);
return findLastIndex;
});

View File

@ -0,0 +1,11 @@
define(['./matcher', './find'], function (matcher, find) {
// Convenience version of a common use case of `_.find`: getting the first
// object containing specific `key:value` pairs.
function findWhere(obj, attrs) {
return find(obj, matcher(attrs));
}
return findWhere;
});

View File

@ -0,0 +1,13 @@
define(['./initial'], function (initial) {
// Get the first element of an array. Passing **n** will return the first N
// values in the array. The **guard** check allows it to work with `_.map`.
function first(array, n, guard) {
if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
if (n == null || guard) return array[0];
return initial(array, array.length - n);
}
return first;
});

View File

@ -0,0 +1,11 @@
define(['./_flatten'], function (_flatten) {
// Flatten out an array, either recursively (by default), or up to `depth`.
// Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively.
function flatten(array, depth) {
return _flatten(array, depth, false);
}
return flatten;
});

View File

@ -0,0 +1,14 @@
define(['./isFunction'], function (isFunction) {
// Return a sorted list of the function names available on the object.
function functions(obj) {
var names = [];
for (var key in obj) {
if (isFunction(obj[key])) names.push(key);
}
return names.sort();
}
return functions;
});

View File

@ -0,0 +1,11 @@
define(['./_has', './_group'], function (_has, _group) {
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
var groupBy = _group(function(result, value, key) {
if (_has(result, key)) result[key].push(value); else result[key] = [value];
});
return groupBy;
});

View File

@ -0,0 +1,23 @@
define(['./_setup', './isArray', './_has'], function (_setup, isArray, _has) {
// Shortcut function for checking if an object has a given property directly on
// itself (in other words, not on a prototype). Unlike the internal `has`
// function, this public version can also traverse nested properties.
function has(obj, path) {
if (!isArray(path)) {
return _has(obj, path);
}
var length = path.length;
for (var i = 0; i < length; i++) {
var key = path[i];
if (obj == null || !_setup.hasOwnProperty.call(obj, key)) {
return false;
}
obj = obj[key];
}
return !!length;
}
return has;
});

View File

@ -0,0 +1,10 @@
define(function () {
// Keep the identity function around for default iteratees.
function identity(value) {
return value;
}
return identity;
});

View File

@ -0,0 +1,12 @@
define(['./mixin', './index'], function (mixin, index) {
// Default Export
// Add all of the Underscore functions to the wrapper object.
var _ = mixin(index);
// Legacy Node.js API.
_._ = _;
return _;
});

View File

@ -0,0 +1,152 @@
define(['exports', './isObject', './_setup', './identity', './isFunction', './isArray', './keys', './extendOwn', './isMatch', './matcher', './property', './iteratee', './isNumber', './isNaN', './isArguments', './each', './invert', './after', './allKeys', './before', './restArguments', './bind', './bindAll', './chain', './chunk', './extend', './clone', './filter', './compact', './compose', './constant', './values', './sortedIndex', './findIndex', './indexOf', './contains', './countBy', './create', './delay', './debounce', './defaults', './partial', './defer', './difference', './escape', './every', './findKey', './find', './findLastIndex', './findWhere', './initial', './first', './flatten', './functions', './groupBy', './has', './isNull', './isUndefined', './isBoolean', './isElement', './isString', './isDate', './isRegExp', './isError', './isSymbol', './isMap', './isWeakMap', './isSet', './isWeakSet', './isArrayBuffer', './isDataView', './isFinite', './isTypedArray', './isEmpty', './isEqual', './pairs', './tap', './mapObject', './noop', './propertyOf', './times', './random', './now', './unescape', './templateSettings', './template', './result', './uniqueId', './memoize', './throttle', './wrap', './negate', './once', './lastIndexOf', './map', './reduce', './reduceRight', './reject', './some', './invoke', './pluck', './where', './max', './min', './sample', './shuffle', './sortBy', './indexBy', './partition', './toArray', './size', './pick', './omit', './rest', './last', './without', './uniq', './union', './intersection', './unzip', './zip', './object', './range', './mixin', './underscore-array-methods'], function (exports, isObject, _setup, identity, isFunction, isArray, keys, extendOwn, isMatch, matcher, property, iteratee, isNumber, _isNaN, isArguments, each, invert, after, allKeys, before, restArguments, bind, bindAll, chain, chunk, extend, clone, filter, compact, compose, constant, values, sortedIndex, findIndex, indexOf, contains, countBy, create, delay, debounce, defaults, partial, defer, difference, _escape, every, findKey, find, findLastIndex, findWhere, initial, first, flatten, functions, groupBy, has, isNull, isUndefined, isBoolean, isElement, isString, isDate, isRegExp, isError, isSymbol, isMap, isWeakMap, isSet, isWeakSet, isArrayBuffer, isDataView, _isFinite, isTypedArray, isEmpty, isEqual, pairs, tap, mapObject, noop, propertyOf, times, random, now, _unescape, templateSettings, template, result, uniqueId, memoize, throttle, wrap, negate, once, lastIndexOf, map, reduce, reduceRight, reject, some, invoke, pluck, where, max, min, sample, shuffle, sortBy, indexBy, partition, toArray, size, pick, omit, rest, last, without, uniq, union, intersection, unzip, zip, object, range, mixin, underscoreArrayMethods) {
// Named Exports
exports.isObject = isObject;
exports.VERSION = _setup.VERSION;
exports.identity = identity;
exports.isFunction = isFunction;
exports.isArray = isArray;
exports.keys = keys;
exports.assign = extendOwn;
exports.extendOwn = extendOwn;
exports.isMatch = isMatch;
exports.matcher = matcher;
exports.matches = matcher;
exports.property = property;
exports.iteratee = iteratee;
exports.isNumber = isNumber;
exports.isNaN = _isNaN;
exports.isArguments = isArguments;
exports.each = each;
exports.forEach = each;
exports.invert = invert;
exports.after = after;
exports.allKeys = allKeys;
exports.before = before;
exports.restArguments = restArguments;
exports.bind = bind;
exports.bindAll = bindAll;
exports.chain = chain;
exports.chunk = chunk;
exports.extend = extend;
exports.clone = clone;
exports.filter = filter;
exports.select = filter;
exports.compact = compact;
exports.compose = compose;
exports.constant = constant;
exports.values = values;
exports.sortedIndex = sortedIndex;
exports.findIndex = findIndex;
exports.indexOf = indexOf;
exports.contains = contains;
exports.include = contains;
exports.includes = contains;
exports.countBy = countBy;
exports.create = create;
exports.delay = delay;
exports.debounce = debounce;
exports.defaults = defaults;
exports.partial = partial;
exports.defer = defer;
exports.difference = difference;
exports.escape = _escape;
exports.all = every;
exports.every = every;
exports.findKey = findKey;
exports.detect = find;
exports.find = find;
exports.findLastIndex = findLastIndex;
exports.findWhere = findWhere;
exports.initial = initial;
exports.first = first;
exports.head = first;
exports.take = first;
exports.flatten = flatten;
exports.functions = functions;
exports.methods = functions;
exports.groupBy = groupBy;
exports.has = has;
exports.isNull = isNull;
exports.isUndefined = isUndefined;
exports.isBoolean = isBoolean;
exports.isElement = isElement;
exports.isString = isString;
exports.isDate = isDate;
exports.isRegExp = isRegExp;
exports.isError = isError;
exports.isSymbol = isSymbol;
exports.isMap = isMap;
exports.isWeakMap = isWeakMap;
exports.isSet = isSet;
exports.isWeakSet = isWeakSet;
exports.isArrayBuffer = isArrayBuffer;
exports.isDataView = isDataView;
exports.isFinite = _isFinite;
exports.isTypedArray = isTypedArray;
exports.isEmpty = isEmpty;
exports.isEqual = isEqual;
exports.pairs = pairs;
exports.tap = tap;
exports.mapObject = mapObject;
exports.noop = noop;
exports.propertyOf = propertyOf;
exports.times = times;
exports.random = random;
exports.now = now;
exports.unescape = _unescape;
exports.templateSettings = templateSettings;
exports.template = template;
exports.result = result;
exports.uniqueId = uniqueId;
exports.memoize = memoize;
exports.throttle = throttle;
exports.wrap = wrap;
exports.negate = negate;
exports.once = once;
exports.lastIndexOf = lastIndexOf;
exports.collect = map;
exports.map = map;
exports.foldl = reduce;
exports.inject = reduce;
exports.reduce = reduce;
exports.foldr = reduceRight;
exports.reduceRight = reduceRight;
exports.reject = reject;
exports.any = some;
exports.some = some;
exports.invoke = invoke;
exports.pluck = pluck;
exports.where = where;
exports.max = max;
exports.min = min;
exports.sample = sample;
exports.shuffle = shuffle;
exports.sortBy = sortBy;
exports.indexBy = indexBy;
exports.partition = partition;
exports.toArray = toArray;
exports.size = size;
exports.pick = pick;
exports.omit = omit;
exports.drop = rest;
exports.rest = rest;
exports.tail = rest;
exports.last = last;
exports.without = without;
exports.uniq = uniq;
exports.unique = uniq;
exports.union = union;
exports.intersection = intersection;
exports.transpose = unzip;
exports.unzip = unzip;
exports.zip = zip;
exports.object = object;
exports.range = range;
exports.mixin = mixin;
exports.default = underscoreArrayMethods;
Object.defineProperty(exports, '__esModule', { value: true });
});

View File

@ -0,0 +1,11 @@
define(['./_group'], function (_group) {
// Indexes the object's values by a criterion, similar to `_.groupBy`, but for
// when you know that your index values will be unique.
var indexBy = _group(function(result, value, key) {
result[key] = value;
});
return indexBy;
});

View File

@ -0,0 +1,11 @@
define(['./_createIndexFinder', './sortedIndex', './findIndex'], function (_createIndexFinder, sortedIndex, findIndex) {
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
var indexOf = _createIndexFinder(1, findIndex, sortedIndex);
return indexOf;
});

View File

@ -0,0 +1,12 @@
define(['./_setup'], function (_setup) {
// Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in
// the array, excluding the last N.
function initial(array, n, guard) {
return _setup.slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
}
return initial;
});

View File

@ -0,0 +1,22 @@
define(['./_getLength', './contains'], function (_getLength, contains) {
// Produce an array that contains every item shared between all the
// passed-in arrays.
function intersection(array) {
var result = [];
var argsLength = arguments.length;
for (var i = 0, length = _getLength(array); i < length; i++) {
var item = array[i];
if (contains(result, item)) continue;
var j;
for (j = 1; j < argsLength; j++) {
if (!contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
}
return intersection;
});

View File

@ -0,0 +1,15 @@
define(['./keys'], function (keys) {
// Invert the keys and values of an object. The values must be serializable.
function invert(obj) {
var result = {};
var _keys = keys(obj);
for (var i = 0, length = _keys.length; i < length; i++) {
result[obj[_keys[i]]] = _keys[i];
}
return result;
}
return invert;
});

View File

@ -0,0 +1,27 @@
define(['./isFunction', './isArray', './_deepGet', './restArguments', './map'], function (isFunction, isArray, _deepGet, restArguments, map) {
// Invoke a method (with arguments) on every item in a collection.
var invoke = restArguments(function(obj, path, args) {
var contextPath, func;
if (isFunction(path)) {
func = path;
} else if (isArray(path)) {
contextPath = path.slice(0, -1);
path = path[path.length - 1];
}
return map(obj, function(context) {
var method = func;
if (!method) {
if (contextPath && contextPath.length) {
context = _deepGet(context, contextPath);
}
if (context == null) return void 0;
method = context[path];
}
return method == null ? method : method.apply(context, args);
});
});
return invoke;
});

View File

@ -0,0 +1,19 @@
define(['./_tagTester', './_has'], function (_tagTester, _has) {
var isArguments = _tagTester('Arguments');
// Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type.
(function() {
if (!isArguments(arguments)) {
isArguments = function(obj) {
return _has(obj, 'callee');
};
}
}());
var isArguments$1 = isArguments;
return isArguments$1;
});

View File

@ -0,0 +1,9 @@
define(['./_setup', './_tagTester'], function (_setup, _tagTester) {
// Is a given value an array?
// Delegates to ECMA5's native `Array.isArray`.
var isArray = _setup.nativeIsArray || _tagTester('Array');
return isArray;
});

View File

@ -0,0 +1,7 @@
define(['./_tagTester'], function (_tagTester) {
var isArrayBuffer = _tagTester('ArrayBuffer');
return isArrayBuffer;
});

View File

@ -0,0 +1,10 @@
define(['./_setup'], function (_setup) {
// Is a given value a boolean?
function isBoolean(obj) {
return obj === true || obj === false || _setup.toString.call(obj) === '[object Boolean]';
}
return isBoolean;
});

View File

@ -0,0 +1,7 @@
define(['./_tagTester'], function (_tagTester) {
var isDataView = _tagTester('DataView');
return isDataView;
});

View File

@ -0,0 +1,7 @@
define(['./_tagTester'], function (_tagTester) {
var isDate = _tagTester('Date');
return isDate;
});

View File

@ -0,0 +1,10 @@
define(function () {
// Is a given value a DOM element?
function isElement(obj) {
return !!(obj && obj.nodeType === 1);
}
return isElement;
});

View File

@ -0,0 +1,15 @@
define(['./isArray', './keys', './_isArrayLike', './isArguments', './isString'], function (isArray, keys, _isArrayLike, isArguments, isString) {
// Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties.
function isEmpty(obj) {
if (obj == null) return true;
// Skip the more expensive `toString`-based type checks if `obj` has no
// `.length`.
if (_isArrayLike(obj) && (isArray(obj) || isString(obj) || isArguments(obj))) return obj.length === 0;
return keys(obj).length === 0;
}
return isEmpty;
});

View File

@ -0,0 +1,134 @@
define(['./_setup', './isFunction', './_has', './keys', './underscore', './_getByteLength', './isTypedArray'], function (_setup, isFunction, _has, keys, underscore, _getByteLength, isTypedArray) {
// Internal recursive comparison function for `_.isEqual`.
function eq(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a === 1 / b;
// `null` or `undefined` only equal to itself (strict comparison).
if (a == null || b == null) return false;
// `NaN`s are equivalent, but non-reflexive.
if (a !== a) return b !== b;
// Exhaust primitive checks
var type = typeof a;
if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
return deepEq(a, b, aStack, bStack);
}
// Internal recursive comparison function for `_.isEqual`.
function deepEq(a, b, aStack, bStack) {
// Unwrap any wrapped objects.
if (a instanceof underscore) a = a._wrapped;
if (b instanceof underscore) b = b._wrapped;
// Compare `[[Class]]` names.
var className = _setup.toString.call(a);
if (className !== _setup.toString.call(b)) return false;
switch (className) {
// These types are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return '' + a === '' + b;
case '[object Number]':
// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN.
if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return +a === +b;
case '[object Symbol]':
return _setup.SymbolProto.valueOf.call(a) === _setup.SymbolProto.valueOf.call(b);
case '[object ArrayBuffer]':
// Coerce to `DataView` so we can fall through to the next case.
return deepEq(new DataView(a), new DataView(b), aStack, bStack);
case '[object DataView]':
var byteLength = _getByteLength(a);
if (byteLength !== _getByteLength(b)) {
return false;
}
while (byteLength--) {
if (a.getUint8(byteLength) !== b.getUint8(byteLength)) {
return false;
}
}
return true;
}
if (isTypedArray(a)) {
// Coerce typed arrays to `DataView`.
return deepEq(new DataView(a.buffer), new DataView(b.buffer), aStack, bStack);
}
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] === a) return bStack[length] === b;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
// Recursively compare objects and arrays.
if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary.
length = a.length;
if (length !== b.length) return false;
// Deep compare the contents, ignoring non-numeric properties.
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} else {
// Deep compare objects.
var _keys = keys(a), key;
length = _keys.length;
// Ensure that both objects contain the same number of properties before comparing deep equality.
if (keys(b).length !== length) return false;
while (length--) {
// Deep compare each member
key = _keys[length];
if (!(_has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return true;
}
// Perform a deep comparison to check if two objects are equal.
function isEqual(a, b) {
return eq(a, b);
}
return isEqual;
});

View File

@ -0,0 +1,7 @@
define(['./_tagTester'], function (_tagTester) {
var isError = _tagTester('Error');
return isError;
});

View File

@ -0,0 +1,10 @@
define(['./_setup', './isSymbol'], function (_setup, isSymbol) {
// Is a given object a finite number?
function isFinite(obj) {
return !isSymbol(obj) && _setup._isFinite(obj) && !isNaN(parseFloat(obj));
}
return isFinite;
});

View File

@ -0,0 +1,18 @@
define(['./_setup', './_tagTester'], function (_setup, _tagTester) {
var isFunction = _tagTester('Function');
// Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old
// v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
var nodelist = _setup.root.document && _setup.root.document.childNodes;
if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') {
isFunction = function(obj) {
return typeof obj == 'function' || false;
};
}
var isFunction$1 = isFunction;
return isFunction$1;
});

Some files were not shown because too many files have changed in this diff Show More