Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /** vim: et:ts=4:sw=4:sts=4 | |
| 2 * @license RequireJS 2.1.22 Copyright (c) 2010-2015, | |
| 3 * The Dojo Foundation All Rights Reserved. | |
| 4 * Available via the MIT or new BSD license. | |
| 5 * see: http://github.com/jrburke/requirejs for details | |
| 6 */ | |
| 7 //Not using strict: uneven strict support in browsers, #392, and causes | |
| 8 //problems with requirejs.exec()/transpiler plugins that may not be strict. | |
| 9 /*jslint regexp: true, nomen: true, sloppy: true */ | |
| 10 /*global window, navigator, document, importScripts, setTimeout, opera */ | |
| 11 | |
| 12 goog.provide('__crWeb.webUIRequire'); | |
| 13 | |
| 14 goog.require('__crWeb.webUIModuleLoadNotifier'); | |
|
dpapad
2016/04/28 21:28:07
Are those goog statements added on purpose? Is IOS
Eugene But (OOO till 7-30)
2016/04/29 18:04:42
Yes, here: https://codereview.chromium.org/1929783
| |
| 15 | |
| 16 | |
| 17 __crWeb.webUIModuleLoadNotifier = new WebUIModuleLoadNotifier(); | |
| 18 | |
| 19 | |
| 20 var requirejs, define; | |
| 21 (function() { | |
| 22 var req, s, | |
| 23 commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, | |
| 24 cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, | |
| 25 op = Object.prototype, | |
| 26 ostring = op.toString, | |
| 27 hasOwn = op.hasOwnProperty, | |
| 28 defContextName = '_', | |
| 29 contexts = {}, | |
| 30 globalDefQueue = []; | |
| 31 | |
| 32 | |
| 33 function isFunction(it) { | |
| 34 return ostring.call(it) === '[object Function]'; | |
| 35 } | |
| 36 | |
| 37 function isArray(it) { | |
| 38 return ostring.call(it) === '[object Array]'; | |
| 39 } | |
| 40 | |
| 41 /** | |
| 42 * Helper function for iterating over an array. If the func returns | |
| 43 * a true value, it will break out of the loop. | |
| 44 */ | |
| 45 function each(ary, func) { | |
| 46 if (ary) { | |
| 47 var i; | |
| 48 for (i = 0; i < ary.length; i += 1) { | |
| 49 if (ary[i] && func(ary[i], i, ary)) { | |
| 50 break; | |
| 51 } | |
| 52 } | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 function hasProp(obj, prop) { | |
| 57 return hasOwn.call(obj, prop); | |
| 58 } | |
| 59 | |
| 60 function getOwn(obj, prop) { | |
| 61 return hasProp(obj, prop) && obj[prop]; | |
| 62 } | |
| 63 | |
| 64 /** | |
| 65 * Cycles over properties in an object and calls a function for each | |
| 66 * property value. If the function returns a truthy value, then the | |
| 67 * iteration is stopped. | |
| 68 */ | |
| 69 function eachProp(obj, func) { | |
| 70 var prop; | |
| 71 for (prop in obj) { | |
| 72 if (hasProp(obj, prop)) { | |
| 73 if (func(obj[prop], prop)) { | |
| 74 break; | |
| 75 } | |
| 76 } | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 // Similar to Function.prototype.bind, but the 'this' object is specified | |
| 81 // first, since it is easier to read/figure out what 'this' will be. | |
| 82 function bind(obj, fn) { | |
| 83 return function() { | |
| 84 return fn.apply(obj, arguments); | |
| 85 }; | |
| 86 } | |
| 87 | |
| 88 function defaultOnError(err) { | |
| 89 throw err; | |
| 90 } | |
| 91 | |
| 92 /** | |
| 93 * Constructs an error with a pointer to an URL with more information. | |
| 94 * @param {String} id the error ID that maps to an ID on a web page. | |
| 95 * @param {String} message human readable error. | |
| 96 * @param {Error} [err] the original error, if there is one. | |
| 97 * | |
| 98 * @returns {Error} | |
| 99 */ | |
| 100 function makeError(id, msg, err, requireModules) { | |
| 101 var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); | |
| 102 e.requireType = id; | |
| 103 e.requireModules = requireModules; | |
| 104 if (err) { | |
| 105 e.originalError = err; | |
| 106 } | |
| 107 return e; | |
| 108 } | |
| 109 | |
| 110 function newContext(contextName) { | |
| 111 var inCheckLoaded, Module, context, handlers, | |
| 112 checkLoadedTimeoutId, | |
| 113 config = { | |
| 114 // Defaults. Do not set a default for map | |
| 115 // config to speed up normalize(), which | |
| 116 // will run faster if there is no default. | |
| 117 waitSeconds: 7, | |
| 118 baseUrl: './' | |
| 119 }, | |
| 120 registry = {}, | |
| 121 // registry of just enabled modules, to speed | |
| 122 // cycle breaking code when lots of modules | |
| 123 // are registered, but not activated. | |
| 124 enabledRegistry = {}, | |
| 125 defQueue = [], | |
| 126 defined = {}, | |
| 127 urlFetched = {}, | |
| 128 requireCounter = 1; | |
| 129 | |
| 130 /** | |
| 131 * Creates a module mapping that includes, module name, and path. | |
| 132 * | |
| 133 * @param {String} name the module name | |
| 134 * @param {String} [parentModuleMap] parent module map | |
| 135 * for the module name, used to resolve relative names. | |
| 136 * This is true if this call is done for a define() module ID. | |
| 137 * @param {Boolean} applyMap: apply the map config to the ID. | |
| 138 * Should only be true if this map is for a dependency. | |
| 139 * | |
| 140 * @returns {Object} | |
| 141 */ | |
| 142 function makeModuleMap(name, parentModuleMap, applyMap) { | |
| 143 var url, | |
| 144 parentName = parentModuleMap ? parentModuleMap.name : null, | |
| 145 isDefine = true; | |
| 146 | |
| 147 // If no name, then it means it is a require call, generate an | |
| 148 // internal name. | |
| 149 if (!name) { | |
| 150 isDefine = false; | |
| 151 name = '_@r' + (requireCounter += 1); | |
| 152 } | |
| 153 | |
| 154 // Account for relative paths if there is a base name. | |
| 155 url = context.nameToUrl(name); | |
| 156 | |
| 157 return { | |
| 158 name: name, | |
| 159 parentMap: parentModuleMap, | |
| 160 url: url, | |
| 161 isDefine: isDefine, | |
| 162 id: name | |
| 163 }; | |
| 164 } | |
| 165 | |
| 166 function getModule(depMap) { | |
| 167 var id = depMap.id, | |
| 168 mod = getOwn(registry, id); | |
| 169 | |
| 170 if (!mod) { | |
| 171 mod = registry[id] = new context.Module(depMap); | |
| 172 } | |
| 173 | |
| 174 return mod; | |
| 175 } | |
| 176 | |
| 177 function on(depMap, name, fn) { | |
| 178 var id = depMap.id, | |
| 179 mod = getOwn(registry, id); | |
| 180 | |
| 181 if (hasProp(defined, id) && (!mod || mod.defineEmitComplete)) { | |
| 182 if (name === 'defined') { | |
| 183 fn(defined[id]); | |
| 184 } | |
| 185 } else { | |
| 186 mod = getModule(depMap); | |
| 187 if (mod.error && name === 'error') { | |
| 188 fn(mod.error); | |
| 189 } else { | |
| 190 mod.on(name, fn); | |
| 191 } | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 function onError(err, errback) { | |
| 196 var ids = err.requireModules, | |
| 197 notified = false; | |
| 198 | |
| 199 if (errback) { | |
| 200 errback(err); | |
| 201 } else { | |
| 202 each(ids, function(id) { | |
| 203 var mod = getOwn(registry, id); | |
| 204 if (mod) { | |
| 205 // Set error on module, so it skips timeout checks. | |
| 206 mod.error = err; | |
| 207 if (mod.events.error) { | |
| 208 notified = true; | |
| 209 mod.emit('error', err); | |
| 210 } | |
| 211 } | |
| 212 }); | |
| 213 | |
| 214 if (!notified) { | |
| 215 req.onError(err); | |
| 216 } | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 /** | |
| 221 * Internal method to transfer globalQueue items to this context's | |
| 222 * defQueue. | |
| 223 */ | |
| 224 function takeGlobalQueue() { | |
| 225 // Push all the globalDefQueue items into the context's defQueue | |
| 226 if (globalDefQueue.length) { | |
| 227 each(globalDefQueue, function(queueItem) { | |
| 228 var id = queueItem[0]; | |
| 229 if (typeof id === 'string') { | |
| 230 context.defQueueMap[id] = true; | |
| 231 } | |
| 232 defQueue.push(queueItem); | |
| 233 }); | |
| 234 globalDefQueue = []; | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 handlers = { | |
| 239 'require': function(mod) { | |
| 240 if (mod.require) { | |
| 241 return mod.require; | |
| 242 } else { | |
| 243 return (mod.require = context.makeRequire()); | |
| 244 } | |
| 245 }, | |
| 246 'exports': function(mod) { | |
| 247 mod.usingExports = true; | |
| 248 if (mod.map.isDefine) { | |
| 249 if (mod.exports) { | |
| 250 return (defined[mod.map.id] = mod.exports); | |
| 251 } else { | |
| 252 return (mod.exports = defined[mod.map.id] = {}); | |
| 253 } | |
| 254 } | |
| 255 }, | |
| 256 'module': function(mod) { | |
| 257 if (mod.module) { | |
| 258 return mod.module; | |
| 259 } else { | |
| 260 return (mod.module = { | |
| 261 id: mod.map.id, | |
| 262 uri: mod.map.url, | |
| 263 config: function() { | |
| 264 return getOwn(config.config, mod.map.id) || {}; | |
| 265 }, | |
| 266 exports: mod.exports || (mod.exports = {}) | |
| 267 }); | |
| 268 } | |
| 269 } | |
| 270 }; | |
| 271 | |
| 272 function cleanRegistry(id) { | |
| 273 // Clean up machinery used for waiting modules. | |
| 274 delete registry[id]; | |
| 275 delete enabledRegistry[id]; | |
| 276 } | |
| 277 | |
| 278 function breakCycle(mod, traced, processed) { | |
| 279 var id = mod.map.id; | |
| 280 | |
| 281 if (mod.error) { | |
| 282 mod.emit('error', mod.error); | |
| 283 } else { | |
| 284 traced[id] = true; | |
| 285 each(mod.depMaps, function(depMap, i) { | |
| 286 var depId = depMap.id, | |
| 287 dep = getOwn(registry, depId); | |
| 288 | |
| 289 // Only force things that have not completed | |
| 290 // being defined, so still in the registry, | |
| 291 // and only if it has not been matched up | |
| 292 // in the module already. | |
| 293 if (dep && !mod.depMatched[i] && !processed[depId]) { | |
| 294 if (getOwn(traced, depId)) { | |
| 295 mod.defineDep(i, defined[depId]); | |
| 296 mod.check(); //pass false? | |
| 297 } else { | |
| 298 breakCycle(dep, traced, processed); | |
| 299 } | |
| 300 } | |
| 301 }); | |
| 302 processed[id] = true; | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 function checkLoaded() { | |
| 307 var err, | |
| 308 waitInterval = config.waitSeconds * 1000, | |
| 309 // It is possible to disable the wait interval by using | |
| 310 // waitSeconds of 0. | |
| 311 expired = waitInterval && | |
| 312 (context.startTime + waitInterval) < new Date().getTime(), | |
| 313 noLoads = [], | |
| 314 reqCalls = [], | |
| 315 stillLoading = false, | |
| 316 needCycleCheck = true; | |
| 317 | |
| 318 // Do not bother if this call was a result of a cycle break. | |
| 319 if (inCheckLoaded) { | |
| 320 return; | |
| 321 } | |
| 322 | |
| 323 inCheckLoaded = true; | |
| 324 | |
| 325 // Figure out the state of all the modules. | |
| 326 eachProp(enabledRegistry, function(mod) { | |
| 327 var map = mod.map, | |
| 328 modId = map.id; | |
| 329 | |
| 330 // Skip things that are not enabled or in error state. | |
| 331 if (!mod.enabled) { | |
| 332 return; | |
| 333 } | |
| 334 | |
| 335 if (!map.isDefine) { | |
| 336 reqCalls.push(mod); | |
| 337 } | |
| 338 | |
| 339 if (!mod.error) { | |
| 340 // If the module should be executed, and it has not | |
| 341 // been inited and time is up, remember it. | |
| 342 if (!mod.inited && expired) { | |
| 343 noLoads.push(modId); | |
| 344 } else if (!mod.inited && mod.fetched && map.isDefine) { | |
| 345 stillLoading = true; | |
| 346 return (needCycleCheck = false); | |
| 347 } | |
| 348 } | |
| 349 }); | |
| 350 | |
| 351 if (expired && noLoads.length) { | |
| 352 // If wait time expired, throw error of unloaded modules. | |
| 353 err = makeError('timeout', | |
| 354 'Load timeout for modules: ' + noLoads, | |
| 355 null, | |
| 356 noLoads); | |
| 357 err.contextName = context.contextName; | |
| 358 return onError(err); | |
| 359 } | |
| 360 | |
| 361 // Not expired, check for a cycle. | |
| 362 if (needCycleCheck) { | |
| 363 each(reqCalls, function(mod) { | |
| 364 breakCycle(mod, {}, {}); | |
| 365 }); | |
| 366 } | |
| 367 | |
| 368 // If still waiting on loads, and the waiting load is something | |
| 369 // other than a plugin resource, or there are still outstanding | |
| 370 // scripts, then just try back later. | |
| 371 if (!expired && stillLoading) { | |
| 372 // Something is still waiting to load. Wait for it, but only | |
| 373 // if a timeout is not already in effect. | |
| 374 if (!checkLoadedTimeoutId) { | |
| 375 checkLoadedTimeoutId = setTimeout(function() { | |
| 376 checkLoadedTimeoutId = 0; | |
| 377 checkLoaded(); | |
| 378 }, 50); | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 inCheckLoaded = false; | |
| 383 } | |
| 384 | |
| 385 Module = function(map) { | |
| 386 this.events = {}; | |
| 387 this.map = map; | |
| 388 this.depExports = []; | |
| 389 this.depMaps = []; | |
| 390 this.depMatched = []; | |
| 391 this.depCount = 0; | |
| 392 | |
| 393 /* this.exports this.factory | |
| 394 this.depMaps = [], | |
| 395 this.enabled, this.fetched | |
| 396 */ | |
| 397 }; | |
| 398 | |
| 399 Module.prototype = { | |
| 400 init: function(depMaps, factory, errback, options) { | |
| 401 options = options || {}; | |
| 402 | |
| 403 // Do not do more inits if already done. Can happen if there | |
| 404 // are multiple define calls for the same module. That is not | |
| 405 // a normal, common case, but it is also not unexpected. | |
| 406 if (this.inited) { | |
| 407 return; | |
| 408 } | |
| 409 | |
| 410 this.factory = factory; | |
| 411 | |
| 412 if (errback) { | |
| 413 // Register for errors on this module. | |
| 414 this.on('error', errback); | |
| 415 } else if (this.events.error) { | |
| 416 // If no errback already, but there are error listeners | |
| 417 // on this module, set up an errback to pass to the deps. | |
| 418 errback = bind(this, function(err) { | |
| 419 this.emit('error', err); | |
| 420 }); | |
| 421 } | |
| 422 | |
| 423 // Do a copy of the dependency array, so that | |
| 424 // source inputs are not modified. | |
| 425 this.depMaps = depMaps && depMaps.slice(0); | |
| 426 | |
| 427 this.errback = errback; | |
| 428 | |
| 429 // Indicate this module has be initialized | |
| 430 this.inited = true; | |
| 431 | |
| 432 this.ignore = options.ignore; | |
| 433 | |
| 434 // Could have option to init this module in enabled mode, | |
| 435 // or could have been previously marked as enabled. However, | |
| 436 // the dependencies are not known until init is called. So | |
| 437 // if enabled previously, now trigger dependencies as enabled. | |
| 438 if (options.enabled || this.enabled) { | |
| 439 // Enable this module and dependencies. | |
| 440 // Will call this.check() | |
| 441 this.enable(); | |
| 442 } else { | |
| 443 this.check(); | |
| 444 } | |
| 445 }, | |
| 446 | |
| 447 defineDep: function(i, depExports) { | |
| 448 // Because of cycles, defined callback for a given | |
| 449 // export can be called more than once. | |
| 450 if (!this.depMatched[i]) { | |
| 451 this.depMatched[i] = true; | |
| 452 this.depCount -= 1; | |
| 453 this.depExports[i] = depExports; | |
| 454 } | |
| 455 }, | |
| 456 | |
| 457 fetch: function() { | |
| 458 if (this.fetched) { | |
| 459 return; | |
| 460 } | |
| 461 this.fetched = true; | |
| 462 | |
| 463 context.startTime = (new Date()).getTime(); | |
| 464 | |
| 465 return this.load(); | |
| 466 }, | |
| 467 | |
| 468 load: function() { | |
| 469 var url = this.map.url; | |
| 470 | |
| 471 // Regular dependency. | |
| 472 if (!urlFetched[url]) { | |
| 473 urlFetched[url] = true; | |
| 474 context.load(this.map.id, url); | |
| 475 } | |
| 476 }, | |
| 477 | |
| 478 /** | |
| 479 * Checks if the module is ready to define itself, and if so, | |
| 480 * define it. | |
| 481 */ | |
| 482 check: function() { | |
| 483 if (!this.enabled || this.enabling) { | |
| 484 return; | |
| 485 } | |
| 486 | |
| 487 var err, cjsModule, | |
| 488 id = this.map.id, | |
| 489 depExports = this.depExports, | |
| 490 exports = this.exports, | |
| 491 factory = this.factory; | |
| 492 | |
| 493 if (!this.inited) { | |
| 494 // Only fetch if not already in the defQueue and not 'main' module. | |
| 495 if (!hasProp(context.defQueueMap, id) && this.map.name != 'main') { | |
| 496 this.fetch(); | |
| 497 } | |
| 498 } else if (this.error) { | |
| 499 this.emit('error', this.error); | |
| 500 } else if (!this.defining) { | |
| 501 // The factory could trigger another require call | |
| 502 // that would result in checking this module to | |
| 503 // define itself again. If already in the process | |
| 504 // of doing that, skip this work. | |
| 505 this.defining = true; | |
| 506 | |
| 507 if (this.depCount < 1 && !this.defined) { | |
| 508 if (isFunction(factory)) { | |
| 509 try { | |
| 510 exports = context.execCb(id, factory, depExports, exports); | |
| 511 } catch (e) { | |
| 512 err = e; | |
| 513 } | |
| 514 | |
| 515 // Favor return value over exports. If node/cjs in | |
| 516 // play, then will not have a return value anyway. | |
| 517 // Favor module.exports assignment over exports | |
| 518 // object. | |
| 519 if (this.map.isDefine && exports === undefined) { | |
| 520 cjsModule = this.module; | |
| 521 if (cjsModule) { | |
| 522 exports = cjsModule.exports; | |
| 523 } else if (this.usingExports) { | |
| 524 // exports already set the defined value. | |
| 525 exports = this.exports; | |
| 526 } | |
| 527 } | |
| 528 | |
| 529 if (err) { | |
| 530 // If there is an error listener, favor passing | |
| 531 // to that instead of throwing an error. However, | |
| 532 // only do it for define()'d modules. require | |
| 533 // errbacks should not be called for failures in | |
| 534 // their callbacks (#699). However if a global | |
| 535 // onError is set, use that. | |
| 536 if ((this.events.error && this.map.isDefine) || | |
| 537 req.onError !== defaultOnError) { | |
| 538 err.requireMap = this.map; | |
| 539 err.requireModules = this.map.isDefine ? [this.map.id] : null; | |
| 540 err.requireType = this.map.isDefine ? 'define' : 'require'; | |
| 541 return onError((this.error = err)); | |
| 542 } else if (typeof console !== 'undefined' && console.error) { | |
| 543 // Log the error for debugging. If promises could be | |
| 544 // used, this would be different, but making do. | |
| 545 console.error(err); | |
| 546 } else { | |
| 547 // Do not want to completely lose the error. While this | |
| 548 // will mess up processing and lead to similar results | |
| 549 // as bug 1440, it at least surfaces the error. | |
| 550 req.onError(err); | |
| 551 } | |
| 552 } | |
| 553 } else { | |
| 554 // Just a literal value | |
| 555 exports = factory; | |
| 556 } | |
| 557 | |
| 558 this.exports = exports; | |
| 559 | |
| 560 if (this.map.isDefine && !this.ignore) { | |
| 561 defined[id] = exports; | |
| 562 | |
| 563 if (req.onResourceLoad) { | |
| 564 var resLoadMaps = []; | |
| 565 each(this.depMaps, function(depMap) { | |
| 566 resLoadMaps.push(depMap.normalizedMap || depMap); | |
| 567 }); | |
| 568 req.onResourceLoad(context, this.map, resLoadMaps); | |
| 569 } | |
| 570 } | |
| 571 | |
| 572 // Clean up | |
| 573 cleanRegistry(id); | |
| 574 | |
| 575 this.defined = true; | |
| 576 } | |
| 577 | |
| 578 // Finished the define stage. Allow calling check again | |
| 579 // to allow define notifications below in the case of a | |
| 580 // cycle. | |
| 581 this.defining = false; | |
| 582 | |
| 583 if (this.defined && !this.defineEmitted) { | |
| 584 this.defineEmitted = true; | |
| 585 this.emit('defined', this.exports); | |
| 586 this.defineEmitComplete = true; | |
| 587 } | |
| 588 } | |
| 589 }, | |
| 590 | |
| 591 enable: function() { | |
| 592 enabledRegistry[this.map.id] = this; | |
| 593 this.enabled = true; | |
| 594 | |
| 595 // Set flag mentioning that the module is enabling, | |
| 596 // so that immediate calls to the defined callbacks | |
| 597 // for dependencies do not trigger inadvertent load | |
| 598 // with the depCount still being zero. | |
| 599 this.enabling = true; | |
| 600 | |
| 601 // Enable each dependency | |
| 602 each(this.depMaps, bind(this, function(depMap, i) { | |
| 603 var id, mod, handler; | |
| 604 | |
| 605 if (typeof depMap === 'string') { | |
| 606 // Dependency needs to be converted to a depMap | |
| 607 // and wired up to this module. | |
| 608 depMap = makeModuleMap( | |
| 609 depMap, | |
| 610 (this.map.isDefine ? this.map : this.map.parentMap), | |
| 611 true); | |
| 612 this.depMaps[i] = depMap; | |
| 613 | |
| 614 this.depCount += 1; | |
| 615 | |
| 616 on(depMap, 'defined', bind(this, function(depExports) { | |
| 617 if (this.undefed) { | |
| 618 return; | |
| 619 } | |
| 620 this.defineDep(i, depExports); | |
| 621 this.check(); | |
| 622 })); | |
| 623 | |
| 624 if (this.errback) { | |
| 625 on(depMap, 'error', bind(this, this.errback)); | |
| 626 } else if (this.events.error) { | |
| 627 // No direct errback on this module, but something | |
| 628 // else is listening for errors, so be sure to | |
| 629 // propagate the error correctly. | |
| 630 on(depMap, 'error', bind(this, function(err) { | |
| 631 this.emit('error', err); | |
| 632 })); | |
| 633 } | |
| 634 } | |
| 635 | |
| 636 id = depMap.id; | |
| 637 mod = registry[id]; | |
| 638 | |
| 639 // Skip special modules like 'require', 'exports', 'module' | |
| 640 // Also, don't call enable if it is already enabled, | |
| 641 // important in circular dependency cases. | |
| 642 if (!hasProp(handlers, id) && mod && !mod.enabled) { | |
| 643 context.enable(depMap, this); | |
| 644 } | |
| 645 })); | |
| 646 | |
| 647 this.enabling = false; | |
| 648 | |
| 649 this.check(); | |
| 650 }, | |
| 651 | |
| 652 on: function(name, cb) { | |
| 653 var cbs = this.events[name]; | |
| 654 if (!cbs) { | |
| 655 cbs = this.events[name] = []; | |
| 656 } | |
| 657 cbs.push(cb); | |
| 658 }, | |
| 659 | |
| 660 emit: function(name, evt) { | |
| 661 each(this.events[name], function(cb) { | |
| 662 cb(evt); | |
| 663 }); | |
| 664 if (name === 'error') { | |
| 665 // Now that the error handler was triggered, remove | |
| 666 // the listeners, since this broken Module instance | |
| 667 // can stay around for a while in the registry. | |
| 668 delete this.events[name]; | |
| 669 } | |
| 670 } | |
| 671 }; | |
| 672 | |
| 673 function callGetModule(args) { | |
| 674 // Skip modules already defined. | |
| 675 if (!hasProp(defined, args[0])) { | |
| 676 getModule(makeModuleMap(args[0], null)).init(args[1], args[2]); | |
| 677 } | |
| 678 } | |
| 679 | |
| 680 function intakeDefines() { | |
| 681 var args; | |
| 682 | |
| 683 // Any defined modules in the global queue, intake them now. | |
| 684 takeGlobalQueue(); | |
| 685 | |
| 686 // Make sure any remaining defQueue items get properly processed. | |
| 687 while (defQueue.length) { | |
| 688 args = defQueue.shift(); | |
| 689 if (args[0] === null) { | |
| 690 return onError(makeError('mismatch', | |
| 691 'Mismatched anonymous define() module: ' + | |
| 692 args[args.length - 1])); | |
| 693 } else { | |
| 694 // args are id, deps, factory. Should be normalized by the | |
| 695 // define() function. | |
| 696 callGetModule(args); | |
| 697 } | |
| 698 } | |
| 699 context.defQueueMap = {}; | |
| 700 } | |
| 701 | |
| 702 context = { | |
| 703 config: config, | |
| 704 contextName: contextName, | |
| 705 registry: registry, | |
| 706 defined: defined, | |
| 707 urlFetched: urlFetched, | |
| 708 defQueue: defQueue, | |
| 709 defQueueMap: {}, | |
| 710 Module: Module, | |
| 711 makeModuleMap: makeModuleMap, | |
| 712 nextTick: req.nextTick, | |
| 713 onError: onError, | |
| 714 | |
| 715 /** | |
| 716 * Set a configuration for the context. | |
| 717 */ | |
| 718 configure: function() { | |
| 719 // If there are any "waiting to execute" modules in the registry, | |
| 720 // update the maps for them, since their info, like URLs to load, | |
| 721 // may have changed. | |
| 722 eachProp(registry, function(mod, id) { | |
| 723 // If module already has init called, since it is too | |
| 724 // late to modify them. | |
| 725 if (!mod.inited) { | |
| 726 mod.map = makeModuleMap(id, null); | |
| 727 } | |
| 728 }); | |
| 729 }, | |
| 730 | |
| 731 makeRequire: function() { | |
| 732 function localRequire(deps, callback, errback) { | |
| 733 var id, map, requireMod; | |
| 734 | |
| 735 if (typeof deps === 'string') { | |
| 736 if (isFunction(callback)) { | |
| 737 // Invalid call | |
| 738 return onError(makeError('requireargs', 'Invalid require call'), | |
| 739 errback); | |
| 740 } | |
| 741 | |
| 742 // Synchronous access to one module. If require.get is | |
| 743 // available (as in the Node adapter), prefer that. | |
| 744 if (req.get) { | |
| 745 return req.get(context, deps, null, localRequire); | |
| 746 } | |
| 747 | |
| 748 // Normalize module name, if it contains . or .. | |
| 749 map = makeModuleMap(deps, null, true); | |
| 750 id = map.id; | |
| 751 | |
| 752 if (!hasProp(defined, id)) { | |
| 753 return onError(makeError( | |
| 754 'notloaded', 'Module name "' + id + | |
| 755 '" has not been loaded yet for context: ' + | |
| 756 contextName + '. Use require([])')); | |
| 757 } | |
| 758 return defined[id]; | |
| 759 } | |
| 760 | |
| 761 // Grab defines waiting in the global queue. | |
| 762 intakeDefines(); | |
| 763 | |
| 764 // Mark all the dependencies as needing to be loaded. | |
| 765 context.nextTick(function() { | |
| 766 // Some defines could have been added since the | |
| 767 // require call, collect them. | |
| 768 intakeDefines(); | |
| 769 | |
| 770 requireMod = getModule(makeModuleMap(null)); | |
| 771 | |
| 772 requireMod.init(deps, callback, errback, { | |
| 773 enabled: true | |
| 774 }); | |
| 775 | |
| 776 checkLoaded(); | |
| 777 }); | |
| 778 | |
| 779 return localRequire; | |
| 780 } | |
| 781 | |
| 782 return localRequire; | |
| 783 }, | |
| 784 | |
| 785 /** | |
| 786 * Called to enable a module if it is still in the registry | |
| 787 * awaiting enablement. A second arg, parent, the parent module, | |
| 788 * is passed in for context, when this method is overridden by | |
| 789 * the optimizer. Not shown here to keep code compact. | |
| 790 */ | |
| 791 enable: function(depMap) { | |
| 792 var mod = getOwn(registry, depMap.id); | |
| 793 if (mod) { | |
| 794 getModule(depMap).enable(); | |
| 795 } | |
| 796 }, | |
| 797 | |
| 798 /** | |
| 799 * Internal method used by environment adapters to complete a load event. | |
| 800 * A load event could be a script load or just a load pass from a | |
| 801 * synchronous load call. | |
| 802 * @param {String} moduleName the name of the module to potentially | |
| 803 * complete. | |
| 804 */ | |
| 805 completeLoad: function(moduleName) { | |
| 806 var found, args, mod; | |
| 807 takeGlobalQueue(); | |
| 808 | |
| 809 while (defQueue.length) { | |
| 810 args = defQueue.shift(); | |
| 811 if (args[0] === null) { | |
| 812 args[0] = moduleName; | |
| 813 // If already found an anonymous module and bound it | |
| 814 // to this name, then this is some other anon module | |
| 815 // waiting for its completeLoad to fire. | |
| 816 if (found) { | |
| 817 break; | |
| 818 } | |
| 819 found = true; | |
| 820 } else if (args[0] === moduleName) { | |
| 821 // Found matching define call for this script! | |
| 822 found = true; | |
| 823 } | |
| 824 | |
| 825 callGetModule(args); | |
| 826 } | |
| 827 context.defQueueMap = {}; | |
| 828 | |
| 829 // Do this after the cycle of callGetModule in case the result | |
| 830 // of those calls/init calls changes the registry. | |
| 831 mod = getOwn(registry, moduleName); | |
| 832 | |
| 833 if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { | |
| 834 // A script that does not call define(), so just simulate | |
| 835 // the call for it. | |
| 836 callGetModule([moduleName, [], null]); | |
| 837 } | |
| 838 | |
| 839 checkLoaded(); | |
| 840 }, | |
| 841 | |
| 842 /** | |
| 843 * Converts a module name to a file path. Supports cases where | |
| 844 * moduleName may actually be just an URL. | |
| 845 */ | |
| 846 nameToUrl: function(moduleName, ext) { | |
| 847 var syms, i, url, parentPath, bundleId; | |
| 848 | |
| 849 // If a colon is in the URL, it indicates a protocol is used and it | |
| 850 // is just an URL to a file, or if it starts with a slash, contains a | |
| 851 // query arg (i.e. ?) or ends with .js, then assume the user meant to | |
| 852 // use an url and not a module id. The slash is important for | |
| 853 // protocol-less URLs as well as full paths. | |
| 854 if (req.jsExtRegExp.test(moduleName)) { | |
| 855 // Just a plain path, not module name lookup, so just return it. | |
| 856 // Add extension if it is included. This is a bit wonky, only | |
| 857 // non-.js things pass an extension, this method probably needs | |
| 858 // to be reworked. | |
| 859 url = moduleName; | |
| 860 } else { | |
| 861 syms = moduleName.split('/'); | |
| 862 // Join the path parts together, then figure out if baseUrl is needed. | |
| 863 url = syms.join('/'); | |
| 864 url += (/^data\:|\?/.test(url) || '.js'); | |
| 865 url = (url.charAt(0) === '/' || | |
| 866 url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; | |
| 867 } | |
| 868 | |
| 869 return url; | |
| 870 }, | |
| 871 | |
| 872 // Delegates to req.load. Broken out as a separate function to | |
| 873 // allow overriding in the optimizer. | |
| 874 load: function(id, url) { | |
| 875 req.load(context, id, url); | |
| 876 }, | |
| 877 | |
| 878 /** | |
| 879 * Executes a module callback function. Broken out as a separate function | |
| 880 * solely to allow the build system to sequence the files in the built | |
| 881 * layer in the right sequence. | |
| 882 * | |
| 883 * @private | |
| 884 */ | |
| 885 execCb: function(name, callback, args, exports) { | |
| 886 return callback.apply(exports, args); | |
| 887 }, | |
| 888 | |
| 889 /** | |
| 890 * Direct callback for load error. | |
| 891 */ | |
| 892 onScriptFailure: function(moduleName) { | |
| 893 onError(makeError('scripterror', 'Script error for "' + | |
| 894 moduleName + '"'), null, [moduleName]); | |
| 895 }, | |
| 896 }; | |
| 897 | |
| 898 context.require = context.makeRequire(); | |
| 899 return context; | |
| 900 } | |
| 901 | |
| 902 /** | |
| 903 * Main entry point. | |
| 904 * | |
| 905 * If the only argument to require is a string, then the module that | |
| 906 * is represented by that string is fetched for the appropriate context. | |
| 907 * | |
| 908 * If the first argument is an array, then it will be treated as an array | |
| 909 * of dependency string names to fetch. An optional function callback can | |
| 910 * be specified to execute when all of those dependencies are available. | |
| 911 * | |
| 912 * Make a local req variable to help Caja compliance (it assumes things | |
| 913 * on a require that are not standardized), and to give a short | |
| 914 * name for minification/local scope use. | |
| 915 */ | |
| 916 req = requirejs = function(deps, callback, errback, optional) { | |
| 917 | |
| 918 // Find the right context, use default | |
| 919 var context, config, | |
| 920 contextName = defContextName; | |
| 921 | |
| 922 // Determine if have config object in the call. | |
| 923 if (!isArray(deps) && typeof deps !== 'string') { | |
| 924 // deps is a config object | |
| 925 config = deps; | |
| 926 if (isArray(callback)) { | |
| 927 // Adjust args if there are dependencies | |
| 928 deps = callback; | |
| 929 callback = errback; | |
| 930 errback = optional; | |
| 931 } else { | |
| 932 deps = []; | |
| 933 } | |
| 934 } | |
| 935 | |
| 936 context = getOwn(contexts, contextName); | |
| 937 if (!context) { | |
| 938 context = contexts[contextName] = req.s.newContext(contextName); | |
| 939 } | |
| 940 | |
| 941 if (config) { | |
| 942 context.configure(config); | |
| 943 } | |
| 944 | |
| 945 return context.require(deps, callback, errback); | |
| 946 }; | |
| 947 | |
| 948 /** | |
| 949 * Execute something after the current tick | |
| 950 * of the event loop. Override for other envs | |
| 951 * that have a better solution than setTimeout. | |
| 952 * @param {Function} fn function to execute later. | |
| 953 */ | |
| 954 req.nextTick = typeof setTimeout !== 'undefined' ? function(fn) { | |
| 955 setTimeout(fn, 4); | |
| 956 } : function(fn) { fn(); }; | |
| 957 | |
| 958 // Used to filter out dependencies that are already paths. | |
| 959 req.jsExtRegExp = /^\/|:|\?|\.js$/; | |
| 960 s = req.s = { | |
| 961 contexts: contexts, | |
| 962 newContext: newContext | |
| 963 }; | |
| 964 | |
| 965 // Create default context. | |
| 966 req({}); | |
| 967 | |
| 968 /** | |
| 969 * Any errors that require explicitly generates will be passed to this | |
| 970 * function. Intercept/override it if you want custom error handling. | |
| 971 * @param {Error} err the error object. | |
| 972 */ | |
| 973 req.onError = defaultOnError; | |
| 974 | |
| 975 /** | |
| 976 * Does the request to load a module for the browser case. | |
| 977 * Make this a separate function to allow other environments | |
| 978 * to override it. | |
| 979 * | |
| 980 * @param {Object} context the require context to find state. | |
| 981 * @param {String} moduleName the name of the module. | |
| 982 * @param {Object} url the URL to the module. | |
| 983 */ | |
| 984 req.load = function(context, moduleName, url) { | |
| 985 var config = (context && context.config) || {}; | |
| 986 var loadId = __crWeb.webUIModuleLoadNotifier.addPendingContext( | |
| 987 moduleName, context); | |
| 988 chrome.send('webui.loadMojo', [moduleName, loadId]); | |
| 989 }; | |
| 990 | |
| 991 /** | |
| 992 * The function that handles definitions of modules. Differs from | |
| 993 * require() in that a string for the module should be the first argument, | |
| 994 * and the function to execute after dependencies are loaded should | |
| 995 * return a value to define the module corresponding to the first argument's | |
| 996 * name. | |
| 997 */ | |
| 998 define = function(name, deps, callback) { | |
| 999 var node, context; | |
| 1000 | |
| 1001 // Allow for anonymous modules | |
| 1002 if (typeof name !== 'string') { | |
| 1003 // Adjust args appropriately | |
| 1004 callback = deps; | |
| 1005 deps = name; | |
| 1006 name = null; | |
| 1007 } | |
| 1008 | |
| 1009 // This module may not have dependencies | |
| 1010 if (!isArray(deps)) { | |
| 1011 callback = deps; | |
| 1012 deps = null; | |
| 1013 } | |
| 1014 | |
| 1015 // If no name, and callback is a function, then figure out if it a | |
| 1016 // CommonJS thing with dependencies. | |
| 1017 if (!deps && isFunction(callback)) { | |
| 1018 deps = []; | |
| 1019 // Remove comments from the callback string, | |
| 1020 // look for require calls, and pull them into the dependencies, | |
| 1021 // but only if there are function args. | |
| 1022 if (callback.length) { | |
| 1023 callback | |
| 1024 .toString() | |
| 1025 .replace(commentRegExp, '') | |
| 1026 .replace(cjsRequireRegExp, function(match, dep) { | |
| 1027 deps.push(dep); | |
| 1028 }); | |
| 1029 | |
| 1030 // May be a CommonJS thing even without require calls, but still | |
| 1031 // could use exports, and module. Avoid doing exports and module | |
| 1032 // work though if it just needs require. | |
| 1033 // REQUIRES the function to expect the CommonJS variables in the | |
| 1034 // order listed below. | |
| 1035 deps = (callback.length === 1 ? | |
| 1036 ['require'] : | |
| 1037 ['require', 'exports', 'module']).concat(deps); | |
| 1038 } | |
| 1039 } | |
| 1040 | |
| 1041 // Always save off evaluating the def call until the script onload | |
| 1042 // handler. This allows multiple modules to be in a file without | |
| 1043 // prematurely tracing dependencies, and allows for anonymous module | |
| 1044 // support, where the module name is not known until the script onload | |
| 1045 // event occurs. If no context, use the global queue, and get it | |
| 1046 // processed in the onscript load callback. | |
| 1047 if (context) { | |
| 1048 context.defQueue.push([name, deps, callback]); | |
| 1049 context.defQueueMap[name] = true; | |
| 1050 } else { | |
| 1051 globalDefQueue.push([name, deps, callback]); | |
| 1052 } | |
| 1053 }; | |
| 1054 | |
| 1055 req(); | |
| 1056 }(this)); | |
| 1057 | |
| 1058 document.addEventListener("DOMContentLoaded", function(event) { | |
| 1059 requirejs(['main'], function(main) { | |
| 1060 main(); | |
| 1061 }, function(error) { | |
| 1062 throw error; | |
| 1063 }); | |
| 1064 }); | |
| OLD | NEW |