Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80559 views
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
});
320
321