]> git.r.bdr.sh - rbdr/dotfiles/blob
976f6cabb08d2fcb05ae2ee575ba4d4d73a0e5a6
[rbdr/dotfiles] /
1 /* -*- Mode: js; js-indent-level: 2; -*- */
2 /*
3 * Copyright 2011 Mozilla Foundation and contributors
4 * Licensed under the New BSD license. See LICENSE or:
5 * http://opensource.org/licenses/BSD-3-Clause
6 */
7 if (typeof define !== 'function') {
8 var define = require('amdefine')(module, require);
9 }
10 define(function (require, exports, module) {
11
12 /**
13 * This is a helper function for getting values from parameter/options
14 * objects.
15 *
16 * @param args The object we are extracting values from
17 * @param name The name of the property we are getting.
18 * @param defaultValue An optional value to return if the property is missing
19 * from the object. If this is not specified and the property is missing, an
20 * error will be thrown.
21 */
22 function getArg(aArgs, aName, aDefaultValue) {
23 if (aName in aArgs) {
24 return aArgs[aName];
25 } else if (arguments.length === 3) {
26 return aDefaultValue;
27 } else {
28 throw new Error('"' + aName + '" is a required argument.');
29 }
30 }
31 exports.getArg = getArg;
32
33 var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/;
34 var dataUrlRegexp = /^data:.+\,.+$/;
35
36 function urlParse(aUrl) {
37 var match = aUrl.match(urlRegexp);
38 if (!match) {
39 return null;
40 }
41 return {
42 scheme: match[1],
43 auth: match[2],
44 host: match[3],
45 port: match[4],
46 path: match[5]
47 };
48 }
49 exports.urlParse = urlParse;
50
51 function urlGenerate(aParsedUrl) {
52 var url = '';
53 if (aParsedUrl.scheme) {
54 url += aParsedUrl.scheme + ':';
55 }
56 url += '//';
57 if (aParsedUrl.auth) {
58 url += aParsedUrl.auth + '@';
59 }
60 if (aParsedUrl.host) {
61 url += aParsedUrl.host;
62 }
63 if (aParsedUrl.port) {
64 url += ":" + aParsedUrl.port
65 }
66 if (aParsedUrl.path) {
67 url += aParsedUrl.path;
68 }
69 return url;
70 }
71 exports.urlGenerate = urlGenerate;
72
73 /**
74 * Normalizes a path, or the path portion of a URL:
75 *
76 * - Replaces consequtive slashes with one slash.
77 * - Removes unnecessary '.' parts.
78 * - Removes unnecessary '<dir>/..' parts.
79 *
80 * Based on code in the Node.js 'path' core module.
81 *
82 * @param aPath The path or url to normalize.
83 */
84 function normalize(aPath) {
85 var path = aPath;
86 var url = urlParse(aPath);
87 if (url) {
88 if (!url.path) {
89 return aPath;
90 }
91 path = url.path;
92 }
93 var isAbsolute = (path.charAt(0) === '/');
94
95 var parts = path.split(/\/+/);
96 for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
97 part = parts[i];
98 if (part === '.') {
99 parts.splice(i, 1);
100 } else if (part === '..') {
101 up++;
102 } else if (up > 0) {
103 if (part === '') {
104 // The first part is blank if the path is absolute. Trying to go
105 // above the root is a no-op. Therefore we can remove all '..' parts
106 // directly after the root.
107 parts.splice(i + 1, up);
108 up = 0;
109 } else {
110 parts.splice(i, 2);
111 up--;
112 }
113 }
114 }
115 path = parts.join('/');
116
117 if (path === '') {
118 path = isAbsolute ? '/' : '.';
119 }
120
121 if (url) {
122 url.path = path;
123 return urlGenerate(url);
124 }
125 return path;
126 }
127 exports.normalize = normalize;
128
129 /**
130 * Joins two paths/URLs.
131 *
132 * @param aRoot The root path or URL.
133 * @param aPath The path or URL to be joined with the root.
134 *
135 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
136 * scheme-relative URL: Then the scheme of aRoot, if any, is prepended
137 * first.
138 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion
139 * is updated with the result and aRoot is returned. Otherwise the result
140 * is returned.
141 * - If aPath is absolute, the result is aPath.
142 * - Otherwise the two paths are joined with a slash.
143 * - Joining for example 'http://' and 'www.example.com' is also supported.
144 */
145 function join(aRoot, aPath) {
146 if (aRoot === "") {
147 aRoot = ".";
148 }
149 if (aPath === "") {
150 aPath = ".";
151 }
152 var aPathUrl = urlParse(aPath);
153 var aRootUrl = urlParse(aRoot);
154 if (aRootUrl) {
155 aRoot = aRootUrl.path || '/';
156 }
157
158 // `join(foo, '//www.example.org')`
159 if (aPathUrl && !aPathUrl.scheme) {
160 if (aRootUrl) {
161 aPathUrl.scheme = aRootUrl.scheme;
162 }
163 return urlGenerate(aPathUrl);
164 }
165
166 if (aPathUrl || aPath.match(dataUrlRegexp)) {
167 return aPath;
168 }
169
170 // `join('http://', 'www.example.com')`
171 if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
172 aRootUrl.host = aPath;
173 return urlGenerate(aRootUrl);
174 }
175
176 var joined = aPath.charAt(0) === '/'
177 ? aPath
178 : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
179
180 if (aRootUrl) {
181 aRootUrl.path = joined;
182 return urlGenerate(aRootUrl);
183 }
184 return joined;
185 }
186 exports.join = join;
187
188 /**
189 * Make a path relative to a URL or another path.
190 *
191 * @param aRoot The root path or URL.
192 * @param aPath The path or URL to be made relative to aRoot.
193 */
194 function relative(aRoot, aPath) {
195 if (aRoot === "") {
196 aRoot = ".";
197 }
198
199 aRoot = aRoot.replace(/\/$/, '');
200
201 // XXX: It is possible to remove this block, and the tests still pass!
202 var url = urlParse(aRoot);
203 if (aPath.charAt(0) == "/" && url && url.path == "/") {
204 return aPath.slice(1);
205 }
206
207 return aPath.indexOf(aRoot + '/') === 0
208 ? aPath.substr(aRoot.length + 1)
209 : aPath;
210 }
211 exports.relative = relative;
212
213 /**
214 * Because behavior goes wacky when you set `__proto__` on objects, we
215 * have to prefix all the strings in our set with an arbitrary character.
216 *
217 * See https://github.com/mozilla/source-map/pull/31 and
218 * https://github.com/mozilla/source-map/issues/30
219 *
220 * @param String aStr
221 */
222 function toSetString(aStr) {
223 return '$' + aStr;
224 }
225 exports.toSetString = toSetString;
226
227 function fromSetString(aStr) {
228 return aStr.substr(1);
229 }
230 exports.fromSetString = fromSetString;
231
232 function strcmp(aStr1, aStr2) {
233 var s1 = aStr1 || "";
234 var s2 = aStr2 || "";
235 return (s1 > s2) - (s1 < s2);
236 }
237
238 /**
239 * Comparator between two mappings where the original positions are compared.
240 *
241 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
242 * mappings with the same original source/line/column, but different generated
243 * line and column the same. Useful when searching for a mapping with a
244 * stubbed out mapping.
245 */
246 function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
247 var cmp;
248
249 cmp = strcmp(mappingA.source, mappingB.source);
250 if (cmp) {
251 return cmp;
252 }
253
254 cmp = mappingA.originalLine - mappingB.originalLine;
255 if (cmp) {
256 return cmp;
257 }
258
259 cmp = mappingA.originalColumn - mappingB.originalColumn;
260 if (cmp || onlyCompareOriginal) {
261 return cmp;
262 }
263
264 cmp = strcmp(mappingA.name, mappingB.name);
265 if (cmp) {
266 return cmp;
267 }
268
269 cmp = mappingA.generatedLine - mappingB.generatedLine;
270 if (cmp) {
271 return cmp;
272 }
273
274 return mappingA.generatedColumn - mappingB.generatedColumn;
275 };
276 exports.compareByOriginalPositions = compareByOriginalPositions;
277
278 /**
279 * Comparator between two mappings where the generated positions are
280 * compared.
281 *
282 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
283 * mappings with the same generated line and column, but different
284 * source/name/original line and column the same. Useful when searching for a
285 * mapping with a stubbed out mapping.
286 */
287 function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) {
288 var cmp;
289
290 cmp = mappingA.generatedLine - mappingB.generatedLine;
291 if (cmp) {
292 return cmp;
293 }
294
295 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
296 if (cmp || onlyCompareGenerated) {
297 return cmp;
298 }
299
300 cmp = strcmp(mappingA.source, mappingB.source);
301 if (cmp) {
302 return cmp;
303 }
304
305 cmp = mappingA.originalLine - mappingB.originalLine;
306 if (cmp) {
307 return cmp;
308 }
309
310 cmp = mappingA.originalColumn - mappingB.originalColumn;
311 if (cmp) {
312 return cmp;
313 }
314
315 return strcmp(mappingA.name, mappingB.name);
316 };
317 exports.compareByGeneratedPositions = compareByGeneratedPositions;
318
319 });