Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/functions/functions.js
2868 views
1
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Utilities for creating functions. Loosely inspired by the
17
* java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8.
18
*
19
* @author [email protected] (Nick Santos)
20
*/
21
22
23
goog.provide('goog.functions');
24
25
26
/**
27
* Creates a function that always returns the same value.
28
* @param {T} retValue The value to return.
29
* @return {function():T} The new function.
30
* @template T
31
*/
32
goog.functions.constant = function(retValue) {
33
return function() { return retValue; };
34
};
35
36
37
/**
38
* Always returns false.
39
* @type {function(...): boolean}
40
*/
41
goog.functions.FALSE = goog.functions.constant(false);
42
43
44
/**
45
* Always returns true.
46
* @type {function(...): boolean}
47
*/
48
goog.functions.TRUE = goog.functions.constant(true);
49
50
51
/**
52
* Always returns NULL.
53
* @type {function(...): null}
54
*/
55
goog.functions.NULL = goog.functions.constant(null);
56
57
58
/**
59
* A simple function that returns the first argument of whatever is passed
60
* into it.
61
* @param {T=} opt_returnValue The single value that will be returned.
62
* @param {...*} var_args Optional trailing arguments. These are ignored.
63
* @return {T} The first argument passed in, or undefined if nothing was passed.
64
* @template T
65
*/
66
goog.functions.identity = function(opt_returnValue, var_args) {
67
return opt_returnValue;
68
};
69
70
71
/**
72
* Creates a function that always throws an error with the given message.
73
* @param {string} message The error message.
74
* @return {!Function} The error-throwing function.
75
*/
76
goog.functions.error = function(message) {
77
return function() { throw Error(message); };
78
};
79
80
81
/**
82
* Creates a function that throws the given object.
83
* @param {*} err An object to be thrown.
84
* @return {!Function} The error-throwing function.
85
*/
86
goog.functions.fail = function(err) {
87
return function() { throw err; };
88
};
89
90
91
/**
92
* Given a function, create a function that keeps opt_numArgs arguments and
93
* silently discards all additional arguments.
94
* @param {Function} f The original function.
95
* @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
96
* @return {!Function} A version of f that only keeps the first opt_numArgs
97
* arguments.
98
*/
99
goog.functions.lock = function(f, opt_numArgs) {
100
opt_numArgs = opt_numArgs || 0;
101
return function() {
102
return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs));
103
};
104
};
105
106
107
/**
108
* Creates a function that returns its nth argument.
109
* @param {number} n The position of the return argument.
110
* @return {!Function} A new function.
111
*/
112
goog.functions.nth = function(n) {
113
return function() { return arguments[n]; };
114
};
115
116
117
/**
118
* Like goog.partial(), except that arguments are added after arguments to the
119
* returned function.
120
*
121
* Usage:
122
* function f(arg1, arg2, arg3, arg4) { ... }
123
* var g = goog.functions.partialRight(f, arg3, arg4);
124
* g(arg1, arg2);
125
*
126
* @param {!Function} fn A function to partially apply.
127
* @param {...*} var_args Additional arguments that are partially applied to fn
128
* at the end.
129
* @return {!Function} A partially-applied form of the function goog.partial()
130
* was invoked as a method of.
131
*/
132
goog.functions.partialRight = function(fn, var_args) {
133
var rightArgs = Array.prototype.slice.call(arguments, 1);
134
return function() {
135
var newArgs = Array.prototype.slice.call(arguments);
136
newArgs.push.apply(newArgs, rightArgs);
137
return fn.apply(this, newArgs);
138
};
139
};
140
141
142
/**
143
* Given a function, create a new function that swallows its return value
144
* and replaces it with a new one.
145
* @param {Function} f A function.
146
* @param {T} retValue A new return value.
147
* @return {function(...?):T} A new function.
148
* @template T
149
*/
150
goog.functions.withReturnValue = function(f, retValue) {
151
return goog.functions.sequence(f, goog.functions.constant(retValue));
152
};
153
154
155
/**
156
* Creates a function that returns whether its argument equals the given value.
157
*
158
* Example:
159
* var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
160
*
161
* @param {*} value The value to compare to.
162
* @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
163
* comparison rather than a strict (===) one. Defaults to false.
164
* @return {function(*):boolean} The new function.
165
*/
166
goog.functions.equalTo = function(value, opt_useLooseComparison) {
167
return function(other) {
168
return opt_useLooseComparison ? (value == other) : (value === other);
169
};
170
};
171
172
173
/**
174
* Creates the composition of the functions passed in.
175
* For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
176
* @param {function(...?):T} fn The final function.
177
* @param {...Function} var_args A list of functions.
178
* @return {function(...?):T} The composition of all inputs.
179
* @template T
180
*/
181
goog.functions.compose = function(fn, var_args) {
182
var functions = arguments;
183
var length = functions.length;
184
return function() {
185
var result;
186
if (length) {
187
result = functions[length - 1].apply(this, arguments);
188
}
189
190
for (var i = length - 2; i >= 0; i--) {
191
result = functions[i].call(this, result);
192
}
193
return result;
194
};
195
};
196
197
198
/**
199
* Creates a function that calls the functions passed in in sequence, and
200
* returns the value of the last function. For example,
201
* (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
202
* @param {...Function} var_args A list of functions.
203
* @return {!Function} A function that calls all inputs in sequence.
204
*/
205
goog.functions.sequence = function(var_args) {
206
var functions = arguments;
207
var length = functions.length;
208
return function() {
209
var result;
210
for (var i = 0; i < length; i++) {
211
result = functions[i].apply(this, arguments);
212
}
213
return result;
214
};
215
};
216
217
218
/**
219
* Creates a function that returns true if each of its components evaluates
220
* to true. The components are evaluated in order, and the evaluation will be
221
* short-circuited as soon as a function returns false.
222
* For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
223
* @param {...Function} var_args A list of functions.
224
* @return {function(...?):boolean} A function that ANDs its component
225
* functions.
226
*/
227
goog.functions.and = function(var_args) {
228
var functions = arguments;
229
var length = functions.length;
230
return function() {
231
for (var i = 0; i < length; i++) {
232
if (!functions[i].apply(this, arguments)) {
233
return false;
234
}
235
}
236
return true;
237
};
238
};
239
240
241
/**
242
* Creates a function that returns true if any of its components evaluates
243
* to true. The components are evaluated in order, and the evaluation will be
244
* short-circuited as soon as a function returns true.
245
* For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
246
* @param {...Function} var_args A list of functions.
247
* @return {function(...?):boolean} A function that ORs its component
248
* functions.
249
*/
250
goog.functions.or = function(var_args) {
251
var functions = arguments;
252
var length = functions.length;
253
return function() {
254
for (var i = 0; i < length; i++) {
255
if (functions[i].apply(this, arguments)) {
256
return true;
257
}
258
}
259
return false;
260
};
261
};
262
263
264
/**
265
* Creates a function that returns the Boolean opposite of a provided function.
266
* For example, (goog.functions.not(f))(x) is equivalent to !f(x).
267
* @param {!Function} f The original function.
268
* @return {function(...?):boolean} A function that delegates to f and returns
269
* opposite.
270
*/
271
goog.functions.not = function(f) {
272
return function() { return !f.apply(this, arguments); };
273
};
274
275
276
/**
277
* Generic factory function to construct an object given the constructor
278
* and the arguments. Intended to be bound to create object factories.
279
*
280
* Example:
281
*
282
* var factory = goog.partial(goog.functions.create, Class);
283
*
284
* @param {function(new:T, ...)} constructor The constructor for the Object.
285
* @param {...*} var_args The arguments to be passed to the constructor.
286
* @return {T} A new instance of the class given in {@code constructor}.
287
* @template T
288
*/
289
goog.functions.create = function(constructor, var_args) {
290
/**
291
* @constructor
292
* @final
293
*/
294
var temp = function() {};
295
temp.prototype = constructor.prototype;
296
297
// obj will have constructor's prototype in its chain and
298
// 'obj instanceof constructor' will be true.
299
var obj = new temp();
300
301
// obj is initialized by constructor.
302
// arguments is only array-like so lacks shift(), but can be used with
303
// the Array prototype function.
304
constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
305
return obj;
306
};
307
308
309
/**
310
* @define {boolean} Whether the return value cache should be used.
311
* This should only be used to disable caches when testing.
312
*/
313
goog.define('goog.functions.CACHE_RETURN_VALUE', true);
314
315
316
/**
317
* Gives a wrapper function that caches the return value of a parameterless
318
* function when first called.
319
*
320
* When called for the first time, the given function is called and its
321
* return value is cached (thus this is only appropriate for idempotent
322
* functions). Subsequent calls will return the cached return value. This
323
* allows the evaluation of expensive functions to be delayed until first used.
324
*
325
* To cache the return values of functions with parameters, see goog.memoize.
326
*
327
* @param {function():T} fn A function to lazily evaluate.
328
* @return {function():T} A wrapped version the function.
329
* @template T
330
*/
331
goog.functions.cacheReturnValue = function(fn) {
332
var called = false;
333
var value;
334
335
return function() {
336
if (!goog.functions.CACHE_RETURN_VALUE) {
337
return fn();
338
}
339
340
if (!called) {
341
value = fn();
342
called = true;
343
}
344
345
return value;
346
};
347
};
348
349
350
/**
351
* Wraps a function to allow it to be called, at most, once. All
352
* additional calls are no-ops.
353
*
354
* This is particularly useful for initialization functions
355
* that should be called, at most, once.
356
*
357
* @param {function():*} f Function to call.
358
* @return {function():undefined} Wrapped function.
359
*/
360
goog.functions.once = function(f) {
361
// Keep a reference to the function that we null out when we're done with
362
// it -- that way, the function can be GC'd when we're done with it.
363
var inner = f;
364
return function() {
365
if (inner) {
366
var tmp = inner;
367
inner = null;
368
tmp();
369
}
370
};
371
};
372
373
374
/**
375
* Wraps a function to allow it to be called, at most, once per interval
376
* (specified in milliseconds). If the wrapper function is called N times within
377
* that interval, only the Nth call will go through.
378
*
379
* This is particularly useful for batching up repeated actions where the
380
* last action should win. This can be used, for example, for refreshing an
381
* autocomplete pop-up every so often rather than updating with every keystroke,
382
* since the final text typed by the user is the one that should produce the
383
* final autocomplete results. For more stateful debouncing with support for
384
* pausing, resuming, and canceling debounced actions, use {@code
385
* goog.async.Debouncer}.
386
*
387
* @param {function(this:SCOPE, ...?)} f Function to call.
388
* @param {number} interval Interval over which to debounce. The function will
389
* only be called after the full interval has elapsed since the last call.
390
* @param {SCOPE=} opt_scope Object in whose scope to call the function.
391
* @return {function(...?): undefined} Wrapped function.
392
* @template SCOPE
393
*/
394
goog.functions.debounce = function(f, interval, opt_scope) {
395
var timeout = 0;
396
return /** @type {function(...?)} */ (function(var_args) {
397
goog.global.clearTimeout(timeout);
398
var args = arguments;
399
timeout = goog.global.setTimeout(function() {
400
f.apply(opt_scope, args);
401
}, interval);
402
});
403
};
404
405
406
/**
407
* Wraps a function to allow it to be called, at most, once per interval
408
* (specified in milliseconds). If the wrapper function is called N times in
409
* that interval, both the 1st and the Nth calls will go through.
410
*
411
* This is particularly useful for limiting repeated user requests where the
412
* the last action should win, but you also don't want to wait until the end of
413
* the interval before sending a request out, as it leads to a perception of
414
* slowness for the user.
415
*
416
* @param {function(this:SCOPE, ...?)} f Function to call.
417
* @param {number} interval Interval over which to throttle. The function can
418
* only be called once per interval.
419
* @param {SCOPE=} opt_scope Object in whose scope to call the function.
420
* @return {function(...?): undefined} Wrapped function.
421
* @template SCOPE
422
*/
423
goog.functions.throttle = function(f, interval, opt_scope) {
424
var timeout = 0;
425
var shouldFire = false;
426
var args = [];
427
428
var handleTimeout = function() {
429
timeout = 0;
430
if (shouldFire) {
431
shouldFire = false;
432
fire();
433
}
434
};
435
436
var fire = function() {
437
timeout = goog.global.setTimeout(handleTimeout, interval);
438
f.apply(opt_scope, args);
439
};
440
441
return /** @type {function(...?)} */ (function(var_args) {
442
args = arguments;
443
if (!timeout) {
444
fire();
445
} else {
446
shouldFire = true;
447
}
448
});
449
};
450
451
452
/**
453
* Wraps a function to allow it to be called, at most, once per interval
454
* (specified in milliseconds). If the wrapper function is called N times within
455
* that interval, only the 1st call will go through.
456
*
457
* This is particularly useful for limiting repeated user requests where the
458
* first request is guaranteed to have all the data required to perform the
459
* final action, so there's no need to wait until the end of the interval before
460
* sending the request out.
461
*
462
* @param {function(this:SCOPE, ...?)} f Function to call.
463
* @param {number} interval Interval over which to rate-limit. The function will
464
* only be called once per interval, and ignored for the remainer of the
465
* interval.
466
* @param {SCOPE=} opt_scope Object in whose scope to call the function.
467
* @return {function(...?): undefined} Wrapped function.
468
* @template SCOPE
469
*/
470
goog.functions.rateLimit = function(f, interval, opt_scope) {
471
var timeout = 0;
472
473
var handleTimeout = function() {
474
timeout = 0;
475
};
476
477
return /** @type {function(...?)} */ (function(var_args) {
478
if (!timeout) {
479
timeout = goog.global.setTimeout(handleTimeout, interval);
480
f.apply(opt_scope, arguments);
481
}
482
});
483
};
484
485