Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / escodegen / node_modules / source-map / lib / source-map / basic-source-map-consumer.js
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   var util = require('./util');
13   var binarySearch = require('./binary-search');
14   var ArraySet = require('./array-set').ArraySet;
15   var base64VLQ = require('./base64-vlq');
16   var SourceMapConsumer = require('./source-map-consumer').SourceMapConsumer;
17
18   /**
19    * A BasicSourceMapConsumer instance represents a parsed source map which we can
20    * query for information about the original file positions by giving it a file
21    * position in the generated source.
22    *
23    * The only parameter is the raw source map (either as a JSON string, or
24    * already parsed to an object). According to the spec, source maps have the
25    * following attributes:
26    *
27    *   - version: Which version of the source map spec this map is following.
28    *   - sources: An array of URLs to the original source files.
29    *   - names: An array of identifiers which can be referrenced by individual mappings.
30    *   - sourceRoot: Optional. The URL root from which all sources are relative.
31    *   - sourcesContent: Optional. An array of contents of the original source files.
32    *   - mappings: A string of base64 VLQs which contain the actual mappings.
33    *   - file: Optional. The generated file this source map is associated with.
34    *
35    * Here is an example source map, taken from the source map spec[0]:
36    *
37    *     {
38    *       version : 3,
39    *       file: "out.js",
40    *       sourceRoot : "",
41    *       sources: ["foo.js", "bar.js"],
42    *       names: ["src", "maps", "are", "fun"],
43    *       mappings: "AA,AB;;ABCDE;"
44    *     }
45    *
46    * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
47    */
48   function BasicSourceMapConsumer(aSourceMap) {
49     var sourceMap = aSourceMap;
50     if (typeof aSourceMap === 'string') {
51       sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
52     }
53
54     var version = util.getArg(sourceMap, 'version');
55     var sources = util.getArg(sourceMap, 'sources');
56     // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
57     // requires the array) to play nice here.
58     var names = util.getArg(sourceMap, 'names', []);
59     var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
60     var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
61     var mappings = util.getArg(sourceMap, 'mappings');
62     var file = util.getArg(sourceMap, 'file', null);
63
64     // Once again, Sass deviates from the spec and supplies the version as a
65     // string rather than a number, so we use loose equality checking here.
66     if (version != this._version) {
67       throw new Error('Unsupported version: ' + version);
68     }
69
70     // Some source maps produce relative source paths like "./foo.js" instead of
71     // "foo.js".  Normalize these first so that future comparisons will succeed.
72     // See bugzil.la/1090768.
73     sources = sources.map(util.normalize);
74
75     // Pass `true` below to allow duplicate names and sources. While source maps
76     // are intended to be compressed and deduplicated, the TypeScript compiler
77     // sometimes generates source maps with duplicates in them. See Github issue
78     // #72 and bugzil.la/889492.
79     this._names = ArraySet.fromArray(names, true);
80     this._sources = ArraySet.fromArray(sources, true);
81
82     this.sourceRoot = sourceRoot;
83     this.sourcesContent = sourcesContent;
84     this._mappings = mappings;
85     this.file = file;
86   }
87
88   BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
89   BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;
90
91   /**
92    * Create a BasicSourceMapConsumer from a SourceMapGenerator.
93    *
94    * @param SourceMapGenerator aSourceMap
95    *        The source map that will be consumed.
96    * @returns BasicSourceMapConsumer
97    */
98   BasicSourceMapConsumer.fromSourceMap =
99     function SourceMapConsumer_fromSourceMap(aSourceMap) {
100       var smc = Object.create(BasicSourceMapConsumer.prototype);
101
102       smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
103       smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
104       smc.sourceRoot = aSourceMap._sourceRoot;
105       smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
106                                                               smc.sourceRoot);
107       smc.file = aSourceMap._file;
108
109       smc.__generatedMappings = aSourceMap._mappings.toArray().slice();
110       smc.__originalMappings = aSourceMap._mappings.toArray().slice()
111         .sort(util.compareByOriginalPositions);
112
113       return smc;
114     };
115
116   /**
117    * The version of the source mapping spec that we are consuming.
118    */
119   BasicSourceMapConsumer.prototype._version = 3;
120
121   /**
122    * The list of original sources.
123    */
124   Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
125     get: function () {
126       return this._sources.toArray().map(function (s) {
127         return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
128       }, this);
129     }
130   });
131
132   /**
133    * Parse the mappings in a string in to a data structure which we can easily
134    * query (the ordered arrays in the `this.__generatedMappings` and
135    * `this.__originalMappings` properties).
136    */
137   BasicSourceMapConsumer.prototype._parseMappings =
138     function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
139       var generatedLine = 1;
140       var previousGeneratedColumn = 0;
141       var previousOriginalLine = 0;
142       var previousOriginalColumn = 0;
143       var previousSource = 0;
144       var previousName = 0;
145       var str = aStr;
146       var temp = {};
147       var mapping;
148
149       while (str.length > 0) {
150         if (str.charAt(0) === ';') {
151           generatedLine++;
152           str = str.slice(1);
153           previousGeneratedColumn = 0;
154         }
155         else if (str.charAt(0) === ',') {
156           str = str.slice(1);
157         }
158         else {
159           mapping = {};
160           mapping.generatedLine = generatedLine;
161
162           // Generated column.
163           base64VLQ.decode(str, temp);
164           mapping.generatedColumn = previousGeneratedColumn + temp.value;
165           previousGeneratedColumn = mapping.generatedColumn;
166           str = temp.rest;
167
168           if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
169             // Original source.
170             base64VLQ.decode(str, temp);
171             mapping.source = this._sources.at(previousSource + temp.value);
172             previousSource += temp.value;
173             str = temp.rest;
174             if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
175               throw new Error('Found a source, but no line and column');
176             }
177
178             // Original line.
179             base64VLQ.decode(str, temp);
180             mapping.originalLine = previousOriginalLine + temp.value;
181             previousOriginalLine = mapping.originalLine;
182             // Lines are stored 0-based
183             mapping.originalLine += 1;
184             str = temp.rest;
185             if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
186               throw new Error('Found a source and line, but no column');
187             }
188
189             // Original column.
190             base64VLQ.decode(str, temp);
191             mapping.originalColumn = previousOriginalColumn + temp.value;
192             previousOriginalColumn = mapping.originalColumn;
193             str = temp.rest;
194
195             if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
196               // Original name.
197               base64VLQ.decode(str, temp);
198               mapping.name = this._names.at(previousName + temp.value);
199               previousName += temp.value;
200               str = temp.rest;
201             }
202           }
203
204           this.__generatedMappings.push(mapping);
205           if (typeof mapping.originalLine === 'number') {
206             this.__originalMappings.push(mapping);
207           }
208         }
209       }
210
211       this.__generatedMappings.sort(util.compareByGeneratedPositions);
212       this.__originalMappings.sort(util.compareByOriginalPositions);
213     };
214
215   /**
216    * Find the mapping that best matches the hypothetical "needle" mapping that
217    * we are searching for in the given "haystack" of mappings.
218    */
219   BasicSourceMapConsumer.prototype._findMapping =
220     function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
221                                            aColumnName, aComparator) {
222       // To return the position we are searching for, we must first find the
223       // mapping for the given position and then return the opposite position it
224       // points to. Because the mappings are sorted, we can use binary search to
225       // find the best mapping.
226
227       if (aNeedle[aLineName] <= 0) {
228         throw new TypeError('Line must be greater than or equal to 1, got '
229                             + aNeedle[aLineName]);
230       }
231       if (aNeedle[aColumnName] < 0) {
232         throw new TypeError('Column must be greater than or equal to 0, got '
233                             + aNeedle[aColumnName]);
234       }
235
236       return binarySearch.search(aNeedle, aMappings, aComparator);
237     };
238
239   /**
240    * Compute the last column for each generated mapping. The last column is
241    * inclusive.
242    */
243   BasicSourceMapConsumer.prototype.computeColumnSpans =
244     function SourceMapConsumer_computeColumnSpans() {
245       for (var index = 0; index < this._generatedMappings.length; ++index) {
246         var mapping = this._generatedMappings[index];
247
248         // Mappings do not contain a field for the last generated columnt. We
249         // can come up with an optimistic estimate, however, by assuming that
250         // mappings are contiguous (i.e. given two consecutive mappings, the
251         // first mapping ends where the second one starts).
252         if (index + 1 < this._generatedMappings.length) {
253           var nextMapping = this._generatedMappings[index + 1];
254
255           if (mapping.generatedLine === nextMapping.generatedLine) {
256             mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
257             continue;
258           }
259         }
260
261         // The last mapping for each line spans the entire line.
262         mapping.lastGeneratedColumn = Infinity;
263       }
264     };
265
266   /**
267    * Returns the original source, line, and column information for the generated
268    * source's line and column positions provided. The only argument is an object
269    * with the following properties:
270    *
271    *   - line: The line number in the generated source.
272    *   - column: The column number in the generated source.
273    *
274    * and an object is returned with the following properties:
275    *
276    *   - source: The original source file, or null.
277    *   - line: The line number in the original source, or null.
278    *   - column: The column number in the original source, or null.
279    *   - name: The original identifier, or null.
280    */
281   BasicSourceMapConsumer.prototype.originalPositionFor =
282     function SourceMapConsumer_originalPositionFor(aArgs) {
283       var needle = {
284         generatedLine: util.getArg(aArgs, 'line'),
285         generatedColumn: util.getArg(aArgs, 'column')
286       };
287
288       var index = this._findMapping(needle,
289                                     this._generatedMappings,
290                                     "generatedLine",
291                                     "generatedColumn",
292                                     util.compareByGeneratedPositions);
293
294       if (index >= 0) {
295         var mapping = this._generatedMappings[index];
296
297         if (mapping.generatedLine === needle.generatedLine) {
298           var source = util.getArg(mapping, 'source', null);
299           if (source != null && this.sourceRoot != null) {
300             source = util.join(this.sourceRoot, source);
301           }
302           return {
303             source: source,
304             line: util.getArg(mapping, 'originalLine', null),
305             column: util.getArg(mapping, 'originalColumn', null),
306             name: util.getArg(mapping, 'name', null)
307           };
308         }
309       }
310
311       return {
312         source: null,
313         line: null,
314         column: null,
315         name: null
316       };
317     };
318
319   /**
320    * Returns the original source content. The only argument is the url of the
321    * original source file. Returns null if no original source content is
322    * availible.
323    */
324   BasicSourceMapConsumer.prototype.sourceContentFor =
325     function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
326       if (!this.sourcesContent) {
327         return null;
328       }
329
330       if (this.sourceRoot != null) {
331         aSource = util.relative(this.sourceRoot, aSource);
332       }
333
334       if (this._sources.has(aSource)) {
335         return this.sourcesContent[this._sources.indexOf(aSource)];
336       }
337
338       var url;
339       if (this.sourceRoot != null
340           && (url = util.urlParse(this.sourceRoot))) {
341         // XXX: file:// URIs and absolute paths lead to unexpected behavior for
342         // many users. We can help them out when they expect file:// URIs to
343         // behave like it would if they were running a local HTTP server. See
344         // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
345         var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
346         if (url.scheme == "file"
347             && this._sources.has(fileUriAbsPath)) {
348           return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
349         }
350
351         if ((!url.path || url.path == "/")
352             && this._sources.has("/" + aSource)) {
353           return this.sourcesContent[this._sources.indexOf("/" + aSource)];
354         }
355       }
356
357       // This function is used recursively from
358       // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we
359       // don't want to throw if we can't find the source - we just want to
360       // return null, so we provide a flag to exit gracefully.
361       if (nullOnMissing) {
362         return null;
363       }
364       else {
365         throw new Error('"' + aSource + '" is not in the SourceMap.');
366       }
367     };
368
369   /**
370    * Returns the generated line and column information for the original source,
371    * line, and column positions provided. The only argument is an object with
372    * the following properties:
373    *
374    *   - source: The filename of the original source.
375    *   - line: The line number in the original source.
376    *   - column: The column number in the original source.
377    *
378    * and an object is returned with the following properties:
379    *
380    *   - line: The line number in the generated source, or null.
381    *   - column: The column number in the generated source, or null.
382    */
383   BasicSourceMapConsumer.prototype.generatedPositionFor =
384     function SourceMapConsumer_generatedPositionFor(aArgs) {
385       var needle = {
386         source: util.getArg(aArgs, 'source'),
387         originalLine: util.getArg(aArgs, 'line'),
388         originalColumn: util.getArg(aArgs, 'column')
389       };
390
391       if (this.sourceRoot != null) {
392         needle.source = util.relative(this.sourceRoot, needle.source);
393       }
394
395       var index = this._findMapping(needle,
396                                     this._originalMappings,
397                                     "originalLine",
398                                     "originalColumn",
399                                     util.compareByOriginalPositions);
400
401       if (index >= 0) {
402         var mapping = this._originalMappings[index];
403
404         return {
405           line: util.getArg(mapping, 'generatedLine', null),
406           column: util.getArg(mapping, 'generatedColumn', null),
407           lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
408         };
409       }
410
411       return {
412         line: null,
413         column: null,
414         lastColumn: null
415       };
416     };
417
418   exports.BasicSourceMapConsumer = BasicSourceMapConsumer;
419
420 });