/**
* 执行fn并把一个新的Wrapper的$()和$$()传递给它
* 如果没有传递任何参数,则执行{@link M.exportDSL}
* @namespace {Function} M
* @param {Function} [fn]
*/
var M=function(fn){
if(arguments.length == 0){
return M.exportDSL();
}else if(fn){
var wrapper = M.$wrapper();
var args = Array.prototype.slice.call(arguments, 1);
return fn.apply(this, [wrapper.$, wrapper.$$].concat(args));
}
}
/**
* 引用当前运行环境的全局对象
* 浏览器中指向window,node环境下指向global
*/
M.global = this;
if(typeof global != "undefined")M.global = global;
/**
* 将May.js的关键字方法复制到目标对象
* 如果未传递target参数,则使用eval()导出到当前作用域内
* @param {Object} [target] 目标对象
*/
M.exportDSL = function(target) {
var _getKeywordFunc = function(){
return Object.keys(M).filter(function(name){
return (/^\$/).test(name) && ["$", "$$"].indexOf(name) == -1;
});
}
if(target){
_getKeywordFunc().forEach(function (prop) {
target[prop] = M[prop];
});
}else{
return M.util.dsl(M, _getKeywordFunc()) + M.util.dsl(M.$wrapper());
}
}
if(typeof(module) != "undefined")module.exports = M;
/** @namespace M.util **/
M.util = {
/**
* 获取函数的参数名称
* @example
* function Add(number1, number2){}
* M.util.parseArguNames(Add);
* => ["number1", "number2"]
* @param {function} fn
* @returns {Array}
*/
parseArguNames: function (fn) {
var m = fn.toString().match(/.*?\((.*)?\)/);
if(m && m[1]) {
return m[1].split(",").map(function(i){ return i.trim();});
}
return [];
},
/**
* 包装只有两个参数的函数, 包装后会把第二个参数开始的所有参数依次传递给原函数运行
* @param {function(param, param2)} fn
* @returns {function}
*/
makeMultiTargetFn: function (fn){
return function(){
if(arguments.length <= 2){
return fn(arguments[0], arguments[1]);
}else{//3个以上
var arg0 = arguments[0];
for(var i=1, l=arguments.length; i<l; i++){
if(fn(arg0, arguments[i]) === false){
return false;
}
}
return true;
}
}
},
/**
* 将值转换成其对应的引用对象
* @param {string|number|bool} value
* @returns {Object}
*/
toObject: function(value) {
var obj = value;
switch(typeof value){
case 'string':
obj = new String(value);
break;
case 'number':
obj = new Number(value);
break;
case 'boolean':
obj = new Boolean(value);
break;
}
return obj;
},
/** 在函数内部调用函数自身, 代替引用auguments.callee **/
fn: function() {
return arguments.callee.caller.apply(this, arguments);
},
/**
* 将类Array对象转换成真正的Array
* @param {Object} arrayLikeObj
* @returns {Array}
*/
parseArray: function(arrayLikeObj) {
return Array.prototype.slice.call(arrayLikeObj, 0);
},
/**
* 声明一个枚举
* @param {...String} names enumeration key
* @example
* var color = M.$enum("BLUE", "RED", "YELLOW");
* color.BLUE
* color.RED
* color.YELLOW
*
* var color = M.$enum({
* "BLUE": -1,
* "RED": 1
* })
*/
enumeration: function(names) {
if(typeof names == "object") {
return arguments[0];
}
var _enum = {};
for(var i = 0, l = arguments.length; i < l; i++) {
_enum[arguments[i]] = {};
}
return _enum;
},
/**
* 包装纯函数,包装时指定纯函数的第一参数
* @param {function} fn 纯函数
* @param {Object} [firstParam=this] fn的第一个参数,如果未传递getFirstParam参数
* @param {function(firstParam)} [getFirstParam] 获取fn的第一个参数的函数,调用时将把firstParam传递给它
* @return {function}
*/
methodize: function(fn, firstParam, getFirstParam) {
return function() {
//获取第一个参数
var p1 = firstParam || this;
if(getFirstParam) p1 = getFirstParam(p1);
//把第一个参数和其他参数放在一起
var slice = Array.prototype.slice;
var args = [p1].concat(slice.call(arguments));
return fn.apply(this, args);
}
},
/**
* 重写对象的方法,新方法将调用overwriter并把原方法作为第一个参数传递给它
* @param {Object} obj 要重写方法的对象
* @param {string} funcName 被重写的方法名
* @param {function} overwriter 真正的覆盖函数
* @example
* var Jim = {
* sayHi: function(){ return "Hi"}
* }
*
* M.util.overwrite(Jim, "sayHi", function(oldFn, name){
* return oldFn.call(this) + ", " + name + "!";
* })
*
* Jim.sayHi("Lucy");
* => "Hi, Lucy!"
*/
overwrite: function(obj, funcName, overwriter) {
var _oldFn = obj[funcName].bind(obj);
obj[funcName] = function() {
var args = [_oldFn].concat(Array.prototype.slice.call(arguments, 0));
return overwriter.apply(this, args);
};
},
/**
* 生成将对象的成员导出到当前作用域的代码,该代码可被eval()正确执行,
* 该函数生成的代码不能在strict模式下运行
* @param {string} [obj=this]
* @param {string} [members] 指定要导入的成员,未指定则导入全部成员,用空格分隔成员名
* @return {string}
* @example
* var Calculator = {
* add: function(a, b){ return a + b },
* sub: function(a, b){ return a - b }
* }
*
* eval(M.util.dsl(Calculator));
*
* add(4, 6);
* sub(10, 4);
*/
dsl: function(obj, members) {
obj = obj || this;
var tempVarName = "_temp" + Date.now() + Math.random().toString().substr(2);
eval(tempVarName + "={value: {}}");
var temp = eval(tempVarName);
temp.value = obj;
if(typeof members == "string" && members !== ""){
members = members.split(" ").map(function(n){ return n.trim(); });
}else if(!members){
members = Object.keys(obj);
}
var codes = members.map(function(name) {
//可以加入检查是否已经定义的功能,如已定义则警告。
return name + "=" + tempVarName + ".value" + "['" + name + "']";
});
return "var " + codes.join(",") + ";delete " + tempVarName + ";";
},
/**
* 运行指定方法,避免在全局作用域下产生全局变量
* @param {function} fn
*/
run: function(fn) {
if(arguments.length == 1) {
return fn();
} else {
return fn.apply(this, Array.prototype.slice.call(arguments, 1));
}
}
}
/**
* 在函数内部调用函数自身, 代替引用auguments.callee,是{@link M.util.fn}的别名
* @memberof M
* @function
**/
M.$fn = M.util.fn;
/**
* 运行指定方法,避免在全局作用域下产生全局变量,是{@link M.util.run}的别名
* @memberof M
* @function
* @param {function} fn
*/
M.$run = M.util.run;
/**
* 声明一个枚举,是{@link M.util.enumeration}的别名
* @memberof M
* @function
* @param {...String} names enumeration key
* @example
* var color = M.$enum("BLUE", "RED", "YELLOW");
* color.BLUE
* color.RED
* color.YELLOW
*
* var color = M.$enum({
* "BLUE": -1,
* "RED": 1
* })
*/
M.$enum = M.util.enumeration;
/**
* 重写对象的方法,新方法将调用overwriter并把原方法作为第一个参数传递给它,是{@link M.util.overwrite}的别名
* @memberof M
* @function
* @param {Object} obj 要重写方法的对象
* @param {string} funcName 被重写的方法名
* @param {function} overwriter 真正的覆盖函数
* @example
* var Jim = {
* sayHi: function(){ return "Hi"}
* }
*
* M.util.overwrite(Jim, "sayHi", function(oldFn, name){
* return oldFn.call(this) + ", " + name + "!";
* })
*
* Jim.sayHi("Lucy");
* => "Hi, Lucy!"
*/
M.$overwrite = M.util.overwrite;
/**
* 包装纯函数,包装时指定纯函数的第一参数,是{@link M.util.methodize}的别名
* @memberof M
* @function
* @param {function} fn 纯函数
* @param {Object} [firstParam=this] fn的第一个参数,如果未传递getFirstParam参数
* @param {function(firstParam)} [getFirstParam] 获取fn的第一个参数的函数,调用时将把firstParam传递给它
* @return {function}
*/
M.$methodize = M.util.methodize;
/**
* 生成将对象的成员导出到当前作用域的代码,该代码可被eval()正确执行,
* 该函数生成的代码不能在strict模式下运行,是{@link M.util.dsl}的别名
* @memberof M
* @function
* @param {string} [obj=this]
* @param {string} [members] 指定要导入的成员,未指定则导入全部成员,用空格分隔成员名
* @return {string}
* @example
* var Calculator = {
* add: function(a, b){ return a + b },
* sub: function(a, b){ return a - b }
* }
*
* eval(M.util.dsl(Calculator));
*
* add(4, 6);
* sub(10, 4);
*/
M.$dsl = M.util.dsl;
/** @namespace M.MObjectUtil **/
M.MObjectUtil = {
/**
* 判断name是否符合私有成员的名称规范
* @param {string} name
* @returns {boolean}
*/
isPrivate: function(name) {
return(/^__/).test(name);
},
/**
* 判断name是否符合受保护成员的名称规范
* @param {string} name
* @returns {boolean}
*/
isProtected: function(name) {
return(/^_(?!_)/).test(name);
},
/**
* 判断name是否符合公开成员的名称规范
* @param {string} name
* @returns {boolean}
*/
isPublic: function(name) {
return !this.isProtected(name) && !this.isPrivate(name);
},
/**
* 判断对象是否拥有指定属性,该属性不能为function
* @param {string} obj
* @param {string} property
* @returns {boolean}
*/
has: function(obj, property) {
return(obj && obj.hasOwnProperty(property) && typeof obj[property] != "function") || false;
},
/**
* 判断对象是否可响应指定方法
* @param {string} obj
* @param {string} funcName
* @returns {boolean}
*/
can: function(obj, funcName) {
return(obj && obj[funcName] && typeof obj[funcName] == "function") || false;
},
/**
* 遍历对象,调用指定函数
* @param {string} obj
* @param {function} fn
*/
eachAll: function(obj, fn) {
for(var p in obj) {
if(fn(p, obj[p]) === false) break;
}
},
/**
* 遍历对象拥有的成员,调用指定函数
* @param {string} obj
* @param {function} fn
*/
eachOwn: function(obj, fn) {
for(var p in obj) {
if(obj.hasOwnProperty(p) && this.isPublic(p)) {
if(fn(p, obj[p]) === false) break;
}
}
},
/**
* 遍历对象的属性(除方法外的所有成员),调用指定函数
* @param {string} obj
* @param {function} fn
*/
eachProp: function(obj, fn) {
this.eachOwn(obj, function(p, op) {
if(typeof op != "function") {
return fn(p, op);
}
});
},
/**
* 根据指定属性来追溯
* @param {Object} obj 对象
* @param {String} prop 属性名
* @param {function(a)} fn 处理函数(追溯到的对象)
* @returns {boolean} 全部处理完返回true,否则false
*/
traverseChain: function(obj, prop, fn) {
var v = obj[prop];
while(v) {
if(fn(v) === false) return false;
v = v[prop];
}
return true;
},
/**
* clone克隆指定对象,如果对象自己有clone方法,则调用对象自己的clone方法
* @param {Object} obj 被克隆的对象
* @param {boolean} [deep=false] 是否深度克隆
* @returns {Object}
*/
clone: function(o, deep) {
if(!o) return o;
if(['object', 'function'].indexOf(typeof(o)) == -1) { //value type
return o;
}
if(typeof o.clone == "function") {
return o.clone(deep);
}
var cloneObj = {};
var className = Object.prototype.toString.call(o).slice(8, -1);
if(className === 'Array') {
cloneObj = [];
if(deep) {
for(var i = 0, l = o.length; i < l; i++) {
cloneObj.push(arguments.callee(o[i], deep));
}
} else {
cloneObj = o.slice(0);
}
} else if(className !== 'Object') {
cloneObj = new o.constructor(o.valueOf());
}
if(deep) {
for(var p in o) {
if( p == 'constructor') continue;
var op = o[p];
if( p == '__proto__'){
cloneObj[p] = op;
continue;
}
if(Object.prototype.isPrototypeOf(op)) {
cloneObj[p] = arguments.callee(op, deep);
} else {
cloneObj[p] = op;
}
}
} else {
for(var p in o) {
cloneObj[p] = o[p];
}
}
return cloneObj;
},
/**
* copy members from src to obj
* @param {Object} obj [description]
* @param {Object} src [description]
* @param {String[]} [whitelist=null] 不想被覆盖的成员
* @return {Object}
*/
mix: function(obj, src, whitelist) {
if(!src) return obj;
var p;
if(whitelist) {
for(p in src) {
if(whitelist.indexOf(p) == -1) {
obj[p] = src[p];
}
}
} else {
for(p in src) {
obj[p] = src[p];
}
}
return obj;
},
/**
* 依次合并给定的所有对象到一个新的对象
* @param {...Object} obj
* @returns {Object} new object, merge
*/
merge: function(/*a,b,c,d,...*/) {
var obj = {},
curr = null,
p;
for(var i = 0, l = arguments.length; i < l; i++) {
curr = arguments[i];
if(!curr) continue;
for(p in curr) {
obj[p] = curr[p];
}
}
return obj;
}
}
/**
* 依次合并给定的所有对象到一个新的对象,是{@link M.MObjectUtil.merge}的别名
* @memberof M
* @function
* @param {...Object} obj
* @returns {Object} new object, merge
*/
M.$merge = M.MObjectUtil.merge;
/**
* copy members from src to obj,是{@link M.MObjectUtil.mix}的别名
* @memberof M
* @function
* @param {Object} obj [description]
* @param {Object} src [description]
* @param {String[]} [whitelist=null] 不想被覆盖的成员
* @return {Object}
*/
M.$mix = M.MObjectUtil.mix;
/**
* clone克隆指定对象,如果对象自己有clone方法,则调用对象自己的clone方法,是{@link M.MObjectUtil.clone}的别名
* @memberof M
* @function
* @param {Object} obj 被克隆的对象
* @param {boolean} [deep=false] 是否深度克隆
* @returns {Object}
*/
M.$clone = M.MObjectUtil.clone;
M.util.run(function(M){
/**
* Mayjs的interface的原型对象
* @memberof M
* @type Object
**/
var Interface = {};
var _getType = function(obj){
return Object.prototype.toString.call(obj);
}
/* validate types = [null, undefined, "undefined",
"number", "string", "boolean", "function",
Number, String, Boolean, Function];
*/
var _isValueType = M.util.makeMultiTargetFn(function(type, obj){
if(type == null || type == "undefined")return obj == null;
var objType = _getType(obj)
if(type == "number" || type == Number){
return objType == _getType(Number.prototype);
}else if(type == "string" || type == String){
return objType == _getType(String.prototype);
}else if(type == "boolean" || type == Boolean){
return objType == _getType(Boolean.prototype);
}else if(type == "function" || type == Function){
return typeof(obj)== "function";
}else{
return false;
}
});
var _isInstanceof = M.util.makeMultiTargetFn(function(Clazz, obj){
if(typeof Clazz != "function")return false;
if([Array, RegExp, Error, Date].indexOf(Clazz) != -1){
return _getType(Clazz.prototype) === _getType(obj);
}
return obj instanceof Clazz;
});
/**
* 判断对象是否为指定类型
* @memberof M
* @function
* @param {string|function|undefined} type
* @param {...Object} obj
* @returns {boolean}
*/
var $is = M.util.makeMultiTargetFn(function(type, obj){
if(_isValueType(type, obj))return true;
if(_isInstanceof(type, obj))return true;
return false;
});
/**
* 判断proto是否为obj的原型
* @memberof M
* @function
* @param {Object} proto
* @param {Object} obj
* @returns {boolean}
**/
var $hasProto = M.util.makeMultiTargetFn(
function(proto, obj){
if(typeof proto != "object")return false;
if(proto == null)return false;
return proto.isPrototypeOf(obj);
}
);
/**
* 依次判断给定的参数是否为false,一旦发现为false立即抛出错误
* @memberof M
* @function
* @param {...boolean} result
*/
var $check = function(result, msg){
if(result === false){
if(msg)throw msg;
throw "$check failed";
}
}
function _parseArguTypes(arguTypes, arguNames) {
var meta = [];
if(_is(Array, arguTypes)) {
if(arguNames) { //$func声明时带了方法定义,参数类型声明中无参数名项,参数名列表从方法定义中获取
for(var i = 0, l=arguNames.length; i < l; i++) {
meta.push({
"name": arguNames[i],
"type": arguTypes[i]
});
}
} else { //在$interface中声明成员方法的参数类型时,需要指定对映参数名,故无须提供参数名列表
arguTypes.forEach(function(item){
for(var arguName in item){
if(arguName != "returns"){
meta.push({"name": arguName, "type": item[arguName] });
}
break;
}
});
}
} else { //在$func中定义的option,即$func({argu1: Type1, argu2: Type2}, function(argu1, argu2){});
meta.push({
"name": arguNames[0],
"type": $interface(arguTypes)
});
}
return meta;
}
/**
* 给指定方法设定参数的元类型信息
* @memberof M
* @param {Object|Interface} arguTypes 参数的类型定义
* @param {function} fn
**/
function $func(arguTypes, fn) {
fn.__argu_types__ = _parseArguTypes(arguTypes, M.util.parseArguNames(fn));
return fn;
}
/**
* 创建Interface的快捷方法
* @memberof M
* @param {Object} define interface define
* @param {Interface} base base interface
* @returns {Interface}
*/
function $interface(define, base) {
if(base) {
interface_ = Object.create(base);
} else {
interface_ = Object.create(Interface);
}
for(var p in define){
interface_[p] = define[p];
}
return interface_;
}
/**
* 判断对象是否为指定类型或者符合指定协议
* @private
* @memberof M
* @param {function|Object|Interface|string} type 类型或者协议
* @param {Object} obj
*/
function _is(type, obj){
if($is(type, obj) || $hasProto(type, obj)){
return true;
}
var t = typeof(type);
if(t == "function"){
if(type.prototype && $hasProto(type.prototype, obj))return true;
}else if(t == "object"){
return $support(type, obj);
}
return false;
}
/**
* 判断一个对象是否支持指定协议
* @memberof M
* @param {Interface|Object} interface_
* @param {Object} obj
* @param {bool} [exactly=false] 如果为false且对象的已实现接口元信息中包含了该接口,则不再次检查是否支持
* @returns {boolean}
*/
function $support(interface_, obj, exactly) {
if(!exactly && obj.__interfaces__ && obj.__interfaces__.indexOf(interface_) != -1) {
return true;
}
var isOptionalName = /^\[(.*?)\]$/;
var isMataName = /^__.*__$/;
for(var name in interface_) {
var member = obj[name];
var type = interface_[name];
var optionalName = name.match(isOptionalName);
if(optionalName){
name = optionalName[1];
member = obj[name];
if(member == null)continue; //可选参数为null或者undefined则表示没有出现,不用检查
}
if(isMataName.test(name))continue;
if($is(Array, type)){ //用数组实例表示方法签名,如[TypeOfP1, TypeOfP2],要表示成员类型是数组,用Array类
if(!typeof(member) == "function"){
//return false;
throw name + " invalid";
}
continue;
}else if(!_is(type, member)){
//return false;
throw name + " invalid";
}
}
return true;
}
/**
* 把指定协议加入对象的已实现协议元信息中,加入前检查是否支持指定协议
* @memberof M
* @param {Interface|Object} interface_
* @param {Object} obj
*/
function $implement(interface_, obj) {
var interfaces = obj.__interfaces__ || (obj.__interfaces__ = []);
if(interfaces.indexOf(interface_) == -1) {
if(!$support(interface_, obj)) {
throw "object did not implement given interface";
}
//write arguments meta to methods of obj
Object.keys(interface_).forEach(function(p) {
if(_is(Array, interface_[p])) { //接口声明用Array来表示方法签名
obj[p].__argu_types__ = _parseArguTypes(interface_[p]);
}
});
interfaces.push(interface_);
}
}
M.$ensure = function(fn){
try{
return fn()
}catch(e){
if(typeof(console) != undefined){
console.error && console.error(e);
}
return false;
}
}
M.Interface = Interface;
M.$interface = $interface;
M.$support = $support;
M.$implement = $implement;
M.$is = $is;
M.$hasProto = $hasProto;
M.$func = $func;
M.$check = $check;
M._is = _is;
}, M);
M.util.run(function(M) {
/**
* 定义一个module,暂时啥也不干,原样返回传入的对象,标识作用
* @memberof M
* @param {Object} obj
* @returns {Object}
*/
function $module(o) {
return o;
}
/**
* 供include module时使用的选项的接口
* @namespace M.IModuleOption
*/
var IModuleOption = {
/**
* 执行onincluded和methodize时会用到
* @alias M.IModuleOption.context
* @type {Object}
*/
"[context]": Object,
/**
* 是否对所有函数成员进行methodize
* @alias M.IModuleOption.methodize
* @type {boolean}
*/
"[methdize]": Boolean,
/**
* 通过这个函数获得methodize时的第一参数
* @alias M.IModuleOption.methodizeTo
* @type {function}
*/
"[methdizeTo]": [Object],
/**
* 可以被mix到哪些类型
* @alias M.IModuleOption.supports
* @type {Array}
*/
"[supports]": Array,
/**
* 停止调用module.onIncluded,
* 考虑类似这种情况:当include一个module类时,应该copy成员到类的prototype,module的onIncluded则在类的initialize中调用
* @alias M.IModuleOption.stopCallback
* @type {boolean}
*/
"[stopCallback]": Boolean
}
/**
* module interface
* @memberof M
* @interface
**/
var IModule = {
"[__option__]": IModuleOption,
"[onIncluded]": Function //include给object后被自动调用,一般不用于include给prototype object
}
/**
* include module to obj with option
* @memberof M
* @param {Object} opt.module
* @param {Object} opt.to
* @param {Object} opt.option
* @returns {Object}
*/
function $include(obj, module, option) {
var defauls = {
"methodize": false,
"context": null, //methodize的参数
"methodizeTo": null, //methodize的参数
"stopCallback": false
};
option = M.MObjectUtil.merge(defauls, module.__option__, option);
var needMethodize = option.methodize;
M.MObjectUtil.eachOwn(module, function(k, v){
if("onIncluded" !== k && !k.match(/^__.*__$/)) {
//var name = (option.alias && option.alias[k]) ? option.alias[k] : k;
if(needMethodize && typeof v == "function") {
obj[k] = M.util.methodize(v, option.context, option.methodizeTo);
} else {
obj[k] = v;
}
}
});
if(module.__interfaces__) {
module.__interfaces__.forEach(function(interface_) {
M.$implement(interface_, obj);
});
}
if(!option.stopCallback && module.onIncluded) {
module.onIncluded.call(obj, option.context || obj);
}
}
M.$module = $module;
M.$include = $include;
M.IModuleOption = IModuleOption;
M.IModule = IModule;
}, M);
M.util.run(function(M) {
var traverseChain = M.MObjectUtil.traverseChain;
var mix = M.MObjectUtil.mix;
/**
* @namespace
* @memberOf M
* @type {Object}
*/
var BaseObj = {
/**
* 元信息:已实现的接口
* @member
*/
__interfaces__: [],
/** 初始化方法 **/
/**
* 使用定义信息生成新的对象,新对象的prototype为当前对象
* @member
* @param {Object} objDefined 对象定义
**/
extend: function(objDefine){
var obj = Object.create(this);
if(!Object["__proto__"]) {//for IE browser
obj["__proto__"] = this;
}
for(var name in objDefine){
var member = objDefine[name];
obj[name] = member;
//add __name__ to method
if(typeof(member) == "function"){
member.__name__ = name;
}
}
return obj;
},
/**
* 模拟super关键字,访问原型链中的方法
* @member
*/
base: function(){
var caller = arguments.callee.caller;
var callerName = caller.name || caller.__name__;
var callerOwner = this.__getCallerOwner(caller, callerName);
if(!callerName)callerName = caller.__name__; //在this._getCallerOwner方法中会为caller设置name meta;
var base = callerOwner ? callerOwner.__proto__ : null;
var fn = base ? base[callerName] : null;
if(typeof fn == "function") {
return fn.apply(this, arguments);
}
},
__getCallerOwner: function(caller, callerName){
var callerOwner = null;
if(callerName){
if(this.hasOwnProperty(callerName) && this[callerName] === caller)return this;
if(this["__proto__"][callerName] == caller){
return this["__proto__"];
}
traverseChain(this, "__proto__", function(proto) {
if(proto.hasOwnProperty(callerName) && proto[callerName] == caller){
callerOwner = proto;
return false;
}
});
}else{
for(var p in this){
if(this[p] === caller){
callerOwner = this;
caller.__name__ = p;
break;
}
}
if(callerOwner)return callerOwner;
traverseChain(this, "__proto__", function(proto) {
Object.keys(proto).forEach(function(p) {
if(proto[p] == caller) {
callerOwner = proto;
caller.__name__ = p;
return false;
}
});
});
}
return callerOwner;
}
}
/**
* Klass类,{@link M.BaseObj}是其prototype
* @inner
* @memberof M
* @augments {M.BaseObj}
* @constructor
*/
function Klass(){}
Klass.prototype = BaseObj.extend(/** @lends M~Klass.prototype **/{
initialize: function(){
/**
* 已实现接口元信息
* @instance
* @type {Array}
*/
this.__interfaces__ = [];
this.constructor.fireInitialized && this.constructor.fireInitialized(this);
}
});
/** @lends M~Klass */
var KlazzStatics = {
__observers__: [],
/**
* 触发类的oninitialize事件
* @param {Object} instance
*/
fireInitialized: function(instance){
this.__observers__.forEach(function(observer){
observer(instance);
});
},
/**
* 添加类的初始化事件的监听者
* @param {function} observer
*/
onInitialize: function(observer){
this.__observers__.push(observer);
},
/**
* 包含指定的module到当前类中
* @param {IModule} module
* @param {IModuleOption} option
*/
include: function(module, option){
if(module.onIncluded){
option = option || {};
option.stopCallback = true;
M.$include(this.prototype, module, option);
this.onInitialize(function(instance){
var context = option.context || instance;
module.onIncluded.call(instance, context);
});
}else{
M.$include(this.prototype, module, option);
}
},
/**
* 继承当前类,产生新类
* @memberof M~Klass
* @param {Object} classDefine
*/
extend: function(classDefine){
var proto = this.prototype.extend(classDefine);
//如果prototype未定义initialize,则为其添加一个
if(!proto.hasOwnProperty("initialize")){
proto.initialize = function(){
//调用父类的initiazlie
this.base.apply(this, arguments);
}
}
var clazz;
if(!Object["__proto__"]) {//for IE browser
clazz = function(){
if(!proto.isPrototypeOf(this)){
return new (arguments.callee);
}
this.constructor = clazz;
this["__proto__"] = proto;
proto.initialize.apply(this, arguments);
}
}else{
clazz = function(){
if(!proto.isPrototypeOf(this)){
return new (arguments.callee);
}
this.constructor = clazz;
proto.initialize.apply(this, arguments);
}
}
proto.constructor = this;
clazz.prototype = proto;
/*
var excludes = ["prototype"];
for(var p in Klass){
if(excludes.indexOf(p) == -1){
clazz[p] = this[p];
}
}*/
M.MObjectUtil.mix(clazz, Object.create(KlazzStatics));
if(classDefine.modules && clazz.include){
classDefine.modules.forEach(function(module){
clazz.include(module);
})
}
return clazz;
}
}
M.MObjectUtil.mix(Klass, Object.create(KlazzStatics));
/**
* BaseClass
* @class
* @augments {M~Klass}
* @memberof M
*/
var BaseClass = Klass.extend({})
/**
* May.js Object的接口
* @memberof M
*/
var IBase = M.$interface({
"base": [],
"__interfaces__": Array
});
M.$implement(IBase, BaseObj);
/**
* 定义一个Mayjs类,该类自动继承{@link M.BaseClass}
* @memberof M
* @param {Object} prototype 新类的prototype
*/
function $class(prototype){
return BaseClass.extend(prototype);
}
/**
* 定义一个对象,该对象的原型为{@link M.BaseObj}
* @memberof M
* @param {Object} obj
*/
function $obj(obj){
return BaseObj.extend(obj);
}
M.IBase = IBase;
M.BaseObj = BaseObj;
M.BaseClass = BaseClass;
M.$class = $class;
M.$obj = $obj;
}, M);
M.util.run(function(M) {
var toObject = M.util.toObject;
var merge = M.MObjectUtil.merge;
var mix = M.MObjectUtil.mix;
/**
* @memberof M
* @class
*/
var Wrapper = M.$class(
/** @lends M.Wrapper.prototype **/
{
/**
* @alias M.Wrapper
* @constructor
*/
initialize: function() {
/**
* type -- module map
* @type Array
*/
this.__map__ = [];
/**
* @type Object
*/
this.__DSL__ = {
$: this.$.bind(this),
$$: this.$$.bind(this),
}
this.__DSL__.$.reg = this.$reg.bind(this);
this.__DSL__.$.clear = this.$clear.bind(this);
},
__wrap: function(obj, proxy, option){
obj = toObject(obj);
if(!proxy){
proxy = obj;
}
var wrappers = this.__findWrappersByObj(obj);
if(wrappers.length === 0) return obj;
wrappers.forEach(function(wrapper) {
var includeOption = merge(option || {}, wrapper.includeOption);
M.$include(proxy, wrapper.module, includeOption);
});
return proxy;
},
/**
* 清空wrap module表
*/
$clear: function(){
this.__map__ = [];
},
/**
* wrap对象,非侵入
* @param {Object} obj
*/
$: function(obj) {
var proxy = {
valueOf: function(){ return obj}
}
return this.__wrap(obj, proxy, {context: obj});
},
/**
* 直接复制wrap modules中的成员到指定对象
* @param {Object} obj 对象
*/
$$: function(obj) {
return this.__wrap(obj);
},
/**
* 将wrap module注册到prototype,Interface或Class
* @param {Object} module
* @param {Object|Interface|Function} supports
* @param {Object} [option]
*/
$reg: function(module, supports, option) {
var includeOption = option || module.__option__ || {};
supports = supports || includeOption.supports;
var types = Array.prototype.isPrototypeOf(supports) ? supports : [supports];
for(var i=0,l=types.length; i<l; i++){
var type = types[i];
if(type != Function.prototype) { // typeof Function.prototype == "function" true
if(typeof type == "function") {
type = type.prototype;
}
if(type != Function.prototype) {
if(!type || ["string", "object"].indexOf(typeof type) == -1) return;
}
}
if(typeof module != "object") return;
var map = this.__map__;
var typeWrappers = map.filter(function(item) {
return item.type == type;
});
var wrapper = {
"module": module,
"includeOption": includeOption
};
if(typeWrappers.length === 0) {
typeWrappers = {
"type": type,
modules: [wrapper]
};
map.push(typeWrappers);
} else {
if(typeWrappers[0].modules.filter(function(wrapper) {
return wrapper.module == module;
}).length === 0) {
typeWrappers[0].modules.push(wrapper);
}
}
}
return this;
},
__findWrappersByType: function(type) {
var ms = this.__map__.filter(function(item) {
return item.type == type;
});
return ms.length === 0 ? [] : ms[0].modules;
},
/**
* 根据prototype,Interface或Class查找已注册的wrap modules
* @param {Object|Interface|Function} type
* @return {Array}
*/
findWrappersByType: function(type){
if(this != _globalWrapper){
return _globalWrapper.__findWrappersByType(type).concat(this.__findWrappersByType(type));
}else{
return this.__findWrappersByType(type);
}
},
__findWrappersByPrototype: function(proto) {
var self = this;
var wrappers = [];
var oldProto;
while(proto) {
wrappers = wrappers.concat(self.findWrappersByType(proto));
if(proto.hasOwnProperty("__interfaces__")){
proto.__interfaces__.forEach(function(interface_) {
wrappers = wrappers.concat(self.findWrappersByType(interface_));
});
}
oldProto = proto;
proto = oldProto["__proto__"] || (oldProto.constructor ? oldProto.constructor.prototype : null);
if(proto == oldProto) {
break;
}
}
return wrappers;
},
__findWrappersByObj: function(obj) {
if(obj === null) return [];
var wrappers = [];
var self = this;
var addTypeWrappers = function(type) {
wrappers = wrappers.concat(self.findWrappersByType(type));
};
var objType = typeof obj;
if(objType == "object" || objType == "function") { //reference type
wrappers = wrappers.concat(this.__findWrappersByPrototype(obj["__proto__"] || obj.constructor.prototype));
if(obj.hasOwnProperty("__interfaces__")){
obj.__interfaces__.forEach(function(interface_) {
addTypeWrappers(interface_);
});
}
} //else { //value type
// addTypeWrappers(objType);
//}
return wrappers;
}
});
/**
* 创建一个新的{@link M.Wrapper}并返回它的__DSL__
* @memberof M
*/
M.$wrapper = function () {
return new Wrapper().__DSL__;
}
/**
* @memberof M~_globalWrapper
* @instance M.Wrapper
*/
var _globalWrapper = new Wrapper();
M.MObjectUtil.mix(M, _globalWrapper.__DSL__);
M.Wrapper = Wrapper;
}, M);
M.util.run(function(M){
var $func = M.$func;
function _checkParams(fn, params) {
var caller = fn || arguments.callee.caller;
var paramsMeta = caller.__argu_types__;
params = params || caller["arguments"];
var type;
for(var i = 0, l = params.length; i < l; i++) {
type = paramsMeta[i].type;
//将方法的参数声明为null类型,表明其可为任何值,所以总是验证通过
if(type === null) return true;
if(type instanceof RegExp){
if(!type.test(params[i])) return false;
}else{
if(!M.$ensure(function(){ return M._is(type, params[i]) })){
//if(typeof type == "function"){ //参数的类型为function,且不是参数的原型或者构造器,则可能是验证函数
//@todo type.isChecker = true;
//if(!type(params[i]) === false)return false;
//}
return false;
}
}
}
return true;
}
function dispatch(overloads, params) {
var arguCount = params.length;
var matches = overloads.filter(function(fn) {
return fn.__argu_types__.length >= arguCount;
});
if(matches.length == 0) return null;
if(params.length == 0) return matches[0];
var fn;
while((fn = matches.shift())) {
if(_checkParams(fn, params)) {
return fn;
}
}
}
/**
* function overload
* @memberof M
* @param {Array} paramsTypes params types
* @param {function} fn overload function
* @returns {function}
* @example
* fn = M.$overload(["string","number"], function(name, age){
* return "I'm "+name+ " and I'm " + age + " years old";
* }).overload(["string"], function(name){
* return "i'm " + name;
* });
*
* fn.overload(["string", "string"], function(name, interest){
* return "I'm " + name + ", and i'm interesting "+ interest;
* });
*
* fn("lily"); // => "i'm lily"
* fn("lily", 18); // => "I'm lily and I'm 18 years old"
* fn("lily", "singing"); //=> "I'm lily, and i'm interesting singing"
*/
function $overload(paramTypes, fn) {
//存储重载的方法
var _overloads = {value: []};
var pushFn = function(paramTypes, fn){
if(typeof paramTypes == "function"){
fn=paramTypes;
paramTypes = null;
if(!fn.hasOwnProperty("__argu_types__")){
fn.__argu_types__ = [];
}
}else{
$func(paramTypes, fn);
}
_overloads.value.push(fn);
}
pushFn(paramTypes, fn);
var main = function() {
var params = arguments;
var fn = dispatch(_overloads.value, params);
if(fn) {
return fn.apply(this, params);
}
};
main.overload = function(paramTypes, fn) {
pushFn(paramTypes, fn);
//_overloads.value.push(typeof paramTypes == "function" ? paramTypes : $func(paramTypes, fn));
_overloads.value = _overloads.value.sort(function(fn1, fn2) {
return fn1.__argu_types__.length - fn2.__argu_types__.length;
});
return this;
};
return main;
}
M.$overload = $overload;
}, M);
M.util.run(function() {
var Tap = function(lastResult) {
this.valueOf = function(){
return lastResult;
}
}
Tap.prototype.tap = function(fn) {
return new Tap(fn(this.valueOf()));
}
M.MObjectWrapper = {
tap: function(fn){
return new Tap(fn(this.valueOf()));
},
mix: function(src, whitelist){
M.$mix(this.valueOf(), src, whitelist);
return this;
},
include: function(module, option){
M.$include(this.valueOf(), option);
return this;
},
has: function(prop){
return M.MObjectUtil.has(this.valueOf(), prop);
},
can: function(methodName){
return M.MObjectUtil.can(this.valueOf(), methodName);
},
eachProp: function(fn){
M.MObjectUtil.eachProp(this.valueOf(), fn);
return this;
},
__option__: {
supports: [Object]
}
}
})