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