libcore
Version:
Kicks-start helpers for cross-browser libraries and different versions of nodejs
2,058 lines (1,640 loc) • 70.4 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.libcore = {})));
}(this, (function (exports) { 'use strict';
var global$1 = typeof global !== "undefined" ? global :
typeof self !== "undefined" ? self :
typeof window !== "undefined" ? window : {};
var ROOT = global$1;
var browser = isBrowser();
var nodeVersions = nodeVersion(browser);
var nodejs = nodeVersions && !!nodeVersions.node;
var userAgent = getUserAgent(browser,
nodeVersions);
var validSignature = hasValidSignature();
var ajax = ROOT.XMLHttpRequest || null;
var indexOfSupport = typeof Array.prototype.indexOf !== "undefined";
// detect browser
function isBrowser() {
var G = ROOT,
win = G.document,
doc = G,
result = !!doc && !!win &&
win.self === (doc.defaultView || doc.parentWindow);
// cleanup
G = win = doc = null;
return result;
}
// detect nodejs info
function nodeVersion(browser) {
var G = ROOT,
result = browser ?
false :
('process' in G && G.process.versions) || false;
G = null;
return result;
}
// detect userAgent
function getUserAgent(browser, nodeVersions) {
var G = ROOT,
result = 'Unknown',
proc = null;
if (browser) {
result = G.navigator.userAgent;
}
else if (nodeVersions && 'process' in G) {
proc = G.process;
result = (['Node ',
nodeVersions.node,
'(',
proc.platform,
'; V8 ',
nodeVersions.v8 || 'unknown',
'; arch ',
proc.arch,
')']).
join('');
}
G = proc = null;
return result;
}
function hasValidSignature() {
var toString = Object.prototype.toString,
objectSignature = '[object Object]';
return toString.call(null) !== objectSignature ||
toString.call(void(0)) !== objectSignature;
}
ROOT = null;
var detect = Object.freeze({
browser: browser,
nodeVersions: nodeVersions,
nodejs: nodejs,
userAgent: userAgent,
validSignature: validSignature,
ajax: ajax,
indexOfSupport: indexOfSupport
});
var OBJECT_SIGNATURE = '[object Object]';
var ARRAY_SIGNATURE = '[object Array]';
var NULL_SIGNATURE = '[object Null]';
var UNDEFINED_SIGNATURE = '[object Undefined]';
var NUMBER_SIGNATURE = '[object Number]';
var STRING_SIGNATURE = '[object String]';
var BOOLEAN_SIGNATURE = '[object Boolean]';
var METHOD_SIGNATURE = '[object Function]';
var DATE_SIGNATURE = '[object Date]';
var REGEX_SIGNATURE = '[object RegExp]';
var STRING = 'string';
var NUMBER = 'number';
var BOOLEAN = 'boolean';
var OBJECT = Object;
var O$1 = OBJECT.prototype;
var toString = O$1.toString;
var object = validSignature ? w3cIsObject : ieIsObject;
/** is object **/
function w3cIsObject(subject) {
return toString.call(subject) === OBJECT_SIGNATURE;
}
function ieIsObject(subject) {
return subject !== null &&
subject !== void(0) &&
toString.call(subject) === OBJECT_SIGNATURE;
}
/** is object signature **/
function signature(subject) {
if (subject === undefined) {
return UNDEFINED_SIGNATURE;
}
if (subject === null ||
(typeof subject === NUMBER && !isFinite(subject))) {
return NULL_SIGNATURE;
}
return toString.call(subject);
}
/** is native object **/
function nativeObject(subject) {
var O = OBJECT;
var constructor, result;
if (signature(subject) === OBJECT_SIGNATURE) {
constructor = subject.constructor;
// check constructor
if (O.hasOwnProperty.call(subject, 'constructor')) {
delete subject.constructor;
result = subject.constructor === O;
subject.constructor = constructor;
return result;
}
return constructor === O;
}
return false;
}
/** is string **/
function string(subject, allowEmpty) {
return (typeof subject === STRING ||
O$1.toString.call(subject) === STRING_SIGNATURE) &&
(allowEmpty === true || subject.length !== 0);
}
/** is number **/
function number(subject) {
return typeof subject === NUMBER && isFinite(subject);
}
/** is scalar **/
function scalar(subject) {
switch (typeof subject) {
case NUMBER: return isFinite(subject);
case BOOLEAN:
case STRING: return true;
}
return false;
}
/** is array **/
function array(subject, notEmpty) {
return toString.call(subject) === ARRAY_SIGNATURE &&
(notEmpty !== true || subject.length !== 0);
}
/** is function **/
function method(subject) {
return toString.call(subject) === METHOD_SIGNATURE;
}
/** is date **/
function date(subject) {
return toString.call(subject) === DATE_SIGNATURE;
}
/** is regexp **/
function regex(subject) {
return toString.call(subject) === REGEX_SIGNATURE;
}
/** is promise or thenable **/
function thenable(subject) {
// filter non-thenable scalar natives
switch (subject) {
case undefined:
case null:
case true:
case false: return false;
}
// filter scalar
switch (signature(subject)) {
case NUMBER_SIGNATURE:
case STRING_SIGNATURE:
case BOOLEAN_SIGNATURE:
case NULL_SIGNATURE:
case UNDEFINED_SIGNATURE: return false;
}
return 'then' in subject && method(subject.then);
}
/** is array-like iterable **/
function iterable(subject) {
var len;
// filter non-iterable scalar natives
switch (subject) {
case undefined:
case null:
case true:
case false:
case NaN: return false;
}
// try signature
switch (signature(subject)) {
case NUMBER_SIGNATURE:
case BOOLEAN_SIGNATURE:
// bogus js engines provides readonly "length" property to functions
case METHOD_SIGNATURE: return false;
case STRING_SIGNATURE:
case ARRAY_SIGNATURE: return true;
}
return 'length' in subject &&
number(len = subject.length) &&
len > -1;
}
function type(subject, isType) {
var len;
switch (isType) {
case "scalar":
switch (signature(subject)) {
case STRING_SIGNATURE:
case NUMBER_SIGNATURE:
case BOOLEAN_SIGNATURE: return true;
}
return false;
case "regexp":
case "regex":
isType = "RegExp";
break;
case "method":
isType = "Function";
break;
case "native":
case "nativeObject":
return nativeObject(subject);
}
if (typeof isType === STRING) {
len = isType.length;
if (len) {
return signature(subject) === '[object ' +
isType.charAt(0).toUpperCase() +
isType.substring(1, len) +
']';
}
}
return false;
}
/**
* @external libcore
*/
var Obj = Object;
var O = Obj.prototype;
var EACH = typeof Obj.getOwnPropertyNames === 'function' ?
es5each : es3each;
var OHasOwn = O.hasOwnProperty;
var ARRAY_INDEX_RE = /^[1-9][0-9]*|0$/;
function empty() {
}
function isValidObject(target) {
var signature$$1 = signature(target);
switch (signature$$1) {
case REGEX_SIGNATURE:
case DATE_SIGNATURE:
case ARRAY_SIGNATURE:
case OBJECT_SIGNATURE:
case METHOD_SIGNATURE: return signature$$1;
}
return false;
}
/**
* Assign properties of source Object to target Object
* @alias module:libcore.assign
* @param {Object} target - the target object
* @param {Object} source - the source object containing properties
* to be assigned to target object
* @param {Object} [defaults] - object containing default properties
* which will be assigned first to
* target before source.
* @param {Boolean} [ownedOnly] - only assign properties owned by "source"
* @returns {Object} target object from first parameter
*/
function apply(value, name) {
/*jshint validthis:true */
this[name] = value;
}
/**
* Relocate and rename properties of source Object into target Object.
*
* @name libcore.rehash
* @function
* @param {Object|Function} target - the target object
* @param {Object|Function} source - the source object containing properties
* to be relocated.
* @param {Object} access - the rename map object containing "renamed property"
* as map object's property name, and
* "source property name" as map object's
* property value. (e.g. { "newname": "from source" })
* @returns {Object} target object from first parameter
*/
function applyProperties(value, name) {
/*jshint validthis:true */
var target = this;
target[0][name] = target[1][value];
target = null;
}
function assignAll(target, source, defaults) {
var onAssign = apply,
eachProperty = EACH;
if (defaults) {
eachProperty(defaults, onAssign, target, false);
}
eachProperty(source, onAssign, target);
return target;
}
/**
* Iterates all iteratable property of an object calling "handler" parameter on
* each iteration.
* @name libcore.each
* @function
* @param {Object} subject
* @param {Function} handler - the callback of each iteration of
* "subject" object's property.
* @param {*} [scope] - "this" object to use inside the "handler" parameter
* @param {boolean} [hasown] - performs checking to only include
* source object property that is overridden
* (Object.protototype.hasOwnProperty() returns true)
* when this parameter is set to true.
* @returns {Object} The subject parameter
*/
function es3each(subject, handler, scope, hasown) {
var hasOwn = OHasOwn,
noChecking = hasown === false;
var name;
if (!isValidObject(subject)) {
throw new Error("Invalid [subject] parameter.");
}
if (arguments.length > 3 && typeof hasown !== 'boolean') {
throw new Error("Invalid [hasown] hasOwnProperty parameter.");
}
if (scope === void(0)) {
scope = null;
}
for (name in subject) {
if ((noChecking || hasOwn.call(subject, name)) &&
handler.call(scope, subject[name], name, subject) === false) {
break;
}
}
return subject;
}
function es5each(subject, handler, scope, hasown) {
var hasOwn = OHasOwn,
noChecking = hasown === false;
var names, name, c, l;
if (!isValidObject(subject)) {
throw new Error("Invalid [subject] parameter.");
}
if (arguments.length > 3 && typeof hasown !== 'boolean') {
throw new Error("Invalid [hasown] hasOwnProperty parameter.");
}
if (scope === void(0)) {
scope = null;
}
names = Obj.getOwnPropertyNames(subject);
for (c = -1, l = names.length; l--;) {
name = names[++c];
if ((noChecking || hasOwn.call(subject, name)) &&
handler.call(scope, subject[name], name, subject) === false) {
break;
}
}
return subject;
}
/**
* Checks if "subject" Object contains overridden property.
* The same symantics of Object.prototype.hasOwnProperty.
*
* @name libcore.contains
* @function
* @param {Object} subject
* @param {String} property - Property Name to inspect
* @returns {boolean} True if subject Object contains property and dirty.
* False if subject Object's property do not exist or not
* dirty.
*/
/**
* Clears Object properties. This method only deletes overridden properties and
* will not fill "undefined" to non-owned properties from its prototype.
* @name libcore.clear
* @function
* @param {Object} subject
* @returns {Object} subject parameter.
*/
function applyClear() {
delete arguments[2][arguments[1]];
}
function applyFillin(value, name) {
/* jshint validthis:true */
var target = this;
if (!contains(target, name)) {
target[name] = value;
}
target = null;
}
/**
* Builds instance of "Class" parameter without executing its constructor.
* @name libcore.instantiate
* @function
* @param {Function} Class
* @param {Object} overrides
* @returns {Object} Instance created from Class without executing
* its constructor.
*/
/**
* Deep compares two scalar, array, object, regex and date objects
* @name libcore.compare
* @function
* @param {*} object1
* @param {*} object2
* @returns {boolean} True if scalar, regex, date, object properties, or array
* items of object1 is identical to object2.
*/
function compareLookback(object1, object2, references) {
var isObject = object,
isArray = array,
isRegex = regex,
isDate = date,
onCompare = onEachCompareObject,
each = EACH,
me = compareLookback,
depth = references.length;
var len, context;
switch (true) {
// prioritize same object, same type comparison
case object1 === object2: return true;
// native object comparison
case isObject(object1):
if (!isObject(object2)) {
return false;
}
// check if object is in references
if (references.lastIndexOf(object1) !== -1 &&
references.lastIndexOf(object2) !== -1) {
return true;
}
// proceed
references[depth] = object1;
references[depth + 1] = object2;
context = [object2, references, true];
each(object1, onCompare, context);
if (!context[2]) {
return false;
}
context[0] = object1;
each(object2, onCompare, context);
if (!context[2]) {
return false;
}
references.length = depth;
return true;
// array comparison
case isArray(object1):
if (!isArray(object2)) {
return false;
}
// check references
if (references.lastIndexOf(object1) !== -1 &&
references.lastIndexOf(object2) !== -1) {
return true;
}
len = object1.length;
if (len !== object2.length) {
return false;
}
// proceed
references[depth] = object1;
references[depth + 1] = object2;
for (; len--;) {
if (!me(object1[len], object2[len], references)) {
return false;
}
}
references.length = depth;
return true;
// RegExp compare
case isRegex(object1):
return isRegex(object2) && object1.source === object2.source;
// Date compare
case isDate(object1):
return isDate(object2) && object1.toString() === object2.toString();
}
return false;
}
function onEachCompareObject(value, name) {
/* jshint validthis:true */
var context = this,
target = context[0],
result = name in target ?
compareLookback(value, target[name], context[1]) :
false;
context[2] = result;
return result;
}
/**
* Clones scalar, array, object, regex or date objects
* @name libcore.clone
* @function
* @param {*} data - scalar, array, object, regex or date object to clone.
* @param {boolean} [deep] - apply deep clone to object properties or
* array items.
* @returns {*} Cloned object based from data
*/
function cloneObject(data, parents, cloned) {
var depth = parents.length,
recreated = {},
context = [recreated,
parents,
cloned];
parents[depth] = data;
cloned[depth] = recreated;
EACH(data, onEachClonedProperty, context);
parents.length = cloned.length = depth;
return recreated;
}
function cloneArray(data, parents, cloned) {
var depth = parents.length,
onProperty = onEachClonedProperty,
recreated = [],
context = [recreated,
parents,
cloned],
c = 0,
l = data.length;
parents[depth] = data;
cloned[depth] = recreated;
for (; l--; c++) {
onProperty.call(context,
data[c],
c,
data);
}
parents.length = cloned.length = depth;
return recreated;
}
function onEachClonedProperty(value, name) {
var /* jshint validthis:true */
context = this,
isNative = nativeObject(value),
parents = context[1],
cloned = context[2];
var index;
if (isNative || array(value)) {
index = parents.lastIndexOf(value);
value = index === -1 ?
(isNative ?
cloneObject :
cloneArray)(value, parents, cloned) :
cloned[index];
}
else {
value = clone(value, false);
}
context[0][name] = value;
}
function onMaxNumericIndex(value, name, context) {
if (ARRAY_INDEX_RE.test(name)) {
context[0] = Math.max(1 * name, context[0]);
}
}
function assign(target, source, defaults, ownedOnly) {
var onAssign = apply,
is = isValidObject,
eachProperty = EACH,
len = arguments.length;
if (!is(target)) {
throw new Error("Invalid [target] parameter.");
}
if (!is(source)) {
throw new Error("Invalid [source] parameter.");
}
if (typeof defaults === 'boolean') {
ownedOnly = defaults;
len = 2;
}
else {
ownedOnly = ownedOnly !== false;
}
if (is(defaults)) {
eachProperty(defaults, onAssign, target, ownedOnly);
}
else if (len > 2) {
throw new Error("Invalid [defaults] parameter.");
}
eachProperty(source, onAssign, target, ownedOnly);
return target;
}
function rehash(target, source, access) {
var is = isValidObject,
context = [target, source];
if (!is(target)) {
throw new Error("Invalid [target] parameter.");
}
if (!is(source)) {
throw new Error("Invalid [source] parameter.");
}
if (!object(access)) {
throw new Error("Invalid [access] parameter.");
}
EACH(access, applyProperties, context);
context = context[0] = context[1] = null;
return target;
}
function contains(subject, property) {
if (!string(property) && !number(property)) {
throw new Error("Invalid [property] parameter.");
}
return OHasOwn.call(subject, property);
}
function instantiate(Class, overrides) {
empty.prototype = Class.prototype;
if (object(overrides)) {
return assign(new empty(), overrides);
}
return new empty();
}
function clone(data, deep) {
var isNative = nativeObject(data);
deep = deep === true;
if (isNative || array(data)) {
return deep ?
(isNative ? cloneObject : cloneArray)(data, [], []) :
(isNative ? assignAll({}, data) : data.slice(0));
}
if (regex(data)) {
return new RegExp(data.source, data.flags);
}
else if (date(data)) {
return new Date(data.getFullYear(),
data.getMonth(),
data.getDate(),
data.getHours(),
data.getMinutes(),
data.getSeconds(),
data.getMilliseconds());
}
return data;
}
function compare(object1, object2) {
return compareLookback(object1, object2, []);
}
/**
* Assign properties of source Object to target Object only if property do not
* exist or not overridden from the target Object.
* @name libcore.fillin
* @function
* @param {Object} target - the target object
* @param {Object} source - the source object containing properties
* to be assigned to target object
* @param {boolean} [hasown] - performs checking to only include
* source object property that is overridden
* (Object.protototype.hasOwnProperty() returns true)
* when this parameter is set to true.
* @returns {Object} subject parameter.
*/
function fillin(target, source, hasown) {
if (!isValidObject(target)) {
throw new Error("Invalid [target] parameter");
}
EACH(source, applyFillin, target, hasown !== false);
return target;
}
function clear(subject) {
EACH(subject, applyClear, null, true);
return subject;
}
function maxObjectIndex(subject) {
var context;
if (array(subject)) {
return subject.length - 1;
}
if (isValidObject(subject)) {
context = [-1];
EACH(subject, onMaxNumericIndex, context);
return context[0];
}
return false;
}
var CHAIN = null;
function use(chain) {
CHAIN = chain;
}
function getModule() {
return CHAIN;
}
var G = global$1;
var NAME_RE = /^(([^\.]+\.)*)((before|after)\:)?([a-zA-Z0-9\_\-\.]+)$/;
var POSITION_BEFORE = 1;
var POSITION_AFTER = 2;
var RUNNERS = {};
var NAMESPACES = {};
var INVALID_NAME = 'Invalid [name] parameter.';
var INVALID_HANDLER = 'Invalid [handler] parameter.';
var NATIVE_SET_IMMEDIATE = !!G.setImmediate;
var setAsync = NATIVE_SET_IMMEDIATE ?
nativeSetImmediate : timeoutAsync;
var clearAsync = NATIVE_SET_IMMEDIATE ?
nativeClearImmediate : clearTimeoutAsync;
function empty$1() {
}
function get(name) {
var info = getRunners(name);
if (info) {
return info[0][info[1]];
}
return void(0);
}
function getRunners(name) {
var list = RUNNERS,
parsed = parseName(name);
var access, position;
if (parsed) {
access = ':' + parsed[1];
if (access in list) {
position = parsed[0];
return [list[access],
getPositionAccess(position),
position];
}
}
return void(0);
}
function purgeRunners(name, after) {
var info = getRunners(name);
var runners, access;
if (info) {
access = info[1];
switch (after) {
case true:
access = 'after';
break;
case false:
access = 'before';
break;
case null:
case undefined:
access = false;
}
if (!access || access === 'before') {
runners = info[0].before;
runners.splice(0, runners.length);
}
if (!access || access === 'after') {
runners = info[0].after;
runners.splice(0, runners.length);
}
}
return getModule();
}
function getPositionAccess(input) {
return input === POSITION_BEFORE ? 'before' : 'after';
}
function parseName(name) {
var match = string(name) && name.match(NAME_RE);
var position, namespace;
if (match) {
namespace = match[1];
position = match[4] === 'before' ? POSITION_BEFORE : POSITION_AFTER;
return [position, (namespace || '') + match[5]];
}
return void(0);
}
function timeoutAsync(handler) {
if (!method(handler)) {
throw new Error(INVALID_HANDLER);
}
return G.setTimeout(handler, 1);
}
function clearTimeoutAsync(id) {
try {
G.clearTimeout(id);
}
catch (e) {}
return getModule();
}
function nativeSetImmediate (handler) {
if (!method(handler)) {
throw new Error(INVALID_HANDLER);
}
return G.setImmediate(handler);
}
function nativeClearImmediate(id) {
try {
G.clearImmediate(id);
}
catch (e) {}
return getModule();
}
function BaseMiddleware() {
}
BaseMiddleware.prototype = {
constructor: BaseMiddleware,
run: function (name, args, scope) {
return run(this.access + name, args, scope);
},
register: function (name, handler) {
register(this.access + name, handler);
return this;
},
clear: function (name, after) {
var access = this.access;
if (!string(name)) {
throw new Error(INVALID_NAME);
}
if (arguments.length > 1) {
purgeRunners(access + name, after);
}
else {
purgeRunners(access + name);
}
return this;
}
};
function run(name, args, scope) {
var c, l, runners, result;
if (!string(name)) {
throw new Error(INVALID_NAME);
}
runners = get(name);
if (runners) {
if (typeof scope === 'undefined') {
scope = null;
}
args = iterable(args) ?
Array.prototype.slice.call(args, 0) : [];
for (c = -1, l = runners.length; l--;) {
result = runners[++c].apply(scope, args);
if (result !== undefined) {
args = [result];
}
}
args.splice(0, args.length);
return result;
}
return undefined;
}
function register(name, handler) {
var list = RUNNERS;
var access, items, parsed;
if (!string(name)) {
throw new Error(INVALID_NAME);
}
parsed = parseName(name);
if (!method(handler)) {
throw new Error(INVALID_HANDLER);
}
if (parsed) {
name = parsed[1];
access = ':' + name;
if (!(access in list)) {
list[access] = {
name: name,
before: [],
after: []
};
}
items = list[access][getPositionAccess(parsed[0])];
items[items.length] = handler;
}
return getModule();
}
function clearRunner(name, after) {
if (!string(name)) {
throw new Error(INVALID_NAME);
}
if (arguments.length > 1) {
purgeRunners(name, after);
}
else {
purgeRunners(name);
}
return getModule();
}
function middleware(name) {
var list = NAMESPACES;
var access, registered, proto;
function Middleware() {
BaseMiddleware.apply(this, arguments);
}
if (!string(name)) {
throw new Error(INVALID_NAME);
}
access = name + '.';
if (!(access in list)) {
empty$1.prototype = BaseMiddleware.prototype;
proto = new empty$1(access);
proto.constructor = Middleware;
proto.access = access;
Middleware.prototype = proto;
list[access] = registered = new Middleware();
return registered;
}
return list[access];
}
// motivation of set operations:
// https://www.probabilitycourse.com/chapter1/1_2_2_set_operations.php
//DETECT = require('./detect.js'),
//OBJECT = require('./object.js'),
//TYPE = require('./type.js'),
var INVALID_ARRAY1 = 'Invalid [array1] parameter.';
var INVALID_ARRAY2 = 'Invalid [array2] parameter.';
var A = Array.prototype;
function indexOf(subject) {
/*jshint validthis:true */
var array$$1 = this,
l = array$$1.length,
c = -1;
for (; l--;) {
if (subject === array$$1[++c]) {
array$$1 = null;
return c;
}
}
return -1;
}
function lastIndexOf(subject) {
/*jshint validthis:true */
var array$$1 = this,
l = array$$1.length;
for (; l--;) {
if (subject === array$$1[l]) {
array$$1 = null;
return l;
}
}
return -1;
}
// apply polyfill
if (!indexOfSupport) {
assign(A, {
indexOf: indexOf,
lastIndexOf: lastIndexOf
});
}
/**
* Creates a union of two arrays
* @name libcore.unionList
* @function
* @param {Array} array1 - source array
* @param {Array} array2 - array to merge
* @param {boolean} [clone] - Filters array1 parameter with union of array2
* if this parameter is false. It returns a new set
* of array containing union of array1 and array2
* otherwise.
* @returns {Array} union of first two array parameters
*/
function unionList(array1, array2, clone$$1) {
var isarray = array;
var subject, l, len, total;
if (!isarray(array1)) {
throw new Error(INVALID_ARRAY1);
}
if (!isarray(array2)) {
throw new Error(INVALID_ARRAY2);
}
array1 = clone$$1 === true ? array1.slice(0) : array1;
// apply
array1.push.apply(array1, array2);
total = array1.length;
// apply unique
found: for (l = total; l--;) {
subject = array1[l];
// remove if not unique
for (len = total; len--;) {
if (l !== len && subject === array1[len]) {
total--;
array1.splice(l, 1);
continue found;
}
}
}
return array1;
}
/**
* Creates an intersection of two arrays
* @name libcore.intersect
* @function
* @param {Array} array1 - source array
* @param {Array} array2 - array to intersect
* @param {boolean} [clone] - Filters array1 parameter with intersection of
* array2 if this parameter is false. It returns a
* new set of array containing intersection of
* array1 and array2 otherwise.
* @returns {Array} intersection of first two array parameters
*/
function intersectList(array1, array2, clone$$1) {
var isarray = array;
var subject, l1, l2, total1, total2;
if (!isarray(array1)) {
throw new Error(INVALID_ARRAY1);
}
if (!isarray(array2)) {
throw new Error(INVALID_ARRAY2);
}
total1 = array1.length;
total2 = array2.length;
// create a copy
array1 = clone$$1 === true ? array1.slice(0) : array1;
found: for (l1 = total1; l1--;) {
subject = array1[l1];
foundSame: for (l2 = total2; l2--;) {
if (subject === array2[l2]) {
// intersect must be unique
for (l2 = total1; l2--;) {
if (l2 !== l1 && subject === array1[l2]) {
break foundSame;
}
}
continue found;
}
}
array1.splice(l1, 1);
total1--;
}
return array1;
}
/**
* Creates a difference of two arrays
* @name libcore.differenceList
* @function
* @param {Array} array1 - source array
* @param {Array} array2 - array to be applied as difference of array1
* @param {boolean} [clone] - Filters array1 parameter with difference of array2
* if this parameter is false. It returns a new set
* of array containing difference of
* array1 and array2 otherwise.
* @returns {Array} difference of first two array parameters
*/
function differenceList(array1, array2, clone$$1) {
var isarray = array;
var subject, l1, l2, total1, total2;
if (!isarray(array1)) {
throw new Error(INVALID_ARRAY1);
}
if (!isarray(array2)) {
throw new Error(INVALID_ARRAY2);
}
total1 = array1.length;
total2 = array2.length;
// create a copy
array1 = clone$$1 === true ? array1.slice(0) : array1;
found: for (l1 = total1; l1--;) {
subject = array1[l1];
// remove if found
for (l2 = total2; l2--;) {
if (subject === array2[l2]) {
array1.splice(l1, 1);
total1--;
continue found;
}
}
// diff must be unique
for (l2 = total1; l2--;) {
if (l2 !== l1 && subject === array1[l2]) {
array1.splice(l1, 1);
total1--;
continue found;
}
}
}
return array1;
}
var HALF_BYTE = 0x80;
var SIX_BITS = 0x3f;
var ONE_BYTE = 0xff;
var fromCharCode = String.fromCharCode;
var BASE64_MAP =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var NOT_BASE64_RE = /[^a-zA-Z0-9\+\/\=]/g;
var BASE64_EXCESS_REMOVE_RE = /[^a-zA-Z0-9\+\/]/;
var CAMEL_RE = /[^a-z]+[a-z]/ig;
var UNCAMEL_RE = /\-*[A-Z]/g;
var TRIM_RE = /^\s+|\s+$/g;
var INVALID_SUBJECT = 'Invalid [subject] parameter.';
function applyCamelize(all) {
return all.charAt(all.length - 1).toUpperCase();
}
function applyUncamelize(all) {
return '-' + all.charAt(all.length -1).toLowerCase();
}
function camelize(subject) {
return subject.replace(CAMEL_RE, applyCamelize);
}
function uncamelize(subject) {
return subject.replace(UNCAMEL_RE, applyUncamelize);
}
function utf2bin(subject) {
var half = HALF_BYTE,
sixBits = SIX_BITS,
code2char = fromCharCode,
utf8 = [],
ul = 0;
var code, c, l;
if (!string(subject, true)) {
throw new Error(INVALID_SUBJECT);
}
for (c = -1, l = subject.length; l--;) {
code = subject.charCodeAt(++c);
if (code < half) {
utf8[ul++] = code2char(code);
}
else if (code < 0x800) {
utf8[ul++] = code2char(0xc0 | (code >> 6));
utf8[ul++] = code2char(half | (code & sixBits));
}
else if (code < 0xd800 || code > 0xdfff) {
utf8[ul++] = code2char(0xe0 | (code >> 12));
utf8[ul++] = code2char(half | ((code >> 6) & sixBits));
utf8[ul++] = code2char(half | (code & sixBits));
}
else {
l--;
code = 0x10000 + (((code & 0x3ff)<<10)
| (subject.charCodeAt(++c) & 0x3ff));
utf8[ul++] = code2char(0xf0 | (code >> 18));
utf8[ul++] = code2char(half | ((code >> 12) & sixBits));
utf8[ul++] = code2char(half | ((code >> 6) & sixBits));
utf8[ul++] = code2char(half | (code >> sixBits));
}
}
return utf8.join('');
}
// based from https://gist.github.com/weishuaiwang/4221687
function bin2utf(subject) {
var code2char = fromCharCode;
var utf16, ul, c, l, code;
if (!string(subject, true)) {
throw new Error(INVALID_SUBJECT);
}
utf16 = [];
ul = 0;
for (c = -1, l = subject.length; l--;) {
code = subject.charCodeAt(++c);
switch (code >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
utf16[ul++] = subject.charAt(c);
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
l--;
utf16[ul++] = code2char(((code & 0x1F) << 6) |
(subject.charCodeAt(++c) & 0x3F));
break;
case 14:
// 1110 xxxx10xx xxxx10xx xxxx
utf16[ul++] = code2char(((code & 0x0F) << 12) |
((subject.charCodeAt(++c) & 0x3F) << 6) |
((subject.charCodeAt(++c) & 0x3F) << 0));
l -= 2;
break;
}
}
return utf16.join("");
}
function encode64(subject) {
var map = BASE64_MAP,
buffer = [],
bl = 0,
c = -1,
excess = false,
pad = map.charAt(64);
var l, total, code, flag, end, chr;
if (!string(subject, true)) {
throw new Error(INVALID_SUBJECT);
}
// decode to ascii
subject = utf2bin(subject);
l = total = subject.length;
for (; l--;) {
code = subject.charCodeAt(++c);
flag = c % 3;
switch (flag) {
case 0:
chr = map.charAt((code & 0xfc) >> 2);
excess = (code & 0x03) << 4;
break;
case 1:
chr = map.charAt(excess | (code & 0xf0) >> 4);
excess = (code & 0x0f) << 2;
break;
case 2:
chr = map.charAt(excess | (code & 0xc0) >> 6);
excess = code & 0x3f;
}
buffer[bl++] = chr;
end = !l;
if ((end || flag === 2)) {
buffer[bl++] = map.charAt(excess);
}
if (!l) {
l = bl % 4;
for (l = l && 4 - l; l--;) {
buffer[bl++] = pad;
}
break;
}
}
return buffer.join('');
}
function decode64(subject) {
var map = BASE64_MAP,
oneByte = ONE_BYTE,
buffer = [],
bl = 0,
c = -1,
code2str = fromCharCode;
var l, code, excess, chr, flag;
if (!string(subject, true) || NOT_BASE64_RE.test(subject)) {
throw new Error(INVALID_SUBJECT);
}
subject = subject.replace(BASE64_EXCESS_REMOVE_RE, '');
l = subject.length;
for (; l--;) {
code = map.indexOf(subject.charAt(++c));
flag = c % 4;
switch (flag) {
case 0:
chr = 0;
break;
case 1:
chr = ((excess << 2) | (code >> 4)) & oneByte;
break;
case 2:
chr = ((excess << 4) | (code >> 2)) & oneByte;
break;
case 3:
chr = ((excess << 6) | code) & oneByte;
}
excess = code;
if (!l && flag < 3 && chr < 64) {
break;
}
if (flag) {
buffer[bl++] = code2str(chr);
}
}
return bin2utf(buffer.join(""));
}
function trim(subject) {
if (!string(subject, true)) {
throw new Error(INVALID_SUBJECT);
}
return subject ? subject.replace(TRIM_RE, "") : subject;
}
var NUMERIC_RE = /^([1-9][0-9]*|0)$/;
var ARRAY_INDEX_RE$1 = /^([1-9][0-9]*|0|)$/;
var ERROR_NATIVE_OBJECT = "Root [subject] requires native Object to accept " +
"non-numeric property name.";
var ERROR_PATH_INVALID = 'Invalid [path] parameter.';
var START = "start";
var START_ESCAPED = "start_escaped";
var QUEUE = "queue";
var END = "end";
var END_EMPTY = "end_empty";
var STATE = {
"start": {
"[": "bracket_start",
"'": "any_sq_start",
'"': "any_dq_start",
"default": "any",
"\\": "any_escape"
},
"bracket_start": {
"]": "property_end",
"'": "sq_start",
'"': "dq_start",
"default": "bracket_any"
},
"any_sq_start": {
"'": "property_end",
"\\": "any_sq_escape",
"default": "any_sq"
},
"any_sq": {
"'": "property_end",
"\\": "any_sq_escape",
"default": "any_sq"
},
"any_sq_escape": {
"default": "any_sq"
},
"any_dq_start": {
'"': "property_end",
"\\": "any_dq_escape",
"default": "any_dq"
},
"any_dq": {
'"': "property_end",
"\\": "any_dq_escape",
"default": "any_dq"
},
"any_dq_escape": {
"default": "any_dq"
},
"sq_start": {
"'": "bracket_end",
"\\": "sq_escape",
"default": "sq"
},
"sq": {
"'": "bracket_end",
"\\": "sq_escape",
"default": "sq"
},
"sq_escape": {
"default": "sq"
},
"dq_start": {
'"': "bracket_end",
"\\": "dq_escape",
"default": "dq"
},
"dq": {
'"': "bracket_end",
"\\": "dq_escape",
"default": "dq"
},
"dq_escape": {
"default": "dq"
},
"bracket_any": {
"]": "property_end",
"\\": "bracket_any_escape",
"default": "bracket_any"
},
"bracket_any_escape": {
"default": "bracket_any"
},
"bracket_end": {
"]": "property_end"
},
"any": {
".": "start",
"\\": "any_escape",
"[": "bracket_start",
"default": "any"
},
"any_escape": {
"default": "any"
},
"property_end": {
"[": "bracket_start",
".": "start"
}
};
var STATE_ACTION = {
"start": {
"any": START,
"any_escape": START_ESCAPED
},
"any_sq_start": {
"any_sq": START,
"property_end": END_EMPTY
},
"any_sq": {
"any_sq": QUEUE,
"property_end": END
},
"any_sq_escape": {
"any_sq": QUEUE
},
"any_dq_start": {
"any_dq": START,
"property_end": END_EMPTY
},
"any_dq": {
"any_dq": QUEUE,
"property_end": END
},
"any_dq_escape": {
"any_dq": QUEUE
},
"any": {
"any": QUEUE,
"start": END,
"bracket_start": END
},
"any_escape": {
"any": QUEUE,
"bracket_start": END,
"start": START
},
"bracket_start": {
"bracket_any": START,
"property_end": END_EMPTY
},
"bracket_any": {
"bracket_any": QUEUE,
"property_end": END
},
"bracket_any_escape": {
"bracket_any": QUEUE
},
"sq_start": {
"sq": START,
"bracket_end": END_EMPTY
},
"sq": {
"sq": QUEUE,
"bracket_end": END
},
"sq_escape": {
"sq": QUEUE
},
"dq_start": {
"dq": START,
"bracket_end": END_EMPTY
},
"dq": {
"dq": QUEUE,
"bracket_end": END
},
"dq_escape": {
"dq": QUEUE
}
};
function onParsePath(property, last, context) {
context[context.length] = property;
}
function isAccessible(subject, item) {
var signature$$1 = signature(subject);
switch (signature$$1) {
case NUMBER_SIGNATURE:
return isFinite(subject) && item in Number.prototype && signature$$1;
case STRING_SIGNATURE:
return item in String.prototype && signature$$1;
case BOOLEAN_SIGNATURE:
return item in Boolean.prototype && signature$$1;
case REGEX_SIGNATURE:
case DATE_SIGNATURE:
case ARRAY_SIGNATURE:
case OBJECT_SIGNATURE:
case METHOD_SIGNATURE:
if (item in subject) {
return signature$$1;
}
}
return false;
}
function isWritable(subject) {
var signature$$1 = signature(subject);
switch (signature$$1) {
case REGEX_SIGNATURE:
case DATE_SIGNATURE:
case ARRAY_SIGNATURE:
case OBJECT_SIGNATURE:
case METHOD_SIGNATURE:
return signature$$1;
}
return false;
}
function isJSONWritable(subject) {
var signature$$1 = signature(subject);
switch (signature$$1) {
case ARRAY_SIGNATURE:
case OBJECT_SIGNATURE:
return signature$$1;
}
return false;
}
function findCallback(item, last, operation) {
var subject = operation[1];
if (!isAccessible(subject, item)) {
operation[0] = void(0);
return false;
}
operation[last ? 0 : 1] = subject[item];
return true;
}
function onPopulatePath(item, last, context) {
var subject = context[1],
iswritable = isWritable,
writable = iswritable(subject),
U = void(0),
success = false;
// populate
if (!last) {
// populate
if (writable) {
// set object
if (!(item in subject)) {
subject[item] = {};
success = true;
}
// allow only when writable
else if (iswritable(subject[item])) {
success = true;
}
}
context[1] = success ? subject[item] : U;
}
// end it with writable state?
else {
success = writable;
context[2] = success && item;
}
return success;
}
function onRemovePath(item, last, context) {
var subject = context[1],
iswritable = isWritable,
writable = iswritable(subject),
U = void(0),
success = false;
// populate
if (!last) {
if (writable && item in subject) {
// go to next
if (iswritable(subject[item])) {
success = true;
}
// still a success, nothing to remove
else {
context[3] = true;
}
}
context[1] = success ? subject[item] : U;
}
// end it with writable state?
else {
success = writable;
context[2] = success && item;
context[3] = true;
}
return success;
}
function existsCallback(item, last, context) {
var subject = context[0],
exists = isAccessible(subject, item);
if (exists) {
context[0] = subject[item];
}
if (last) {
context[1] = !!exists;
}
return exists;
}
function jsonParsePath(path) {
var items = [];
return jsonEach(path, onParsePath, items) && items.length ?
items : null;
}
function jsonFind(path, object$$1) {
var operation = [void(0), object$$1];
jsonEach(path, findCallback, operation);
operation[1] = null;
return operation[0];
}
function jsonCompare(path, object1, object2) {
return compare(jsonFind(path, object1), object2);
}
function jsonClone(path, object$$1, deep) {
return clone(jsonFind(path, object$$1), deep === true);
}
function jsonEach(path, callback, arg1, arg2, arg3, arg4, arg5) {
var map = STATE,
action = STATE_ACTION,
start = START,
start_escaped = START_ESCAPED,
queue = QUEUE,
end = END,
end_empty = END_EMPTY,
DEFAULT = "default";
var c, l, chr, state, stateObject, items, len, last,
next, actionObject, buffer, bl, buffered, pending,
start_queue, restart;
if (!string(path)) {
throw new Error(ERROR_PATH_INVALID);
}
if (!method(callback)) {
throw new Error("Invalid [callback] parameter");
}
buffer = bl = false;
state = "start";
stateObject = map.start;
items = [];
len = pending = 0;
for (c = -1, l = path.length; l--;) {
buffered = false;
chr = path.charAt(++c);
last = !l;
// find next state
if (chr in stateObject) {
next = stateObject[chr];
}
else if (DEFAULT in stateObject) {
next = stateObject[DEFAULT];
}
else {
return null;
}
// check for actions
if (state in action) {
actionObject = action[state];
if (next in actionObject) {
start_queue = restart = false;
switch (actionObject[next]) {
case start:
start_queue = true;
/* falls through */
case start_escaped:
if (buffer !== false) {
return false;
}
if (start_queue && !last) {
buffer = [chr];
bl = 1;
}
else {
buffer = [];
bl = 0;
}
// exit if not last
if (!last) {
break;
}
/* falls through */
case queue:
if (buffer === false) {
return false;
}
buffer[bl++] = chr;
// exit if not last
if (!last) {
break;
}
/*