Browse Source

adding the fuller version of Flight

master
Stephanie Chung 12 years ago
parent
commit
88764fa0d4
  1. 326
      js/libs/es5-shim/es5-sham.js
  2. 6
      js/libs/es5-shim/es5-sham.min.js
  3. 778
      js/libs/es5-shim/es5-shim.js
  4. 13
      js/libs/es5-shim/es5-shim.min.js
  5. 31
      js/libs/es5-shim/package.json
  6. 59
      js/libs/es5-shim/tests/helpers/h-kill.js
  7. 34
      js/libs/es5-shim/tests/helpers/h-matchers.js
  8. 3
      js/libs/es5-shim/tests/helpers/h.js
  9. 62
      js/libs/es5-shim/tests/index.html
  10. 190
      js/libs/es5-shim/tests/lib/jasmine-html.js
  11. 166
      js/libs/es5-shim/tests/lib/jasmine.css
  12. 2477
      js/libs/es5-shim/tests/lib/jasmine.js
  13. BIN
      js/libs/es5-shim/tests/lib/jasmine_favicon.png
  14. 478
      js/libs/es5-shim/tests/lib/json2.js
  15. 1070
      js/libs/es5-shim/tests/spec/s-array.js
  16. 40
      js/libs/es5-shim/tests/spec/s-date.js
  17. 137
      js/libs/es5-shim/tests/spec/s-function.js
  18. 84
      js/libs/es5-shim/tests/spec/s-object.js
  19. 11
      js/libs/es5-shim/tests/spec/s-string.js
  20. 33
      js/libs/flight/.bower.json
  21. 19
      js/libs/flight/LICENSE
  22. 242
      js/libs/flight/README.md
  23. 22
      js/libs/flight/bower.json
  24. 69
      js/libs/flight/lib/advice.js
  25. 237
      js/libs/flight/lib/base.js
  26. 136
      js/libs/flight/lib/component.js
  27. 85
      js/libs/flight/lib/compose.js
  28. 165
      js/libs/flight/lib/debug.js
  29. 31
      js/libs/flight/lib/index.js
  30. 100
      js/libs/flight/lib/logger.js
  31. 228
      js/libs/flight/lib/registry.js
  32. 263
      js/libs/flight/lib/utils.js

326
js/libs/es5-shim/es5-sham.js

@ -0,0 +1,326 @@
// Copyright 2009-2012 by contributors, MIT License
// vim: ts=4 sts=4 sw=4 expandtab
// Module systems magic dance
(function (definition) {
// RequireJS
if (typeof define == "function") {
define(definition);
// YUI3
} else if (typeof YUI == "function") {
YUI.add("es5-sham", definition);
// CommonJS and <script>
} else {
definition();
}
})(function () {
// ES5 15.2.3.2
// http://es5.github.com/#x15.2.3.2
if (!Object.getPrototypeOf) {
// https://github.com/kriskowal/es5-shim/issues#issue/2
// http://ejohn.org/blog/objectgetprototypeof/
// recommended by fschaefer on github
Object.getPrototypeOf = function getPrototypeOf(object) {
return object.__proto__ || (
object.constructor
? object.constructor.prototype
: prototypeOfObject
);
};
}
// ES5 15.2.3.3
// http://es5.github.com/#x15.2.3.3
if (!Object.getOwnPropertyDescriptor) {
var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a non-object: ";
Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError(ERR_NON_OBJECT + object);
}
// If object does not owns property return undefined immediately.
if (!owns(object, property)) {
return;
}
// If object has a property then it's for sure both `enumerable` and
// `configurable`.
var descriptor = { enumerable: true, configurable: true };
// If JS engine supports accessor properties then property may be a
// getter or setter.
if (supportsAccessors) {
// Unfortunately `__lookupGetter__` will return a getter even
// if object has own non getter property along with a same named
// inherited getter. To avoid misbehavior we temporary remove
// `__proto__` so that `__lookupGetter__` will return getter only
// if it's owned by an object.
var prototype = object.__proto__;
object.__proto__ = prototypeOfObject;
var getter = lookupGetter(object, property);
var setter = lookupSetter(object, property);
// Once we have getter and setter we can put values back.
object.__proto__ = prototype;
if (getter || setter) {
if (getter) {
descriptor.get = getter;
}
if (setter) {
descriptor.set = setter;
}
// If it was accessor property we're done and return here
// in order to avoid adding `value` to the descriptor.
return descriptor;
}
}
// If we got this far we know that object has an own property that is
// not an accessor so we set it as a value and return descriptor.
descriptor.value = object[property];
return descriptor;
};
}
// ES5 15.2.3.4
// http://es5.github.com/#x15.2.3.4
if (!Object.getOwnPropertyNames) {
Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
return Object.keys(object);
};
}
// ES5 15.2.3.5
// http://es5.github.com/#x15.2.3.5
if (!Object.create) {
Object.create = function create(prototype, properties) {
var object;
if (prototype === null) {
object = { "__proto__": null };
} else {
if (typeof prototype != "object") {
throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
}
var Type = function () {};
Type.prototype = prototype;
object = new Type();
// IE has no built-in implementation of `Object.getPrototypeOf`
// neither `__proto__`, but this manually setting `__proto__` will
// guarantee that `Object.getPrototypeOf` will work as expected with
// objects created using `Object.create`
object.__proto__ = prototype;
}
if (properties !== void 0) {
Object.defineProperties(object, properties);
}
return object;
};
}
// ES5 15.2.3.6
// http://es5.github.com/#x15.2.3.6
// Patch for WebKit and IE8 standard mode
// Designed by hax <hax.github.com>
// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5
// IE8 Reference:
// http://msdn.microsoft.com/en-us/library/dd282900.aspx
// http://msdn.microsoft.com/en-us/library/dd229916.aspx
// WebKit Bugs:
// https://bugs.webkit.org/show_bug.cgi?id=36423
function doesDefinePropertyWork(object) {
try {
Object.defineProperty(object, "sentinel", {});
return "sentinel" in object;
} catch (exception) {
// returns falsy
}
}
// check whether defineProperty works if it's given. Otherwise,
// shim partially.
if (Object.defineProperty) {
var definePropertyWorksOnObject = doesDefinePropertyWork({});
var definePropertyWorksOnDom = typeof document == "undefined" ||
doesDefinePropertyWork(document.createElement("div"));
if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
var definePropertyFallback = Object.defineProperty;
}
}
if (!Object.defineProperty || definePropertyFallback) {
var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
"on this javascript engine";
Object.defineProperty = function defineProperty(object, property, descriptor) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError(ERR_NON_OBJECT_TARGET + object);
}
if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) {
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
}
// make a valiant attempt to use the real defineProperty
// for I8's DOM elements.
if (definePropertyFallback) {
try {
return definePropertyFallback.call(Object, object, property, descriptor);
} catch (exception) {
// try the shim if the real one doesn't work
}
}
// If it's a data property.
if (owns(descriptor, "value")) {
// fail silently if "writable", "enumerable", or "configurable"
// are requested but not supported
/*
// alternate approach:
if ( // can't implement these features; allow false but not true
!(owns(descriptor, "writable") ? descriptor.writable : true) ||
!(owns(descriptor, "enumerable") ? descriptor.enumerable : true) ||
!(owns(descriptor, "configurable") ? descriptor.configurable : true)
)
throw new RangeError(
"This implementation of Object.defineProperty does not " +
"support configurable, enumerable, or writable."
);
*/
if (supportsAccessors && (lookupGetter(object, property) ||
lookupSetter(object, property)))
{
// As accessors are supported only on engines implementing
// `__proto__` we can safely override `__proto__` while defining
// a property to make sure that we don't hit an inherited
// accessor.
var prototype = object.__proto__;
object.__proto__ = prototypeOfObject;
// Deleting a property anyway since getter / setter may be
// defined on object itself.
delete object[property];
object[property] = descriptor.value;
// Setting original `__proto__` back now.
object.__proto__ = prototype;
} else {
object[property] = descriptor.value;
}
} else {
if (!supportsAccessors) {
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
}
// If we got that far then getters and setters can be defined !!
if (owns(descriptor, "get")) {
defineGetter(object, property, descriptor.get);
}
if (owns(descriptor, "set")) {
defineSetter(object, property, descriptor.set);
}
}
return object;
};
}
// ES5 15.2.3.7
// http://es5.github.com/#x15.2.3.7
if (!Object.defineProperties) {
Object.defineProperties = function defineProperties(object, properties) {
for (var property in properties) {
if (owns(properties, property) && property != "__proto__") {
Object.defineProperty(object, property, properties[property]);
}
}
return object;
};
}
// ES5 15.2.3.8
// http://es5.github.com/#x15.2.3.8
if (!Object.seal) {
Object.seal = function seal(object) {
// this is misleading and breaks feature-detection, but
// allows "securable" code to "gracefully" degrade to working
// but insecure code.
return object;
};
}
// ES5 15.2.3.9
// http://es5.github.com/#x15.2.3.9
if (!Object.freeze) {
Object.freeze = function freeze(object) {
// this is misleading and breaks feature-detection, but
// allows "securable" code to "gracefully" degrade to working
// but insecure code.
return object;
};
}
// detect a Rhino bug and patch it
try {
Object.freeze(function () {});
} catch (exception) {
Object.freeze = (function freeze(freezeObject) {
return function freeze(object) {
if (typeof object == "function") {
return object;
} else {
return freezeObject(object);
}
};
})(Object.freeze);
}
// ES5 15.2.3.10
// http://es5.github.com/#x15.2.3.10
if (!Object.preventExtensions) {
Object.preventExtensions = function preventExtensions(object) {
// this is misleading and breaks feature-detection, but
// allows "securable" code to "gracefully" degrade to working
// but insecure code.
return object;
};
}
// ES5 15.2.3.11
// http://es5.github.com/#x15.2.3.11
if (!Object.isSealed) {
Object.isSealed = function isSealed(object) {
return false;
};
}
// ES5 15.2.3.12
// http://es5.github.com/#x15.2.3.12
if (!Object.isFrozen) {
Object.isFrozen = function isFrozen(object) {
return false;
};
}
// ES5 15.2.3.13
// http://es5.github.com/#x15.2.3.13
if (!Object.isExtensible) {
Object.isExtensible = function isExtensible(object) {
// 1. If Type(O) is not Object throw a TypeError exception.
if (Object(object) !== object) {
throw new TypeError(); // TODO message
}
// 2. Return the Boolean value of the [[Extensible]] internal property of O.
var name = '';
while (owns(object, name)) {
name += '?';
}
object[name] = true;
var returnValue = owns(object, name);
delete object[name];
return returnValue;
};
}
});

6
js/libs/es5-shim/es5-sham.min.js vendored

@ -0,0 +1,6 @@
(function(d){"function"==typeof define?define(d):"function"==typeof YUI?YUI.add("es5-sham",d):d()})(function(){function d(a){try{return Object.defineProperty(a,"sentinel",{}),"sentinel"in a}catch(c){}}Object.getPrototypeOf||(Object.getPrototypeOf=function(a){return a.__proto__||(a.constructor?a.constructor.prototype:prototypeOfObject)});Object.getOwnPropertyDescriptor||(Object.getOwnPropertyDescriptor=function(a,c){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("Object.getOwnPropertyDescriptor called on a non-object: "+
a);if(owns(a,c)){var b={enumerable:true,configurable:true};if(supportsAccessors){var d=a.__proto__;a.__proto__=prototypeOfObject;var f=lookupGetter(a,c),e=lookupSetter(a,c);a.__proto__=d;if(f||e){if(f)b.get=f;if(e)b.set=e;return b}}b.value=a[c];return b}});Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(a){return Object.keys(a)});Object.create||(Object.create=function(a,c){var b;if(a===null)b={__proto__:null};else{if(typeof a!="object")throw new TypeError("typeof prototype["+typeof a+
"] != 'object'");b=function(){};b.prototype=a;b=new b;b.__proto__=a}c!==void 0&&Object.defineProperties(b,c);return b});if(Object.defineProperty){var g=d({}),h="undefined"==typeof document||d(document.createElement("div"));if(!g||!h)var e=Object.defineProperty}if(!Object.defineProperty||e)Object.defineProperty=function(a,c,b){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("Object.defineProperty called on non-object: "+a);if(typeof b!="object"&&typeof b!="function"||b===
null)throw new TypeError("Property description must be an object: "+b);if(e)try{return e.call(Object,a,c,b)}catch(d){}if(owns(b,"value"))if(supportsAccessors&&(lookupGetter(a,c)||lookupSetter(a,c))){var f=a.__proto__;a.__proto__=prototypeOfObject;delete a[c];a[c]=b.value;a.__proto__=f}else a[c]=b.value;else{if(!supportsAccessors)throw new TypeError("getters & setters can not be defined on this javascript engine");owns(b,"get")&&defineGetter(a,c,b.get);owns(b,"set")&&defineSetter(a,c,b.set)}return a};
Object.defineProperties||(Object.defineProperties=function(a,c){for(var b in c)owns(c,b)&&b!="__proto__"&&Object.defineProperty(a,b,c[b]);return a});Object.seal||(Object.seal=function(a){return a});Object.freeze||(Object.freeze=function(a){return a});try{Object.freeze(function(){})}catch(j){var i=Object.freeze;Object.freeze=function(a){return typeof a=="function"?a:i(a)}}Object.preventExtensions||(Object.preventExtensions=function(a){return a});Object.isSealed||(Object.isSealed=function(){return false});
Object.isFrozen||(Object.isFrozen=function(){return false});Object.isExtensible||(Object.isExtensible=function(a){if(Object(a)!==a)throw new TypeError;for(var c="";owns(a,c);)c=c+"?";a[c]=true;var b=owns(a,c);delete a[c];return b})});

778
js/libs/es5-shim/es5-shim.js

@ -0,0 +1,778 @@
// Copyright 2009-2012 by contributors, MIT License
// vim: ts=4 sts=4 sw=4 expandtab
// Module systems magic dance
(function (definition) {
// RequireJS
if (typeof define == "function") {
define(definition);
// YUI3
} else if (typeof YUI == "function") {
YUI.add("es5", definition);
// CommonJS and <script>
} else {
definition();
}
})(function () {
/**
* Brings an environment as close to ECMAScript 5 compliance
* as is possible with the facilities of erstwhile engines.
*
* Annotated ES5: http://es5.github.com/ (specific links below)
* ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
* Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
*/
//
// Function
// ========
//
// ES-5 15.3.4.5
// http://es5.github.com/#x15.3.4.5
if (!Function.prototype.bind) {
Function.prototype.bind = function bind(that) { // .length is 1
// 1. Let Target be the this value.
var target = this;
// 2. If IsCallable(Target) is false, throw a TypeError exception.
if (typeof target != "function") {
throw new TypeError("Function.prototype.bind called on incompatible " + target);
}
// 3. Let A be a new (possibly empty) internal list of all of the
// argument values provided after thisArg (arg1, arg2 etc), in order.
// XXX slicedArgs will stand in for "A" if used
var args = slice.call(arguments, 1); // for normal call
// 4. Let F be a new native ECMAScript object.
// 11. Set the [[Prototype]] internal property of F to the standard
// built-in Function prototype object as specified in 15.3.3.1.
// 12. Set the [[Call]] internal property of F as described in
// 15.3.4.5.1.
// 13. Set the [[Construct]] internal property of F as described in
// 15.3.4.5.2.
// 14. Set the [[HasInstance]] internal property of F as described in
// 15.3.4.5.3.
var bound = function () {
if (this instanceof bound) {
// 15.3.4.5.2 [[Construct]]
// When the [[Construct]] internal method of a function object,
// F that was created using the bind function is called with a
// list of arguments ExtraArgs, the following steps are taken:
// 1. Let target be the value of F's [[TargetFunction]]
// internal property.
// 2. If target has no [[Construct]] internal method, a
// TypeError exception is thrown.
// 3. Let boundArgs be the value of F's [[BoundArgs]] internal
// property.
// 4. Let args be a new list containing the same values as the
// list boundArgs in the same order followed by the same
// values as the list ExtraArgs in the same order.
// 5. Return the result of calling the [[Construct]] internal
// method of target providing args as the arguments.
var F = function(){};
F.prototype = target.prototype;
var self = new F;
var result = target.apply(
self,
args.concat(slice.call(arguments))
);
if (Object(result) === result) {
return result;
}
return self;
} else {
// 15.3.4.5.1 [[Call]]
// When the [[Call]] internal method of a function object, F,
// which was created using the bind function is called with a
// this value and a list of arguments ExtraArgs, the following
// steps are taken:
// 1. Let boundArgs be the value of F's [[BoundArgs]] internal
// property.
// 2. Let boundThis be the value of F's [[BoundThis]] internal
// property.
// 3. Let target be the value of F's [[TargetFunction]] internal
// property.
// 4. Let args be a new list containing the same values as the
// list boundArgs in the same order followed by the same
// values as the list ExtraArgs in the same order.
// 5. Return the result of calling the [[Call]] internal method
// of target providing boundThis as the this value and
// providing args as the arguments.
// equiv: target.call(this, ...boundArgs, ...args)
return target.apply(
that,
args.concat(slice.call(arguments))
);
}
};
// XXX bound.length is never writable, so don't even try
//
// 15. If the [[Class]] internal property of Target is "Function", then
// a. Let L be the length property of Target minus the length of A.
// b. Set the length own property of F to either 0 or L, whichever is
// larger.
// 16. Else set the length own property of F to 0.
// 17. Set the attributes of the length own property of F to the values
// specified in 15.3.5.1.
// TODO
// 18. Set the [[Extensible]] internal property of F to true.
// TODO
// 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
// 20. Call the [[DefineOwnProperty]] internal method of F with
// arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
// thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
// false.
// 21. Call the [[DefineOwnProperty]] internal method of F with
// arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
// [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
// and false.
// TODO
// NOTE Function objects created using Function.prototype.bind do not
// have a prototype property or the [[Code]], [[FormalParameters]], and
// [[Scope]] internal properties.
// XXX can't delete prototype in pure-js.
// 22. Return F.
return bound;
};
}
// Shortcut to an often accessed properties, in order to avoid multiple
// dereference that costs universally.
// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
// us it in defining shortcuts.
var call = Function.prototype.call;
var prototypeOfArray = Array.prototype;
var prototypeOfObject = Object.prototype;
var slice = prototypeOfArray.slice;
// Having a toString local variable name breaks in Opera so use _toString.
var _toString = call.bind(prototypeOfObject.toString);
var owns = call.bind(prototypeOfObject.hasOwnProperty);
// If JS engine supports accessors creating shortcuts.
var defineGetter;
var defineSetter;
var lookupGetter;
var lookupSetter;
var supportsAccessors;
if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
defineGetter = call.bind(prototypeOfObject.__defineGetter__);
defineSetter = call.bind(prototypeOfObject.__defineSetter__);
lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
}
//
// Array
// =====
//
// ES5 15.4.3.2
// http://es5.github.com/#x15.4.3.2
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray) {
Array.isArray = function isArray(obj) {
return _toString(obj) == "[object Array]";
};
}
// The IsCallable() check in the Array functions
// has been replaced with a strict check on the
// internal class of the object to trap cases where
// the provided function was actually a regular
// expression literal, which in V8 and
// JavaScriptCore is a typeof "function". Only in
// V8 are regular expression literals permitted as
// reduce parameters, so it is desirable in the
// general case for the shim to match the more
// strict and common behavior of rejecting regular
// expressions.
// ES5 15.4.4.18
// http://es5.github.com/#x15.4.4.18
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
if (!Array.prototype.forEach) {
Array.prototype.forEach = function forEach(fun /*, thisp*/) {
var self = toObject(this),
thisp = arguments[1],
i = -1,
length = self.length >>> 0;
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(); // TODO message
}
while (++i < length) {
if (i in self) {
// Invoke the callback function with call, passing arguments:
// context, property value, property key, thisArg object context
fun.call(thisp, self[i], i, self);
}
}
};
}
// ES5 15.4.4.19
// http://es5.github.com/#x15.4.4.19
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
if (!Array.prototype.map) {
Array.prototype.map = function map(fun /*, thisp*/) {
var self = toObject(this),
length = self.length >>> 0,
result = Array(length),
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self)
result[i] = fun.call(thisp, self[i], i, self);
}
return result;
};
}
// ES5 15.4.4.20
// http://es5.github.com/#x15.4.4.20
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
if (!Array.prototype.filter) {
Array.prototype.filter = function filter(fun /*, thisp */) {
var self = toObject(this),
length = self.length >>> 0,
result = [],
value,
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self) {
value = self[i];
if (fun.call(thisp, value, i, self)) {
result.push(value);
}
}
}
return result;
};
}
// ES5 15.4.4.16
// http://es5.github.com/#x15.4.4.16
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
if (!Array.prototype.every) {
Array.prototype.every = function every(fun /*, thisp */) {
var self = toObject(this),
length = self.length >>> 0,
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self && !fun.call(thisp, self[i], i, self)) {
return false;
}
}
return true;
};
}
// ES5 15.4.4.17
// http://es5.github.com/#x15.4.4.17
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
if (!Array.prototype.some) {
Array.prototype.some = function some(fun /*, thisp */) {
var self = toObject(this),
length = self.length >>> 0,
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self && fun.call(thisp, self[i], i, self)) {
return true;
}
}
return false;
};
}
// ES5 15.4.4.21
// http://es5.github.com/#x15.4.4.21
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(fun /*, initial*/) {
var self = toObject(this),
length = self.length >>> 0;
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
// no value to return if no initial value and an empty array
if (!length && arguments.length == 1) {
throw new TypeError('reduce of empty array with no initial value');
}
var i = 0;
var result;
if (arguments.length >= 2) {
result = arguments[1];
} else {
do {
if (i in self) {
result = self[i++];
break;
}
// if array contains no values, no initial value to return
if (++i >= length) {
throw new TypeError('reduce of empty array with no initial value');
}
} while (true);
}
for (; i < length; i++) {
if (i in self) {
result = fun.call(void 0, result, self[i], i, self);
}
}
return result;
};
}
// ES5 15.4.4.22
// http://es5.github.com/#x15.4.4.22
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
if (!Array.prototype.reduceRight) {
Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
var self = toObject(this),
length = self.length >>> 0;
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
// no value to return if no initial value, empty array
if (!length && arguments.length == 1) {
throw new TypeError('reduceRight of empty array with no initial value');
}
var result, i = length - 1;
if (arguments.length >= 2) {
result = arguments[1];
} else {
do {
if (i in self) {
result = self[i--];
break;
}
// if array contains no values, no initial value to return
if (--i < 0) {
throw new TypeError('reduceRight of empty array with no initial value');
}
} while (true);
}
do {
if (i in this) {
result = fun.call(void 0, result, self[i], i, self);
}
} while (i--);
return result;
};
}
// ES5 15.4.4.14
// http://es5.github.com/#x15.4.4.14
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
var self = toObject(this),
length = self.length >>> 0;
if (!length) {
return -1;
}
var i = 0;
if (arguments.length > 1) {
i = toInteger(arguments[1]);
}
// handle negative indices
i = i >= 0 ? i : Math.max(0, length + i);
for (; i < length; i++) {
if (i in self && self[i] === sought) {
return i;
}
}
return -1;
};
}
// ES5 15.4.4.15
// http://es5.github.com/#x15.4.4.15
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
if (!Array.prototype.lastIndexOf) {
Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
var self = toObject(this),
length = self.length >>> 0;
if (!length) {
return -1;
}
var i = length - 1;
if (arguments.length > 1) {
i = Math.min(i, toInteger(arguments[1]));
}
// handle negative indices
i = i >= 0 ? i : length - Math.abs(i);
for (; i >= 0; i--) {
if (i in self && sought === self[i]) {
return i;
}
}
return -1;
};
}
//
// Object
// ======
//
// ES5 15.2.3.14
// http://es5.github.com/#x15.2.3.14
if (!Object.keys) {
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
var hasDontEnumBug = true,
dontEnums = [
"toString",
"toLocaleString",
"valueOf",
"hasOwnProperty",
"isPrototypeOf",
"propertyIsEnumerable",
"constructor"
],
dontEnumsLength = dontEnums.length;
for (var key in {"toString": null}) {
hasDontEnumBug = false;
}
Object.keys = function keys(object) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError("Object.keys called on a non-object");
}
var keys = [];
for (var name in object) {
if (owns(object, name)) {
keys.push(name);
}
}
if (hasDontEnumBug) {
for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
var dontEnum = dontEnums[i];
if (owns(object, dontEnum)) {
keys.push(dontEnum);
}
}
}
return keys;
};
}
//
// Date
// ====
//
// ES5 15.9.5.43
// http://es5.github.com/#x15.9.5.43
// This function returns a String value represent the instance in time
// represented by this Date object. The format of the String is the Date Time
// string format defined in 15.9.1.15. All fields are present in the String.
// The time zone is always UTC, denoted by the suffix Z. If the time value of
// this object is not a finite Number a RangeError exception is thrown.
if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) {
Date.prototype.toISOString = function toISOString() {
var result, length, value, year;
if (!isFinite(this)) {
throw new RangeError("Date.prototype.toISOString called on non-finite value.");
}
// the date time string format is specified in 15.9.1.15.
result = [this.getUTCMonth() + 1, this.getUTCDate(),
this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
year = this.getUTCFullYear();
year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6);
length = result.length;
while (length--) {
value = result[length];
// pad months, days, hours, minutes, and seconds to have two digits.
if (value < 10) {
result[length] = "0" + value;
}
}
// pad milliseconds to have three digits.
return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." +
("000" + this.getUTCMilliseconds()).slice(-3) + "Z";
}
}
// ES5 15.9.4.4
// http://es5.github.com/#x15.9.4.4
if (!Date.now) {
Date.now = function now() {
return new Date().getTime();
};
}
// ES5 15.9.5.44
// http://es5.github.com/#x15.9.5.44
// This function provides a String representation of a Date object for use by
// JSON.stringify (15.12.3).
if (!Date.prototype.toJSON) {
Date.prototype.toJSON = function toJSON(key) {
// When the toJSON method is called with argument key, the following
// steps are taken:
// 1. Let O be the result of calling ToObject, giving it the this
// value as its argument.
// 2. Let tv be ToPrimitive(O, hint Number).
// 3. If tv is a Number and is not finite, return null.
// XXX
// 4. Let toISO be the result of calling the [[Get]] internal method of
// O with argument "toISOString".
// 5. If IsCallable(toISO) is false, throw a TypeError exception.
if (typeof this.toISOString != "function") {
throw new TypeError('toISOString property is not callable');
}
// 6. Return the result of calling the [[Call]] internal method of
// toISO with O as the this value and an empty argument list.
return this.toISOString();
// NOTE 1 The argument is ignored.
// NOTE 2 The toJSON function is intentionally generic; it does not
// require that its this value be a Date object. Therefore, it can be
// transferred to other kinds of objects for use as a method. However,
// it does require that any such object have a toISOString method. An
// object is free to use the argument key to filter its
// stringification.
};
}
// ES5 15.9.4.2
// http://es5.github.com/#x15.9.4.2
// based on work shared by Daniel Friesen (dantman)
// http://gist.github.com/303249
if (!Date.parse || Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) {
// XXX global assignment won't work in embeddings that use
// an alternate object for the context.
Date = (function(NativeDate) {
// Date.length === 7
var Date = function Date(Y, M, D, h, m, s, ms) {
var length = arguments.length;
if (this instanceof NativeDate) {
var date = length == 1 && String(Y) === Y ? // isString(Y)
// We explicitly pass it through parse:
new NativeDate(Date.parse(Y)) :
// We have to manually make calls depending on argument
// length here
length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
length >= 5 ? new NativeDate(Y, M, D, h, m) :
length >= 4 ? new NativeDate(Y, M, D, h) :
length >= 3 ? new NativeDate(Y, M, D) :
length >= 2 ? new NativeDate(Y, M) :
length >= 1 ? new NativeDate(Y) :
new NativeDate();
// Prevent mixups with unfixed Date object
date.constructor = Date;
return date;
}
return NativeDate.apply(this, arguments);
};
// 15.9.1.15 Date Time String Format.
var isoDateExpression = new RegExp("^" +
"(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign + 6-digit extended year
"(?:-(\\d{2})" + // optional month capture
"(?:-(\\d{2})" + // optional day capture
"(?:" + // capture hours:minutes:seconds.milliseconds
"T(\\d{2})" + // hours capture
":(\\d{2})" + // minutes capture
"(?:" + // optional :seconds.milliseconds
":(\\d{2})" + // seconds capture
"(?:\\.(\\d{3}))?" + // milliseconds capture
")?" +
"(?:" + // capture UTC offset component
"Z|" + // UTC capture
"(?:" + // offset specifier +/-hours:minutes
"([-+])" + // sign capture
"(\\d{2})" + // hours offset capture
":(\\d{2})" + // minutes offset capture
")" +
")?)?)?)?" +
"$");
// Copy any custom methods a 3rd party library may have added
for (var key in NativeDate) {
Date[key] = NativeDate[key];
}
// Copy "native" methods explicitly; they may be non-enumerable
Date.now = NativeDate.now;
Date.UTC = NativeDate.UTC;
Date.prototype = NativeDate.prototype;
Date.prototype.constructor = Date;
// Upgrade Date.parse to handle simplified ISO 8601 strings
Date.parse = function parse(string) {
var match = isoDateExpression.exec(string);
if (match) {
match.shift(); // kill match[0], the full match
// parse months, days, hours, minutes, seconds, and milliseconds
for (var i = 1; i < 7; i++) {
// provide default values if necessary
match[i] = +(match[i] || (i < 3 ? 1 : 0));
// match[1] is the month. Months are 0-11 in JavaScript
// `Date` objects, but 1-12 in ISO notation, so we
// decrement.
if (i == 1) {
match[i]--;
}
}
// parse the UTC offset component
var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop();
// compute the explicit time zone offset if specified
var offset = 0;
if (sign) {
// detect invalid offsets and return early
if (hourOffset > 23 || minuteOffset > 59) {
return NaN;
}
// express the provided time zone offset in minutes. The offset is
// negative for time zones west of UTC; positive otherwise.
offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1);
}
// Date.UTC for years between 0 and 99 converts year to 1900 + year
// The Gregorian calendar has a 400-year cycle, so
// to Date.UTC(year + 400, .... ) - 12622780800000 == Date.UTC(year, ...),
// where 12622780800000 - number of milliseconds in Gregorian calendar 400 years
var year = +match[0];
if (0 <= year && year <= 99) {
match[0] = year + 400;
return NativeDate.UTC.apply(this, match) + offset - 12622780800000;
}
// compute a new UTC date value, accounting for the optional offset
return NativeDate.UTC.apply(this, match) + offset;
}
return NativeDate.parse.apply(this, arguments);
};
return Date;
})(Date);
}
//
// String
// ======
//
// ES5 15.5.4.20
// http://es5.github.com/#x15.5.4.20
var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
"\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
"\u2029\uFEFF";
if (!String.prototype.trim || ws.trim()) {
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
// http://perfectionkills.com/whitespace-deviations/
ws = "[" + ws + "]";
var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
trimEndRegexp = new RegExp(ws + ws + "*$");
String.prototype.trim = function trim() {
if (this === undefined || this === null) {
throw new TypeError("can't convert "+this+" to object");
}
return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
};
}
//
// Util
// ======
//
// ES5 9.4
// http://es5.github.com/#x9.4
// http://jsperf.com/to-integer
var toInteger = function (n) {
n = +n;
if (n !== n) { // isNaN
n = 0;
} else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
return n;
};
var prepareString = "a"[0] != "a";
// ES5 9.9
// http://es5.github.com/#x9.9
var toObject = function (o) {
if (o == null) { // this matches both null and undefined
throw new TypeError("can't convert "+o+" to object");
}
// If the implementation doesn't support by-index access of
// string characters (ex. IE < 9), split the string
if (prepareString && typeof o == "string" && o) {
return o.split("");
}
return Object(o);
};
});

13
js/libs/es5-shim/es5-shim.min.js vendored

@ -0,0 +1,13 @@
(function(f){"function"==typeof define?define(f):"function"==typeof YUI?YUI.add("es5",f):f()})(function(){Function.prototype.bind||(Function.prototype.bind=function(d){var c=this;if("function"!=typeof c)throw new TypeError("Function.prototype.bind called on incompatible "+c);var a=n.call(arguments,1),b=function(){if(this instanceof b){var e=function(){};e.prototype=c.prototype;var e=new e,i=c.apply(e,a.concat(n.call(arguments)));return Object(i)===i?i:e}return c.apply(d,a.concat(n.call(arguments)))};
return b});var f=Function.prototype.call,m=Object.prototype,n=Array.prototype.slice,l=f.bind(m.toString),o=f.bind(m.hasOwnProperty);o(m,"__defineGetter__")&&(f.bind(m.__defineGetter__),f.bind(m.__defineSetter__),f.bind(m.__lookupGetter__),f.bind(m.__lookupSetter__));Array.isArray||(Array.isArray=function(d){return l(d)=="[object Array]"});Array.prototype.forEach||(Array.prototype.forEach=function(d,c){var a=j(this),b=-1,e=a.length>>>0;if(l(d)!="[object Function]")throw new TypeError;for(;++b<e;)b in
a&&d.call(c,a[b],b,a)});Array.prototype.map||(Array.prototype.map=function(d,c){var a=j(this),b=a.length>>>0,e=Array(b);if(l(d)!="[object Function]")throw new TypeError(d+" is not a function");for(var i=0;i<b;i++)i in a&&(e[i]=d.call(c,a[i],i,a));return e});Array.prototype.filter||(Array.prototype.filter=function(d,c){var a=j(this),b=a.length>>>0,e=[],i;if(l(d)!="[object Function]")throw new TypeError(d+" is not a function");for(var f=0;f<b;f++)if(f in a){i=a[f];d.call(c,i,f,a)&&e.push(i)}return e});
Array.prototype.every||(Array.prototype.every=function(d,c){var a=j(this),b=a.length>>>0;if(l(d)!="[object Function]")throw new TypeError(d+" is not a function");for(var e=0;e<b;e++)if(e in a&&!d.call(c,a[e],e,a))return false;return true});Array.prototype.some||(Array.prototype.some=function(d,c){var a=j(this),b=a.length>>>0;if(l(d)!="[object Function]")throw new TypeError(d+" is not a function");for(var e=0;e<b;e++)if(e in a&&d.call(c,a[e],e,a))return true;return false});Array.prototype.reduce||
(Array.prototype.reduce=function(d){var c=j(this),a=c.length>>>0;if(l(d)!="[object Function]")throw new TypeError(d+" is not a function");if(!a&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var b=0,e;if(arguments.length>=2)e=arguments[1];else{do{if(b in c){e=c[b++];break}if(++b>=a)throw new TypeError("reduce of empty array with no initial value");}while(1)}for(;b<a;b++)b in c&&(e=d.call(void 0,e,c[b],b,c));return e});Array.prototype.reduceRight||(Array.prototype.reduceRight=
function(d){var c=j(this),a=c.length>>>0;if(l(d)!="[object Function]")throw new TypeError(d+" is not a function");if(!a&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var b,a=a-1;if(arguments.length>=2)b=arguments[1];else{do{if(a in c){b=c[a--];break}if(--a<0)throw new TypeError("reduceRight of empty array with no initial value");}while(1)}do a in this&&(b=d.call(void 0,b,c[a],a,c));while(a--);return b});Array.prototype.indexOf||(Array.prototype.indexOf=
function(d){var c=j(this),a=c.length>>>0;if(!a)return-1;var b=0;arguments.length>1&&(b=p(arguments[1]));for(b=b>=0?b:Math.max(0,a+b);b<a;b++)if(b in c&&c[b]===d)return b;return-1});Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(d){var c=j(this),a=c.length>>>0;if(!a)return-1;var b=a-1;arguments.length>1&&(b=Math.min(b,p(arguments[1])));for(b=b>=0?b:a-Math.abs(b);b>=0;b--)if(b in c&&d===c[b])return b;return-1});if(!Object.keys){var q=!0,r="toString toLocaleString valueOf hasOwnProperty isPrototypeOf propertyIsEnumerable constructor".split(" "),
s=r.length,t;for(t in{toString:null})q=!1;Object.keys=function(d){if(typeof d!="object"&&typeof d!="function"||d===null)throw new TypeError("Object.keys called on a non-object");var c=[],a;for(a in d)o(d,a)&&c.push(a);if(q)for(a=0;a<s;a++){var b=r[a];o(d,b)&&c.push(b)}return c}}if(!Date.prototype.toISOString||-1===(new Date(-621987552E5)).toISOString().indexOf("-000001"))Date.prototype.toISOString=function(){var d,c,a,b;if(!isFinite(this))throw new RangeError("Date.prototype.toISOString called on non-finite value.");
d=[this.getUTCMonth()+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];b=this.getUTCFullYear();b=(b<0?"-":b>9999?"+":"")+("00000"+Math.abs(b)).slice(0<=b&&b<=9999?-4:-6);for(c=d.length;c--;){a=d[c];a<10&&(d[c]="0"+a)}return b+"-"+d.slice(0,2).join("-")+"T"+d.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()});Date.prototype.toJSON||(Date.prototype.toJSON=function(){if(typeof this.toISOString!=
"function")throw new TypeError("toISOString property is not callable");return this.toISOString()});if(!Date.parse||864E13!==Date.parse("+275760-09-13T00:00:00.000Z")){var g=Date,f=function c(a,b,e,f,h,j,l){var k=arguments.length;if(this instanceof g){k=k==1&&String(a)===a?new g(c.parse(a)):k>=7?new g(a,b,e,f,h,j,l):k>=6?new g(a,b,e,f,h,j):k>=5?new g(a,b,e,f,h):k>=4?new g(a,b,e,f):k>=3?new g(a,b,e):k>=2?new g(a,b):k>=1?new g(a):new g;k.constructor=c;return k}return g.apply(this,arguments)},u=RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$"),
h;for(h in g)f[h]=g[h];f.now=g.now;f.UTC=g.UTC;f.prototype=g.prototype;f.prototype.constructor=f;f.parse=function(c){var a=u.exec(c);if(a){a.shift();for(var b=1;b<7;b++){a[b]=+(a[b]||(b<3?1:0));b==1&&a[b]--}var e=+a.pop(),f=+a.pop(),h=a.pop(),b=0;if(h){if(f>23||e>59)return NaN;b=(f*60+e)*6E4*(h=="+"?-1:1)}e=+a[0];if(0<=e&&e<=99){a[0]=e+400;return g.UTC.apply(this,a)+b-126227808E5}return g.UTC.apply(this,a)+b}return g.parse.apply(this,arguments)};Date=f}h="\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff";
if(!String.prototype.trim||h.trim()){h="["+h+"]";var v=RegExp("^"+h+h+"*"),w=RegExp(h+h+"*$");String.prototype.trim=function(){if(this===void 0||this===null)throw new TypeError("can't convert "+this+" to object");return String(this).replace(v,"").replace(w,"")}}var p=function(c){c=+c;c!==c?c=0:c!==0&&(c!==1/0&&c!==-(1/0))&&(c=(c>0||-1)*Math.floor(Math.abs(c)));return c},x="a"!="a"[0],j=function(c){if(c==null)throw new TypeError("can't convert "+c+" to object");return x&&typeof c=="string"&&c?c.split(""):
Object(c)}});

31
js/libs/es5-shim/package.json

@ -0,0 +1,31 @@
{
"name": "es5-shim",
"version": "2.0.0",
"description": "ES5 as implementable on previous engines",
"homepage": "http://github.com/kriskowal/es5-shim/",
"contributors": [
"Kris Kowal <kris@cixar.com> (http://github.com/kriskowal/)",
"Sami Samhuri <sami.samhuri@gmail.com> (http://samhuri.net/)",
"Florian Schäfer <florian.schaefer@gmail.com> (http://github.com/fschaefer)",
"Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
"Kit Cambridge <kitcambridge@gmail.com> (http://kitcambridge.github.com)"
],
"bugs": {
"mail": "kris@cixar.com",
"url": "http://github.com/kriskowal/es5-shim/issues"
},
"licenses": [
{
"type": "MIT",
"url": "http://github.com/kriskowal/es5-shim/raw/master/LICENSE"
}
],
"main": "es5-shim.js",
"repository": {
"type": "git",
"url": "http://github.com/kriskowal/es5-shim.git"
},
"engines": {
"node": ">=0.2.0"
}
}

59
js/libs/es5-shim/tests/helpers/h-kill.js

@ -0,0 +1,59 @@
// This methods allows the killing of built-in functions,
// so the shim can take over with that implementation
var HLP = (function() {
"use strict";
var kill;
kill = function(_class, methods) {
/*if(!Array.isArray(methods))
return;*/
if(!_class.originals)
_class.originals = {};
for (var i = 0, len = methods.length; i < len; i++) {
var obj = methods[i];
_class.originals[obj] = _class[obj];
delete _class[obj];
if (obj in _class) {
// try something more aggressive since V8 at least
// appears to ignore the delete.
_class[obj] = null;
if (_class[obj]) {
console.log("Couln't overwrite", obj, "of", _class);
}
}
}
};
return { kill: kill };
}());
HLP.kill(Function.prototype, [
'bind'
]);
HLP.kill(Array, [
'isArray'
]);
HLP.kill(String.prototype, [
"trim"
]);
HLP.kill(Object, [
'keys'
]);
HLP.kill(Date, [
'now', 'parse'
]);
HLP.kill(Date.prototype, [
"toJSON", "toISOString"
]);
HLP.kill(Array.prototype, [
'forEach', 'some', 'every',
'indexOf', 'lastIndexOf',
'map', 'filter',
'reduce', 'reduceRight'
]);

34
js/libs/es5-shim/tests/helpers/h-matchers.js

@ -0,0 +1,34 @@
beforeEach(function() {
this.addMatchers({
toExactlyMatch: function(expected) {
var a1, a2,
l, i,
key,
actual = this.actual;
var getKeys = function(o) {
var a = [];
for(key in o) {
if(o.hasOwnProperty(key)) {
a.push(key);
}
}
return a;
}
a1 = getKeys(actual);
a2 = getKeys(expected);
l = a1.length;
if(l !== a2.length) {
return false;
}
for(i = 0; i < l; i++) {
key = a1[i];
expect(key).toEqual(a2[i]);
expect(actual[key]).toEqual(expected[key]);
}
return true;
}
})
});

3
js/libs/es5-shim/tests/helpers/h.js

@ -0,0 +1,3 @@
function implement() {
throw 'Not implemented';
}

62
js/libs/es5-shim/tests/index.html

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine.css">
<script type="text/javascript" src="lib/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-html.js"></script>
<script type="text/javascript" src="lib/json2.js"></script>
<!-- include helper files here... -->
<script src="helpers/h.js"></script>
<script src="helpers/h-kill.js"></script>
<script src="helpers/h-matchers.js"></script>
<!-- include source files here... -->
<script src="../es5-shim.js"></script>
<!-- include spec files here... -->
<script src="spec/s-array.js"></script>
<script src="spec/s-function.js"></script>
<script src="spec/s-string.js"></script>
<script src="spec/s-object.js"></script>
<script src="spec/s-date.js"></script>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var trivialReporter = new jasmine.TrivialReporter();
jasmineEnv.addReporter(trivialReporter);
jasmineEnv.specFilter = function(spec) {
return trivialReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
</body>
</html>

190
js/libs/es5-shim/tests/lib/jasmine-html.js

@ -0,0 +1,190 @@
jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
if (child) { el.appendChild(child); }
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
};
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
var showPassed, showSkipped;
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('span', { className: 'title' }, "Jasmine"),
this.createDom('span', { className: 'version' }, runner.env.versionString())),
this.createDom('div', { className: 'options' },
"Show ",
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
)
),
this.runnerDiv = this.createDom('div', { className: 'runner running' },
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
);
this.document.body.appendChild(this.outerDiv);
var suites = runner.suites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteDiv = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
this.suiteDivs[suite.id] = suiteDiv;
var parentDiv = this.outerDiv;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.id];
}
parentDiv.appendChild(suiteDiv);
}
this.startedAt = new Date();
var self = this;
showPassed.onclick = function(evt) {
if (showPassed.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onclick = function(evt) {
if (showSkipped.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
var results = runner.results();
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
//do it twice for IE
this.runnerDiv.setAttribute("className", className);
var specs = runner.specs();
var specCount = 0;
for (var i = 0; i < specs.length; i++) {
if (this.specFilter(specs[i])) {
specCount++;
}
}
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
};
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
var results = suite.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount === 0) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.id].className += " " + status;
};
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
if (this.logRunningSpecs) {
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var results = spec.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(spec.getFullName()),
title: spec.getFullName()
}, spec.description));
var resultItems = results.getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
jasmine.TrivialReporter.prototype.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
var paramMap = {};
var params = this.getLocation().search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
if (!paramMap.spec) {
return true;
}
return spec.getFullName().indexOf(paramMap.spec) === 0;
};

166
js/libs/es5-shim/tests/lib/jasmine.css

@ -0,0 +1,166 @@
body {
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
}
.jasmine_reporter a:visited, .jasmine_reporter a {
color: #303;
}
.jasmine_reporter a:hover, .jasmine_reporter a:active {
color: blue;
}
.run_spec {
float:right;
padding-right: 5px;
font-size: .8em;
text-decoration: none;
}
.jasmine_reporter {
margin: 0 5px;
}
.banner {
color: #303;
background-color: #fef;
padding: 5px;
}
.logo {
float: left;
font-size: 1.1em;
padding-left: 5px;
}
.logo .version {
font-size: .6em;
padding-left: 1em;
}
.runner.running {
background-color: yellow;
}
.options {
text-align: right;
font-size: .8em;
}
.suite {
border: 1px outset gray;
margin: 5px 0;
padding-left: 1em;
}
.suite .suite {
margin: 5px;
}
.suite.passed {
background-color: #dfd;
}
.suite.failed {
background-color: #fdd;
}
.spec {
margin: 5px;
padding-left: 1em;
clear: both;
}
.spec.failed, .spec.passed, .spec.skipped {
padding-bottom: 5px;
border: 1px solid gray;
}
.spec.failed {
background-color: #fbb;
border-color: red;
}
.spec.passed {
background-color: #bfb;
border-color: green;
}
.spec.skipped {
background-color: #bbb;
}
.messages {
border-left: 1px dashed gray;
padding-left: 1em;
padding-right: 1em;
}
.passed {
background-color: #cfc;
display: none;
}
.failed {
background-color: #fbb;
}
.skipped {
color: #777;
background-color: #eee;
display: none;
}
/*.resultMessage {*/
/*white-space: pre;*/
/*}*/
.resultMessage span.result {
display: block;
line-height: 2em;
color: black;
}
.resultMessage .mismatch {
color: black;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
max-height: 5em;
overflow: auto;
border: 1px inset red;
padding: 1em;
background: #eef;
}
.finished-at {
padding-left: 1em;
font-size: .6em;
}
.show-passed .passed,
.show-skipped .skipped {
display: block;
}
#jasmine_content {
position:fixed;
right: 100%;
}
.runner {
border: 1px solid gray;
display: block;
margin: 5px 0;
padding: 2px 0 2px 10px;
}

2477
js/libs/es5-shim/tests/lib/jasmine.js

File diff suppressed because it is too large Load Diff

BIN
js/libs/es5-shim/tests/lib/jasmine_favicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

478
js/libs/es5-shim/tests/lib/json2.js

@ -0,0 +1,478 @@
/*
http://www.JSON.org/json2.js
2009-08-17
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
*/
/*jslint evil: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
"use strict";
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (!this.JSON) {
this.JSON = {};
}
(function () {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ?
'"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' :
'"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' :
gap ? '[\n' + gap +
partial.join(',\n' + gap) + '\n' +
mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
k = rep[i];
if (typeof k === 'string') {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' :
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
mind + '}' : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());

1070
js/libs/es5-shim/tests/spec/s-array.js

File diff suppressed because it is too large Load Diff

40
js/libs/es5-shim/tests/spec/s-date.js

@ -0,0 +1,40 @@
describe('Date', function () {
describe('now', function () {
it('should be the current time', function () {
expect(Date.now() === new Date().getTime()).toBe(true);
});
});
describe("parse", function () {
// TODO: Write the rest of the test.
it('should support extended years', function () {
expect(Date.parse('0001-01-01T00:00:00Z')).toBe(-62135596800000);
expect(Date.parse('+275760-09-13T00:00:00.000Z')).toBe(8.64e15);
expect(Date.parse('+033658-09-27T01:46:40.000Z')).toBe(1e15);
expect(Date.parse('-000001-01-01T00:00:00Z')).toBe(-62198755200000);
expect(Date.parse('+002009-12-15T00:00:00Z')).toBe(1260835200000);
});
});
describe("toISOString", function () {
// TODO: write the rest of the test.
it('should support extended years', function () {
expect(new Date(-62198755200000).toISOString().indexOf('-000001-01-01')).toBe(0);
expect(new Date(8.64e15).toISOString().indexOf('+275760-09-13')).toBe(0);
});
});
describe("toJSON", function () {
it('should return the isoString when stringified', function () {
var date = new Date();
expect(JSON.stringify(date.toISOString())).toBe(JSON.stringify(date));
})
});
});

137
js/libs/es5-shim/tests/spec/s-function.js

@ -0,0 +1,137 @@
describe('Function', function() {
"use strict";
describe('bind', function() {
var actual, expected,
testSubject;
testSubject = {
push: function(o) {
this.a.push(o);
}
};
function func() {
Array.prototype.forEach.call(arguments, function(a) {
this.push(a);
}, this);
return this;
};
beforeEach(function() {
actual = [];
testSubject.a = [];
});
it('binds properly without a context', function() {
var context;
testSubject.func = function() {
context = this;
}.bind();
testSubject.func();
expect(context).toBe(function() {return this}.call());
});
it('binds properly without a context, and still supplies bound arguments', function() {
var a, context;
testSubject.func = function() {
a = Array.prototype.slice.call(arguments);
context = this;
}.bind(undefined, 1,2,3);
testSubject.func(1,2,3);
expect(a).toEqual([1,2,3,1,2,3]);
expect(context).toBe(function() {return this}.call());
});
it('binds a context properly', function() {
testSubject.func = func.bind(actual);
testSubject.func(1,2,3);
expect(actual).toEqual([1,2,3]);
expect(testSubject.a).toEqual([]);
});
it('binds a context and supplies bound arguments', function() {
testSubject.func = func.bind(actual, 1,2,3);
testSubject.func(4,5,6);
expect(actual).toEqual([1,2,3,4,5,6]);
expect(testSubject.a).toEqual([]);
});
it('returns properly without binding a context', function() {
testSubject.func = function() {
return this;
}.bind();
var context = testSubject.func();
expect(context).toBe(function() {return this}.call());
});
it('returns properly without binding a context, and still supplies bound arguments', function() {
var context;
testSubject.func = function() {
context = this;
return Array.prototype.slice.call(arguments);
}.bind(undefined, 1,2,3);
actual = testSubject.func(1,2,3);
expect(context).toBe(function() {return this}.call());
expect(actual).toEqual([1,2,3,1,2,3]);
});
it('returns properly while binding a context properly', function() {
var ret;
testSubject.func = func.bind(actual);
ret = testSubject.func(1,2,3);
expect(ret).toBe(actual);
expect(ret).not.toBe(testSubject);
});
it('returns properly while binding a context and supplies bound arguments', function() {
var ret;
testSubject.func = func.bind(actual, 1,2,3);
ret = testSubject.func(4,5,6);
expect(ret).toBe(actual);
expect(ret).not.toBe(testSubject);
});
it('passes the correct arguments as a constructor', function() {
var ret, expected = { name: "Correct" };
testSubject.func = function(arg) {
return arg;
}.bind({ name: "Incorrect" });
ret = new testSubject.func(expected);
expect(ret).toBe(expected);
});
it('returns the return value of the bound function when called as a constructor', function () {
var oracle = [1, 2, 3];
var subject = function () {
return oracle;
}.bind(null);
var result = new subject;
expect(result).toBe(oracle);
});
it('returns the correct value if constructor returns primitive', function() {
var oracle = [1, 2, 3];
var subject = function () {
return oracle;
}.bind(null);
var result = new subject;
expect(result).toBe(oracle);
oracle = {};
result = new subject;
expect(result).toBe(oracle);
oracle = function(){};
result = new subject;
expect(result).toBe(oracle);
oracle = "asdf";
result = new subject;
expect(result).not.toBe(oracle);
oracle = null;
result = new subject;
expect(result).not.toBe(oracle);
oracle = true;
result = new subject;
expect(result).not.toBe(oracle);
oracle = 1;
result = new subject;
expect(result).not.toBe(oracle);
});
});
});

84
js/libs/es5-shim/tests/spec/s-object.js

@ -0,0 +1,84 @@
describe('Object', function () {
"use strict";
describe("Object.keys", function () {
var obj = {
"str": "boz",
"obj": { },
"arr": [],
"bool": true,
"num": 42,
"null": null,
"undefined": undefined
};
var loopedValues = [];
for (var k in obj) {
loopedValues.push(k);
}
var keys = Object.keys(obj);
it('should have correct length', function () {
expect(keys.length).toBe(7);
});
it('should return an Array', function () {
expect(Array.isArray(keys)).toBe(true);
});
it('should return names which are own properties', function () {
keys.forEach(function (name) {
expect(obj.hasOwnProperty(name)).toBe(true);
});
});
it('should return names which are enumerable', function () {
keys.forEach(function (name) {
expect(loopedValues.indexOf(name)).toNotBe(-1);
})
});
it('should throw error for non object', function () {
var e = {};
expect(function () {
try {
Object.keys(42)
} catch (err) {
throw e;
}
}).toThrow(e);
});
});
describe("Object.isExtensible", function () {
var obj = { };
it('should return true if object is extensible', function () {
expect(Object.isExtensible(obj)).toBe(true);
});
it('should return false if object is not extensible', function () {
expect(Object.isExtensible(Object.preventExtensions(obj))).toBe(false);
});
it('should return false if object is seal', function () {
expect(Object.isExtensible(Object.seal(obj))).toBe(false);
});
it('should return false if object is freeze', function () {
expect(Object.isExtensible(Object.freeze(obj))).toBe(false);
});
it('should throw error for non object', function () {
var e1 = {};
expect(function () {
try {
Object.isExtensible(42)
} catch (err) {
throw e1;
}
}).toThrow(e1);
});
});
});

11
js/libs/es5-shim/tests/spec/s-string.js

@ -0,0 +1,11 @@
describe('String', function() {
"use strict";
describe("trim", function() {
var test = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFFHello, World!\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF";
it('trims all ES5 whitespace', function() {
expect(test.trim()).toEqual("Hello, World!");
expect(test.trim().length).toEqual(13);
});
});
});

33
js/libs/flight/.bower.json

@ -0,0 +1,33 @@
{
"name": "flight",
"description": "Clientside component infrastructure",
"main": "lib/index.js",
"version": "1.1.4",
"ignore": [
"doc",
"tools",
"test",
".gitignore",
".travis.yml",
"CHANGELOG.md",
"CONTRIBUTING.md",
"Makefile",
"karma.conf.js",
"package.json"
],
"dependencies": {
"es5-shim": "2.0.0",
"jquery": ">=1.8.0"
},
"homepage": "https://github.com/flightjs/flight",
"_release": "1.1.4",
"_resolution": {
"type": "version",
"tag": "v1.1.4",
"commit": "5da831ba9026330b692ecf5668cad8832f1f19cd"
},
"_source": "git://github.com/flightjs/flight.git",
"_target": "~1.1.4",
"_originalSource": "flight",
"_direct": true
}

19
js/libs/flight/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2013-2014 Twitter, Inc and others
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.

242
js/libs/flight/README.md

@ -0,0 +1,242 @@
# Flight
[![Build Status](https://travis-ci.org/flightjs/flight.png?branch=master)](http://travis-ci.org/flightjs/flight)
[Flight](http://flightjs.github.io/) is a lightweight, component-based,
event-driven JavaScript framework that maps behavior to DOM nodes. It was
created at Twitter, and is used by the [twitter.com](https://twitter.com/) and
[TweetDeck](https://web.tweetdeck.com/) web applications.
* [Website](http://flightjs.github.io/)
* [API documentation](doc/README.md)
* [Flight example app](http://flightjs.github.io/example-app/) ([Source](https://github.com/flightjs/example-app))
* [Flight's Google Group](https://groups.google.com/forum/?fromgroups#!forum/twitter-flight)
* [Flight on Twitter](https://twitter.com/flight)
## Why Flight?
Flight is only ~5K minified and gzipped. It's built upon jQuery, and has
first-class support for Asynchronous Module Definition (AMD) and [Bower](http://bower.io/).
Flight components are highly portable and easily testable. This is because a
Flight component (and its API) is entirely decoupled from other components.
Flight components communicate only by triggering and subscribing to events.
Flight also includes a simple and safe
[mixin](https://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/)
infrastructure, allowing components to be easily extended with minimal
boilerplate.
## Development tools
Flight has supporting projects that provide everything you need to setup,
write, and test your application.
* [Flight generator](https://github.com/flightjs/generator-flight/)
Recommended. One-step to setup everything you need to work with Flight.
* [Flight package generator](https://github.com/flightjs/generator-flight-package/)
Recommended. One-step to setup everything you need to write and test a
standalone Flight component.
* [Jasmine Flight](https://github.com/flightjs/jasmine-flight/)
Extensions for the Jasmine test framework.
* [Mocha Flight](https://github.com/flightjs/mocha-flight/)
Extensions for the Mocha test framework.
## Finding and writing standalone components
You can browse all the [Flight components](http://flight-components.jit.su)
available at this time. They can also be found by searching the Bower registry:
```
bower search flight
```
The easiest way to write a standalone Flight component is to use the [Flight
package generator](https://github.com/flightjs/generator-flight-package/):
```
yo flight-package foo
```
## Installation
If you prefer not to use the Flight generators, it's highly recommended that
you install Flight as an AMD package (including all the correct dependencies).
This is best done with [Bower](http://bower.io/), a package manager for the web.
```
npm install -g bower
bower install --save flight
```
You will have to reference Flight's installed dependencies –
[ES5-shim](https://github.com/kriskowal/es5-shim) and
[jQuery](http://jquery.com) – and use an AMD module loader like
[Require.js](http://requirejs.org/) or
[Loadrunner](https://github.com/danwrong/loadrunner).
```html
<script src="bower_components/es5-shim/es5-shim.js"></script>
<script src="bower_components/es5-shim/es5-sham.js"></script>
<script src="bower_components/jquery/dist/jquery.js"></script>
<script data-main="main.js" src="bower_components/requirejs/require.js"></script>
...
```
## Standalone version
Alternatively, you can manually install the [standalone
version](http://flightjs.github.io/release/latest/flight.js) of Flight, also
available on [cdnjs](http://cdnjs.com/). It exposes all of its modules as
properties of a global variable, `flight`:
```html
...
<script src="flight.js"></script>
<script>
var MyComponent = flight.component(function() {
//...
});
</script>
```
N.B. You will also need to manually install the correct versions of Flight's
dependencies: ES5 Shim and jQuery.
## Browser Support
Chrome, Firefox, Safari, Opera, IE 7+.
## Quick Overview
Here's a brief introduction to Flight's key concepts and syntax. Read the [API
documentation](doc) for a comprehensive overview.
### Example
A simple example of how to write and use a Flight component.
```js
define(function (require) {
var defineComponent = require('flight/lib/component');
// define the component
return defineComponent(inbox);
function inbox() {
// define custom functions here
this.doSomething = function() {
//...
}
this.doSomethingElse = function() {
//...
}
// now initialize the component
this.after('initialize', function() {
this.on('click', this.doSomething);
this.on('mouseover', this.doSomethingElse);
});
}
});
```
```js
/* attach an inbox component to a node with id 'inbox' */
define(function (require) {
var Inbox = require('inbox');
Inbox.attachTo('#inbox', {
'nextPageSelector': '#nextPage',
'previousPageSelector': '#previousPage',
});
});
```
### Components ([API](doc/component_api.md))
- A Component is nothing more than a constructor with properties mixed into its prototype.
- Every Component comes with a set of basic functionality such as event handling and component registration.
(see [Base API](doc/base_api.md))
- Additionally, each Component definition mixes in a set of custom properties which describe its behavior.
- When a component is attached to a DOM node, a new instance of that component is created. Each component
instance references the DOM node via its `node` property.
- Component instances cannot be referenced directly; they communicate with other components via events.
### Interacting with the DOM
Once attached, component instances have direct access to their node object via the `node` property. (There's
also a jQuery version of the node available via the `$node` property.)
### Events in Flight
Events are how Flight components interact. The Component prototype supplies methods for triggering events as
well as for subscribing to and unsubscribing from events. These Component event methods are actually just convenient
wrappers around regular event methods on DOM nodes.
### Mixins ([API](doc/mixin_api.md))
- In Flight, a mixin is a function which assigns properties to a target object (represented by the `this`
keyword).
- A typical mixin defines a set of functionality that will be useful to more than one component.
- One mixin can be applied to any number of [Component](#components) definitions.
- One Component definition can have any number of mixins applied to it.
- Each Component defines a [*core*](#core_mixin) mixin within its own module.
- A mixin can itself have mixins applied to it.
### Advice ([API](doc/advice_api.md))
In Flight, advice is a mixin (`'lib/advice.js'`) that defines `before`, `after` and `around` methods.
These can be used to modify existing functions by adding custom code. All Components have advice mixed in to
their prototype so that mixins can augment existing functions without requiring knowledge
of the original implementation. Moreover, since Component's are seeded with an empty `initialize` method,
Component definitions will typically use `after` to define custom `initialize` behavior.
### Debugging ([API](doc/debug_api.md))
Flight ships with a debug module which can help you trace the sequence of event triggering and binding. By default
console logging is turned off, but you can you can log `trigger`, `on` and `off` events by means of the following console
commands.
## Authors
+ [@angus-c](http://github.com/angus-c)
+ [@danwrong](http://github.com/danwrong)
+ [@kpk](http://github.com/kennethkufluk)
Thanks for assistance and contributions:
[@sayrer](https://github.com/sayrer),
[@shinypb](https://github.com/shinypb),
[@kloots](https://github.com/kloots),
[@marcelduran](https://github.com/marcelduran),
[@tbrd](https://github.com/tbrd),
[@necolas](https://github.com/necolas),
[@fat](https://github.com/fat),
[@mkuklis](https://github.com/mkuklis),
[@jrburke](https://github.com/jrburke),
[@garann](https://github.com/garann),
[@WebReflection](https://github.com/WebReflection),
[@coldhead](https://github.com/coldhead),
[@paulirish](https://github.com/paulirish),
[@nimbupani](https://github.com/nimbupani),
[@mootcycle](https://github.com/mootcycle).
Special thanks to the rest of the Twitter web team for their abundant
contributions and feedback.
## License
Copyright 2013 Twitter, Inc and other contributors.
Licensed under the MIT License

22
js/libs/flight/bower.json

@ -0,0 +1,22 @@
{
"name": "flight",
"description": "Clientside component infrastructure",
"main": "lib/index.js",
"version": "1.1.4",
"ignore": [
"doc",
"tools",
"test",
".gitignore",
".travis.yml",
"CHANGELOG.md",
"CONTRIBUTING.md",
"Makefile",
"karma.conf.js",
"package.json"
],
"dependencies": {
"es5-shim": "2.0.0",
"jquery": ">=1.8.0"
}
}

69
js/libs/flight/lib/advice.js

@ -0,0 +1,69 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[
'./compose'
],
function(compose) {
'use strict';
var advice = {
around: function(base, wrapped) {
return function composedAround() {
// unpacking arguments by hand benchmarked faster
var i = 0, l = arguments.length, args = new Array(l + 1);
args[0] = base.bind(this);
for (; i < l; i++) args[i + 1] = arguments[i];
return wrapped.apply(this, args);
};
},
before: function(base, before) {
var beforeFn = (typeof before == 'function') ? before : before.obj[before.fnName];
return function composedBefore() {
beforeFn.apply(this, arguments);
return base.apply(this, arguments);
};
},
after: function(base, after) {
var afterFn = (typeof after == 'function') ? after : after.obj[after.fnName];
return function composedAfter() {
var res = (base.unbound || base).apply(this, arguments);
afterFn.apply(this, arguments);
return res;
};
},
// a mixin that allows other mixins to augment existing functions by adding additional
// code before, after or around.
withAdvice: function() {
['before', 'after', 'around'].forEach(function(m) {
this[m] = function(method, fn) {
compose.unlockProperty(this, method, function() {
if (typeof this[method] == 'function') {
this[method] = advice[m](this[method], fn);
} else {
this[method] = fn;
}
return this[method];
});
};
}, this);
}
};
return advice;
}
);

237
js/libs/flight/lib/base.js

@ -0,0 +1,237 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[
'./utils',
'./registry',
'./debug'
],
function(utils, registry, debug) {
'use strict';
// common mixin allocates basic functionality - used by all component prototypes
// callback context is bound to component
var componentId = 0;
function teardownInstance(instanceInfo){
instanceInfo.events.slice().forEach(function(event) {
var args = [event.type];
event.element && args.unshift(event.element);
(typeof event.callback == 'function') && args.push(event.callback);
this.off.apply(this, args);
}, instanceInfo.instance);
}
function checkSerializable(type, data) {
try {
window.postMessage(data, '*');
} catch(e) {
console.log('unserializable data for event',type,':',data);
throw new Error(
['The event', type, 'on component', this.toString(), 'was triggered with non-serializable data'].join(' ')
);
}
}
function proxyEventTo(targetEvent) {
return function(e, data) {
$(e.target).trigger(targetEvent, data);
};
}
function withBase() {
// delegate trigger, bind and unbind to an element
// if $element not supplied, use component's node
// other arguments are passed on
// event can be either a string specifying the type
// of the event, or a hash specifying both the type
// and a default function to be called.
this.trigger = function() {
var $element, type, data, event, defaultFn;
var lastIndex = arguments.length - 1, lastArg = arguments[lastIndex];
if (typeof lastArg != 'string' && !(lastArg && lastArg.defaultBehavior)) {
lastIndex--;
data = lastArg;
}
if (lastIndex == 1) {
$element = $(arguments[0]);
event = arguments[1];
} else {
$element = this.$node;
event = arguments[0];
}
if (event.defaultBehavior) {
defaultFn = event.defaultBehavior;
event = $.Event(event.type);
}
type = event.type || event;
if (debug.enabled && window.postMessage) {
checkSerializable.call(this, type, data);
}
if (typeof this.attr.eventData === 'object') {
data = $.extend(true, {}, this.attr.eventData, data);
}
$element.trigger((event || type), data);
if (defaultFn && !event.isDefaultPrevented()) {
(this[defaultFn] || defaultFn).call(this);
}
return $element;
};
this.on = function() {
var $element, type, callback, originalCb;
var lastIndex = arguments.length - 1, origin = arguments[lastIndex];
if (typeof origin == 'object') {
//delegate callback
originalCb = utils.delegate(
this.resolveDelegateRules(origin)
);
} else if (typeof origin == 'string') {
originalCb = proxyEventTo(origin);
} else {
originalCb = origin;
}
if (lastIndex == 2) {
$element = $(arguments[0]);
type = arguments[1];
} else {
$element = this.$node;
type = arguments[0];
}
if (typeof originalCb != 'function' && typeof originalCb != 'object') {
throw new Error('Unable to bind to "' + type + '" because the given callback is not a function or an object');
}
callback = originalCb.bind(this);
callback.target = originalCb;
callback.context = this;
$element.on(type, callback);
// store every bound version of the callback
originalCb.bound || (originalCb.bound = []);
originalCb.bound.push(callback);
return callback;
};
this.off = function() {
var $element, type, callback;
var lastIndex = arguments.length - 1;
if (typeof arguments[lastIndex] == 'function') {
callback = arguments[lastIndex];
lastIndex -= 1;
}
if (lastIndex == 1) {
$element = $(arguments[0]);
type = arguments[1];
} else {
$element = this.$node;
type = arguments[0];
}
if (callback) {
//this callback may be the original function or a bound version
var boundFunctions = callback.target ? callback.target.bound : callback.bound || [];
//set callback to version bound against this instance
boundFunctions && boundFunctions.some(function(fn, i, arr) {
if (fn.context && (this.identity == fn.context.identity)) {
arr.splice(i, 1);
callback = fn;
return true;
}
}, this);
}
return $element.off(type, callback);
};
this.resolveDelegateRules = function(ruleInfo) {
var rules = {};
Object.keys(ruleInfo).forEach(function(r) {
if (!(r in this.attr)) {
throw new Error('Component "' + this.toString() + '" wants to listen on "' + r + '" but no such attribute was defined.');
}
rules[this.attr[r]] = (typeof ruleInfo[r] == 'string') ? proxyEventTo(ruleInfo[r]) : ruleInfo[r];
}, this);
return rules;
};
this.defaultAttrs = function(defaults) {
utils.push(this.defaults, defaults, true) || (this.defaults = defaults);
};
this.select = function(attributeKey) {
return this.$node.find(this.attr[attributeKey]);
};
this.initialize = function(node, attrs) {
attrs || (attrs = {});
//only assign identity if there isn't one (initialize can be called multiple times)
this.identity || (this.identity = componentId++);
if (!node) {
throw new Error('Component needs a node');
}
if (node.jquery) {
this.node = node[0];
this.$node = node;
} else {
this.node = node;
this.$node = $(node);
}
// merge defaults with supplied options
// put options in attr.__proto__ to avoid merge overhead
var attr = Object.create(attrs);
for (var key in this.defaults) {
if (!attrs.hasOwnProperty(key)) {
attr[key] = this.defaults[key];
}
}
this.attr = attr;
Object.keys(this.defaults || {}).forEach(function(key) {
if (this.defaults[key] === null && this.attr[key] === null) {
throw new Error('Required attribute "' + key + '" not specified in attachTo for component "' + this.toString() + '".');
}
}, this);
return this;
};
this.teardown = function() {
teardownInstance(registry.findInstanceInfo(this));
};
}
return withBase;
}
);

136
js/libs/flight/lib/component.js

@ -0,0 +1,136 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[
'./advice',
'./utils',
'./compose',
'./base',
'./registry',
'./logger',
'./debug'
],
function(advice, utils, compose, withBase, registry, withLogging, debug) {
'use strict';
var functionNameRegEx = /function (.*?)\s?\(/;
// teardown for all instances of this constructor
function teardownAll() {
var componentInfo = registry.findComponentInfo(this);
componentInfo && Object.keys(componentInfo.instances).forEach(function(k) {
var info = componentInfo.instances[k];
// It's possible that a previous teardown caused another component to teardown,
// so we can't assume that the instances object is as it was.
if (info && info.instance) {
info.instance.teardown();
}
});
}
function checkSerializable(type, data) {
try {
window.postMessage(data, '*');
} catch(e) {
console.log('unserializable data for event',type,':',data);
throw new Error(
['The event', type, 'on component', this.toString(), 'was triggered with non-serializable data'].join(' ')
);
}
}
function attachTo(selector/*, options args */) {
// unpacking arguments by hand benchmarked faster
var l = arguments.length;
var args = new Array(l - 1);
for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
if (!selector) {
throw new Error('Component needs to be attachTo\'d a jQuery object, native node or selector string');
}
var options = utils.merge.apply(utils, args);
var componentInfo = registry.findComponentInfo(this);
$(selector).each(function(i, node) {
if (componentInfo && componentInfo.isAttachedTo(node)) {
// already attached
return;
}
(new this).initialize(node, options);
}.bind(this));
}
function prettyPrintMixins() {
//could be called from constructor or constructor.prototype
var mixedIn = this.mixedIn || this.prototype.mixedIn || [];
return mixedIn.map(function(mixin) {
if (mixin.name == null) {
// function name property not supported by this browser, use regex
var m = mixin.toString().match(functionNameRegEx);
return (m && m[1]) ? m[1] : '';
} else {
return (mixin.name != 'withBase') ? mixin.name : '';
}
}).filter(Boolean).join(', ');
};
// define the constructor for a custom component type
// takes an unlimited number of mixin functions as arguments
// typical api call with 3 mixins: define(timeline, withTweetCapability, withScrollCapability);
function define(/*mixins*/) {
// unpacking arguments by hand benchmarked faster
var l = arguments.length;
var mixins = new Array(l);
for (var i = 0; i < l; i++) mixins[i] = arguments[i];
var Component = function() {};
Component.toString = Component.prototype.toString = prettyPrintMixins;
if (debug.enabled) {
Component.describe = Component.prototype.describe = Component.toString();
}
// 'options' is optional hash to be merged with 'defaults' in the component definition
Component.attachTo = attachTo;
// enables extension of existing "base" Components
Component.mixin = function() {
var newComponent = define(); //TODO: fix pretty print
var newPrototype = Object.create(Component.prototype);
newPrototype.mixedIn = [].concat(Component.prototype.mixedIn);
compose.mixin(newPrototype, arguments);
newComponent.prototype = newPrototype;
newComponent.prototype.constructor = newComponent;
return newComponent;
};
Component.teardownAll = teardownAll;
// prepend common mixins to supplied list, then mixin all flavors
if (debug.enabled) {
mixins.unshift(withLogging);
}
mixins.unshift(withBase, advice.withAdvice, registry.withRegistration);
compose.mixin(Component.prototype, mixins);
return Component;
}
define.teardownAll = function() {
registry.components.slice().forEach(function(c) {
c.component.teardownAll();
});
registry.reset();
};
return define;
}
);

85
js/libs/flight/lib/compose.js

@ -0,0 +1,85 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[
'./utils',
'./debug'
],
function(utils, debug) {
'use strict';
//enumerables are shims - getOwnPropertyDescriptor shim doesn't work
var canWriteProtect = debug.enabled && !utils.isEnumerable(Object, 'getOwnPropertyDescriptor');
//whitelist of unlockable property names
var dontLock = ['mixedIn'];
if (canWriteProtect) {
//IE8 getOwnPropertyDescriptor is built-in but throws exeption on non DOM objects
try {
Object.getOwnPropertyDescriptor(Object, 'keys');
} catch(e) {
canWriteProtect = false;
}
}
function setPropertyWritability(obj, isWritable) {
if (!canWriteProtect) {
return;
}
var props = Object.create(null);
Object.keys(obj).forEach(
function (key) {
if (dontLock.indexOf(key) < 0) {
var desc = Object.getOwnPropertyDescriptor(obj, key);
desc.writable = isWritable;
props[key] = desc;
}
}
);
Object.defineProperties(obj, props);
}
function unlockProperty(obj, prop, op) {
var writable;
if (!canWriteProtect || !obj.hasOwnProperty(prop)) {
op.call(obj);
return;
}
writable = Object.getOwnPropertyDescriptor(obj, prop).writable;
Object.defineProperty(obj, prop, { writable: true });
op.call(obj);
Object.defineProperty(obj, prop, { writable: writable });
}
function mixin(base, mixins) {
base.mixedIn = base.hasOwnProperty('mixedIn') ? base.mixedIn : [];
for (var i=0; i<mixins.length; i++) {
if (base.mixedIn.indexOf(mixins[i]) == -1) {
setPropertyWritability(base, false);
mixins[i].call(base);
base.mixedIn.push(mixins[i]);
}
}
setPropertyWritability(base, true);
}
return {
mixin: mixin,
unlockProperty: unlockProperty
};
}
);

165
js/libs/flight/lib/debug.js

@ -0,0 +1,165 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[],
function() {
'use strict';
// ==========================================
// Search object model
// ==========================================
function traverse(util, searchTerm, options) {
options = options || {};
var obj = options.obj || window;
var path = options.path || ((obj==window) ? 'window' : '');
var props = Object.keys(obj);
props.forEach(function(prop) {
if ((tests[util] || util)(searchTerm, obj, prop)){
console.log([path, '.', prop].join(''), '->', ['(', typeof obj[prop], ')'].join(''), obj[prop]);
}
if (Object.prototype.toString.call(obj[prop]) == '[object Object]' && (obj[prop] != obj) && path.split('.').indexOf(prop) == -1) {
traverse(util, searchTerm, {obj: obj[prop], path: [path,prop].join('.')});
}
});
}
function search(util, expected, searchTerm, options) {
if (!expected || typeof searchTerm == expected) {
traverse(util, searchTerm, options);
} else {
console.error([searchTerm, 'must be', expected].join(' '));
}
}
var tests = {
'name': function(searchTerm, obj, prop) {return searchTerm == prop;},
'nameContains': function(searchTerm, obj, prop) {return prop.indexOf(searchTerm) > -1;},
'type': function(searchTerm, obj, prop) {return obj[prop] instanceof searchTerm;},
'value': function(searchTerm, obj, prop) {return obj[prop] === searchTerm;},
'valueCoerced': function(searchTerm, obj, prop) {return obj[prop] == searchTerm;}
};
function byName(searchTerm, options) {search('name', 'string', searchTerm, options);}
function byNameContains(searchTerm, options) {search('nameContains', 'string', searchTerm, options);}
function byType(searchTerm, options) {search('type', 'function', searchTerm, options);}
function byValue(searchTerm, options) {search('value', null, searchTerm, options);}
function byValueCoerced(searchTerm, options) {search('valueCoerced', null, searchTerm, options);}
function custom(fn, options) {traverse(fn, null, options);}
// ==========================================
// Event logging
// ==========================================
var ALL = 'all'; //no filter
//log nothing by default
var logFilter = {
eventNames: [],
actions: []
}
function filterEventLogsByAction(/*actions*/) {
var actions = [].slice.call(arguments);
logFilter.eventNames.length || (logFilter.eventNames = ALL);
logFilter.actions = actions.length ? actions : ALL;
saveLogFilter();
}
function filterEventLogsByName(/*eventNames*/) {
var eventNames = [].slice.call(arguments);
logFilter.actions.length || (logFilter.actions = ALL);
logFilter.eventNames = eventNames.length ? eventNames : ALL;
saveLogFilter();
}
function hideAllEventLogs() {
logFilter.actions = [];
logFilter.eventNames = [];
saveLogFilter();
}
function showAllEventLogs() {
logFilter.actions = ALL;
logFilter.eventNames = ALL;
saveLogFilter();
}
function saveLogFilter() {
try {
if (window.localStorage) {
localStorage.setItem('logFilter_eventNames', logFilter.eventNames);
localStorage.setItem('logFilter_actions', logFilter.actions);
}
} catch (ignored) {};
}
function retrieveLogFilter() {
var eventNames, actions;
try {
eventNames = (window.localStorage && localStorage.getItem('logFilter_eventNames'));
actions = (window.localStorage && localStorage.getItem('logFilter_actions'));
} catch(ignored) {
return;
}
eventNames && (logFilter.eventNames = eventNames);
actions && (logFilter.actions = actions);
// reconstitute arrays in place
Object.keys(logFilter).forEach(function(k) {
var thisProp = logFilter[k];
if (typeof thisProp == 'string' && thisProp !== ALL) {
logFilter[k] = thisProp ? thisProp.split(',') : [];
}
});
}
return {
enable: function(enable) {
this.enabled = !!enable;
if (enable && window.console) {
console.info('Booting in DEBUG mode');
console.info('You can configure event logging with DEBUG.events.logAll()/logNone()/logByName()/logByAction()');
}
retrieveLogFilter();
window.DEBUG = this;
},
find: {
byName: byName,
byNameContains: byNameContains,
byType: byType,
byValue: byValue,
byValueCoerced: byValueCoerced,
custom: custom
},
events: {
logFilter: logFilter,
// Accepts any number of action args
// e.g. DEBUG.events.logByAction("on", "off")
logByAction: filterEventLogsByAction,
// Accepts any number of event name args (inc. regex or wildcards)
// e.g. DEBUG.events.logByName(/ui.*/, "*Thread*");
logByName: filterEventLogsByName,
logAll: showAllEventLogs,
logNone: hideAllEventLogs
}
};
}
);

31
js/libs/flight/lib/index.js

@ -0,0 +1,31 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[
'./advice',
'./component',
'./compose',
'./logger',
'./registry',
'./utils'
],
function(advice, component, compose, logger, registry, utils) {
'use strict';
return {
advice: advice,
component: component,
compose: compose,
logger: logger,
registry: registry,
utils: utils
};
}
);

100
js/libs/flight/lib/logger.js

@ -0,0 +1,100 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[
'./utils'
],
function(utils) {
'use strict';
var actionSymbols = {
on: '<-',
trigger: '->',
off: 'x '
};
function elemToString(elem) {
var tagStr = elem.tagName ? elem.tagName.toLowerCase() : elem.toString();
var classStr = elem.className ? '.' + (elem.className) : '';
var result = tagStr + classStr;
return elem.tagName ? ['\'', '\''].join(result) : result;
}
function log(action, component, eventArgs) {
if (!window.DEBUG || !window.DEBUG.enabled) return;
var name, eventType, elem, fn, payload, logFilter, toRegExp, actionLoggable, nameLoggable, info;
if (typeof eventArgs[eventArgs.length-1] == 'function') {
fn = eventArgs.pop();
fn = fn.unbound || fn; // use unbound version if any (better info)
}
if (eventArgs.length == 1) {
elem = component.$node[0];
eventType = eventArgs[0];
} else if ((eventArgs.length == 2) && typeof eventArgs[1] == 'object' && !eventArgs[1].type) {
//2 args, first arg is not elem
elem = component.$node[0];
eventType = eventArgs[0];
if (action == "trigger") {
payload = eventArgs[1];
}
} else {
//2+ args, first arg is elem
elem = eventArgs[0];
eventType = eventArgs[1];
if (action == "trigger") {
payload = eventArgs[2];
}
}
name = typeof eventType == 'object' ? eventType.type : eventType;
logFilter = DEBUG.events.logFilter;
// no regex for you, actions...
actionLoggable = logFilter.actions == 'all' || (logFilter.actions.indexOf(action) > -1);
// event name filter allow wildcards or regex...
toRegExp = function(expr) {
return expr.test ? expr : new RegExp('^' + expr.replace(/\*/g, '.*') + '$');
};
nameLoggable =
logFilter.eventNames == 'all' ||
logFilter.eventNames.some(function(e) {return toRegExp(e).test(name);});
if (actionLoggable && nameLoggable) {
info = [actionSymbols[action], action, '[' + name + ']'];
payload && info.push(payload);
info.push(elemToString(elem));
info.push(component.constructor.describe.split(' ').slice(0,3).join(' '));
console.groupCollapsed && action == 'trigger' && console.groupCollapsed(action, name);
console.info.apply(console, info);
}
}
function withLogging() {
this.before('trigger', function() {
log('trigger', this, utils.toArray(arguments));
});
if (console.groupCollapsed) {
this.after('trigger', function() {
console.groupEnd();
});
}
this.before('on', function() {
log('on', this, utils.toArray(arguments));
});
this.before('off', function() {
log('off', this, utils.toArray(arguments));
});
}
return withLogging;
}
);

228
js/libs/flight/lib/registry.js

@ -0,0 +1,228 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[],
function() {
'use strict';
function parseEventArgs(instance, args) {
var element, type, callback;
var end = args.length;
if (typeof args[end - 1] === 'function') {
end -= 1;
callback = args[end];
}
if (typeof args[end - 1] === 'object') {
end -= 1;
}
if (end == 2) {
element = args[0];
type = args[1];
} else {
element = instance.node;
type = args[0];
}
return {
element: element,
type: type,
callback: callback
};
}
function matchEvent(a, b) {
return (
(a.element == b.element) &&
(a.type == b.type) &&
(b.callback == null || (a.callback == b.callback))
);
}
function Registry() {
var registry = this;
(this.reset = function() {
this.components = [];
this.allInstances = {};
this.events = [];
}).call(this);
function ComponentInfo(component) {
this.component = component;
this.attachedTo = [];
this.instances = {};
this.addInstance = function(instance) {
var instanceInfo = new InstanceInfo(instance);
this.instances[instance.identity] = instanceInfo;
this.attachedTo.push(instance.node);
return instanceInfo;
};
this.removeInstance = function(instance) {
delete this.instances[instance.identity];
var indexOfNode = this.attachedTo.indexOf(instance.node);
(indexOfNode > -1) && this.attachedTo.splice(indexOfNode, 1);
if (!Object.keys(this.instances).length) {
//if I hold no more instances remove me from registry
registry.removeComponentInfo(this);
}
};
this.isAttachedTo = function(node) {
return this.attachedTo.indexOf(node) > -1;
};
}
function InstanceInfo(instance) {
this.instance = instance;
this.events = [];
this.addBind = function(event) {
this.events.push(event);
registry.events.push(event);
};
this.removeBind = function(event) {
for (var i = 0, e; e = this.events[i]; i++) {
if (matchEvent(e, event)) {
this.events.splice(i, 1);
}
}
};
}
this.addInstance = function(instance) {
var component = this.findComponentInfo(instance);
if (!component) {
component = new ComponentInfo(instance.constructor);
this.components.push(component);
}
var inst = component.addInstance(instance);
this.allInstances[instance.identity] = inst;
return component;
};
this.removeInstance = function(instance) {
var index, instInfo = this.findInstanceInfo(instance);
//remove from component info
var componentInfo = this.findComponentInfo(instance);
componentInfo && componentInfo.removeInstance(instance);
//remove from registry
delete this.allInstances[instance.identity];
};
this.removeComponentInfo = function(componentInfo) {
var index = this.components.indexOf(componentInfo);
(index > -1) && this.components.splice(index, 1);
};
this.findComponentInfo = function(which) {
var component = which.attachTo ? which : which.constructor;
for (var i = 0, c; c = this.components[i]; i++) {
if (c.component === component) {
return c;
}
}
return null;
};
this.findInstanceInfo = function(instance) {
return this.allInstances[instance.identity] || null;
};
this.getBoundEventNames = function(instance) {
return this.findInstanceInfo(instance).events.map(function(ev) {
return ev.type;
});
};
this.findInstanceInfoByNode = function(node) {
var result = [];
Object.keys(this.allInstances).forEach(function(k) {
var thisInstanceInfo = this.allInstances[k];
if (thisInstanceInfo.instance.node === node) {
result.push(thisInstanceInfo);
}
}, this);
return result;
};
this.on = function(componentOn) {
var instance = registry.findInstanceInfo(this), boundCallback;
// unpacking arguments by hand benchmarked faster
var l = arguments.length, i = 1;
var otherArgs = new Array(l - 1);
for (; i < l; i++) otherArgs[i - 1] = arguments[i];
if (instance) {
boundCallback = componentOn.apply(null, otherArgs);
if (boundCallback) {
otherArgs[otherArgs.length-1] = boundCallback;
}
var event = parseEventArgs(this, otherArgs);
instance.addBind(event);
}
};
this.off = function(/*el, type, callback*/) {
var event = parseEventArgs(this, arguments),
instance = registry.findInstanceInfo(this);
if (instance) {
instance.removeBind(event);
}
//remove from global event registry
for (var i = 0, e; e = registry.events[i]; i++) {
if (matchEvent(e, event)) {
registry.events.splice(i, 1);
}
}
};
// debug tools may want to add advice to trigger
registry.trigger = function() {};
this.teardown = function() {
registry.removeInstance(this);
};
this.withRegistration = function() {
this.after('initialize', function() {
registry.addInstance(this);
});
this.around('on', registry.on);
this.after('off', registry.off);
//debug tools may want to add advice to trigger
window.DEBUG && DEBUG.enabled && this.after('trigger', registry.trigger);
this.after('teardown', {obj: registry, fnName: 'teardown'});
};
}
return new Registry;
}
);

263
js/libs/flight/lib/utils.js

@ -0,0 +1,263 @@
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define(
[],
function() {
'use strict';
var arry = [];
var DEFAULT_INTERVAL = 100;
var utils = {
isDomObj: function(obj) {
return !!(obj.nodeType || (obj === window));
},
toArray: function(obj, from) {
return arry.slice.call(obj, from);
},
// returns new object representing multiple objects merged together
// optional final argument is boolean which specifies if merge is recursive
// original objects are unmodified
//
// usage:
// var base = {a:2, b:6};
// var extra = {b:3, c:4};
// merge(base, extra); //{a:2, b:3, c:4}
// base; //{a:2, b:6}
//
// var base = {a:2, b:6};
// var extra = {b:3, c:4};
// var extraExtra = {a:4, d:9};
// merge(base, extra, extraExtra); //{a:4, b:3, c:4. d: 9}
// base; //{a:2, b:6}
//
// var base = {a:2, b:{bb:4, cc:5}};
// var extra = {a:4, b:{cc:7, dd:1}};
// merge(base, extra, true); //{a:4, b:{bb:4, cc:7, dd:1}}
// base; //{a:2, b:6}
merge: function(/*obj1, obj2,....deepCopy*/) {
// unpacking arguments by hand benchmarked faster
var l = arguments.length,
i = 0,
args = new Array(l + 1);
for (; i < l; i++) args[i + 1] = arguments[i];
if (l === 0) {
return {};
}
//start with empty object so a copy is created
args[0] = {};
if (args[args.length - 1] === true) {
//jquery extend requires deep copy as first arg
args.pop();
args.unshift(true);
}
return $.extend.apply(undefined, args);
},
// updates base in place by copying properties of extra to it
// optionally clobber protected
// usage:
// var base = {a:2, b:6};
// var extra = {c:4};
// push(base, extra); //{a:2, b:6, c:4}
// base; //{a:2, b:6, c:4}
//
// var base = {a:2, b:6};
// var extra = {b: 4 c:4};
// push(base, extra, true); //Error ("utils.push attempted to overwrite 'b' while running in protected mode")
// base; //{a:2, b:6}
//
// objects with the same key will merge recursively when protect is false
// eg:
// var base = {a:16, b:{bb:4, cc:10}};
// var extra = {b:{cc:25, dd:19}, c:5};
// push(base, extra); //{a:16, {bb:4, cc:25, dd:19}, c:5}
//
push: function(base, extra, protect) {
if (base) {
Object.keys(extra || {}).forEach(function(key) {
if (base[key] && protect) {
throw new Error('utils.push attempted to overwrite "' + key + '" while running in protected mode');
}
if (typeof base[key] == 'object' && typeof extra[key] == 'object') {
// recurse
this.push(base[key], extra[key]);
} else {
// no protect, so extra wins
base[key] = extra[key];
}
}, this);
}
return base;
},
isEnumerable: function(obj, property) {
return Object.keys(obj).indexOf(property) > -1;
},
// build a function from other function(s)
// utils.compose(a,b,c) -> a(b(c()));
// implementation lifted from underscore.js (c) 2009-2012 Jeremy Ashkenas
compose: function() {
var funcs = arguments;
return function() {
var args = arguments;
for (var i = funcs.length-1; i >= 0; i--) {
args = [funcs[i].apply(this, args)];
}
return args[0];
};
},
// Can only unique arrays of homogeneous primitives, e.g. an array of only strings, an array of only booleans, or an array of only numerics
uniqueArray: function(array) {
var u = {}, a = [];
for (var i = 0, l = array.length; i < l; ++i) {
if (u.hasOwnProperty(array[i])) {
continue;
}
a.push(array[i]);
u[array[i]] = 1;
}
return a;
},
debounce: function(func, wait, immediate) {
if (typeof wait != 'number') {
wait = DEFAULT_INTERVAL;
}
var timeout, result;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
}
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
}
return result;
};
},
throttle: function(func, wait) {
if (typeof wait != 'number') {
wait = DEFAULT_INTERVAL;
}
var context, args, timeout, throttling, more, result;
var whenDone = this.debounce(function(){
more = throttling = false;
}, wait);
return function() {
context = this; args = arguments;
var later = function() {
timeout = null;
if (more) {
result = func.apply(context, args);
}
whenDone();
};
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (throttling) {
more = true;
} else {
throttling = true;
result = func.apply(context, args);
}
whenDone();
return result;
};
},
countThen: function(num, base) {
return function() {
if (!--num) { return base.apply(this, arguments); }
};
},
delegate: function(rules) {
return function(e, data) {
var target = $(e.target), parent;
Object.keys(rules).forEach(function(selector) {
if (!e.isPropagationStopped() && (parent = target.closest(selector)).length) {
data = data || {};
data.el = parent[0];
return rules[selector].apply(this, [e, data]);
}
}, this);
};
},
// ensures that a function will only be called once.
// usage:
// will only create the application once
// var initialize = utils.once(createApplication)
// initialize();
// initialize();
//
// will only delete a record once
// var myHanlder = function () {
// $.ajax({type: 'DELETE', url: 'someurl.com', data: {id: 1}});
// };
// this.on('click', utils.once(myHandler));
//
once: function(func) {
var ran, result;
return function() {
if (ran) {
return result;
}
ran = true;
result = func.apply(this, arguments);
return result;
};
}
};
return utils;
}
);
Loading…
Cancel
Save