gulp-js-encrypt
Version:
1,674 lines (1,449 loc) • 54.3 kB
JavaScript
/*
base2 - copyright 2007-2009, Dean Edwards
http://code.google.com/p/base2/
http://www.opensource.org/licenses/mit-license.php
Contributors:
Doeke Zanstra
*/
// timestamp: Wed, 23 Sep 2009 19:38:55
var base2 = {
name: "base2",
version: "1.1 (alpha1)",
exports:
"Base,Package,Abstract,Module,Enumerable,Map,Collection,RegGrp," +
"Undefined,Null,This,True,False,assignID,detect,global",
namespace: ""
};
new function(_no_shrink_) { /////////////// BEGIN: CLOSURE ///////////////
// =========================================================================
// base2/header.js
// =========================================================================
/*@cc_on @*/
var Undefined = K(), Null = K(null), True = K(true), False = K(false), This = function(){return this};
// var global = This(), base2 = global.base2;
// private
var _IGNORE = K(),
_FORMAT = /%([1-9])/g,
_LTRIM = /^\s\s*/,
_RTRIM = /\s\s*$/,
_RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g, // safe regular expressions
_BASE = /try/.test(detect) ? /\bbase\b/ : /.*/, // some platforms don't allow decompilation
_HIDDEN = ["constructor", "toString"], // only override these when prototyping
_MSIE_NATIVE_FUNCTION = detect("(jscript)") ?
new RegExp("^" + rescape(isNaN).replace(/isNaN/, "\\w+") + "$") : {test: False},
_counter = 1,
_slice = Array.prototype.slice;
_Function_forEach(); // make sure this is initialised
function assignID(object, name) {
// Assign a unique ID to an object.
if (!name) name = object.nodeType == 1 ? "uniqueID" : "base2ID";
if (!object[name]) object[name] = "b2_" + _counter++;
return object[name];
};
// =========================================================================
// base2/Base.js
// =========================================================================
// http://dean.edwards.name/weblog/2006/03/base/
var _subclass = function(_instance, _static) {
// Build the prototype.
base2.__prototyping = this.prototype;
var _prototype = new this;
if (_instance) extend(_prototype, _instance);
_prototype.base = function() {
// call this method from any other method to invoke that method's ancestor
};
delete base2.__prototyping;
// Create the wrapper for the constructor function.
var _constructor = _prototype.constructor;
function _class() {
// Don't call the constructor function when prototyping.
if (!base2.__prototyping) {
if (this.constructor == _class || this.__constructing) {
// Instantiation.
this.__constructing = true;
_constructor.apply(this, arguments);
delete this.__constructing;
} else {
// Casting.
return extend(arguments[0], _prototype);
}
}
return this;
};
_prototype.constructor = _class;
// Build the static interface.
for (var i in Base) _class[i] = this[i];
if (_static) extend(_class, _static);
_class.ancestor = this;
_class.ancestorOf = Base.ancestorOf;
_class.base = _prototype.base;
_class.prototype = _prototype;
if (_class.init) _class.init();
// introspection (removed when packed)
;;; _class["#implements"] = [];
;;; _class["#implemented_by"] = [];
return _class;
};
var Base = _subclass.call(Object, {
constructor: function() {
if (arguments.length > 0) {
this.extend(arguments[0]);
}
},
extend: delegate(extend),
toString: function() {
if (this.constructor.toString == Function.prototype.toString) {
return "[object base2.Base]";
} else {
return "[object " + String2.slice(this.constructor, 1, -1) + "]";
}
}
}, Base = {
ancestorOf: function(klass) {
return _ancestorOf(this, klass);
},
extend: _subclass,
forEach: function(object, block, context) {
_Function_forEach(this, object, block, context);
},
implement: function(source) {
if (typeof source == "function") {
;;; if (_ancestorOf(Base, source)) {
// introspection (removed when packed)
;;; this["#implements"].push(source);
;;; source["#implemented_by"].push(this);
;;; }
source = source.prototype;
}
// Add the interface using the extend() function.
extend(this.prototype, source);
return this;
}
});
// =========================================================================
// base2/Package.js
// =========================================================================
var Package = Base.extend({
constructor: function(_private, _public) {
var pkg = this;
pkg.extend(_public);
if (pkg.name && pkg.name != "base2") {
if (_public.parent === undefined) pkg.parent = base2;
if (pkg.parent) pkg.parent.addName(pkg.name, pkg);
pkg.namespace = format("var %1=%2;", pkg.name, String2.slice(pkg, 1, -1));
}
if (_private) {
// This next line gets round a bug in old Mozilla browsers
var jsNamespace = base2.js ? base2.js.namespace : "";
// This string should be evaluated immediately after creating a Package object.
var namespace = "var base2=(function(){return this.base2})(),_private=base2.toString;" + base2.namespace + jsNamespace;
var imports = csv(pkg.imports), name;
for (var i = 0; name = imports[i]; i++) {
var ns = lookup(name) || lookup("js." + name);
if (!ns) throw new ReferenceError(format("Object not found: '%1'.", name));
namespace += ns.namespace;
}
_private.init = function() {
if (pkg.init) pkg.init();
};
_private.imports = namespace + lang.namespace + "this.init();";
// This string should be evaluated after you have created all of the objects
// that are being exported.
namespace = "";
var exports = csv(pkg.exports);
for (var i = 0; name = exports[i]; i++) {
var fullName = pkg.name + "." + name;
pkg.namespace += "var " + name + "=" + fullName + ";";
namespace += "if(!" + fullName + ")" + fullName + "=" + name + ";";
}
_private.exports = namespace + "this._label_" + pkg.name + "();";
// give objects and classes pretty toString methods
var packageName = String2.slice(pkg, 1, -1);
_private["_label_" + pkg.name] = function() {
for (var name in pkg) {
var object = pkg[name];
if (object && object.ancestorOf == Base.ancestorOf && name != "constructor") { // it's a class
object.toString = K("[" + packageName + "." + name + "]");
}
}
};
}
function lookup(names) {
names = names.split(".");
var value = base2, i = 0;
while (value && names[i] != null) {
value = value[names[i++]];
}
return value;
};
},
exports: "",
imports: "",
name: "",
namespace: "",
parent: null,
addName: function(name, value) {
if (!this[name]) {
this[name] = value;
this.exports += "," + name;
this.namespace += format("var %1=%2.%1;", name, this.name);
if (value && value.ancestorOf == Base.ancestorOf && name != "constructor") { // it's a class
value.toString = K("[" + String2.slice(this, 1, -1) + "." + name + "]");
}
}
},
addPackage: function(name) {
this.addName(name, new Package(null, {name: name, parent: this}));
},
toString: function() {
return format("[%1]", this.parent ? String2.slice(this.parent, 1, -1) + "." + this.name : this.name);
}
});
// =========================================================================
// base2/Abstract.js
// =========================================================================
// Not very exciting this.
var Abstract = Base.extend({
constructor: function() {
throw new TypeError("Abstract class cannot be instantiated.");
}
});
// =========================================================================
// base2/Module.js
// =========================================================================
var _moduleCount = 0;
var Module = Abstract.extend(null, {
namespace: "",
extend: function(_interface, _static) {
// Extend a module to create a new module.
var module = this.base();
var index = _moduleCount++;
module.namespace = "";
module.partial = this.partial;
module.toString = K("[base2.Module[" + index + "]]");
Module[index] = module;
// Inherit class methods.
module.implement(this);
// Implement module (instance AND static) methods.
if (_interface) module.implement(_interface);
// Implement static properties and methods.
if (_static) {
extend(module, _static);
if (module.init) module.init();
}
return module;
},
forEach: function(block, context) {
_Function_forEach (Module, this.prototype, function(method, name) {
if (typeOf(method) == "function") {
block.call(context, this[name], name, this);
}
}, this);
},
implement: function(_interface) {
var module = this;
var id = module.toString().slice(1, -1);
if (typeof _interface == "function") {
if (!_ancestorOf(_interface, module)) {
this.base(_interface);
}
if (_ancestorOf(Module, _interface)) {
// Implement static methods.
for (var name in _interface) {
if (typeof module[name] == "undefined") {
var property = _interface[name];
if (typeof property == "function" && property.call && _interface.prototype[name]) {
property = _createStaticModuleMethod(_interface, name);
}
module[name] = property;
}
}
module.namespace += _interface.namespace.replace(/base2\.Module\[\d+\]/g, id);
}
} else {
// Add static interface.
extend(module, _interface);
// Add instance interface.
_extendModule(module, _interface);
}
return module;
},
partial: function() {
var module = Module.extend();
var id = module.toString().slice(1, -1);
// partial methods are already bound so remove the binding to speed things up
module.namespace = this.namespace.replace(/(\w+)=b[^\)]+\)/g, "$1=" + id + ".$1");
this.forEach(function(method, name) {
module[name] = partial(bind(method, module));
});
return module;
}
});
Module.prototype.base =
Module.prototype.extend = _IGNORE;
function _extendModule(module, _interface) {
var proto = module.prototype;
var id = module.toString().slice(1, -1);
for (var name in _interface) {
var property = _interface[name], namespace = "";
if (name.indexOf("@") == 0) { // object detection
if (detect(name.slice(1))) _extendModule(module, property);
} else if (!proto[name]) {
if (name == name.toUpperCase()) {
namespace = "var " + name + "=" + id + "." + name + ";";
} else if (typeof property == "function" && property.call) {
namespace = "var " + name + "=base2.lang.bind('" + name + "'," + id + ");";
proto[name] = _createModuleMethod(module, name);
;;; proto[name]._module = module; // introspection
}
if (module.namespace.indexOf(namespace) == -1) {
module.namespace += namespace;
}
}
}
};
function _createStaticModuleMethod(module, name) {
return function() {
return module[name].apply(module, arguments);
};
};
function _createModuleMethod(module, name) {
return function() {
var args = _slice.call(arguments);
args.unshift(this);
return module[name].apply(module, args);
};
};
// =========================================================================
// base2/Enumerable.js
// =========================================================================
var Enumerable = Module.extend({
every: function(object, test, context) {
var result = true;
try {
forEach (object, function(value, key) {
result = test.call(context, value, key, object);
if (!result) throw StopIteration;
});
} catch (error) {
if (error != StopIteration) throw error;
}
return !!result; // cast to boolean
},
filter: function(object, test, context) {
var i = 0;
return this.reduce(object, function(result, value, key) {
if (test.call(context, value, key, object)) {
result[i++] = value;
}
return result;
}, []);
},
invoke: function(object, method) {
// Apply a method to each item in the enumerated object.
var args = _slice.call(arguments, 2);
return this.map(object, typeof method == "function" ? function(item) {
return item == null ? undefined : method.apply(item, args);
} : function(item) {
return item == null ? undefined : item[method].apply(item, args);
});
},
map: function(object, block, context) {
var result = [], i = 0;
forEach (object, function(value, key) {
result[i++] = block.call(context, value, key, object);
});
return result;
},
pluck: function(object, key) {
return this.map(object, function(item) {
return item == null ? undefined : item[key];
});
},
reduce: function(object, block, result, context) {
var initialised = arguments.length > 2;
forEach (object, function(value, key) {
if (initialised) {
result = block.call(context, result, value, key, object);
} else {
result = value;
initialised = true;
}
});
return result;
},
some: function(object, test, context) {
return !this.every(object, not(test), context);
}
});
// =========================================================================
// base2/Map.js
// =========================================================================
// http://wiki.ecmascript.org/doku.php?id=proposals:dictionary
var _HASH = "#";
var Map = Base.extend({
constructor: function(values) {
if (values) this.merge(values);
},
clear: function() {
for (var key in this) if (key.indexOf(_HASH) == 0) {
delete this[key];
}
},
copy: function() {
base2.__prototyping = true; // not really prototyping but it stops [[construct]] being called
var copy = new this.constructor;
delete base2.__prototyping;
for (var i in this) if (this[i] !== copy[i]) {
copy[i] = this[i];
}
return copy;
},
forEach: function(block, context) {
for (var key in this) if (key.indexOf(_HASH) == 0) {
block.call(context, this[key], key.slice(1), this);
}
},
get: function(key) {
return this[_HASH + key];
},
getKeys: function() {
return this.map(II);
},
getValues: function() {
return this.map(I);
},
// Ancient browsers throw an error if we use "in" as an operator.
has: function(key) {
key = _HASH + key;
/*@if (@_jscript_version < 5.5)
return this[key] !== undefined || $Legacy.has(this, key);
@else @*/
return key in this;
/*@end @*/
},
merge: function(values /*, value1, value2, .. ,valueN */) {
var put = flip(this.put);
forEach (arguments, function(values) {
forEach (values, put, this);
}, this);
return this;
},
put: function(key, value) {
// create the new entry (or overwrite the old entry).
this[_HASH + key] = value;
return value;
},
remove: function(key) {
delete this[_HASH + key];
},
size: function() {
// this is expensive because we are not storing the keys
var size = 0;
for (var key in this) if (key.indexOf(_HASH) == 0) size++;
return size;
},
union: function(values) {
return this.merge.apply(this.copy(), arguments);
}
});
Map.implement(Enumerable);
Map.prototype.filter = function(test, context) {
return this.reduce(function(result, value, key) {
if (!test.call(context, value, key, this)) {
result.remove(key);
}
return result;
}, this.copy(), this);
};
// =========================================================================
// base2/Collection.js
// =========================================================================
// A Map that is more array-like (accessible by index).
// Collection classes have a special (optional) property: Item
// The Item property points to a constructor function.
// Members of the collection must be an instance of Item.
// The static create() method is responsible for all construction of collection items.
// Instance methods that add new items (add, put, insertAt, putAt) pass *all* of their arguments
// to the static create() method. If you want to modify the way collection items are
// created then you only need to override this method for custom collections.
var _KEYS = "~";
var Collection = Map.extend({
constructor: function(values) {
this[_KEYS] = new Array2;
this.base(values);
},
add: function(key, item) {
// Duplicates not allowed using add().
// But you can still overwrite entries using put().
if (this.has(key)) throw "Duplicate key '" + key + "'.";
return this.put.apply(this, arguments);
},
clear: function() {
this.base();
this[_KEYS].length = 0;
},
copy: function() {
var copy = this.base();
copy[_KEYS] = this[_KEYS].copy();
return copy;
},
forEach: function(block, context) {
var keys = this[_KEYS].concat();
var length = keys.length;
for (var i = 0; i < length; i++) {
block.call(context, this[_HASH + keys[i]], keys[i], this);
}
},
getAt: function(index) {
var key = this[_KEYS].item(index);
return (key === undefined) ? undefined : this[_HASH + key];
},
getKeys: function() {
return this[_KEYS].copy();
},
indexOf: function(key) {
return this[_KEYS].indexOf(String(key));
},
insertAt: function(index, key, item) {
if (this[_KEYS].item(index) == null) throw "Index out of bounds.";
if (this.has(key)) throw "Duplicate key '" + key + "'.";
this[_KEYS].insertAt(index, String(key));
this[_HASH + key] = null; // placeholder
return this.put.apply(this, _slice.call(arguments, 1));
},
item: function(keyOrIndex) {
return this[typeof keyOrIndex == "number" ? "getAt" : "get"](keyOrIndex);
},
put: function(key, item) {
var klass = this.constructor;
if (klass.Item && !instanceOf(item, klass.Item)) {
item = klass.create.apply(klass, arguments);
}
if (!this.has(key)) {
this[_KEYS].push(String(key));
}
this[_HASH + key] = item;
return item;
},
putAt: function(index, item) {
arguments[0] = this[_KEYS].item(index);
if (arguments[0] == null) throw "Index out of bounds.";
return this.put.apply(this, arguments);
},
remove: function(key) {
// The remove() method of the Array object can be slow so check if the key exists first.
if (this.has(key)) {
this[_KEYS].remove(String(key));
delete this[_HASH + key];
}
},
removeAt: function(index) {
var key = this[_KEYS].item(index);
if (key !== undefined) {
this[_KEYS].removeAt(index);
delete this[_HASH + key];
}
},
reverse: function() {
this[_KEYS].reverse();
return this;
},
size: function() {
return this[_KEYS].length;
},
slice: function(start, end) {
var sliced = this.copy();
if (arguments.length > 0) {
var keys = this[_KEYS], removed = keys;
sliced[_KEYS] = Array2(_slice.apply(keys, arguments));
if (sliced[_KEYS].length) {
removed = removed.slice(0, start);
if (arguments.length > 1) {
removed = removed.concat(keys.slice(end));
}
}
for (var i = 0; i < removed.length; i++) {
delete sliced[_HASH + removed[i]];
}
}
return sliced;
},
sort: function(compare) { // optimised (refers to _HASH)
if (compare) {
this[_KEYS].sort(bind(function(key1, key2) {
return compare(this[_HASH + key1], this[_HASH + key2], key1, key2);
}, this));
} else this[_KEYS].sort();
return this;
},
toString: function() {
return "(" + (this[_KEYS] || "") + ")";
}
}, {
Item: null, // If specified, all members of the collection must be instances of Item.
create: function(key, item) {
return this.Item ? new this.Item(key, item) : item;
},
extend: function(_instance, _static) {
var klass = this.base(_instance);
klass.create = this.create;
if (_static) extend(klass, _static);
if (!klass.Item) {
klass.Item = this.Item;
} else if (typeof klass.Item != "function") {
klass.Item = (this.Item || Base).extend(klass.Item);
}
if (klass.init) klass.init();
return klass;
}
});
// =========================================================================
// base2/RegGrp.js
// =========================================================================
// A collection of regular expressions and their associated replacement values.
// A Base class for creating parsers.
var _RG_BACK_REF = /\\(\d+)/g,
_RG_ESCAPE_CHARS = /\\./g,
_RG_ESCAPE_BRACKETS = /\(\?[:=!]|\[[^\]]+\]/g,
_RG_BRACKETS = /\(/g,
_RG_LOOKUP = /\$(\d+)/,
_RG_LOOKUP_SIMPLE = /^\$\d+$/;
var RegGrp = Collection.extend({
constructor: function(values, ignoreCase) {
this.base(values);
this.ignoreCase = !!ignoreCase;
},
ignoreCase: false,
exec: function(string, override) { // optimised (refers to _HASH/_KEYS)
string += ""; // type-safe
var items = this, keys = this[_KEYS];
if (!keys.length) return string;
if (override == RegGrp.IGNORE) override = 0;
return string.replace(new RegExp(this, this.ignoreCase ? "gi" : "g"), function(match) {
var item, offset = 1, i = 0;
// Loop through the RegGrp items.
while ((item = items[_HASH + keys[i++]])) {
var next = offset + item.length + 1;
if (arguments[offset]) { // do we have a result?
var replacement = override == null ? item.replacement : override;
switch (typeof replacement) {
case "function":
return replacement.apply(items, _slice.call(arguments, offset, next));
case "number":
return arguments[offset + replacement];
default:
return replacement;
}
}
offset = next;
}
return match;
});
},
insertAt: function(index, expression, replacement) {
if (instanceOf(expression, RegExp)) {
arguments[1] = expression.source;
}
return this.base.apply(this, arguments);
},
test: function(string) {
// The slow way to do it. Hopefully, this isn't called too often. :-)
return this.exec(string) != string;
},
toString: function() {
var offset = 1;
return "(" + this.map(function(item) {
// Fix back references.
var expression = (item + "").replace(_RG_BACK_REF, function(match, index) {
return "\\" + (offset + Number(index));
});
offset += item.length + 1;
return expression;
}).join(")|(") + ")";
}
}, {
IGNORE: "$0",
init: function() {
forEach ("add,get,has,put,remove".split(","), function(name) {
this[name] = _override(this, name, function(expression) {
if (instanceOf(expression, RegExp)) {
arguments[0] = expression.source;
}
return this.base.apply(this, arguments);
});
}, this.prototype);
},
Item: {
constructor: function(expression, replacement) {
if (replacement == null) replacement = RegGrp.IGNORE;
else if (replacement.replacement != null) replacement = replacement.replacement;
else if (typeof replacement != "function") replacement = String(replacement);
// does the pattern use sub-expressions?
if (typeof replacement == "string" && _RG_LOOKUP.test(replacement)) {
// a simple lookup? (e.g. "$2")
if (_RG_LOOKUP_SIMPLE.test(replacement)) {
// store the index (used for fast retrieval of matched strings)
replacement = parseInt(replacement.slice(1), 10);
} else { // a complicated lookup (e.g. "Hello $2 $1")
// build a function to do the lookup
// Improved version by Alexei Gorkov:
var Q = '"';
replacement = replacement
.replace(/\\/g, "\\\\")
.replace(/"/g, "\\x22")
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r")
.replace(/\$(\d+)/g, Q + "+(arguments[$1]||" + Q+Q + ")+" + Q)
.replace(/(['"])\1\+(.*)\+\1\1$/, "$1");
replacement = new Function("return " + Q + replacement + Q);
}
}
this.length = RegGrp.count(expression);
this.replacement = replacement;
this.toString = K(expression + "");
},
disabled: false,
length: 0,
replacement: ""
},
count: function(expression) {
// Count the number of sub-expressions in a RegExp/RegGrp.Item.
expression = (expression + "").replace(_RG_ESCAPE_CHARS, "").replace(_RG_ESCAPE_BRACKETS, "");
return match(expression, _RG_BRACKETS).length;
}
});
// =========================================================================
// lang/package.js
// =========================================================================
var lang = {
name: "lang",
version: base2.version,
exports: "assert,assertArity,assertType,bind,copy,extend,forEach,format,instanceOf,match,pcopy,rescape,trim,typeOf",
namespace: "" // Fixed later.
};
// =========================================================================
// lang/assert.js
// =========================================================================
function assert(condition, message, ErrorClass) {
if (!condition) {
throw new (ErrorClass || Error)(message || "Assertion failed.");
}
};
function assertArity(args, arity, message) {
if (arity == null) arity = args.callee.length; //-@DRE
if (args.length < arity) {
throw new SyntaxError(message || "Not enough arguments.");
}
};
function assertType(object, type, message) {
if (type && (typeof type == "function" ? !instanceOf(object, type) : typeOf(object) != type)) {
throw new TypeError(message || "Invalid type.");
}
};
// =========================================================================
// lang/copy.js
// =========================================================================
function copy(object) { // A quick copy.
var copy = {};
for (var i in object) {
copy[i] = object[i];
}
return copy;
};
function pcopy(object) { // Prototype-base copy.
// Doug Crockford / Richard Cornford
_dummy.prototype = object;
return new _dummy;
};
function _dummy(){};
// =========================================================================
// lang/extend.js
// =========================================================================
function extend(object, source) { // or extend(object, key, value)
if (object && source) {
var useProto = base2.__prototyping;
if (arguments.length > 2) { // Extending with a key/value pair.
var key = source;
source = {};
source[key] = arguments[2];
useProto = true;
}
//var proto = (typeof source == "function" ? Function : Object).prototype;
var proto = global[(typeof source == "function" ? "Function" : "Object")].prototype;
// Add constructor, toString etc
if (useProto) {
var i = _HIDDEN.length, key;
while ((key = _HIDDEN[--i])) {
var value = source[key];
if (value != proto[key]) {
if (_BASE.test(value)) {
object[key] = _override(object, key, value);
} else {
object[key] = value;
}
}
}
}
// Copy each of the source object's properties to the target object.
for (key in source) {
if (typeof proto[key] == "undefined") {
value = source[key];
// Object detection.
if (key.indexOf("@") == 0) {
if (detect(key.slice(1))) extend(object, value);
} else if (value != _IGNORE) {
// Check for method overriding.
var ancestor = object[key];
if (ancestor && typeof value == "function") {
if (value != ancestor) {
if (_BASE.test(value)) {
object[key] = _override(object, key, value);
} else {
value.ancestor = ancestor;
object[key] = value;
}
}
} else {
object[key] = value;
}
}
}
}
}
// http://www.hedgerwow.com/360/dhtml/ie6_memory_leak_fix/
/*@if (@_jscript) {
try {
return object;
} finally {
object = null;
}
}
@else @*/
return object;
/*@end @*/
};
function _ancestorOf(ancestor, fn) {
// Check if a function is in another function's inheritance chain.
while (fn) {
if (!fn.ancestor) return false;
fn = fn.ancestor;
if (fn == ancestor) return true;
}
return false;
};
function _override(object, name, method) {
// Return a method that overrides an existing method.
var ancestor = object[name];
var superObject = base2.__prototyping; // late binding for prototypes
if (superObject && ancestor != superObject[name]) superObject = null;
function _base() {
var previous = this.base;
this.base = superObject ? superObject[name] : ancestor;
var returnValue = method.apply(this, arguments);
this.base = previous;
return returnValue;
};
_base.method = method;
_base.ancestor = ancestor;
// introspection (removed when packed)
;;; _base.toString = K(method + "");
return _base;
};
// =========================================================================
// lang/forEach.js
// =========================================================================
// http://dean.edwards.name/weblog/2006/07/enum/
if (typeof StopIteration == "undefined") {
StopIteration = new Error("StopIteration");
}
function forEach(object, block, context, fn) {
if (object == null) return;
if (!fn) {
if (typeof object == "function" && object.call) {
// Functions are a special case.
fn = Function;
} else if (typeof object.forEach == "function" && object.forEach != forEach) {
// The object implements a custom forEach method.
object.forEach(block, context);
return;
} else if (typeof object.length == "number") {
// The object is array-like.
_Array_forEach(object, block, context);
return;
}
}
_Function_forEach(fn || Object, object, block, context);
};
forEach.csv = function(string, block, context) {
forEach (csv(string), block, context);
};
forEach.detect = function(object, block, context) {
var filter = function(value, key) {
if (key.indexOf("@") == 0) { // object detection
if (detect(key.slice(1))) forEach (value, filter);
} else block.call(context, value, key, object);
};
forEach (object, filter);
};
// These are the two core enumeration methods. All other forEach methods
// eventually call one of these two.
function _Array_forEach(array, block, context) {
if (array == null) array = global;
var length = array.length || 0, i; // preserve length
if (typeof array == "string") {
for (i = 0; i < length; i++) {
block.call(context, array.charAt(i), i, array);
}
} else { // Cater for sparse arrays.
for (i = 0; i < length; i++) {
/*@if (@_jscript_version < 5.2)
if (array[i] !== undefined && $Legacy.has(array, i))
@else @*/
if (i in array)
/*@end @*/
block.call(context, array[i], i, array);
}
}
};
function _Function_forEach(fn, object, block, context) {
// http://code.google.com/p/base2/issues/detail?id=10
// Run the test for Safari's buggy enumeration.
var Temp = function(){this.i=1};
Temp.prototype = {i:1};
var count = 0;
for (var i in new Temp) count++;
// Overwrite the main function the first time it is called.
_Function_forEach = count > 1 ? function(fn, object, block, context) {
// Safari fix (pre version 3)
var processed = {};
for (var key in object) {
if (!processed[key] && fn.prototype[key] === undefined) {
processed[key] = true;
block.call(context, object[key], key, object);
}
}
} : function(fn, object, block, context) {
// Enumerate an object and compare its keys with fn's prototype.
for (var key in object) {
if (typeof fn.prototype[key] == "undefined") {
block.call(context, object[key], key, object);
}
}
};
_Function_forEach(fn, object, block, context);
};
// =========================================================================
// lang/instanceOf.js
// =========================================================================
function instanceOf(object, klass) {
// Handle exceptions where the target object originates from another frame.
// This is handy for JSON parsing (amongst other things).
if (typeof klass != "function") {
throw new TypeError("Invalid 'instanceOf' operand.");
}
if (object == null) return false;
// COM objects don't have a constructor
/*@if (@_jscript)
if (typeof object.constructor != "function") {
return klass == Object;
}
/*@end @*/
if (object.constructor == klass) return true;
if (klass.ancestorOf) return klass.ancestorOf(object.constructor);
/*@if (@_jscript_version < 5.1)
// do nothing
@else @*/
if (object instanceof klass) return true;
/*@end @*/
// If the class is a base2 class then it would have passed the test above.
if (Base.ancestorOf == klass.ancestorOf) return false;
// base2 objects can only be instances of Object.
if (Base.ancestorOf == object.constructor.ancestorOf) return klass == Object;
switch (klass) {
case Array:
return _toString.call(object) == "[object Array]";
case Date:
return _toString.call(object) == "[object Date]";
case RegExp:
return _toString.call(object) == "[object RegExp]";
case Function:
return typeOf(object) == "function";
case String:
case Number:
case Boolean:
return typeOf(object) == typeof klass.prototype.valueOf();
case Object:
return true;
}
return false;
};
var _toString = Object.prototype.toString;
// =========================================================================
// lang/typeOf.js
// =========================================================================
// http://wiki.ecmascript.org/doku.php?id=proposals:typeof
function typeOf(object) {
var type = typeof object;
switch (type) {
case "object":
return object == null
? "null"
: typeof object.constructor != "function" // COM object
? _MSIE_NATIVE_FUNCTION.test(object)
? "function"
: type
: _toString.call(object) == "[object Date]"
? type
: typeof object.constructor.prototype.valueOf(); // underlying type
case "function":
return typeof object.call == "function" ? type : "object";
default:
return type;
}
};
// =========================================================================
// js/package.js
// =========================================================================
var js = {
name: "js",
version: base2.version,
exports: "Array2,Date2,Function2,String2",
namespace: "", // fixed later
bind: function(host) {
var top = global;
global = host;
forEach.csv(this.exports, function(name2) {
var name = name2.slice(0, -1);
extend(host[name], this[name2]);
this[name2](host[name].prototype); // cast
}, this);
global = top;
return host;
}
};
function _createObject2(Native, constructor, generics, extensions) {
// Clone native objects and extend them.
// Create a Module that will contain all the new methods.
var INative = Module.extend();
var id = INative.toString().slice(1, -1);
// http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6#Array_and_String_generics
forEach.csv(generics, function(name) {
INative[name] = unbind(Native.prototype[name]);
INative.namespace += format("var %1=%2.%1;", name, id);
});
forEach (_slice.call(arguments, 3), INative.implement, INative);
// create a faux constructor that augments the native object
var Native2 = function() {
return INative(this.constructor == INative ? constructor.apply(null, arguments) : arguments[0]);
};
Native2.prototype = INative.prototype;
// Remove methods that are already implemented.
for (var name in INative) {
var method = Native[name];
if (method && name != "prototype" && name != "toString" && method != Function.prototype[name]) {
INative[name] = method;
delete INative.prototype[name];
}
Native2[name] = INative[name];
}
Native2.ancestor = Object;
delete Native2.extend;
// remove "lang.bind.."
Native2.namespace = Native2.namespace.replace(/(var (\w+)=)[^,;]+,([^\)]+)\)/g, "$1$3.$2");
return Native2;
};
// =========================================================================
// js/~/Date.js
// =========================================================================
// Fix Date.get/setYear() (IE5-7)
if ((new Date).getYear() > 1900) {
Date.prototype.getYear = function() {
return this.getFullYear() - 1900;
};
Date.prototype.setYear = function(year) {
return this.setFullYear(year + 1900);
};
}
// https://bugs.webkit.org/show_bug.cgi?id=9532
var _testDate = new Date(Date.UTC(2006, 1, 20));
_testDate.setUTCDate(15);
if (_testDate.getUTCHours() != 0) {
forEach.csv("FullYear,Month,Date,Hours,Minutes,Seconds,Milliseconds", function(type) {
extend(Date.prototype, "setUTC" + type, function() {
var value = this.base.apply(this, arguments);
if (value >= 57722401000) {
value -= 3600000;
this.setTime(value);
}
return value;
});
});
}
// =========================================================================
// js/~/Function.js
// =========================================================================
// Some browsers don't define this.
Function.prototype.prototype = {};
// =========================================================================
// js/~/String.js
// =========================================================================
// A KHTML bug.
if ("".replace(/^/, K("$$")) == "$") {
extend(String.prototype, "replace", function(expression, replacement) {
if (typeof replacement == "function") {
var fn = replacement;
replacement = function() {
return String(fn.apply(null, arguments)).split("$").join("$$");
};
}
return this.base(expression, replacement);
});
}
// =========================================================================
// js/Array2.js
// =========================================================================
var Array2 = _createObject2(
Array,
Array,
"concat,join,pop,push,reverse,shift,slice,sort,splice,unshift", // generics
Enumerable, {
batch: function(array, block, timeout, oncomplete, context) {
var index = 0,
length = array.length;
var batch = function() {
var now = Date2.now(), start = now, k = 0;
while (index < length && (now - start < timeout)) {
block.call(context, array[index], index++, array);
if (k++ < 5 || k % 50 == 0) now = Date2.now();
}
if (index < length) {
setTimeout(batch, 10);
} else {
if (oncomplete) oncomplete.call(context);
}
};
setTimeout(batch, 1);
},
combine: function(keys, values) {
// Combine two arrays to make a hash.
if (!values) values = keys;
return Array2.reduce(keys, function(hash, key, index) {
hash[key] = values[index];
return hash;
}, {});
},
contains: function(array, item) {
return Array2.indexOf(array, item) != -1;
},
copy: function(array) {
var copy = _slice.call(array);
if (!copy.swap) Array2(copy); // cast to Array2
return copy;
},
flatten: function(array) {
var i = 0;
var flatten = function(result, item) {
if (Array2.like(item)) {
Array2.reduce(item, flatten, result);
} else {
result[i++] = item;
}
return result;
};
return Array2.reduce(array, flatten, []);
},
forEach: _Array_forEach,
indexOf: function(array, item, fromIndex) {
var length = array.length;
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, length + fromIndex);
}
for (var i = fromIndex; i < length; i++) {
if (array[i] === item) return i;
}
return -1;
},
insertAt: function(array, index, item) {
Array2.splice(array, index, 0, item);
},
item: function(array, index) {
if (index < 0) index += array.length; // starting from the end
return array[index];
},
lastIndexOf: function(array, item, fromIndex) {
var length = array.length;
if (fromIndex == null) {
fromIndex = length - 1;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, length + fromIndex);
}
for (var i = fromIndex; i >= 0; i--) {
if (array[i] === item) return i;
}
return -1;
},
map: function(array, block, context) {
var result = [];
_Array_forEach (array, function(item, index) {
result[index] = block.call(context, item, index, array);
});
return result;
},
remove: function(array, item) {
var index = Array2.indexOf(array, item);
if (index != -1) Array2.removeAt(array, index);
},
removeAt: function(array, index) {
Array2.splice(array, index, 1);
},
swap: function(array, index1, index2) {
if (index1 < 0) index1 += array.length; // starting from the end
if (index2 < 0) index2 += array.length;
var temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
return array;
}
}
);
Array2.forEach = _Array_forEach;
Array2.reduce = Enumerable.reduce; // Mozilla does not implement the thisObj argument
Array2.like = function(object) {
// is the object like an array?
return typeOf(object) == "object" && typeof object.length == "number";
};
// introspection (removed when packed)
;;; Enumerable["#implemented_by"].pop();
;;; Enumerable["#implemented_by"].push(Array2);
// =========================================================================
// js/Date2.js
// =========================================================================
// http://developer.mozilla.org/es4/proposals/date_and_time.html
// big, ugly, regular expression
var _DATE_PATTERN = /^((-\d+|\d{4,})(-(\d{2})(-(\d{2}))?)?)?T((\d{2})(:(\d{2})(:(\d{2})(\.(\d{1,3})(\d)?\d*)?)?)?)?(([+-])(\d{2})(:(\d{2}))?|Z)?$/;
var _DATE_PARTS = { // indexes to the sub-expressions of the RegExp above
FullYear: 2,
Month: 4,
Date: 6,
Hours: 8,
Minutes: 10,
Seconds: 12,
Milliseconds: 14
};
var _TIMEZONE_PARTS = { // idem, but without the getter/setter usage on Date object
Hectomicroseconds: 15, // :-P
UTC: 16,
Sign: 17,
Hours: 18,
Minutes: 20
};
//var _TRIM_ZEROES = /(((00)?:0+)?:0+)?\.0+$/;
//var _TRIM_TIMEZONE = /(T[0-9:.]+)$/;
var Date2 = _createObject2(
Date,
function(yy, mm, dd, h, m, s, ms) {
switch (arguments.length) {
case 0: return new Date;
case 1: return typeof yy == "string" ? new Date(Date2.parse(yy)) : new Date(yy.valueOf());
default: return new Date(yy, mm, arguments.length == 2 ? 1 : dd, h || 0, m || 0, s || 0, ms || 0);
}
}, "", {
toISOString: function(date) {
var string = "####-##-##T##:##:##.###";
for (var part in _DATE_PARTS) {
string = string.replace(/#+/, function(digits) {
var value = date["getUTC" + part]();
if (part == "Month") value++; // js month starts at zero
return ("000" + value).slice(-digits.length); // pad
});
}
//// remove trailing zeroes, and remove UTC timezone, when time's absent
//return string.replace(_TRIM_ZEROES, "").replace(_TRIM_TIMEZONE, "$1Z");
return string + "Z";
}
}
);
delete Date2.forEach;
Date2.now = function() {
return (new Date).valueOf(); // milliseconds since the epoch
};
Date2.parse = function(string, defaultDate) {
if (arguments.length > 1) {
assertType(defaultDate, "number", "Default date should be of type 'number'.")
}
// parse ISO date
var parts = match(string, _DATE_PATTERN);
if (parts.length) {
var month = parts[_DATE_PARTS.Month];
if (month) parts[_DATE_PARTS.Month] = String(month - 1); // js months start at zero
// round milliseconds on 3 digits
if (parts[_TIMEZONE_PARTS.Hectomicroseconds] >= 5) parts[_DATE_PARTS.Milliseconds]++;
var utc = parts[_TIMEZONE_PARTS.UTC] || parts[_TIMEZONE_PARTS.Hours] ? "UTC" : "";
var date = new Date(defaultDate || 0);
if (parts[_DATE_PARTS.Date]) date["set" + utc + "Date"](14);
for (var part in _DATE_PARTS) {
var value = parts[_DATE_PARTS[part]];
if (value) {
// set a date part
date["set" + utc + part](value);
// make sure that this setting does not overflow
if (date["get" + utc + part]() != parts[_DATE_PARTS[part]]) {
return NaN;
}
}
}
// timezone can be set, without time being available
// without a timezone, local timezone is respected
if (parts[_TIMEZONE_PARTS.Hours]) {
var hours = Number(parts[_TIMEZONE_PARTS.Sign] + parts[_TIMEZONE_PARTS.Hours]);
var minutes = Number(parts[_TIMEZONE_PARTS.Sign] + (parts[_TIMEZONE_PARTS.Minutes] || 0));
date.setUTCMinutes(date.getUTCMinutes() + (hours * 60) + minutes);
}
return date.valueOf();
} else {
return Date.parse(string);
}
};
// =========================================================================
// js/String2.js
// =========================================================================
var String2 = _createObject2(
String,
function(string) {
return new String(arguments.length == 0 ? "" : string);
},
"charAt,charCodeAt,concat,indexOf,lastIndexOf,match,replace,search,slice,split,substr,substring,toLowerCase,toUpperCase",
{
csv: csv,
format: format,
rescape: rescape,
trim: trim
}
);
delete String2.forEach;
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
function trim(string) {
return String(string).replace(_LTRIM, "").replace(_RTRIM, "");
};
function csv(string) {
return string ? (string + "").split(/\s*,\s*/) : [];
};
function format(string) {
// Replace %n with arguments[n].
// e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls");
// ==> "she sells sea shells"
// Only %1 - %9 supported.
var args = arguments;
var pattern = new RegExp("%([1-" + (arguments.length - 1) + "])", "g");
return (string + "").replace(pattern, function(match, index) {
return args[index];
});
};
function match(string, expression) {
// Same as String.match() except that this function will return an
// empty array if there is no match.
return (string + "").match(expression) || [];
};
function rescape(string) {
// Make a string safe for creating a RegExp.
return (string + "").replace(_RESCAPE, "\\$1");
};
// =========================================================================
// js/Function2.js
// =========================================================================
var Function2 = _createObject2(
Function,
Function,
"", {
I: I,
II: II,
K: K,
bind: bind,
compose: compose,
delegate: delegate,
flip: flip,
not: not,
partial: partial,
unbind: unbind
}
);
function I(i) { // Return first argument.
return i;
};
function II(i, ii) { // Return second argument.
return ii;
};
function K(k) {
return function() {
return k;
};
};
function bind(fn, context) {
var lateBound = typeof fn != "function";
if (arguments.length > 2) {
var args = _slice.call(arguments, 2);
return function() {
return (lateBound ? context[fn] : fn).apply(context, args.concat.apply(args, arguments));
};
} else { // Faster if there are no additional arguments.
return function() {
return (lateBound ? context[fn] : fn).apply(context, arguments);
};
}
};
function compose() {
var fns = _slice.call(arguments);
return function() {
var i = fns.length, result = fns[--i].apply(this, arguments);
while (i--) result = fns[i].call(this, result);
return result;
};
};
function delegate(fn, context) {
return function() {
var args = _slice.call(arguments);
args.unshift(this);
return fn.apply(context, args);
};
};
function flip(fn) {
return function() {
return fn.apply(this, Array2.swap(arguments, 0, 1));
};
};
function not(fn) {
return function() {
return !fn.apply(this, arguments);
};
};
function partial(fn) { // Based on Oliver Steele's version.
var args = _slice.call(arguments, 1);
return function() {
var specialised = args.concat(), i = 0, j = 0;
while (i < args.length && j < arguments.length) {
if (specialised[i] === undefined) specialised[i] = arguments[j++];
i++;
}
while (j < arguments.length) {
specialised[i++] = arguments[j++];
}
if (Array2.contains(specialised, undefined)) {
specialised.unshift(fn);
return partial.apply(null, specialised);
}
return fn.apply(this, specialised);
};
};
function unbind(fn) {
return function(context) {
return fn.apply(context, _slice.call(arguments, 1));
};
};
// =========================================================================
// base2/detect.js
// =========================================================================
function detect() {
// Two types of detection: