• requirejs--源码分析


       1 /*---------------------------------------start-------------------------------*/
       2 req({}); // num == 1 跳到 num == 2
       3 
       4 //Exports some context-sensitive methods on global require.
       5 each([
       6     'toUrl',
       7     'undef',
       8     'defined',
       9     'specified'
      10 ], function (prop) {
      11     //Reference from contexts instead of early binding to default context,
      12     //so that during builds, the latest instance of the default context
      13     //with its config gets used.
      14     req[prop] = function () {
      15         var ctx = contexts[defContextName];
      16         return ctx.require[prop].apply(ctx, arguments);
      17     };
      18 });
      19 
      20 if (isBrowser && !cfg.skipDataMain) {}  //req.deps[mainscript]
      21 
      22 
      23 //Set up with config info.
      24 req(cfg); //最后启动。 按照之前写的num 一步一步的去加载。
      25 
      26 /*----------------------------------------start---------------------------------*/
      27 //第一次     num == 2
      28 //params
      29 
      30 var deps = {},
      31     callback = undefined,
      32     errback = undefined,
      33     optional = undefined;
      34 
      35 
      36 //--------------声明------------------
      37 var context = undefined,
      38     config = undefined,
      39     contextName = defContextName;
      40 
      41 //-------------判断---------------
      42 
      43 config = {};
      44 deps = [];
      45 
      46 //------------判断--------------
      47 context = contexts[contextName] = req.s.newContext(contextName);  //跳到num ==3
      48 
      49 //时间上就是执行  localRequire(deps, callback, errback);
      50 context.require(deps, callback, errback);  //跳到 num ==5
      51 
      52 
      53 /*---------------------------------------end-------------------------------*/
      54 /*
      55 *
      56 *
      57 * */
      58 /*---------------------------------------start-------------------------------*/
      59 //-----------------------进入核心函数--------------------------
      60 //第一次
      61 //function newContext(contextName)   num == 3
      62 context = {
      63     config: config,
      64     contextName: contextName,
      65     registry: registry,
      66     defined: defined,
      67     urlFetched: urlFetched,
      68     defQueue: defQueue,
      69     defQueueMap: {},
      70     Module: Module,
      71     makeModuleMap: makeModuleMap,
      72     nextTick: req.nextTick,
      73     onError: onError,
      74 
      75     /**
      76      * Set a configuration for the context.
      77      * @param {Object} cfg config object to integrate.
      78      */
      79     configure: function (cfg) {
      80         //Make sure the baseUrl ends in a slash.
      81         if (cfg.baseUrl) {
      82             if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
      83                 cfg.baseUrl += '/';
      84             }
      85         }
      86 
      87         // Convert old style urlArgs string to a function.
      88         if (typeof cfg.urlArgs === 'string') {
      89             var urlArgs = cfg.urlArgs;
      90             cfg.urlArgs = function(id, url) {
      91                 return (url.indexOf('?') === -1 ? '?' : '&') + urlArgs;
      92             };
      93         }
      94 
      95         //Save off the paths since they require special processing,
      96         //they are additive.
      97         var shim = config.shim,
      98             objs = {
      99                 paths: true,
     100                 bundles: true,
     101                 config: true,
     102                 map: true
     103             };
     104 
     105         eachProp(cfg, function (value, prop) {
     106             if (objs[prop]) {
     107                 if (!config[prop]) {
     108                     config[prop] = {};
     109                 }
     110                 mixin(config[prop], value, true, true);
     111             } else {
     112                 config[prop] = value;
     113             }
     114         });
     115 
     116         //Reverse map the bundles
     117         if (cfg.bundles) {
     118             eachProp(cfg.bundles, function (value, prop) {
     119                 each(value, function (v) {
     120                     if (v !== prop) {
     121                         bundlesMap[v] = prop;
     122                     }
     123                 });
     124             });
     125         }
     126 
     127         //Merge shim
     128         if (cfg.shim) {
     129             eachProp(cfg.shim, function (value, id) {
     130                 //Normalize the structure
     131                 if (isArray(value)) {
     132                     value = {
     133                         deps: value
     134                     };
     135                 }
     136                 if ((value.exports || value.init) && !value.exportsFn) {
     137                     value.exportsFn = context.makeShimExports(value);
     138                 }
     139                 shim[id] = value;
     140             });
     141             config.shim = shim;
     142         }
     143 
     144         //Adjust packages if necessary.
     145         if (cfg.packages) {
     146             each(cfg.packages, function (pkgObj) {
     147                 var location, name;
     148 
     149                 pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj;
     150 
     151                 name = pkgObj.name;
     152                 location = pkgObj.location;
     153                 if (location) {
     154                     config.paths[name] = pkgObj.location;
     155                 }
     156 
     157                 //Save pointer to main module ID for pkg name.
     158                 //Remove leading dot in main, so main paths are normalized,
     159                 //and remove any trailing .js, since different package
     160                 //envs have different conventions: some use a module name,
     161                 //some use a file name.
     162                 config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
     163                         .replace(currDirRegExp, '')
     164                         .replace(jsSuffixRegExp, '');
     165             });
     166         }
     167 
     168         //If there are any "waiting to execute" modules in the registry,
     169         //update the maps for them, since their info, like URLs to load,
     170         //may have changed.
     171         eachProp(registry, function (mod, id) {
     172             //If module already has init called, since it is too
     173             //late to modify them, and ignore unnormalized ones
     174             //since they are transient.
     175             if (!mod.inited && !mod.map.unnormalized) {
     176                 mod.map = makeModuleMap(id, null, true);
     177             }
     178         });
     179 
     180         //If a deps array or a config callback is specified, then call
     181         //require with those args. This is useful when require is defined as a
     182         //config object before require.js is loaded.
     183         if (cfg.deps || cfg.callback) {
     184             context.require(cfg.deps || [], cfg.callback);
     185         }
     186     },
     187 
     188     makeShimExports: function (value) {
     189         function fn() {
     190             var ret;
     191             if (value.init) {
     192                 ret = value.init.apply(global, arguments);
     193             }
     194             return ret || (value.exports && getGlobal(value.exports));
     195         }
     196         return fn;
     197     },
     198 
     199     makeRequire: function (relMap, options) {
     200         options = options || {};
     201 
     202         function localRequire(deps, callback, errback) {
     203             var id, map, requireMod;
     204 
     205             if (options.enableBuildCallback && callback && isFunction(callback)) {
     206                 callback.__requireJsBuild = true;
     207             }
     208 
     209             if (typeof deps === 'string') {
     210                 if (isFunction(callback)) {
     211                     //Invalid call
     212                     return onError(makeError('requireargs', 'Invalid require call'), errback);
     213                 }
     214 
     215                 //If require|exports|module are requested, get the
     216                 //value for them from the special handlers. Caveat:
     217                 //this only works while module is being defined.
     218                 if (relMap && hasProp(handlers, deps)) {
     219                     return handlers[deps](registry[relMap.id]);
     220                 }
     221 
     222                 //Synchronous access to one module. If require.get is
     223                 //available (as in the Node adapter), prefer that.
     224                 if (req.get) {
     225                     return req.get(context, deps, relMap, localRequire);
     226                 }
     227 
     228                 //Normalize module name, if it contains . or ..
     229                 map = makeModuleMap(deps, relMap, false, true);
     230                 id = map.id;
     231 
     232                 if (!hasProp(defined, id)) {
     233                     return onError(makeError('notloaded', 'Module name "' +
     234                         id +
     235                         '" has not been loaded yet for context: ' +
     236                         contextName +
     237                         (relMap ? '' : '. Use require([])')));
     238                 }
     239                 return defined[id];
     240             }
     241 
     242             //Grab defines waiting in the global queue.
     243             intakeDefines();
     244 
     245             //Mark all the dependencies as needing to be loaded.
     246             context.nextTick(function () {
     247                 //Some defines could have been added since the
     248                 //require call, collect them.
     249                 intakeDefines();
     250 
     251                 requireMod = getModule(makeModuleMap(null, relMap));
     252 
     253                 //Store if map config should be applied to this require
     254                 //call for dependencies.
     255                 requireMod.skipMap = options.skipMap;
     256 
     257                 requireMod.init(deps, callback, errback, {
     258                     enabled: true
     259                 });
     260 
     261                 checkLoaded();
     262             });
     263 
     264             return localRequire;
     265         }
     266 
     267         mixin(localRequire, {
     268             isBrowser: isBrowser,
     269 
     270             /**
     271              * Converts a module name + .extension into an URL path.
     272              * *Requires* the use of a module name. It does not support using
     273              * plain URLs like nameToUrl.
     274              */
     275             toUrl: function (moduleNamePlusExt) {
     276                 var ext,
     277                     index = moduleNamePlusExt.lastIndexOf('.'),
     278                     segment = moduleNamePlusExt.split('/')[0],
     279                     isRelative = segment === '.' || segment === '..';
     280 
     281                 //Have a file extension alias, and it is not the
     282                 //dots from a relative path.
     283                 if (index !== -1 && (!isRelative || index > 1)) {
     284                     ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
     285                     moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
     286                 }
     287 
     288                 return context.nameToUrl(normalize(moduleNamePlusExt,
     289                     relMap && relMap.id, true), ext,  true);
     290             },
     291 
     292             defined: function (id) {
     293                 return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
     294             },
     295 
     296             specified: function (id) {
     297                 id = makeModuleMap(id, relMap, false, true).id;
     298                 return hasProp(defined, id) || hasProp(registry, id);
     299             }
     300         });
     301 
     302         //Only allow undef on top level require calls
     303         if (!relMap) {
     304             localRequire.undef = function (id) {
     305                 //Bind any waiting define() calls to this context,
     306                 //fix for #408
     307                 takeGlobalQueue();
     308 
     309                 var map = makeModuleMap(id, relMap, true),
     310                     mod = getOwn(registry, id);
     311 
     312                 mod.undefed = true;
     313                 removeScript(id);
     314 
     315                 delete defined[id];
     316                 delete urlFetched[map.url];
     317                 delete undefEvents[id];
     318 
     319                 //Clean queued defines too. Go backwards
     320                 //in array so that the splices do not
     321                 //mess up the iteration.
     322                 eachReverse(defQueue, function(args, i) {
     323                     if (args[0] === id) {
     324                         defQueue.splice(i, 1);
     325                     }
     326                 });
     327                 delete context.defQueueMap[id];
     328 
     329                 if (mod) {
     330                     //Hold on to listeners in case the
     331                     //module will be attempted to be reloaded
     332                     //using a different config.
     333                     if (mod.events.defined) {
     334                         undefEvents[id] = mod.events;
     335                     }
     336 
     337                     cleanRegistry(id);
     338                 }
     339             };
     340         }
     341 
     342         return localRequire;
     343     },
     344 
     345     /**
     346      * Called to enable a module if it is still in the registry
     347      * awaiting enablement. A second arg, parent, the parent module,
     348      * is passed in for context, when this method is overridden by
     349      * the optimizer. Not shown here to keep code compact.
     350      */
     351     enable: function (depMap) {
     352         var mod = getOwn(registry, depMap.id);
     353         if (mod) {
     354             getModule(depMap).enable();
     355         }
     356     },
     357 
     358     /**
     359      * Internal method used by environment adapters to complete a load event.
     360      * A load event could be a script load or just a load pass from a synchronous
     361      * load call.
     362      * @param {String} moduleName the name of the module to potentially complete.
     363      */
     364     completeLoad: function (moduleName) {
     365         var found, args, mod,
     366             shim = getOwn(config.shim, moduleName) || {},
     367             shExports = shim.exports;
     368 
     369         takeGlobalQueue();
     370 
     371         while (defQueue.length) {
     372             args = defQueue.shift();
     373             if (args[0] === null) {
     374                 args[0] = moduleName;
     375                 //If already found an anonymous module and bound it
     376                 //to this name, then this is some other anon module
     377                 //waiting for its completeLoad to fire.
     378                 if (found) {
     379                     break;
     380                 }
     381                 found = true;
     382             } else if (args[0] === moduleName) {
     383                 //Found matching define call for this script!
     384                 found = true;
     385             }
     386 
     387             callGetModule(args);
     388         }
     389         context.defQueueMap = {};
     390 
     391         //Do this after the cycle of callGetModule in case the result
     392         //of those calls/init calls changes the registry.
     393         mod = getOwn(registry, moduleName);
     394 
     395         if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
     396             if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
     397                 if (hasPathFallback(moduleName)) {
     398                     return;
     399                 } else {
     400                     return onError(makeError('nodefine',
     401                         'No define call for ' + moduleName,
     402                         null,
     403                         [moduleName]));
     404                 }
     405             } else {
     406                 //A script that does not call define(), so just simulate
     407                 //the call for it.
     408                 callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
     409             }
     410         }
     411 
     412         checkLoaded();
     413     },
     414 
     415     /**
     416      * Converts a module name to a file path. Supports cases where
     417      * moduleName may actually be just an URL.
     418      * Note that it **does not** call normalize on the moduleName,
     419      * it is assumed to have already been normalized. This is an
     420      * internal API, not a public one. Use toUrl for the public API.
     421      */
     422     nameToUrl: function (moduleName, ext, skipExt) {
     423         var paths, syms, i, parentModule, url,
     424             parentPath, bundleId,
     425             pkgMain = getOwn(config.pkgs, moduleName);
     426 
     427         if (pkgMain) {
     428             moduleName = pkgMain;
     429         }
     430 
     431         bundleId = getOwn(bundlesMap, moduleName);
     432 
     433         if (bundleId) {
     434             return context.nameToUrl(bundleId, ext, skipExt);
     435         }
     436 
     437         //If a colon is in the URL, it indicates a protocol is used and it is just
     438         //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
     439         //or ends with .js, then assume the user meant to use an url and not a module id.
     440         //The slash is important for protocol-less URLs as well as full paths.
     441         if (req.jsExtRegExp.test(moduleName)) {
     442             //Just a plain path, not module name lookup, so just return it.
     443             //Add extension if it is included. This is a bit wonky, only non-.js things pass
     444             //an extension, this method probably needs to be reworked.
     445             url = moduleName + (ext || '');
     446         } else {
     447             //A module that needs to be converted to a path.
     448             paths = config.paths;
     449 
     450             syms = moduleName.split('/');
     451             //For each module name segment, see if there is a path
     452             //registered for it. Start with most specific name
     453             //and work up from it.
     454             for (i = syms.length; i > 0; i -= 1) {
     455                 parentModule = syms.slice(0, i).join('/');
     456 
     457                 parentPath = getOwn(paths, parentModule);
     458                 if (parentPath) {
     459                     //If an array, it means there are a few choices,
     460                     //Choose the one that is desired
     461                     if (isArray(parentPath)) {
     462                         parentPath = parentPath[0];
     463                     }
     464                     syms.splice(0, i, parentPath);
     465                     break;
     466                 }
     467             }
     468 
     469             //Join the path parts together, then figure out if baseUrl is needed.
     470             url = syms.join('/');
     471             url += (ext || (/^data:|^blob:|?/.test(url) || skipExt ? '' : '.js'));
     472             url = (url.charAt(0) === '/' || url.match(/^[w+.-]+:/) ? '' : config.baseUrl) + url;
     473         }
     474 
     475         return config.urlArgs && !/^blob:/.test(url) ?
     476         url + config.urlArgs(moduleName, url) : url;
     477     },
     478 
     479     //Delegates to req.load. Broken out as a separate function to
     480     //allow overriding in the optimizer.
     481     load: function (id, url) {
     482         req.load(context, id, url);
     483     },
     484 
     485     /**
     486      * Executes a module callback function. Broken out as a separate function
     487      * solely to allow the build system to sequence the files in the built
     488      * layer in the right sequence.
     489      *
     490      * @private
     491      */
     492     execCb: function (name, callback, args, exports) {
     493         return callback.apply(exports, args);
     494     },
     495 
     496     /**
     497      * callback for script loads, used to check status of loading.
     498      *
     499      * @param {Event} evt the event from the browser for the script
     500      * that was loaded.
     501      */
     502     onScriptLoad: function (evt) {
     503         //Using currentTarget instead of target for Firefox 2.0's sake. Not
     504         //all old browsers will be supported, but this one was easy enough
     505         //to support and still makes sense.
     506         if (evt.type === 'load' ||
     507             (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
     508             //Reset interactive script so a script node is not held onto for
     509             //to long.
     510             interactiveScript = null;
     511 
     512             //Pull out the name of the module and the context.
     513             var data = getScriptData(evt);
     514             context.completeLoad(data.id);
     515         }
     516     },
     517 
     518     /**
     519      * Callback for script errors.
     520      */
     521     onScriptError: function (evt) {
     522         var data = getScriptData(evt);
     523         if (!hasPathFallback(data.id)) {
     524             var parents = [];
     525             eachProp(registry, function(value, key) {
     526                 if (key.indexOf('_@r') !== 0) {
     527                     each(value.depMaps, function(depMap) {
     528                         if (depMap.id === data.id) {
     529                             parents.push(key);
     530                             return true;
     531                         }
     532                     });
     533                 }
     534             });
     535             return onError(makeError('scripterror', 'Script error for "' + data.id +
     536                 (parents.length ?
     537                 '", needed by: ' + parents.join(', ') :
     538                     '"'), evt, [data.id]));
     539         }
     540     }
     541 };
     542 
     543 //得到一个闭包环境
     544 context.require = context.makeRequire();  //跳到num ===4
     545 
     546 //return context;
     547 /*---------------------------------------end-------------------------------*/
     548 /*
     549 *
     550 *
     551 *
     552 *
     553 *
     554 * */
     555 /*---------------------------------------start-------------------------------*/
     556 //--------------------------进入makeRequire------------------------
     557 //第一次
     558 //params [relMap , options]   num == 4
     559 
     560 var relMap = undefined,
     561      options = {};
     562 
     563 
     564 //声明localRequire函数
     565 var localRequire= function(deps, callback, errback){};
     566 
     567 //给localRequire加属性
     568 var fn1={
     569     isBrowser: isBrowser,
     570 
     571     /**
     572      * Converts a module name + .extension into an URL path.
     573      * *Requires* the use of a module name. It does not support using
     574      * plain URLs like nameToUrl.
     575      */
     576         toUrl: function (moduleNamePlusExt) {
     577     var ext,
     578         index = moduleNamePlusExt.lastIndexOf('.'),
     579         segment = moduleNamePlusExt.split('/')[0],
     580         isRelative = segment === '.' || segment === '..';
     581 
     582     //Have a file extension alias, and it is not the
     583     //dots from a relative path.
     584     if (index !== -1 && (!isRelative || index > 1)) {
     585         ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
     586         moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
     587     }
     588 
     589     return context.nameToUrl(normalize(moduleNamePlusExt,
     590         relMap && relMap.id, true), ext,  true);
     591 },
     592 
     593     defined: function (id) {
     594         return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
     595     },
     596 
     597     specified: function (id) {
     598         id = makeModuleMap(id, relMap, false, true).id;
     599         return hasProp(defined, id) || hasProp(registry, id);
     600     }
     601 };
     602 
     603 
     604 //---------------------- 判断 if (!relMap)----------------------
     605 
     606 //加属性
     607 
     608 var fn2 =  undef = function(id){};
     609 
     610 //返回return localRequire;
     611 
     612 //总结一下 就是返回一个函数,给他加了一些属性;
     613 /*---------------------------------------end-------------------------------*/
     614 /*
     615 *
     616 * */
     617 
     618 /*---------------------------------------start-------------------------------*/
     619 // num == 5
     620 intakeDefines() // 调到num == 6
     621 /*
     622 *    while (defQueue.length) {}遍历 defQueue;
     623 *
     624 *
     625 *
     626 * */
     627 
     628 callGetModule(args); //args [id,deps,callb]  跳到num = 7
     629 
     630 context.defQueueMap = {};
     631 
     632 context.nextTick(function () {
     633     //Some defines could have been added since the
     634     //require call, collect them.
     635     intakeDefines();
     636 
     637     requireMod = getModule(makeModuleMap(null, relMap));
     638 
     639     //Store if map config should be applied to this require
     640     //call for dependencies.
     641     requireMod.skipMap = options.skipMap;
     642 
     643     requireMod.init(deps, callback, errback, {
     644         enabled: true
     645     });
     646 
     647     checkLoaded();
     648 });  //跳转到 12
     649 
     650 
     651 /*---------------------------------------end-------------------------------*/
     652 /*
     653 *
     654 *
     655 *
     656 *
     657 * */
     658 /*---------------------------------------start-------------------------------*/
     659 /* function takeGlobalQueue()   num == 6
     660  * */
     661 
     662 //把globalDefQueue 里面通过define(id,desp,callback) 都放到  特定context 下的 defQueue
     663 
     664 //并且最后清空   globalDefQueue = [];
     665 
     666 /*---------------------------------------end-------------------------------*/
     667 /*
     668 *
     669 *
     670 *
     671 *
     672 * */
     673 /*---------------------------------------start-------------------------------*/
     674 //   function callGetModule(args)   num == 7
     675 
     676 //将 defined里没有的 id进行构建模块
     677 if (!hasProp(defined, args[0])) {
     678     getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
     679 }
     680 
     681 makeModuleMap(args[0], null, true) //跳转到 num== 8
     682 
     683 getModule(makeModuleMap(args[0], null, true))  //跳转到 num == 9
     684 
     685 getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);//跳转到 num == 11
     686 //生成的Module 里面的map属性 就是 makeModuleMap返回的对象。
     687 
     688 
     689 /*---------------------------------------end-------------------------------*/
     690 /*
     691 *
     692 *
     693 *
     694 *
     695 * */
     696 /*---------------------------------------start-------------------------------*/
     697 
     698 //function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) //num == 8
     699 
     700 //返回obj
     701 var obj =  {
     702     prefix: prefix,
     703     name: normalizedName,
     704     parentMap: parentModuleMap,
     705     unnormalized: !!suffix,
     706     url: url,
     707     originalName: originalName,
     708     isDefine: isDefine,
     709     id: (prefix ?
     710     prefix + '!' + normalizedName :
     711         normalizedName) + suffix
     712 };
     713 
     714 /*---------------------------------------end-------------------------------*/
     715 /*
     716  *
     717  *
     718  *
     719  *
     720  * */
     721 /*-----------------------------------------start--------------------------------*/
     722 
     723 //function getModule(depMap)   num == 9
     724 var id = depMap.id,
     725     mod = getOwn(registry, id);
     726 
     727 if (!mod) {
     728     mod = registry[id] = new context.Module(depMap);
     729 }
     730 
     731 new context.Module(depMap); //跳转到10
     732 
     733 //return mod;
     734 
     735 /*----------------------------------------end-------------------------*/
     736 /*
     737  *
     738  *
     739  *
     740  *
     741  * */
     742 /*-----------------------------------------start--------------------------------*/
     743 //num ===10
     744 Module = function (map) {
     745     this.events = getOwn(undefEvents, map.id) || {};
     746     this.map = map;
     747     this.shim = getOwn(config.shim, map.id);
     748     this.depExports = [];
     749     this.depMaps = [];
     750     this.depMatched = [];
     751     this.pluginMaps = {};
     752     this.depCount = 0;
     753 
     754     /* this.exports this.factory
     755      this.depMaps = [],
     756      this.enabled, this.fetched
     757      */
     758 };
     759 
     760 Module.prototype = {
     761     init: function (depMaps, factory, errback, options) {
     762         options = options || {};
     763 
     764         //Do not do more inits if already done. Can happen if there
     765         //are multiple define calls for the same module. That is not
     766         //a normal, common case, but it is also not unexpected.
     767         if (this.inited) {
     768             return;
     769         }
     770 
     771         this.factory = factory;
     772 
     773         if (errback) {
     774             //Register for errors on this module.
     775             this.on('error', errback);
     776         } else if (this.events.error) {
     777             //If no errback already, but there are error listeners
     778             //on this module, set up an errback to pass to the deps.
     779             errback = bind(this, function (err) {
     780                 this.emit('error', err);
     781             });
     782         }
     783 
     784         //Do a copy of the dependency array, so that
     785         //source inputs are not modified. For example
     786         //"shim" deps are passed in here directly, and
     787         //doing a direct modification of the depMaps array
     788         //would affect that config.
     789         this.depMaps = depMaps && depMaps.slice(0);
     790 
     791         this.errback = errback;
     792 
     793         //Indicate this module has be initialized
     794         this.inited = true;
     795 
     796         this.ignore = options.ignore;
     797 
     798         //Could have option to init this module in enabled mode,
     799         //or could have been previously marked as enabled. However,
     800         //the dependencies are not known until init is called. So
     801         //if enabled previously, now trigger dependencies as enabled.
     802         if (options.enabled || this.enabled) {
     803             //Enable this module and dependencies.
     804             //Will call this.check()
     805             this.enable();
     806         } else {
     807             this.check();
     808         }
     809     },
     810 
     811     defineDep: function (i, depExports) {
     812         //Because of cycles, defined callback for a given
     813         //export can be called more than once.
     814         if (!this.depMatched[i]) {
     815             this.depMatched[i] = true;
     816             this.depCount -= 1;
     817             this.depExports[i] = depExports;
     818         }
     819     },
     820 
     821     fetch: function () {
     822         if (this.fetched) {
     823             return;
     824         }
     825         this.fetched = true;
     826 
     827         context.startTime = (new Date()).getTime();
     828 
     829         var map = this.map;
     830 
     831         //If the manager is for a plugin managed resource,
     832         //ask the plugin to load it now.
     833         if (this.shim) {
     834             context.makeRequire(this.map, {
     835                 enableBuildCallback: true
     836             })(this.shim.deps || [], bind(this, function () {
     837                 return map.prefix ? this.callPlugin() : this.load();
     838             }));
     839         } else {
     840             //Regular dependency.
     841             return map.prefix ? this.callPlugin() : this.load();
     842         }
     843     },
     844 
     845     load: function () {
     846         var url = this.map.url;
     847 
     848         //Regular dependency.
     849         if (!urlFetched[url]) {
     850             urlFetched[url] = true;
     851             context.load(this.map.id, url);
     852         }
     853     },
     854 
     855     /**
     856      * Checks if the module is ready to define itself, and if so,
     857      * define it.
     858      */
     859     check: function () {
     860         if (!this.enabled || this.enabling) {
     861             return;
     862         }
     863 
     864         var err, cjsModule,
     865             id = this.map.id,
     866             depExports = this.depExports,
     867             exports = this.exports,
     868             factory = this.factory;
     869 
     870         if (!this.inited) {
     871             // Only fetch if not already in the defQueue.
     872             if (!hasProp(context.defQueueMap, id)) {
     873                 this.fetch();
     874             }
     875         } else if (this.error) {
     876             this.emit('error', this.error);
     877         } else if (!this.defining) {
     878             //The factory could trigger another require call
     879             //that would result in checking this module to
     880             //define itself again. If already in the process
     881             //of doing that, skip this work.
     882             this.defining = true;
     883 
     884             if (this.depCount < 1 && !this.defined) {
     885                 if (isFunction(factory)) {
     886                     //If there is an error listener, favor passing
     887                     //to that instead of throwing an error. However,
     888                     //only do it for define()'d  modules. require
     889                     //errbacks should not be called for failures in
     890                     //their callbacks (#699). However if a global
     891                     //onError is set, use that.
     892                     if ((this.events.error && this.map.isDefine) ||
     893                         req.onError !== defaultOnError) {
     894                         try {
     895                             exports = context.execCb(id, factory, depExports, exports);
     896                         } catch (e) {
     897                             err = e;
     898                         }
     899                     } else {
     900                         exports = context.execCb(id, factory, depExports, exports);
     901                     }
     902 
     903                     // Favor return value over exports. If node/cjs in play,
     904                     // then will not have a return value anyway. Favor
     905                     // module.exports assignment over exports object.
     906                     if (this.map.isDefine && exports === undefined) {
     907                         cjsModule = this.module;
     908                         if (cjsModule) {
     909                             exports = cjsModule.exports;
     910                         } else if (this.usingExports) {
     911                             //exports already set the defined value.
     912                             exports = this.exports;
     913                         }
     914                     }
     915 
     916                     if (err) {
     917                         err.requireMap = this.map;
     918                         err.requireModules = this.map.isDefine ? [this.map.id] : null;
     919                         err.requireType = this.map.isDefine ? 'define' : 'require';
     920                         return onError((this.error = err));
     921                     }
     922 
     923                 } else {
     924                     //Just a literal value
     925                     exports = factory;
     926                 }
     927 
     928                 this.exports = exports;
     929 
     930                 if (this.map.isDefine && !this.ignore) {
     931                     defined[id] = exports;
     932 
     933                     if (req.onResourceLoad) {
     934                         var resLoadMaps = [];
     935                         each(this.depMaps, function (depMap) {
     936                             resLoadMaps.push(depMap.normalizedMap || depMap);
     937                         });
     938                         req.onResourceLoad(context, this.map, resLoadMaps);
     939                     }
     940                 }
     941 
     942                 //Clean up
     943                 cleanRegistry(id);
     944 
     945                 this.defined = true;
     946             }
     947 
     948             //Finished the define stage. Allow calling check again
     949             //to allow define notifications below in the case of a
     950             //cycle.
     951             this.defining = false;
     952 
     953             if (this.defined && !this.defineEmitted) {
     954                 this.defineEmitted = true;
     955                 this.emit('defined', this.exports);
     956                 this.defineEmitComplete = true;
     957             }
     958 
     959         }
     960     },
     961 
     962     callPlugin: function () {
     963         var map = this.map,
     964             id = map.id,
     965         //Map already normalized the prefix.
     966             pluginMap = makeModuleMap(map.prefix);
     967 
     968         //Mark this as a dependency for this plugin, so it
     969         //can be traced for cycles.
     970         this.depMaps.push(pluginMap);
     971 
     972         on(pluginMap, 'defined', bind(this, function (plugin) {
     973             var load, normalizedMap, normalizedMod,
     974                 bundleId = getOwn(bundlesMap, this.map.id),
     975                 name = this.map.name,
     976                 parentName = this.map.parentMap ? this.map.parentMap.name : null,
     977                 localRequire = context.makeRequire(map.parentMap, {
     978                     enableBuildCallback: true
     979                 });
     980 
     981             //If current map is not normalized, wait for that
     982             //normalized name to load instead of continuing.
     983             if (this.map.unnormalized) {
     984                 //Normalize the ID if the plugin allows it.
     985                 if (plugin.normalize) {
     986                     name = plugin.normalize(name, function (name) {
     987                             return normalize(name, parentName, true);
     988                         }) || '';
     989                 }
     990 
     991                 //prefix and name should already be normalized, no need
     992                 //for applying map config again either.
     993                 normalizedMap = makeModuleMap(map.prefix + '!' + name,
     994                     this.map.parentMap);
     995                 on(normalizedMap,
     996                     'defined', bind(this, function (value) {
     997                         this.map.normalizedMap = normalizedMap;
     998                         this.init([], function () { return value; }, null, {
     999                             enabled: true,
    1000                             ignore: true
    1001                         });
    1002                     }));
    1003 
    1004                 normalizedMod = getOwn(registry, normalizedMap.id);
    1005                 if (normalizedMod) {
    1006                     //Mark this as a dependency for this plugin, so it
    1007                     //can be traced for cycles.
    1008                     this.depMaps.push(normalizedMap);
    1009 
    1010                     if (this.events.error) {
    1011                         normalizedMod.on('error', bind(this, function (err) {
    1012                             this.emit('error', err);
    1013                         }));
    1014                     }
    1015                     normalizedMod.enable();
    1016                 }
    1017 
    1018                 return;
    1019             }
    1020 
    1021             //If a paths config, then just load that file instead to
    1022             //resolve the plugin, as it is built into that paths layer.
    1023             if (bundleId) {
    1024                 this.map.url = context.nameToUrl(bundleId);
    1025                 this.load();
    1026                 return;
    1027             }
    1028 
    1029             load = bind(this, function (value) {
    1030                 this.init([], function () { return value; }, null, {
    1031                     enabled: true
    1032                 });
    1033             });
    1034 
    1035             load.error = bind(this, function (err) {
    1036                 this.inited = true;
    1037                 this.error = err;
    1038                 err.requireModules = [id];
    1039 
    1040                 //Remove temp unnormalized modules for this module,
    1041                 //since they will never be resolved otherwise now.
    1042                 eachProp(registry, function (mod) {
    1043                     if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
    1044                         cleanRegistry(mod.map.id);
    1045                     }
    1046                 });
    1047 
    1048                 onError(err);
    1049             });
    1050 
    1051             //Allow plugins to load other code without having to know the
    1052             //context or how to 'complete' the load.
    1053             load.fromText = bind(this, function (text, textAlt) {
    1054                 /*jslint evil: true */
    1055                 var moduleName = map.name,
    1056                     moduleMap = makeModuleMap(moduleName),
    1057                     hasInteractive = useInteractive;
    1058 
    1059                 //As of 2.1.0, support just passing the text, to reinforce
    1060                 //fromText only being called once per resource. Still
    1061                 //support old style of passing moduleName but discard
    1062                 //that moduleName in favor of the internal ref.
    1063                 if (textAlt) {
    1064                     text = textAlt;
    1065                 }
    1066 
    1067                 //Turn off interactive script matching for IE for any define
    1068                 //calls in the text, then turn it back on at the end.
    1069                 if (hasInteractive) {
    1070                     useInteractive = false;
    1071                 }
    1072 
    1073                 //Prime the system by creating a module instance for
    1074                 //it.
    1075                 getModule(moduleMap);
    1076 
    1077                 //Transfer any config to this other module.
    1078                 if (hasProp(config.config, id)) {
    1079                     config.config[moduleName] = config.config[id];
    1080                 }
    1081 
    1082                 try {
    1083                     req.exec(text);
    1084                 } catch (e) {
    1085                     return onError(makeError('fromtexteval',
    1086                         'fromText eval for ' + id +
    1087                         ' failed: ' + e,
    1088                         e,
    1089                         [id]));
    1090                 }
    1091 
    1092                 if (hasInteractive) {
    1093                     useInteractive = true;
    1094                 }
    1095 
    1096                 //Mark this as a dependency for the plugin
    1097                 //resource
    1098                 this.depMaps.push(moduleMap);
    1099 
    1100                 //Support anonymous modules.
    1101                 context.completeLoad(moduleName);
    1102 
    1103                 //Bind the value of that module to the value for this
    1104                 //resource ID.
    1105                 localRequire([moduleName], load);
    1106             });
    1107 
    1108             //Use parentName here since the plugin's name is not reliable,
    1109             //could be some weird string with no path that actually wants to
    1110             //reference the parentName's path.
    1111             plugin.load(map.name, localRequire, load, config);
    1112         }));
    1113 
    1114         context.enable(pluginMap, this);
    1115         this.pluginMaps[pluginMap.id] = pluginMap;
    1116     },
    1117 
    1118     enable: function () {
    1119         enabledRegistry[this.map.id] = this;
    1120         this.enabled = true;
    1121 
    1122         //Set flag mentioning that the module is enabling,
    1123         //so that immediate calls to the defined callbacks
    1124         //for dependencies do not trigger inadvertent load
    1125         //with the depCount still being zero.
    1126         this.enabling = true;
    1127 
    1128         //Enable each dependency
    1129         each(this.depMaps, bind(this, function (depMap, i) {
    1130             var id, mod, handler;
    1131 
    1132             if (typeof depMap === 'string') {
    1133                 //Dependency needs to be converted to a depMap
    1134                 //and wired up to this module.
    1135                 depMap = makeModuleMap(depMap,
    1136                     (this.map.isDefine ? this.map : this.map.parentMap),
    1137                     false,
    1138                     !this.skipMap);
    1139                 this.depMaps[i] = depMap;
    1140 
    1141                 handler = getOwn(handlers, depMap.id);
    1142 
    1143                 if (handler) {
    1144                     this.depExports[i] = handler(this);
    1145                     return;
    1146                 }
    1147 
    1148                 this.depCount += 1;
    1149 
    1150                 on(depMap, 'defined', bind(this, function (depExports) {
    1151                     if (this.undefed) {
    1152                         return;
    1153                     }
    1154                     this.defineDep(i, depExports);
    1155                     this.check();
    1156                 }));
    1157 
    1158                 if (this.errback) {
    1159                     on(depMap, 'error', bind(this, this.errback));
    1160                 } else if (this.events.error) {
    1161                     // No direct errback on this module, but something
    1162                     // else is listening for errors, so be sure to
    1163                     // propagate the error correctly.
    1164                     on(depMap, 'error', bind(this, function(err) {
    1165                         this.emit('error', err);
    1166                     }));
    1167                 }
    1168             }
    1169 
    1170             id = depMap.id;
    1171             mod = registry[id];
    1172 
    1173             //Skip special modules like 'require', 'exports', 'module'
    1174             //Also, don't call enable if it is already enabled,
    1175             //important in circular dependency cases.
    1176             if (!hasProp(handlers, id) && mod && !mod.enabled) {
    1177                 context.enable(depMap, this);
    1178             }
    1179         }));
    1180 
    1181         //Enable each plugin that is used in
    1182         //a dependency
    1183         eachProp(this.pluginMaps, bind(this, function (pluginMap) {
    1184             var mod = getOwn(registry, pluginMap.id);
    1185             if (mod && !mod.enabled) {
    1186                 context.enable(pluginMap, this);
    1187             }
    1188         }));
    1189 
    1190         this.enabling = false;
    1191 
    1192         this.check();
    1193     },
    1194 
    1195     on: function (name, cb) {
    1196         var cbs = this.events[name];
    1197         if (!cbs) {
    1198             cbs = this.events[name] = [];
    1199         }
    1200         cbs.push(cb);
    1201     },
    1202 
    1203     emit: function (name, evt) {
    1204         each(this.events[name], function (cb) {
    1205             cb(evt);
    1206         });
    1207         if (name === 'error') {
    1208             //Now that the error handler was triggered, remove
    1209             //the listeners, since this broken Module instance
    1210             //can stay around for a while in the registry.
    1211             delete this.events[name];
    1212         }
    1213     }
    1214 };
    1215 
    1216 /*-----------------------------------------end--------------------------------*/
    1217 /*
    1218 *
    1219 *
    1220 *
    1221 * */
    1222 /*-----------------------------------------start--------------------------------*/
    1223 //num = 11
    1224 
    1225 //init: function (depMaps, factory, errback, options) {}
    1226 
    1227 this.factory = factory;
    1228 this.depMaps = depMaps && depMaps.slice(0);
    1229 
    1230 this.errback = errback;
    1231 
    1232 //Indicate this module has be initialized
    1233 this.inited = true;
    1234 
    1235 this.ignore = options.ignore;
    1236 
    1237 //总结一句话  就是给module.绑定数据。
    1238 /*----------------------------------------end-------------------------*/
    1239 /*
    1240  *
    1241  * */
    1242 /*----------------------------------------start-------------------------*/
    1243 num == 12
    1244 
    1245 
    1246 /*----------------------------------------end-------------------------*/
    1247 /*
    1248  *
    1249  * */

    /*---------------------------------------start-------------------------------*/
    req({}); // num == 1 跳到 num == 2

    //Exports some context-sensitive methods on global require.
    each([
    'toUrl',
    'undef',
    'defined',
    'specified'
    ], function (prop) {
    //Reference from contexts instead of early binding to default context,
    //so that during builds, the latest instance of the default context
    //with its config gets used.
    req[prop] = function () {
    var ctx = contexts[defContextName];
    return ctx.require[prop].apply(ctx, arguments);
    };
    });

    if (isBrowser && !cfg.skipDataMain) {} //req.deps[mainscript]


    //Set up with config info.
    req(cfg); //最后启动。 按照之前写的num 一步一步的去加载。

    /*----------------------------------------start---------------------------------*/
    //第一次 num == 2
    //params

    var deps = {},
    callback = undefined,
    errback = undefined,
    optional = undefined;


    //--------------声明------------------
    var context = undefined,
    config = undefined,
    contextName = defContextName;

    //-------------判断---------------

    config = {};
    deps = [];

    //------------判断--------------
    context = contexts[contextName] = req.s.newContext(contextName); //跳到num ==3

    //时间上就是执行 localRequire(deps, callback, errback);
    context.require(deps, callback, errback); //跳到 num ==5


    /*---------------------------------------end-------------------------------*/
    /*
    *
    *
    * */
    /*---------------------------------------start-------------------------------*/
    //-----------------------进入核心函数--------------------------
    //第一次
    //function newContext(contextName) num == 3
    context = {
    config: config,
    contextName: contextName,
    registry: registry,
    defined: defined,
    urlFetched: urlFetched,
    defQueue: defQueue,
    defQueueMap: {},
    Module: Module,
    makeModuleMap: makeModuleMap,
    nextTick: req.nextTick,
    onError: onError,

    /**
    * Set a configuration for the context.
    * @param {Object} cfg config object to integrate.
    */
    configure: function (cfg) {
    //Make sure the baseUrl ends in a slash.
    if (cfg.baseUrl) {
    if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
    cfg.baseUrl += '/';
    }
    }

    // Convert old style urlArgs string to a function.
    if (typeof cfg.urlArgs === 'string') {
    var urlArgs = cfg.urlArgs;
    cfg.urlArgs = function(id, url) {
    return (url.indexOf('?') === -1 ? '?' : '&') + urlArgs;
    };
    }

    //Save off the paths since they require special processing,
    //they are additive.
    var shim = config.shim,
    objs = {
    paths: true,
    bundles: true,
    config: true,
    map: true
    };

    eachProp(cfg, function (value, prop) {
    if (objs[prop]) {
    if (!config[prop]) {
    config[prop] = {};
    }
    mixin(config[prop], value, true, true);
    } else {
    config[prop] = value;
    }
    });

    //Reverse map the bundles
    if (cfg.bundles) {
    eachProp(cfg.bundles, function (value, prop) {
    each(value, function (v) {
    if (v !== prop) {
    bundlesMap[v] = prop;
    }
    });
    });
    }

    //Merge shim
    if (cfg.shim) {
    eachProp(cfg.shim, function (value, id) {
    //Normalize the structure
    if (isArray(value)) {
    value = {
    deps: value
    };
    }
    if ((value.exports || value.init) && !value.exportsFn) {
    value.exportsFn = context.makeShimExports(value);
    }
    shim[id] = value;
    });
    config.shim = shim;
    }

    //Adjust packages if necessary.
    if (cfg.packages) {
    each(cfg.packages, function (pkgObj) {
    var location, name;

    pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj;

    name = pkgObj.name;
    location = pkgObj.location;
    if (location) {
    config.paths[name] = pkgObj.location;
    }

    //Save pointer to main module ID for pkg name.
    //Remove leading dot in main, so main paths are normalized,
    //and remove any trailing .js, since different package
    //envs have different conventions: some use a module name,
    //some use a file name.
    config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
    .replace(currDirRegExp, '')
    .replace(jsSuffixRegExp, '');
    });
    }

    //If there are any "waiting to execute" modules in the registry,
    //update the maps for them, since their info, like URLs to load,
    //may have changed.
    eachProp(registry, function (mod, id) {
    //If module already has init called, since it is too
    //late to modify them, and ignore unnormalized ones
    //since they are transient.
    if (!mod.inited && !mod.map.unnormalized) {
    mod.map = makeModuleMap(id, null, true);
    }
    });

    //If a deps array or a config callback is specified, then call
    //require with those args. This is useful when require is defined as a
    //config object before require.js is loaded.
    if (cfg.deps || cfg.callback) {
    context.require(cfg.deps || [], cfg.callback);
    }
    },

    makeShimExports: function (value) {
    function fn() {
    var ret;
    if (value.init) {
    ret = value.init.apply(global, arguments);
    }
    return ret || (value.exports && getGlobal(value.exports));
    }
    return fn;
    },

    makeRequire: function (relMap, options) {
    options = options || {};

    function localRequire(deps, callback, errback) {
    var id, map, requireMod;

    if (options.enableBuildCallback && callback && isFunction(callback)) {
    callback.__requireJsBuild = true;
    }

    if (typeof deps === 'string') {
    if (isFunction(callback)) {
    //Invalid call
    return onError(makeError('requireargs', 'Invalid require call'), errback);
    }

    //If require|exports|module are requested, get the
    //value for them from the special handlers. Caveat:
    //this only works while module is being defined.
    if (relMap && hasProp(handlers, deps)) {
    return handlers[deps](registry[relMap.id]);
    }

    //Synchronous access to one module. If require.get is
    //available (as in the Node adapter), prefer that.
    if (req.get) {
    return req.get(context, deps, relMap, localRequire);
    }

    //Normalize module name, if it contains . or ..
    map = makeModuleMap(deps, relMap, false, true);
    id = map.id;

    if (!hasProp(defined, id)) {
    return onError(makeError('notloaded', 'Module name "' +
    id +
    '" has not been loaded yet for context: ' +
    contextName +
    (relMap ? '' : '. Use require([])')));
    }
    return defined[id];
    }

    //Grab defines waiting in the global queue.
    intakeDefines();

    //Mark all the dependencies as needing to be loaded.
    context.nextTick(function () {
    //Some defines could have been added since the
    //require call, collect them.
    intakeDefines();

    requireMod = getModule(makeModuleMap(null, relMap));

    //Store if map config should be applied to this require
    //call for dependencies.
    requireMod.skipMap = options.skipMap;

    requireMod.init(deps, callback, errback, {
    enabled: true
    });

    checkLoaded();
    });

    return localRequire;
    }

    mixin(localRequire, {
    isBrowser: isBrowser,

    /**
    * Converts a module name + .extension into an URL path.
    * *Requires* the use of a module name. It does not support using
    * plain URLs like nameToUrl.
    */
    toUrl: function (moduleNamePlusExt) {
    var ext,
    index = moduleNamePlusExt.lastIndexOf('.'),
    segment = moduleNamePlusExt.split('/')[0],
    isRelative = segment === '.' || segment === '..';

    //Have a file extension alias, and it is not the
    //dots from a relative path.
    if (index !== -1 && (!isRelative || index > 1)) {
    ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
    moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
    }

    return context.nameToUrl(normalize(moduleNamePlusExt,
    relMap && relMap.id, true), ext, true);
    },

    defined: function (id) {
    return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
    },

    specified: function (id) {
    id = makeModuleMap(id, relMap, false, true).id;
    return hasProp(defined, id) || hasProp(registry, id);
    }
    });

    //Only allow undef on top level require calls
    if (!relMap) {
    localRequire.undef = function (id) {
    //Bind any waiting define() calls to this context,
    //fix for #408
    takeGlobalQueue();

    var map = makeModuleMap(id, relMap, true),
    mod = getOwn(registry, id);

    mod.undefed = true;
    removeScript(id);

    delete defined[id];
    delete urlFetched[map.url];
    delete undefEvents[id];

    //Clean queued defines too. Go backwards
    //in array so that the splices do not
    //mess up the iteration.
    eachReverse(defQueue, function(args, i) {
    if (args[0] === id) {
    defQueue.splice(i, 1);
    }
    });
    delete context.defQueueMap[id];

    if (mod) {
    //Hold on to listeners in case the
    //module will be attempted to be reloaded
    //using a different config.
    if (mod.events.defined) {
    undefEvents[id] = mod.events;
    }

    cleanRegistry(id);
    }
    };
    }

    return localRequire;
    },

    /**
    * Called to enable a module if it is still in the registry
    * awaiting enablement. A second arg, parent, the parent module,
    * is passed in for context, when this method is overridden by
    * the optimizer. Not shown here to keep code compact.
    */
    enable: function (depMap) {
    var mod = getOwn(registry, depMap.id);
    if (mod) {
    getModule(depMap).enable();
    }
    },

    /**
    * Internal method used by environment adapters to complete a load event.
    * A load event could be a script load or just a load pass from a synchronous
    * load call.
    * @param {String} moduleName the name of the module to potentially complete.
    */
    completeLoad: function (moduleName) {
    var found, args, mod,
    shim = getOwn(config.shim, moduleName) || {},
    shExports = shim.exports;

    takeGlobalQueue();

    while (defQueue.length) {
    args = defQueue.shift();
    if (args[0] === null) {
    args[0] = moduleName;
    //If already found an anonymous module and bound it
    //to this name, then this is some other anon module
    //waiting for its completeLoad to fire.
    if (found) {
    break;
    }
    found = true;
    } else if (args[0] === moduleName) {
    //Found matching define call for this script!
    found = true;
    }

    callGetModule(args);
    }
    context.defQueueMap = {};

    //Do this after the cycle of callGetModule in case the result
    //of those calls/init calls changes the registry.
    mod = getOwn(registry, moduleName);

    if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
    if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
    if (hasPathFallback(moduleName)) {
    return;
    } else {
    return onError(makeError('nodefine',
    'No define call for ' + moduleName,
    null,
    [moduleName]));
    }
    } else {
    //A script that does not call define(), so just simulate
    //the call for it.
    callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
    }
    }

    checkLoaded();
    },

    /**
    * Converts a module name to a file path. Supports cases where
    * moduleName may actually be just an URL.
    * Note that it **does not** call normalize on the moduleName,
    * it is assumed to have already been normalized. This is an
    * internal API, not a public one. Use toUrl for the public API.
    */
    nameToUrl: function (moduleName, ext, skipExt) {
    var paths, syms, i, parentModule, url,
    parentPath, bundleId,
    pkgMain = getOwn(config.pkgs, moduleName);

    if (pkgMain) {
    moduleName = pkgMain;
    }

    bundleId = getOwn(bundlesMap, moduleName);

    if (bundleId) {
    return context.nameToUrl(bundleId, ext, skipExt);
    }

    //If a colon is in the URL, it indicates a protocol is used and it is just
    //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
    //or ends with .js, then assume the user meant to use an url and not a module id.
    //The slash is important for protocol-less URLs as well as full paths.
    if (req.jsExtRegExp.test(moduleName)) {
    //Just a plain path, not module name lookup, so just return it.
    //Add extension if it is included. This is a bit wonky, only non-.js things pass
    //an extension, this method probably needs to be reworked.
    url = moduleName + (ext || '');
    } else {
    //A module that needs to be converted to a path.
    paths = config.paths;

    syms = moduleName.split('/');
    //For each module name segment, see if there is a path
    //registered for it. Start with most specific name
    //and work up from it.
    for (i = syms.length; i > 0; i -= 1) {
    parentModule = syms.slice(0, i).join('/');

    parentPath = getOwn(paths, parentModule);
    if (parentPath) {
    //If an array, it means there are a few choices,
    //Choose the one that is desired
    if (isArray(parentPath)) {
    parentPath = parentPath[0];
    }
    syms.splice(0, i, parentPath);
    break;
    }
    }

    //Join the path parts together, then figure out if baseUrl is needed.
    url = syms.join('/');
    url += (ext || (/^data:|^blob:|?/.test(url) || skipExt ? '' : '.js'));
    url = (url.charAt(0) === '/' || url.match(/^[w+.-]+:/) ? '' : config.baseUrl) + url;
    }

    return config.urlArgs && !/^blob:/.test(url) ?
    url + config.urlArgs(moduleName, url) : url;
    },

    //Delegates to req.load. Broken out as a separate function to
    //allow overriding in the optimizer.
    load: function (id, url) {
    req.load(context, id, url);
    },

    /**
    * Executes a module callback function. Broken out as a separate function
    * solely to allow the build system to sequence the files in the built
    * layer in the right sequence.
    *
    * @private
    */
    execCb: function (name, callback, args, exports) {
    return callback.apply(exports, args);
    },

    /**
    * callback for script loads, used to check status of loading.
    *
    * @param {Event} evt the event from the browser for the script
    * that was loaded.
    */
    onScriptLoad: function (evt) {
    //Using currentTarget instead of target for Firefox 2.0's sake. Not
    //all old browsers will be supported, but this one was easy enough
    //to support and still makes sense.
    if (evt.type === 'load' ||
    (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
    //Reset interactive script so a script node is not held onto for
    //to long.
    interactiveScript = null;

    //Pull out the name of the module and the context.
    var data = getScriptData(evt);
    context.completeLoad(data.id);
    }
    },

    /**
    * Callback for script errors.
    */
    onScriptError: function (evt) {
    var data = getScriptData(evt);
    if (!hasPathFallback(data.id)) {
    var parents = [];
    eachProp(registry, function(value, key) {
    if (key.indexOf('_@r') !== 0) {
    each(value.depMaps, function(depMap) {
    if (depMap.id === data.id) {
    parents.push(key);
    return true;
    }
    });
    }
    });
    return onError(makeError('scripterror', 'Script error for "' + data.id +
    (parents.length ?
    '", needed by: ' + parents.join(', ') :
    '"'), evt, [data.id]));
    }
    }
    };

    //得到一个闭包环境
    context.require = context.makeRequire(); //跳到num ===4

    //return context;
    /*---------------------------------------end-------------------------------*/
    /*
    *
    *
    *
    *
    *
    * */
    /*---------------------------------------start-------------------------------*/
    //--------------------------进入makeRequire------------------------
    //第一次
    //params [relMap , options] num == 4

    var relMap = undefined,
    options = {};


    //声明localRequire函数
    var localRequire= function(deps, callback, errback){};

    //给localRequire加属性
    var fn1={
    isBrowser: isBrowser,

    /**
    * Converts a module name + .extension into an URL path.
    * *Requires* the use of a module name. It does not support using
    * plain URLs like nameToUrl.
    */
    toUrl: function (moduleNamePlusExt) {
    var ext,
    index = moduleNamePlusExt.lastIndexOf('.'),
    segment = moduleNamePlusExt.split('/')[0],
    isRelative = segment === '.' || segment === '..';

    //Have a file extension alias, and it is not the
    //dots from a relative path.
    if (index !== -1 && (!isRelative || index > 1)) {
    ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
    moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
    }

    return context.nameToUrl(normalize(moduleNamePlusExt,
    relMap && relMap.id, true), ext, true);
    },

    defined: function (id) {
    return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
    },

    specified: function (id) {
    id = makeModuleMap(id, relMap, false, true).id;
    return hasProp(defined, id) || hasProp(registry, id);
    }
    };


    //---------------------- 判断 if (!relMap)----------------------

    //加属性

    var fn2 = undef = function(id){};

    //返回return localRequire;

    //总结一下 就是返回一个函数,给他加了一些属性;
    /*---------------------------------------end-------------------------------*/
    /*
    *
    * */

    /*---------------------------------------start-------------------------------*/
    // num == 5
    intakeDefines() // 调到num == 6
    /*
    * while (defQueue.length) {}遍历 defQueue;
    *
    *
    *
    * */

    callGetModule(args); //args [id,deps,callb] 跳到num = 7

    context.defQueueMap = {};

    context.nextTick(function () {
    //Some defines could have been added since the
    //require call, collect them.
    intakeDefines();

    requireMod = getModule(makeModuleMap(null, relMap));

    //Store if map config should be applied to this require
    //call for dependencies.
    requireMod.skipMap = options.skipMap;

    requireMod.init(deps, callback, errback, {
    enabled: true
    });

    checkLoaded();
    }); //跳转到 12


    /*---------------------------------------end-------------------------------*/
    /*
    *
    *
    *
    *
    * */
    /*---------------------------------------start-------------------------------*/
    /* function takeGlobalQueue() num == 6
    * */

    //把globalDefQueue 里面通过define(id,desp,callback) 都放到 特定context 下的 defQueue

    //并且最后清空 globalDefQueue = [];

    /*---------------------------------------end-------------------------------*/
    /*
    *
    *
    *
    *
    * */
    /*---------------------------------------start-------------------------------*/
    // function callGetModule(args) num == 7

    //将 defined里没有的 id进行构建模块
    if (!hasProp(defined, args[0])) {
    getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
    }

    makeModuleMap(args[0], null, true) //跳转到 num== 8

    getModule(makeModuleMap(args[0], null, true)) //跳转到 num == 9

    getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);//跳转到 num == 11
    //生成的Module 里面的map属性 就是 makeModuleMap返回的对象。


    /*---------------------------------------end-------------------------------*/
    /*
    *
    *
    *
    *
    * */
    /*---------------------------------------start-------------------------------*/

    //function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) //num == 8

    //返回obj
    var obj = {
    prefix: prefix,
    name: normalizedName,
    parentMap: parentModuleMap,
    unnormalized: !!suffix,
    url: url,
    originalName: originalName,
    isDefine: isDefine,
    id: (prefix ?
    prefix + '!' + normalizedName :
    normalizedName) + suffix
    };

    /*---------------------------------------end-------------------------------*/
    /*
    *
    *
    *
    *
    * */
    /*-----------------------------------------start--------------------------------*/

    //function getModule(depMap) num == 9
    var id = depMap.id,
    mod = getOwn(registry, id);

    if (!mod) {
    mod = registry[id] = new context.Module(depMap);
    }

    new context.Module(depMap); //跳转到10

    //return mod;

    /*----------------------------------------end-------------------------*/
    /*
    *
    *
    *
    *
    * */
    /*-----------------------------------------start--------------------------------*/
    //num ===10
    Module = function (map) {
    this.events = getOwn(undefEvents, map.id) || {};
    this.map = map;
    this.shim = getOwn(config.shim, map.id);
    this.depExports = [];
    this.depMaps = [];
    this.depMatched = [];
    this.pluginMaps = {};
    this.depCount = 0;

    /* this.exports this.factory
    this.depMaps = [],
    this.enabled, this.fetched
    */
    };

    Module.prototype = {
    init: function (depMaps, factory, errback, options) {
    options = options || {};

    //Do not do more inits if already done. Can happen if there
    //are multiple define calls for the same module. That is not
    //a normal, common case, but it is also not unexpected.
    if (this.inited) {
    return;
    }

    this.factory = factory;

    if (errback) {
    //Register for errors on this module.
    this.on('error', errback);
    } else if (this.events.error) {
    //If no errback already, but there are error listeners
    //on this module, set up an errback to pass to the deps.
    errback = bind(this, function (err) {
    this.emit('error', err);
    });
    }

    //Do a copy of the dependency array, so that
    //source inputs are not modified. For example
    //"shim" deps are passed in here directly, and
    //doing a direct modification of the depMaps array
    //would affect that config.
    this.depMaps = depMaps && depMaps.slice(0);

    this.errback = errback;

    //Indicate this module has be initialized
    this.inited = true;

    this.ignore = options.ignore;

    //Could have option to init this module in enabled mode,
    //or could have been previously marked as enabled. However,
    //the dependencies are not known until init is called. So
    //if enabled previously, now trigger dependencies as enabled.
    if (options.enabled || this.enabled) {
    //Enable this module and dependencies.
    //Will call this.check()
    this.enable();
    } else {
    this.check();
    }
    },

    defineDep: function (i, depExports) {
    //Because of cycles, defined callback for a given
    //export can be called more than once.
    if (!this.depMatched[i]) {
    this.depMatched[i] = true;
    this.depCount -= 1;
    this.depExports[i] = depExports;
    }
    },

    fetch: function () {
    if (this.fetched) {
    return;
    }
    this.fetched = true;

    context.startTime = (new Date()).getTime();

    var map = this.map;

    //If the manager is for a plugin managed resource,
    //ask the plugin to load it now.
    if (this.shim) {
    context.makeRequire(this.map, {
    enableBuildCallback: true
    })(this.shim.deps || [], bind(this, function () {
    return map.prefix ? this.callPlugin() : this.load();
    }));
    } else {
    //Regular dependency.
    return map.prefix ? this.callPlugin() : this.load();
    }
    },

    load: function () {
    var url = this.map.url;

    //Regular dependency.
    if (!urlFetched[url]) {
    urlFetched[url] = true;
    context.load(this.map.id, url);
    }
    },

    /**
    * Checks if the module is ready to define itself, and if so,
    * define it.
    */
    check: function () {
    if (!this.enabled || this.enabling) {
    return;
    }

    var err, cjsModule,
    id = this.map.id,
    depExports = this.depExports,
    exports = this.exports,
    factory = this.factory;

    if (!this.inited) {
    // Only fetch if not already in the defQueue.
    if (!hasProp(context.defQueueMap, id)) {
    this.fetch();
    }
    } else if (this.error) {
    this.emit('error', this.error);
    } else if (!this.defining) {
    //The factory could trigger another require call
    //that would result in checking this module to
    //define itself again. If already in the process
    //of doing that, skip this work.
    this.defining = true;

    if (this.depCount < 1 && !this.defined) {
    if (isFunction(factory)) {
    //If there is an error listener, favor passing
    //to that instead of throwing an error. However,
    //only do it for define()'d modules. require
    //errbacks should not be called for failures in
    //their callbacks (#699). However if a global
    //onError is set, use that.
    if ((this.events.error && this.map.isDefine) ||
    req.onError !== defaultOnError) {
    try {
    exports = context.execCb(id, factory, depExports, exports);
    } catch (e) {
    err = e;
    }
    } else {
    exports = context.execCb(id, factory, depExports, exports);
    }

    // Favor return value over exports. If node/cjs in play,
    // then will not have a return value anyway. Favor
    // module.exports assignment over exports object.
    if (this.map.isDefine && exports === undefined) {
    cjsModule = this.module;
    if (cjsModule) {
    exports = cjsModule.exports;
    } else if (this.usingExports) {
    //exports already set the defined value.
    exports = this.exports;
    }
    }

    if (err) {
    err.requireMap = this.map;
    err.requireModules = this.map.isDefine ? [this.map.id] : null;
    err.requireType = this.map.isDefine ? 'define' : 'require';
    return onError((this.error = err));
    }

    } else {
    //Just a literal value
    exports = factory;
    }

    this.exports = exports;

    if (this.map.isDefine && !this.ignore) {
    defined[id] = exports;

    if (req.onResourceLoad) {
    var resLoadMaps = [];
    each(this.depMaps, function (depMap) {
    resLoadMaps.push(depMap.normalizedMap || depMap);
    });
    req.onResourceLoad(context, this.map, resLoadMaps);
    }
    }

    //Clean up
    cleanRegistry(id);

    this.defined = true;
    }

    //Finished the define stage. Allow calling check again
    //to allow define notifications below in the case of a
    //cycle.
    this.defining = false;

    if (this.defined && !this.defineEmitted) {
    this.defineEmitted = true;
    this.emit('defined', this.exports);
    this.defineEmitComplete = true;
    }

    }
    },

    callPlugin: function () {
    var map = this.map,
    id = map.id,
    //Map already normalized the prefix.
    pluginMap = makeModuleMap(map.prefix);

    //Mark this as a dependency for this plugin, so it
    //can be traced for cycles.
    this.depMaps.push(pluginMap);

    on(pluginMap, 'defined', bind(this, function (plugin) {
    var load, normalizedMap, normalizedMod,
    bundleId = getOwn(bundlesMap, this.map.id),
    name = this.map.name,
    parentName = this.map.parentMap ? this.map.parentMap.name : null,
    localRequire = context.makeRequire(map.parentMap, {
    enableBuildCallback: true
    });

    //If current map is not normalized, wait for that
    //normalized name to load instead of continuing.
    if (this.map.unnormalized) {
    //Normalize the ID if the plugin allows it.
    if (plugin.normalize) {
    name = plugin.normalize(name, function (name) {
    return normalize(name, parentName, true);
    }) || '';
    }

    //prefix and name should already be normalized, no need
    //for applying map config again either.
    normalizedMap = makeModuleMap(map.prefix + '!' + name,
    this.map.parentMap);
    on(normalizedMap,
    'defined', bind(this, function (value) {
    this.map.normalizedMap = normalizedMap;
    this.init([], function () { return value; }, null, {
    enabled: true,
    ignore: true
    });
    }));

    normalizedMod = getOwn(registry, normalizedMap.id);
    if (normalizedMod) {
    //Mark this as a dependency for this plugin, so it
    //can be traced for cycles.
    this.depMaps.push(normalizedMap);

    if (this.events.error) {
    normalizedMod.on('error', bind(this, function (err) {
    this.emit('error', err);
    }));
    }
    normalizedMod.enable();
    }

    return;
    }

    //If a paths config, then just load that file instead to
    //resolve the plugin, as it is built into that paths layer.
    if (bundleId) {
    this.map.url = context.nameToUrl(bundleId);
    this.load();
    return;
    }

    load = bind(this, function (value) {
    this.init([], function () { return value; }, null, {
    enabled: true
    });
    });

    load.error = bind(this, function (err) {
    this.inited = true;
    this.error = err;
    err.requireModules = [id];

    //Remove temp unnormalized modules for this module,
    //since they will never be resolved otherwise now.
    eachProp(registry, function (mod) {
    if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
    cleanRegistry(mod.map.id);
    }
    });

    onError(err);
    });

    //Allow plugins to load other code without having to know the
    //context or how to 'complete' the load.
    load.fromText = bind(this, function (text, textAlt) {
    /*jslint evil: true */
    var moduleName = map.name,
    moduleMap = makeModuleMap(moduleName),
    hasInteractive = useInteractive;

    //As of 2.1.0, support just passing the text, to reinforce
    //fromText only being called once per resource. Still
    //support old style of passing moduleName but discard
    //that moduleName in favor of the internal ref.
    if (textAlt) {
    text = textAlt;
    }

    //Turn off interactive script matching for IE for any define
    //calls in the text, then turn it back on at the end.
    if (hasInteractive) {
    useInteractive = false;
    }

    //Prime the system by creating a module instance for
    //it.
    getModule(moduleMap);

    //Transfer any config to this other module.
    if (hasProp(config.config, id)) {
    config.config[moduleName] = config.config[id];
    }

    try {
    req.exec(text);
    } catch (e) {
    return onError(makeError('fromtexteval',
    'fromText eval for ' + id +
    ' failed: ' + e,
    e,
    [id]));
    }

    if (hasInteractive) {
    useInteractive = true;
    }

    //Mark this as a dependency for the plugin
    //resource
    this.depMaps.push(moduleMap);

    //Support anonymous modules.
    context.completeLoad(moduleName);

    //Bind the value of that module to the value for this
    //resource ID.
    localRequire([moduleName], load);
    });

    //Use parentName here since the plugin's name is not reliable,
    //could be some weird string with no path that actually wants to
    //reference the parentName's path.
    plugin.load(map.name, localRequire, load, config);
    }));

    context.enable(pluginMap, this);
    this.pluginMaps[pluginMap.id] = pluginMap;
    },

    enable: function () {
    enabledRegistry[this.map.id] = this;
    this.enabled = true;

    //Set flag mentioning that the module is enabling,
    //so that immediate calls to the defined callbacks
    //for dependencies do not trigger inadvertent load
    //with the depCount still being zero.
    this.enabling = true;

    //Enable each dependency
    each(this.depMaps, bind(this, function (depMap, i) {
    var id, mod, handler;

    if (typeof depMap === 'string') {
    //Dependency needs to be converted to a depMap
    //and wired up to this module.
    depMap = makeModuleMap(depMap,
    (this.map.isDefine ? this.map : this.map.parentMap),
    false,
    !this.skipMap);
    this.depMaps[i] = depMap;

    handler = getOwn(handlers, depMap.id);

    if (handler) {
    this.depExports[i] = handler(this);
    return;
    }

    this.depCount += 1;

    on(depMap, 'defined', bind(this, function (depExports) {
    if (this.undefed) {
    return;
    }
    this.defineDep(i, depExports);
    this.check();
    }));

    if (this.errback) {
    on(depMap, 'error', bind(this, this.errback));
    } else if (this.events.error) {
    // No direct errback on this module, but something
    // else is listening for errors, so be sure to
    // propagate the error correctly.
    on(depMap, 'error', bind(this, function(err) {
    this.emit('error', err);
    }));
    }
    }

    id = depMap.id;
    mod = registry[id];

    //Skip special modules like 'require', 'exports', 'module'
    //Also, don't call enable if it is already enabled,
    //important in circular dependency cases.
    if (!hasProp(handlers, id) && mod && !mod.enabled) {
    context.enable(depMap, this);
    }
    }));

    //Enable each plugin that is used in
    //a dependency
    eachProp(this.pluginMaps, bind(this, function (pluginMap) {
    var mod = getOwn(registry, pluginMap.id);
    if (mod && !mod.enabled) {
    context.enable(pluginMap, this);
    }
    }));

    this.enabling = false;

    this.check();
    },

    on: function (name, cb) {
    var cbs = this.events[name];
    if (!cbs) {
    cbs = this.events[name] = [];
    }
    cbs.push(cb);
    },

    emit: function (name, evt) {
    each(this.events[name], function (cb) {
    cb(evt);
    });
    if (name === 'error') {
    //Now that the error handler was triggered, remove
    //the listeners, since this broken Module instance
    //can stay around for a while in the registry.
    delete this.events[name];
    }
    }
    };

    /*-----------------------------------------end--------------------------------*/
    /*
    *
    *
    *
    * */
    /*-----------------------------------------start--------------------------------*/
    //num = 11

    //init: function (depMaps, factory, errback, options) {}

    this.factory = factory;
    this.depMaps = depMaps && depMaps.slice(0);

    this.errback = errback;

    //Indicate this module has be initialized
    this.inited = true;

    this.ignore = options.ignore;

    //总结一句话 就是给module.绑定数据。
    /*----------------------------------------end-------------------------*/
    /*
    *
    * */
    /*----------------------------------------start-------------------------*/
    num == 12


    /*----------------------------------------end-------------------------*/
    /*
    *
    * */



  • 相关阅读:
    第45节:Java当中的变量,面向对象
    第45节:Java当中的变量,面向对象
    第44节:Java当中的JVM
    第44节:Java当中的JVM
    第44节:Java当中的JVM
    第43节:Java学前要点
    第43节:Java学前要点
    第43节:Java学前要点
    排名次SQL语句【名次可重复时】
    js5:框架的使用,使框架之间无痕连接
  • 原文地址:https://www.cnblogs.com/huenchao/p/6024830.html
Copyright © 2020-2023  润新知