Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame^] | 1 | /** |
| 2 | * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. |
| 3 | * Available via the MIT or new BSD license. |
| 4 | * see: http://github.com/jrburke/almond for details |
| 5 | */ |
| 6 | //Going sloppy to avoid 'use strict' string cost, but strict practices should |
| 7 | //be followed. |
| 8 | /*jslint sloppy: true */ |
| 9 | /*global setTimeout: false */ |
| 10 | |
| 11 | var requirejs, require, define; |
| 12 | (function (undef) { |
| 13 | var main, req, makeMap, handlers, |
| 14 | defined = {}, |
| 15 | waiting = {}, |
| 16 | config = {}, |
| 17 | defining = {}, |
| 18 | hasOwn = Object.prototype.hasOwnProperty, |
| 19 | aps = [].slice, |
| 20 | jsSuffixRegExp = /\.js$/; |
| 21 | |
| 22 | function hasProp(obj, prop) { |
| 23 | return hasOwn.call(obj, prop); |
| 24 | } |
| 25 | |
| 26 | /** |
| 27 | * Given a relative module name, like ./something, normalize it to |
| 28 | * a real name that can be mapped to a path. |
| 29 | * @param {String} name the relative name |
| 30 | * @param {String} baseName a real name that the name arg is relative |
| 31 | * to. |
| 32 | * @returns {String} normalized name |
| 33 | */ |
| 34 | function normalize(name, baseName) { |
| 35 | var nameParts, nameSegment, mapValue, foundMap, lastIndex, |
| 36 | foundI, foundStarMap, starI, i, j, part, |
| 37 | baseParts = baseName && baseName.split("/"), |
| 38 | map = config.map, |
| 39 | starMap = (map && map['*']) || {}; |
| 40 | |
| 41 | //Adjust any relative paths. |
| 42 | if (name && name.charAt(0) === ".") { |
| 43 | //If have a base name, try to normalize against it, |
| 44 | //otherwise, assume it is a top-level require that will |
| 45 | //be relative to baseUrl in the end. |
| 46 | if (baseName) { |
| 47 | name = name.split('/'); |
| 48 | lastIndex = name.length - 1; |
| 49 | |
| 50 | // Node .js allowance: |
| 51 | if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { |
| 52 | name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); |
| 53 | } |
| 54 | |
| 55 | //Lop off the last part of baseParts, so that . matches the |
| 56 | //"directory" and not name of the baseName's module. For instance, |
| 57 | //baseName of "one/two/three", maps to "one/two/three.js", but we |
| 58 | //want the directory, "one/two" for this normalization. |
| 59 | name = baseParts.slice(0, baseParts.length - 1).concat(name); |
| 60 | |
| 61 | //start trimDots |
| 62 | for (i = 0; i < name.length; i += 1) { |
| 63 | part = name[i]; |
| 64 | if (part === ".") { |
| 65 | name.splice(i, 1); |
| 66 | i -= 1; |
| 67 | } else if (part === "..") { |
| 68 | if (i === 1 && (name[2] === '..' || name[0] === '..')) { |
| 69 | //End of the line. Keep at least one non-dot |
| 70 | //path segment at the front so it can be mapped |
| 71 | //correctly to disk. Otherwise, there is likely |
| 72 | //no path mapping for a path starting with '..'. |
| 73 | //This can still fail, but catches the most reasonable |
| 74 | //uses of .. |
| 75 | break; |
| 76 | } else if (i > 0) { |
| 77 | name.splice(i - 1, 2); |
| 78 | i -= 2; |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | //end trimDots |
| 83 | |
| 84 | name = name.join("/"); |
| 85 | } else if (name.indexOf('./') === 0) { |
| 86 | // No baseName, so this is ID is resolved relative |
| 87 | // to baseUrl, pull off the leading dot. |
| 88 | name = name.substring(2); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | //Apply map config if available. |
| 93 | if ((baseParts || starMap) && map) { |
| 94 | nameParts = name.split('/'); |
| 95 | |
| 96 | for (i = nameParts.length; i > 0; i -= 1) { |
| 97 | nameSegment = nameParts.slice(0, i).join("/"); |
| 98 | |
| 99 | if (baseParts) { |
| 100 | //Find the longest baseName segment match in the config. |
| 101 | //So, do joins on the biggest to smallest lengths of baseParts. |
| 102 | for (j = baseParts.length; j > 0; j -= 1) { |
| 103 | mapValue = map[baseParts.slice(0, j).join('/')]; |
| 104 | |
| 105 | //baseName segment has config, find if it has one for |
| 106 | //this name. |
| 107 | if (mapValue) { |
| 108 | mapValue = mapValue[nameSegment]; |
| 109 | if (mapValue) { |
| 110 | //Match, update name to the new value. |
| 111 | foundMap = mapValue; |
| 112 | foundI = i; |
| 113 | break; |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | if (foundMap) { |
| 120 | break; |
| 121 | } |
| 122 | |
| 123 | //Check for a star map match, but just hold on to it, |
| 124 | //if there is a shorter segment match later in a matching |
| 125 | //config, then favor over this star map. |
| 126 | if (!foundStarMap && starMap && starMap[nameSegment]) { |
| 127 | foundStarMap = starMap[nameSegment]; |
| 128 | starI = i; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | if (!foundMap && foundStarMap) { |
| 133 | foundMap = foundStarMap; |
| 134 | foundI = starI; |
| 135 | } |
| 136 | |
| 137 | if (foundMap) { |
| 138 | nameParts.splice(0, foundI, foundMap); |
| 139 | name = nameParts.join('/'); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | return name; |
| 144 | } |
| 145 | |
| 146 | function makeRequire(relName, forceSync) { |
| 147 | return function () { |
| 148 | //A version of a require function that passes a moduleName |
| 149 | //value for items that may need to |
| 150 | //look up paths relative to the moduleName |
| 151 | var args = aps.call(arguments, 0); |
| 152 | |
| 153 | //If first arg is not require('string'), and there is only |
| 154 | //one arg, it is the array form without a callback. Insert |
| 155 | //a null so that the following concat is correct. |
| 156 | if (typeof args[0] !== 'string' && args.length === 1) { |
| 157 | args.push(null); |
| 158 | } |
| 159 | return req.apply(undef, args.concat([relName, forceSync])); |
| 160 | }; |
| 161 | } |
| 162 | |
| 163 | function makeNormalize(relName) { |
| 164 | return function (name) { |
| 165 | return normalize(name, relName); |
| 166 | }; |
| 167 | } |
| 168 | |
| 169 | function makeLoad(depName) { |
| 170 | return function (value) { |
| 171 | defined[depName] = value; |
| 172 | }; |
| 173 | } |
| 174 | |
| 175 | function callDep(name) { |
| 176 | if (hasProp(waiting, name)) { |
| 177 | var args = waiting[name]; |
| 178 | delete waiting[name]; |
| 179 | defining[name] = true; |
| 180 | main.apply(undef, args); |
| 181 | } |
| 182 | |
| 183 | if (!hasProp(defined, name) && !hasProp(defining, name)) { |
| 184 | throw new Error('No ' + name); |
| 185 | } |
| 186 | return defined[name]; |
| 187 | } |
| 188 | |
| 189 | //Turns a plugin!resource to [plugin, resource] |
| 190 | //with the plugin being undefined if the name |
| 191 | //did not have a plugin prefix. |
| 192 | function splitPrefix(name) { |
| 193 | var prefix, |
| 194 | index = name ? name.indexOf('!') : -1; |
| 195 | if (index > -1) { |
| 196 | prefix = name.substring(0, index); |
| 197 | name = name.substring(index + 1, name.length); |
| 198 | } |
| 199 | return [prefix, name]; |
| 200 | } |
| 201 | |
| 202 | /** |
| 203 | * Makes a name map, normalizing the name, and using a plugin |
| 204 | * for normalization if necessary. Grabs a ref to plugin |
| 205 | * too, as an optimization. |
| 206 | */ |
| 207 | makeMap = function (name, relName) { |
| 208 | var plugin, |
| 209 | parts = splitPrefix(name), |
| 210 | prefix = parts[0]; |
| 211 | |
| 212 | name = parts[1]; |
| 213 | |
| 214 | if (prefix) { |
| 215 | prefix = normalize(prefix, relName); |
| 216 | plugin = callDep(prefix); |
| 217 | } |
| 218 | |
| 219 | //Normalize according |
| 220 | if (prefix) { |
| 221 | if (plugin && plugin.normalize) { |
| 222 | name = plugin.normalize(name, makeNormalize(relName)); |
| 223 | } else { |
| 224 | name = normalize(name, relName); |
| 225 | } |
| 226 | } else { |
| 227 | name = normalize(name, relName); |
| 228 | parts = splitPrefix(name); |
| 229 | prefix = parts[0]; |
| 230 | name = parts[1]; |
| 231 | if (prefix) { |
| 232 | plugin = callDep(prefix); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | //Using ridiculous property names for space reasons |
| 237 | return { |
| 238 | f: prefix ? prefix + '!' + name : name, //fullName |
| 239 | n: name, |
| 240 | pr: prefix, |
| 241 | p: plugin |
| 242 | }; |
| 243 | }; |
| 244 | |
| 245 | function makeConfig(name) { |
| 246 | return function () { |
| 247 | return (config && config.config && config.config[name]) || {}; |
| 248 | }; |
| 249 | } |
| 250 | |
| 251 | handlers = { |
| 252 | require: function (name) { |
| 253 | return makeRequire(name); |
| 254 | }, |
| 255 | exports: function (name) { |
| 256 | var e = defined[name]; |
| 257 | if (typeof e !== 'undefined') { |
| 258 | return e; |
| 259 | } else { |
| 260 | return (defined[name] = {}); |
| 261 | } |
| 262 | }, |
| 263 | module: function (name) { |
| 264 | return { |
| 265 | id: name, |
| 266 | uri: '', |
| 267 | exports: defined[name], |
| 268 | config: makeConfig(name) |
| 269 | }; |
| 270 | } |
| 271 | }; |
| 272 | |
| 273 | main = function (name, deps, callback, relName) { |
| 274 | var cjsModule, depName, ret, map, i, |
| 275 | args = [], |
| 276 | callbackType = typeof callback, |
| 277 | usingExports; |
| 278 | |
| 279 | //Use name if no relName |
| 280 | relName = relName || name; |
| 281 | |
| 282 | //Call the callback to define the module, if necessary. |
| 283 | if (callbackType === 'undefined' || callbackType === 'function') { |
| 284 | //Pull out the defined dependencies and pass the ordered |
| 285 | //values to the callback. |
| 286 | //Default to [require, exports, module] if no deps |
| 287 | deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; |
| 288 | for (i = 0; i < deps.length; i += 1) { |
| 289 | map = makeMap(deps[i], relName); |
| 290 | depName = map.f; |
| 291 | |
| 292 | //Fast path CommonJS standard dependencies. |
| 293 | if (depName === "require") { |
| 294 | args[i] = handlers.require(name); |
| 295 | } else if (depName === "exports") { |
| 296 | //CommonJS module spec 1.1 |
| 297 | args[i] = handlers.exports(name); |
| 298 | usingExports = true; |
| 299 | } else if (depName === "module") { |
| 300 | //CommonJS module spec 1.1 |
| 301 | cjsModule = args[i] = handlers.module(name); |
| 302 | } else if (hasProp(defined, depName) || |
| 303 | hasProp(waiting, depName) || |
| 304 | hasProp(defining, depName)) { |
| 305 | args[i] = callDep(depName); |
| 306 | } else if (map.p) { |
| 307 | map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); |
| 308 | args[i] = defined[depName]; |
| 309 | } else { |
| 310 | throw new Error(name + ' missing ' + depName); |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | ret = callback ? callback.apply(defined[name], args) : undefined; |
| 315 | |
| 316 | if (name) { |
| 317 | //If setting exports via "module" is in play, |
| 318 | //favor that over return value and exports. After that, |
| 319 | //favor a non-undefined return value over exports use. |
| 320 | if (cjsModule && cjsModule.exports !== undef && |
| 321 | cjsModule.exports !== defined[name]) { |
| 322 | defined[name] = cjsModule.exports; |
| 323 | } else if (ret !== undef || !usingExports) { |
| 324 | //Use the return value from the function. |
| 325 | defined[name] = ret; |
| 326 | } |
| 327 | } |
| 328 | } else if (name) { |
| 329 | //May just be an object definition for the module. Only |
| 330 | //worry about defining if have a module name. |
| 331 | defined[name] = callback; |
| 332 | } |
| 333 | }; |
| 334 | |
| 335 | requirejs = require = req = function (deps, callback, relName, forceSync, alt) { |
| 336 | if (typeof deps === "string") { |
| 337 | if (handlers[deps]) { |
| 338 | //callback in this case is really relName |
| 339 | return handlers[deps](callback); |
| 340 | } |
| 341 | //Just return the module wanted. In this scenario, the |
| 342 | //deps arg is the module name, and second arg (if passed) |
| 343 | //is just the relName. |
| 344 | //Normalize module name, if it contains . or .. |
| 345 | return callDep(makeMap(deps, callback).f); |
| 346 | } else if (!deps.splice) { |
| 347 | //deps is a config object, not an array. |
| 348 | config = deps; |
| 349 | if (config.deps) { |
| 350 | req(config.deps, config.callback); |
| 351 | } |
| 352 | if (!callback) { |
| 353 | return; |
| 354 | } |
| 355 | |
| 356 | if (callback.splice) { |
| 357 | //callback is an array, which means it is a dependency list. |
| 358 | //Adjust args if there are dependencies |
| 359 | deps = callback; |
| 360 | callback = relName; |
| 361 | relName = null; |
| 362 | } else { |
| 363 | deps = undef; |
| 364 | } |
| 365 | } |
| 366 | |
| 367 | //Support require(['a']) |
| 368 | callback = callback || function () {}; |
| 369 | |
| 370 | //If relName is a function, it is an errback handler, |
| 371 | //so remove it. |
| 372 | if (typeof relName === 'function') { |
| 373 | relName = forceSync; |
| 374 | forceSync = alt; |
| 375 | } |
| 376 | |
| 377 | //Simulate async callback; |
| 378 | if (forceSync) { |
| 379 | main(undef, deps, callback, relName); |
| 380 | } else { |
| 381 | //Using a non-zero value because of concern for what old browsers |
| 382 | //do, and latest browsers "upgrade" to 4 if lower value is used: |
| 383 | //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: |
| 384 | //If want a value immediately, use require('id') instead -- something |
| 385 | //that works in almond on the global level, but not guaranteed and |
| 386 | //unlikely to work in other AMD implementations. |
| 387 | setTimeout(function () { |
| 388 | main(undef, deps, callback, relName); |
| 389 | }, 4); |
| 390 | } |
| 391 | |
| 392 | return req; |
| 393 | }; |
| 394 | |
| 395 | /** |
| 396 | * Just drops the config on the floor, but returns req in case |
| 397 | * the config return value is used. |
| 398 | */ |
| 399 | req.config = function (cfg) { |
| 400 | return req(cfg); |
| 401 | }; |
| 402 | |
| 403 | /** |
| 404 | * Expose module registry for debugging and tooling |
| 405 | */ |
| 406 | requirejs._defined = defined; |
| 407 | |
| 408 | define = function (name, deps, callback) { |
| 409 | if (typeof name !== 'string') { |
| 410 | throw new Error('See almond README: incorrect module build, no module name'); |
| 411 | } |
| 412 | |
| 413 | //This module may not have dependencies |
| 414 | if (!deps.splice) { |
| 415 | //deps is not an array, so probably means |
| 416 | //an object literal or factory function for |
| 417 | //the value. Adjust args. |
| 418 | callback = deps; |
| 419 | deps = []; |
| 420 | } |
| 421 | |
| 422 | if (!hasProp(defined, name) && !hasProp(waiting, name)) { |
| 423 | waiting[name] = [name, deps, callback]; |
| 424 | } |
| 425 | }; |
| 426 | |
| 427 | define.amd = { |
| 428 | jQuery: true |
| 429 | }; |
| 430 | }()); |