UNPKG

13.1 kBJavaScriptView Raw
1var path = require('path');
2var url = require('url');
3
4exports.traceurGet = function(module) {
5 var traceur = require('traceur');
6 var traceurVersion = traceur.loader.NodeTraceurLoader.prototype.version;
7 return $traceurRuntime.ModuleStore.get('traceur@' + traceurVersion + '/src/' + module);
8};
9
10exports.extend = extend;
11function extend(a, b) {
12 for (var p in b)
13 a[p] = b[p];
14 return a;
15}
16
17exports.dextend = dextend;
18function dextend(a, b) {
19 for (var p in b) {
20 if (!b.hasOwnProperty(p))
21 continue;
22 var val = b[p];
23 if (typeof val === 'object')
24 dextend(a[p] = typeof a[p] === 'object' ? a[p] : {}, val);
25 else
26 a[p] = val;
27 }
28 return a;
29}
30
31exports.getFormatHint = getFormatHint;
32function getFormatHint(compileOpts) {
33 var formatHint = '';
34
35 var format = compileOpts.format;
36
37 if (format == 'umd')
38 format = 'amd';
39
40 if (format == 'amd' || format == 'cjs' || format == 'global')
41 formatHint = formatHint + '"format ' + format + '";\n';
42
43 if (compileOpts.format == 'global') {
44 for (var g in compileOpts.globalDeps)
45 formatHint = formatHint + '"globals.' + compileOpts.globalDeps[g] + ' ' + g + '";\n';
46
47 if (compileOpts.globalName)
48 formatHint = formatHint + '"exports ' + compileOpts.globalName + '";\n';
49 }
50
51 return formatHint;
52}
53
54var isWin = process.platform.match(/^win/);
55
56exports.fromFileURL = fromFileURL;
57function fromFileURL(url) {
58 return url.substr(7 + !!isWin).replace(/\//g, path.sep);
59}
60
61exports.toFileURL = toFileURL;
62function toFileURL(path) {
63 return 'file://' + (isWin ? '/' : '') + path.replace(/\\/g, '/');
64}
65
66exports.getAlias = getAlias
67function getAlias(loader, canonicalName) {
68 var pluginIndex = loader.pluginFirst ? canonicalName.indexOf('!') : canonicalName.lastIndexOf('!');
69 if (pluginIndex != -1)
70 return getAlias(loader, canonicalName.substr(0, pluginIndex)) + '!' + getAlias(loader, canonicalName.substr(pluginIndex + 1));
71
72 // replace subpath conditionals with subpath
73 canonicalName = canonicalName.replace('/#:./', '/');
74
75 if (canonicalName.match(/\#[\:\{\?]/))
76 throw new Error('Unable to alias the conditional dependency "' + canonicalName + '".');
77
78 var packageName = getPackage(loader.packages, loader.decanonicalize(canonicalName));
79 var packageMain = packageName && loader.packages[packageName].main;
80 if (packageMain && canonicalName.substr(canonicalName.length - packageMain.length - 1) == '/' + packageMain)
81 canonicalName = canonicalName.substr(0, canonicalName.length - packageMain.length - 1);
82
83 var bestAliasLength = 0;
84 var bestAliasSubpath;
85 var bestAlias;
86 Object.keys(loader.map).forEach(function(alias) {
87 if (alias.split('/').length <= bestAliasLength)
88 return;
89
90 // get mapped without defaultJSExtension
91 var mapped = getCanonicalName(loader, loader.decanonicalize(loader.map[alias]));
92
93 // do matching with defaultJSExtension checking
94 if (loader.defaultJSExtensions && canonicalName == mapped + '.js') {
95 bestAlias = alias;
96 bestAliasSubpath = '';
97 bestAliasLength = alias.split('/').length;
98 }
99 else if (canonicalName.substr(0, mapped.length) == mapped &&
100 (canonicalName.length == mapped.length || canonicalName[mapped.length] == '/')) {
101 bestAlias = alias;
102 bestAliasSubpath = canonicalName.substr(mapped.length);
103 bestAliasLength = alias.split('/').length;
104 }
105 });
106
107 if (bestAlias)
108 return bestAlias + bestAliasSubpath;
109
110 return canonicalName;
111}
112
113exports.verifyTree = verifyTree;
114function verifyTree(tree) {
115 if (typeof tree != 'object' || tree instanceof Array)
116 throw new TypeError('Expected a trace tree object');
117
118 Object.keys(tree).forEach(function(key) {
119 var load = tree[key];
120 if (typeof load === 'boolean')
121 return;
122 if (load && typeof load != 'object' || !load.name || !(load.conditional || load.deps))
123 throw new TypeError('Expected a trace tree object, but "' + key + '" is not a load record.');
124 });
125}
126
127exports.getCanonicalName = getCanonicalName;
128function getCanonicalName(loader, normalized, isPlugin) {
129 // 1. Boolean conditional
130 var booleanIndex = normalized.lastIndexOf('#?');
131 if (booleanIndex != -1) {
132 var booleanModule = normalized.substr(booleanIndex + 2);
133 var negate = booleanModule[0] == '~';
134 if (negate)
135 booleanModule = booleanModule.substr(1);
136 return getCanonicalName(loader, normalized.substr(0, booleanIndex)) + '#?' + (negate ? '~' : '') + canonicalizeCondition(loader, booleanModule);
137 }
138
139 // 2. Plugins
140 var pluginIndex = loader.pluginFirst ? normalized.indexOf('!') : normalized.lastIndexOf('!');
141 if (pluginIndex != -1)
142 return getCanonicalName(loader, normalized.substr(0, pluginIndex), !loader.pluginFirst) + '!' + getCanonicalName(loader, normalized.substr(pluginIndex + 1), loader.pluginFirst);
143
144 // 3. Package environment map
145 var pkgEnvIndex = normalized.indexOf('/#:');
146 if (pkgEnvIndex != -1)
147 return getCanonicalName(loader, normalized.substr(0, pkgEnvIndex), isPlugin) + '/#:' + normalized.substr(pkgEnvIndex + 3);
148
149 // Finally get canonical plain
150 var canonical = getCanonicalNamePlain(loader, normalized, isPlugin);
151
152 // 4. Canonicalize conditional interpolation
153 var conditionalMatch = canonical.match(interpolationRegEx);
154 if (conditionalMatch)
155 return getCanonicalNamePlain(loader, normalized, isPlugin).replace(interpolationRegEx, '#{' + canonicalizeCondition(loader, conditionalMatch[0].substr(2, conditionalMatch[0].length - 3)) + '}');
156
157 return canonical;
158}
159
160// calculate the canonical name of the normalized module
161// unwraps loader syntaxes to derive component parts
162var interpolationRegEx = /#\{[^\}]+\}/;
163function canonicalizeCondition(loader, conditionModule) {
164 var conditionExport;
165 var exportIndex = conditionModule.lastIndexOf('|');
166 if (exportIndex != -1) {
167 conditionExport = conditionModule.substr(exportIndex + 1)
168 conditionModule = conditionModule.substr(0, exportIndex) || '@system-env';
169 }
170 return getCanonicalName(loader, conditionModule) + (conditionExport ? '|' + conditionExport : '');
171}
172
173// syntax-free getCanonicalName
174// just reverse-applies paths and defulatJSExtension to determine the canonical
175function getCanonicalNamePlain(loader, normalized, isPlugin) {
176 // now just reverse apply paths rules to get canonical name
177 var pathMatch;
178
179 // first check exact path matches
180 for (var p in loader.paths) {
181 if (loader.paths[p].indexOf('*') != -1)
182 continue;
183
184 var curPath = normalizePath(loader, loader.paths[p], isPlugin);
185
186 // always stop on first exact match
187 if (normalized === curPath)
188 return p;
189
190 // support trailing / in paths rules
191 else if (curPath[curPath.length - 1] == '/' &&
192 normalized.substr(0, curPath.length - 1) == curPath.substr(0, curPath.length - 1) &&
193 (normalized.length < curPath.length || normalized[curPath.length - 1] == curPath[curPath.length - 1])) {
194 // first case is that canonicalize('src') = 'app' for 'app/': 'src/'
195 return normalized.length < curPath.length ? p.substr(0, p.length - 1) : p + normalized.substr(curPath.length);
196 }
197 }
198
199 // then wildcard matches
200 var pathMatchLength = 0;
201 var curMatchLength;
202 if (!pathMatch)
203 for (var p in loader.paths) {
204 if (loader.paths[p].indexOf('*') == -1)
205 continue;
206
207 // normalize the output path
208 var curPath = normalizePath(loader, loader.paths[p], true);
209
210 // do reverse match
211 var wIndex = curPath.indexOf('*');
212 if (normalized.substr(0, wIndex) === curPath.substr(0, wIndex)
213 && normalized.substr(normalized.length - curPath.length + wIndex + 1) === curPath.substr(wIndex + 1)) {
214 curMatchLength = curPath.split('/').length;
215 if (curMatchLength >= pathMatchLength) {
216 pathMatch = p.replace('*', normalized.substr(wIndex, normalized.length - curPath.length + 1));
217 pathMatchLength = curMatchLength;
218 }
219 }
220 }
221
222 // when no path was matched, act like the standard rule is *: baseURL/*
223 if (!pathMatch) {
224 if (normalized.substr(0, loader.baseURL.length) == loader.baseURL)
225 pathMatch = normalized.substr(loader.baseURL.length);
226 else if (normalized.match(absURLRegEx))
227 throw new Error('Unable to calculate canonical name to bundle ' + normalized + '. Ensure that this module sits within the baseURL or a wildcard path config.');
228 else
229 pathMatch = normalized;
230 }
231
232 return pathMatch;
233}
234
235exports.getPackageConfigPath = getPackageConfigPath;
236
237// check if the given normalized name matches a packageConfigPath
238// if so, loads the config
239var packageConfigPaths = {};
240
241// data object for quick checks against package paths
242function createPkgConfigPathObj(path) {
243 var lastWildcard = path.lastIndexOf('*');
244 var length = Math.max(lastWildcard + 1, path.lastIndexOf('/'));
245 return {
246 length: length,
247 // NB handle regex control character escapes or simply create a test function here
248 regEx: new RegExp('^(' + path.substr(0, length).replace(/\*/g, '[^\\/]+') + ')(\\/|$)'),
249 wildcard: lastWildcard != -1
250 };
251}
252
253// most specific match wins
254exports.getPackageConfigPath = getPackageConfigPath;
255function getPackageConfigPath(packageConfigPaths, normalized) {
256 var pkgName, exactMatch = false, configPath;
257 for (var i = 0; i < packageConfigPaths.length; i++) {
258 var packageConfigPath = packageConfigPaths[i];
259 var p = packageConfigPaths[packageConfigPath] || (packageConfigPaths[packageConfigPath] = createPkgConfigPathObj(packageConfigPath));
260 if (normalized.length < p.length)
261 continue;
262 var match = normalized.match(p.regEx);
263 if (match && (!pkgName || (!(exactMatch && p.wildcard) && pkgName.length < match[1].length))) {
264 pkgName = match[1];
265 exactMatch = !p.wildcard;
266 configPath = pkgName + packageConfigPath.substr(p.length);
267 }
268 }
269
270 if (!pkgName)
271 return;
272
273 // return value is only part modified from SystemJS implementation of getPackageConfigMatch
274 return configPath;
275}
276
277// determine whether the given module name is a package config file
278exports.isPackageConfig = isPackageConfig;
279var curHash;
280var configPathCache = null;
281var canonicalConfigPaths = null;
282function isPackageConfig(loader, canonical) {
283 if (loader.configHash != curHash) {
284 configPathCache = null;
285 curHash = loader.configHash;
286 }
287
288 // generate canonical packageConfigPaths for matching
289 if (!configPathCache) {
290 canonicalConfigPaths = loader.packageConfigPaths.map(function(configPath) {
291 return getCanonicalName(loader, configPath);
292 });
293 configPathCache = {};
294 }
295
296 if (canonical in configPathCache)
297 return configPathCache[canonical];
298
299 // check if the given canonical matches the canonical package config paths
300 var cfgPathMatch = getPackageConfigPath(canonicalConfigPaths, canonical);
301 configPathCache[canonical] = cfgPathMatch && cfgPathMatch.split('/').length == canonical.split('/').length;
302
303 return configPathCache[canonical];
304}
305
306exports.getPackage = getPackage;
307function getPackage(packages, name) {
308 // use most specific package
309 var curPkg, curPkgLen = 0, pkgLen;
310 for (var p in packages) {
311 if (name.substr(0, p.length) === p && (name.length === p.length || name[p.length] === '/')) {
312 pkgLen = p.split('/').length;
313 if (pkgLen > curPkgLen) {
314 curPkg = p;
315 curPkgLen = pkgLen;
316 }
317 }
318 }
319 return curPkg;
320}
321
322var absURLRegEx = /^[^\/]+:\/\//;
323function normalizePath(loader, path, skipExtension) {
324 var curMap = loader.map;
325 var curPaths = loader.paths;
326 var curPackages = loader.packages;
327 loader.map = {};
328 loader.paths = {};
329 loader.packages = {};
330 var normalized = loader.normalizeSync(path);
331 if (skipExtension && path.substr(path.length - 3, 3) != '.js' && normalized.substr(normalized.length - 3, 3) == '.js')
332 normalized = normalized.substr(0, normalized.length - 3);
333 loader.map = curMap;
334 loader.paths = curPaths;
335 loader.packages = curPackages;
336 return normalized;
337}
338
339var sysConditions = ['browser', 'node', 'dev', 'production', 'default'];
340
341exports.parseCondition = parseCondition;
342function parseCondition(condition) {
343 var conditionExport, conditionModule, negation;
344
345 var negation = condition[0] == '~';
346 var conditionExportIndex = condition.lastIndexOf('|');
347 if (conditionExportIndex != -1) {
348 conditionExport = condition.substr(conditionExportIndex + 1);
349 conditionModule = condition.substr(negation, conditionExportIndex - negation);
350
351 if (conditionExport[0] == '~') {
352 negation = true;
353 conditionExport = conditionExport.substr(1);
354 }
355 }
356 else {
357 conditionExport = 'default';
358 conditionModule = condition.substr(negation);
359 if (sysConditions.indexOf(conditionModule) != -1) {
360 conditionExport = conditionModule;
361 conditionModule = '@system-env';
362 }
363 }
364
365 return {
366 module: conditionModule,
367 prop: conditionExport,
368 negate: negation
369 };
370}
371
372exports.serializeCondition = serializeCondition;
373function serializeCondition(conditionObj) {
374 return conditionObj.module + '|' + (conditionObj.negate ? '~' : '') + conditionObj.prop;
375}
376