]> git.r.bdr.sh - rbdr/dotfiles/blob
93f140e39a37fcfad1a109c247be4f0688bea5b9
[rbdr/dotfiles] /
1 /** vim: et:ts=4:sw=4:sts=4
2 * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
3 * Available via the MIT or new BSD license.
4 * see: http://github.com/jrburke/amdefine for details
5 */
6
7 /*jslint node: true */
8 /*global module, process */
9 'use strict';
10
11 /**
12 * Creates a define for node.
13 * @param {Object} module the "module" object that is defined by Node for the
14 * current module.
15 * @param {Function} [requireFn]. Node's require function for the current module.
16 * It only needs to be passed in Node versions before 0.5, when module.require
17 * did not exist.
18 * @returns {Function} a define function that is usable for the current node
19 * module.
20 */
21 function amdefine(module, requireFn) {
22 'use strict';
23 var defineCache = {},
24 loaderCache = {},
25 alreadyCalled = false,
26 path = require('path'),
27 makeRequire, stringRequire;
28
29 /**
30 * Trims the . and .. from an array of path segments.
31 * It will keep a leading path segment if a .. will become
32 * the first path segment, to help with module name lookups,
33 * which act like paths, but can be remapped. But the end result,
34 * all paths that use this function should look normalized.
35 * NOTE: this method MODIFIES the input array.
36 * @param {Array} ary the array of path segments.
37 */
38 function trimDots(ary) {
39 var i, part;
40 for (i = 0; ary[i]; i+= 1) {
41 part = ary[i];
42 if (part === '.') {
43 ary.splice(i, 1);
44 i -= 1;
45 } else if (part === '..') {
46 if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
47 //End of the line. Keep at least one non-dot
48 //path segment at the front so it can be mapped
49 //correctly to disk. Otherwise, there is likely
50 //no path mapping for a path starting with '..'.
51 //This can still fail, but catches the most reasonable
52 //uses of ..
53 break;
54 } else if (i > 0) {
55 ary.splice(i - 1, 2);
56 i -= 2;
57 }
58 }
59 }
60 }
61
62 function normalize(name, baseName) {
63 var baseParts;
64
65 //Adjust any relative paths.
66 if (name && name.charAt(0) === '.') {
67 //If have a base name, try to normalize against it,
68 //otherwise, assume it is a top-level require that will
69 //be relative to baseUrl in the end.
70 if (baseName) {
71 baseParts = baseName.split('/');
72 baseParts = baseParts.slice(0, baseParts.length - 1);
73 baseParts = baseParts.concat(name.split('/'));
74 trimDots(baseParts);
75 name = baseParts.join('/');
76 }
77 }
78
79 return name;
80 }
81
82 /**
83 * Create the normalize() function passed to a loader plugin's
84 * normalize method.
85 */
86 function makeNormalize(relName) {
87 return function (name) {
88 return normalize(name, relName);
89 };
90 }
91
92 function makeLoad(id) {
93 function load(value) {
94 loaderCache[id] = value;
95 }
96
97 load.fromText = function (id, text) {
98 //This one is difficult because the text can/probably uses
99 //define, and any relative paths and requires should be relative
100 //to that id was it would be found on disk. But this would require
101 //bootstrapping a module/require fairly deeply from node core.
102 //Not sure how best to go about that yet.
103 throw new Error('amdefine does not implement load.fromText');
104 };
105
106 return load;
107 }
108
109 makeRequire = function (systemRequire, exports, module, relId) {
110 function amdRequire(deps, callback) {
111 if (typeof deps === 'string') {
112 //Synchronous, single module require('')
113 return stringRequire(systemRequire, exports, module, deps, relId);
114 } else {
115 //Array of dependencies with a callback.
116
117 //Convert the dependencies to modules.
118 deps = deps.map(function (depName) {
119 return stringRequire(systemRequire, exports, module, depName, relId);
120 });
121
122 //Wait for next tick to call back the require call.
123 if (callback) {
124 process.nextTick(function () {
125 callback.apply(null, deps);
126 });
127 }
128 }
129 }
130
131 amdRequire.toUrl = function (filePath) {
132 if (filePath.indexOf('.') === 0) {
133 return normalize(filePath, path.dirname(module.filename));
134 } else {
135 return filePath;
136 }
137 };
138
139 return amdRequire;
140 };
141
142 //Favor explicit value, passed in if the module wants to support Node 0.4.
143 requireFn = requireFn || function req() {
144 return module.require.apply(module, arguments);
145 };
146
147 function runFactory(id, deps, factory) {
148 var r, e, m, result;
149
150 if (id) {
151 e = loaderCache[id] = {};
152 m = {
153 id: id,
154 uri: __filename,
155 exports: e
156 };
157 r = makeRequire(requireFn, e, m, id);
158 } else {
159 //Only support one define call per file
160 if (alreadyCalled) {
161 throw new Error('amdefine with no module ID cannot be called more than once per file.');
162 }
163 alreadyCalled = true;
164
165 //Use the real variables from node
166 //Use module.exports for exports, since
167 //the exports in here is amdefine exports.
168 e = module.exports;
169 m = module;
170 r = makeRequire(requireFn, e, m, module.id);
171 }
172
173 //If there are dependencies, they are strings, so need
174 //to convert them to dependency values.
175 if (deps) {
176 deps = deps.map(function (depName) {
177 return r(depName);
178 });
179 }
180
181 //Call the factory with the right dependencies.
182 if (typeof factory === 'function') {
183 result = factory.apply(m.exports, deps);
184 } else {
185 result = factory;
186 }
187
188 if (result !== undefined) {
189 m.exports = result;
190 if (id) {
191 loaderCache[id] = m.exports;
192 }
193 }
194 }
195
196 stringRequire = function (systemRequire, exports, module, id, relId) {
197 //Split the ID by a ! so that
198 var index = id.indexOf('!'),
199 originalId = id,
200 prefix, plugin;
201
202 if (index === -1) {
203 id = normalize(id, relId);
204
205 //Straight module lookup. If it is one of the special dependencies,
206 //deal with it, otherwise, delegate to node.
207 if (id === 'require') {
208 return makeRequire(systemRequire, exports, module, relId);
209 } else if (id === 'exports') {
210 return exports;
211 } else if (id === 'module') {
212 return module;
213 } else if (loaderCache.hasOwnProperty(id)) {
214 return loaderCache[id];
215 } else if (defineCache[id]) {
216 runFactory.apply(null, defineCache[id]);
217 return loaderCache[id];
218 } else {
219 if(systemRequire) {
220 return systemRequire(originalId);
221 } else {
222 throw new Error('No module with ID: ' + id);
223 }
224 }
225 } else {
226 //There is a plugin in play.
227 prefix = id.substring(0, index);
228 id = id.substring(index + 1, id.length);
229
230 plugin = stringRequire(systemRequire, exports, module, prefix, relId);
231
232 if (plugin.normalize) {
233 id = plugin.normalize(id, makeNormalize(relId));
234 } else {
235 //Normalize the ID normally.
236 id = normalize(id, relId);
237 }
238
239 if (loaderCache[id]) {
240 return loaderCache[id];
241 } else {
242 plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {});
243
244 return loaderCache[id];
245 }
246 }
247 };
248
249 //Create a define function specific to the module asking for amdefine.
250 function define(id, deps, factory) {
251 if (Array.isArray(id)) {
252 factory = deps;
253 deps = id;
254 id = undefined;
255 } else if (typeof id !== 'string') {
256 factory = id;
257 id = deps = undefined;
258 }
259
260 if (deps && !Array.isArray(deps)) {
261 factory = deps;
262 deps = undefined;
263 }
264
265 if (!deps) {
266 deps = ['require', 'exports', 'module'];
267 }
268
269 //Set up properties for this module. If an ID, then use
270 //internal cache. If no ID, then use the external variables
271 //for this node module.
272 if (id) {
273 //Put the module in deep freeze until there is a
274 //require call for it.
275 defineCache[id] = [id, deps, factory];
276 } else {
277 runFactory(id, deps, factory);
278 }
279 }
280
281 //define.require, which has access to all the values in the
282 //cache. Useful for AMD modules that all have IDs in the file,
283 //but need to finally export a value to node based on one of those
284 //IDs.
285 define.require = function (id) {
286 if (loaderCache[id]) {
287 return loaderCache[id];
288 }
289
290 if (defineCache[id]) {
291 runFactory.apply(null, defineCache[id]);
292 return loaderCache[id];
293 }
294 };
295
296 define.amd = {};
297
298 return define;
299 }
300
301 module.exports = amdefine;