Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80559 views
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
process.nextTick(function () {
124
callback.apply(null, deps);
125
});
126
}
127
}
128
129
amdRequire.toUrl = function (filePath) {
130
if (filePath.indexOf('.') === 0) {
131
return normalize(filePath, path.dirname(module.filename));
132
} else {
133
return filePath;
134
}
135
};
136
137
return amdRequire;
138
};
139
140
//Favor explicit value, passed in if the module wants to support Node 0.4.
141
requireFn = requireFn || function req() {
142
return module.require.apply(module, arguments);
143
};
144
145
function runFactory(id, deps, factory) {
146
var r, e, m, result;
147
148
if (id) {
149
e = loaderCache[id] = {};
150
m = {
151
id: id,
152
uri: __filename,
153
exports: e
154
};
155
r = makeRequire(requireFn, e, m, id);
156
} else {
157
//Only support one define call per file
158
if (alreadyCalled) {
159
throw new Error('amdefine with no module ID cannot be called more than once per file.');
160
}
161
alreadyCalled = true;
162
163
//Use the real variables from node
164
//Use module.exports for exports, since
165
//the exports in here is amdefine exports.
166
e = module.exports;
167
m = module;
168
r = makeRequire(requireFn, e, m, module.id);
169
}
170
171
//If there are dependencies, they are strings, so need
172
//to convert them to dependency values.
173
if (deps) {
174
deps = deps.map(function (depName) {
175
return r(depName);
176
});
177
}
178
179
//Call the factory with the right dependencies.
180
if (typeof factory === 'function') {
181
result = factory.apply(m.exports, deps);
182
} else {
183
result = factory;
184
}
185
186
if (result !== undefined) {
187
m.exports = result;
188
if (id) {
189
loaderCache[id] = m.exports;
190
}
191
}
192
}
193
194
stringRequire = function (systemRequire, exports, module, id, relId) {
195
//Split the ID by a ! so that
196
var index = id.indexOf('!'),
197
originalId = id,
198
prefix, plugin;
199
200
if (index === -1) {
201
id = normalize(id, relId);
202
203
//Straight module lookup. If it is one of the special dependencies,
204
//deal with it, otherwise, delegate to node.
205
if (id === 'require') {
206
return makeRequire(systemRequire, exports, module, relId);
207
} else if (id === 'exports') {
208
return exports;
209
} else if (id === 'module') {
210
return module;
211
} else if (loaderCache.hasOwnProperty(id)) {
212
return loaderCache[id];
213
} else if (defineCache[id]) {
214
runFactory.apply(null, defineCache[id]);
215
return loaderCache[id];
216
} else {
217
if(systemRequire) {
218
return systemRequire(originalId);
219
} else {
220
throw new Error('No module with ID: ' + id);
221
}
222
}
223
} else {
224
//There is a plugin in play.
225
prefix = id.substring(0, index);
226
id = id.substring(index + 1, id.length);
227
228
plugin = stringRequire(systemRequire, exports, module, prefix, relId);
229
230
if (plugin.normalize) {
231
id = plugin.normalize(id, makeNormalize(relId));
232
} else {
233
//Normalize the ID normally.
234
id = normalize(id, relId);
235
}
236
237
if (loaderCache[id]) {
238
return loaderCache[id];
239
} else {
240
plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {});
241
242
return loaderCache[id];
243
}
244
}
245
};
246
247
//Create a define function specific to the module asking for amdefine.
248
function define(id, deps, factory) {
249
if (Array.isArray(id)) {
250
factory = deps;
251
deps = id;
252
id = undefined;
253
} else if (typeof id !== 'string') {
254
factory = id;
255
id = deps = undefined;
256
}
257
258
if (deps && !Array.isArray(deps)) {
259
factory = deps;
260
deps = undefined;
261
}
262
263
if (!deps) {
264
deps = ['require', 'exports', 'module'];
265
}
266
267
//Set up properties for this module. If an ID, then use
268
//internal cache. If no ID, then use the external variables
269
//for this node module.
270
if (id) {
271
//Put the module in deep freeze until there is a
272
//require call for it.
273
defineCache[id] = [id, deps, factory];
274
} else {
275
runFactory(id, deps, factory);
276
}
277
}
278
279
//define.require, which has access to all the values in the
280
//cache. Useful for AMD modules that all have IDs in the file,
281
//but need to finally export a value to node based on one of those
282
//IDs.
283
define.require = function (id) {
284
if (loaderCache[id]) {
285
return loaderCache[id];
286
}
287
288
if (defineCache[id]) {
289
runFactory.apply(null, defineCache[id]);
290
return loaderCache[id];
291
}
292
};
293
294
define.amd = {};
295
296
return define;
297
}
298
299
module.exports = amdefine;
300
301