Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / source-map / lib / source-map / source-node.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 SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
13   var util = require('./util');
14
15   // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
16   // operating systems these days (capturing the result).
17   var REGEX_NEWLINE = /(\r?\n)/;
18
19   // Newline character code for charCodeAt() comparisons
20   var NEWLINE_CODE = 10;
21
22   // Private symbol for identifying `SourceNode`s when multiple versions of
23   // the source-map library are loaded. This MUST NOT CHANGE across
24   // versions!
25   var isSourceNode = "$$$isSourceNode$$$";
26
27   /**
28    * SourceNodes provide a way to abstract over interpolating/concatenating
29    * snippets of generated JavaScript source code while maintaining the line and
30    * column information associated with the original source code.
31    *
32    * @param aLine The original line number.
33    * @param aColumn The original column number.
34    * @param aSource The original source's filename.
35    * @param aChunks Optional. An array of strings which are snippets of
36    *        generated JS, or other SourceNodes.
37    * @param aName The original identifier.
38    */
39   function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
40     this.children = [];
41     this.sourceContents = {};
42     this.line = aLine == null ? null : aLine;
43     this.column = aColumn == null ? null : aColumn;
44     this.source = aSource == null ? null : aSource;
45     this.name = aName == null ? null : aName;
46     this[isSourceNode] = true;
47     if (aChunks != null) this.add(aChunks);
48   }
49
50   /**
51    * Creates a SourceNode from generated code and a SourceMapConsumer.
52    *
53    * @param aGeneratedCode The generated code
54    * @param aSourceMapConsumer The SourceMap for the generated code
55    * @param aRelativePath Optional. The path that relative sources in the
56    *        SourceMapConsumer should be relative to.
57    */
58   SourceNode.fromStringWithSourceMap =
59     function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
60       // The SourceNode we want to fill with the generated code
61       // and the SourceMap
62       var node = new SourceNode();
63
64       // All even indices of this array are one line of the generated code,
65       // while all odd indices are the newlines between two adjacent lines
66       // (since `REGEX_NEWLINE` captures its match).
67       // Processed fragments are removed from this array, by calling `shiftNextLine`.
68       var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
69       var shiftNextLine = function() {
70         var lineContents = remainingLines.shift();
71         // The last line of a file might not have a newline.
72         var newLine = remainingLines.shift() || "";
73         return lineContents + newLine;
74       };
75
76       // We need to remember the position of "remainingLines"
77       var lastGeneratedLine = 1, lastGeneratedColumn = 0;
78
79       // The generate SourceNodes we need a code range.
80       // To extract it current and last mapping is used.
81       // Here we store the last mapping.
82       var lastMapping = null;
83
84       aSourceMapConsumer.eachMapping(function (mapping) {
85         if (lastMapping !== null) {
86           // We add the code from "lastMapping" to "mapping":
87           // First check if there is a new line in between.
88           if (lastGeneratedLine < mapping.generatedLine) {
89             var code = "";
90             // Associate first line with "lastMapping"
91             addMappingWithCode(lastMapping, shiftNextLine());
92             lastGeneratedLine++;
93             lastGeneratedColumn = 0;
94             // The remaining code is added without mapping
95           } else {
96             // There is no new line in between.
97             // Associate the code between "lastGeneratedColumn" and
98             // "mapping.generatedColumn" with "lastMapping"
99             var nextLine = remainingLines[0];
100             var code = nextLine.substr(0, mapping.generatedColumn -
101                                           lastGeneratedColumn);
102             remainingLines[0] = nextLine.substr(mapping.generatedColumn -
103                                                 lastGeneratedColumn);
104             lastGeneratedColumn = mapping.generatedColumn;
105             addMappingWithCode(lastMapping, code);
106             // No more remaining code, continue
107             lastMapping = mapping;
108             return;
109           }
110         }
111         // We add the generated code until the first mapping
112         // to the SourceNode without any mapping.
113         // Each line is added as separate string.
114         while (lastGeneratedLine < mapping.generatedLine) {
115           node.add(shiftNextLine());
116           lastGeneratedLine++;
117         }
118         if (lastGeneratedColumn < mapping.generatedColumn) {
119           var nextLine = remainingLines[0];
120           node.add(nextLine.substr(0, mapping.generatedColumn));
121           remainingLines[0] = nextLine.substr(mapping.generatedColumn);
122           lastGeneratedColumn = mapping.generatedColumn;
123         }
124         lastMapping = mapping;
125       }, this);
126       // We have processed all mappings.
127       if (remainingLines.length > 0) {
128         if (lastMapping) {
129           // Associate the remaining code in the current line with "lastMapping"
130           addMappingWithCode(lastMapping, shiftNextLine());
131         }
132         // and add the remaining lines without any mapping
133         node.add(remainingLines.join(""));
134       }
135
136       // Copy sourcesContent into SourceNode
137       aSourceMapConsumer.sources.forEach(function (sourceFile) {
138         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
139         if (content != null) {
140           if (aRelativePath != null) {
141             sourceFile = util.join(aRelativePath, sourceFile);
142           }
143           node.setSourceContent(sourceFile, content);
144         }
145       });
146
147       return node;
148
149       function addMappingWithCode(mapping, code) {
150         if (mapping === null || mapping.source === undefined) {
151           node.add(code);
152         } else {
153           var source = aRelativePath
154             ? util.join(aRelativePath, mapping.source)
155             : mapping.source;
156           node.add(new SourceNode(mapping.originalLine,
157                                   mapping.originalColumn,
158                                   source,
159                                   code,
160                                   mapping.name));
161         }
162       }
163     };
164
165   /**
166    * Add a chunk of generated JS to this source node.
167    *
168    * @param aChunk A string snippet of generated JS code, another instance of
169    *        SourceNode, or an array where each member is one of those things.
170    */
171   SourceNode.prototype.add = function SourceNode_add(aChunk) {
172     if (Array.isArray(aChunk)) {
173       aChunk.forEach(function (chunk) {
174         this.add(chunk);
175       }, this);
176     }
177     else if (aChunk[isSourceNode] || typeof aChunk === "string") {
178       if (aChunk) {
179         this.children.push(aChunk);
180       }
181     }
182     else {
183       throw new TypeError(
184         "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
185       );
186     }
187     return this;
188   };
189
190   /**
191    * Add a chunk of generated JS to the beginning of this source node.
192    *
193    * @param aChunk A string snippet of generated JS code, another instance of
194    *        SourceNode, or an array where each member is one of those things.
195    */
196   SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
197     if (Array.isArray(aChunk)) {
198       for (var i = aChunk.length-1; i >= 0; i--) {
199         this.prepend(aChunk[i]);
200       }
201     }
202     else if (aChunk[isSourceNode] || typeof aChunk === "string") {
203       this.children.unshift(aChunk);
204     }
205     else {
206       throw new TypeError(
207         "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
208       );
209     }
210     return this;
211   };
212
213   /**
214    * Walk over the tree of JS snippets in this node and its children. The
215    * walking function is called once for each snippet of JS and is passed that
216    * snippet and the its original associated source's line/column location.
217    *
218    * @param aFn The traversal function.
219    */
220   SourceNode.prototype.walk = function SourceNode_walk(aFn) {
221     var chunk;
222     for (var i = 0, len = this.children.length; i < len; i++) {
223       chunk = this.children[i];
224       if (chunk[isSourceNode]) {
225         chunk.walk(aFn);
226       }
227       else {
228         if (chunk !== '') {
229           aFn(chunk, { source: this.source,
230                        line: this.line,
231                        column: this.column,
232                        name: this.name });
233         }
234       }
235     }
236   };
237
238   /**
239    * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
240    * each of `this.children`.
241    *
242    * @param aSep The separator.
243    */
244   SourceNode.prototype.join = function SourceNode_join(aSep) {
245     var newChildren;
246     var i;
247     var len = this.children.length;
248     if (len > 0) {
249       newChildren = [];
250       for (i = 0; i < len-1; i++) {
251         newChildren.push(this.children[i]);
252         newChildren.push(aSep);
253       }
254       newChildren.push(this.children[i]);
255       this.children = newChildren;
256     }
257     return this;
258   };
259
260   /**
261    * Call String.prototype.replace on the very right-most source snippet. Useful
262    * for trimming whitespace from the end of a source node, etc.
263    *
264    * @param aPattern The pattern to replace.
265    * @param aReplacement The thing to replace the pattern with.
266    */
267   SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
268     var lastChild = this.children[this.children.length - 1];
269     if (lastChild[isSourceNode]) {
270       lastChild.replaceRight(aPattern, aReplacement);
271     }
272     else if (typeof lastChild === 'string') {
273       this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
274     }
275     else {
276       this.children.push(''.replace(aPattern, aReplacement));
277     }
278     return this;
279   };
280
281   /**
282    * Set the source content for a source file. This will be added to the SourceMapGenerator
283    * in the sourcesContent field.
284    *
285    * @param aSourceFile The filename of the source file
286    * @param aSourceContent The content of the source file
287    */
288   SourceNode.prototype.setSourceContent =
289     function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
290       this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
291     };
292
293   /**
294    * Walk over the tree of SourceNodes. The walking function is called for each
295    * source file content and is passed the filename and source content.
296    *
297    * @param aFn The traversal function.
298    */
299   SourceNode.prototype.walkSourceContents =
300     function SourceNode_walkSourceContents(aFn) {
301       for (var i = 0, len = this.children.length; i < len; i++) {
302         if (this.children[i][isSourceNode]) {
303           this.children[i].walkSourceContents(aFn);
304         }
305       }
306
307       var sources = Object.keys(this.sourceContents);
308       for (var i = 0, len = sources.length; i < len; i++) {
309         aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
310       }
311     };
312
313   /**
314    * Return the string representation of this source node. Walks over the tree
315    * and concatenates all the various snippets together to one string.
316    */
317   SourceNode.prototype.toString = function SourceNode_toString() {
318     var str = "";
319     this.walk(function (chunk) {
320       str += chunk;
321     });
322     return str;
323   };
324
325   /**
326    * Returns the string representation of this source node along with a source
327    * map.
328    */
329   SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
330     var generated = {
331       code: "",
332       line: 1,
333       column: 0
334     };
335     var map = new SourceMapGenerator(aArgs);
336     var sourceMappingActive = false;
337     var lastOriginalSource = null;
338     var lastOriginalLine = null;
339     var lastOriginalColumn = null;
340     var lastOriginalName = null;
341     this.walk(function (chunk, original) {
342       generated.code += chunk;
343       if (original.source !== null
344           && original.line !== null
345           && original.column !== null) {
346         if(lastOriginalSource !== original.source
347            || lastOriginalLine !== original.line
348            || lastOriginalColumn !== original.column
349            || lastOriginalName !== original.name) {
350           map.addMapping({
351             source: original.source,
352             original: {
353               line: original.line,
354               column: original.column
355             },
356             generated: {
357               line: generated.line,
358               column: generated.column
359             },
360             name: original.name
361           });
362         }
363         lastOriginalSource = original.source;
364         lastOriginalLine = original.line;
365         lastOriginalColumn = original.column;
366         lastOriginalName = original.name;
367         sourceMappingActive = true;
368       } else if (sourceMappingActive) {
369         map.addMapping({
370           generated: {
371             line: generated.line,
372             column: generated.column
373           }
374         });
375         lastOriginalSource = null;
376         sourceMappingActive = false;
377       }
378       for (var idx = 0, length = chunk.length; idx < length; idx++) {
379         if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
380           generated.line++;
381           generated.column = 0;
382           // Mappings end at eol
383           if (idx + 1 === length) {
384             lastOriginalSource = null;
385             sourceMappingActive = false;
386           } else if (sourceMappingActive) {
387             map.addMapping({
388               source: original.source,
389               original: {
390                 line: original.line,
391                 column: original.column
392               },
393               generated: {
394                 line: generated.line,
395                 column: generated.column
396               },
397               name: original.name
398             });
399           }
400         } else {
401           generated.column++;
402         }
403       }
404     });
405     this.walkSourceContents(function (sourceFile, sourceContent) {
406       map.setSourceContent(sourceFile, sourceContent);
407     });
408
409     return { code: generated.code, map: map };
410   };
411
412   exports.SourceNode = SourceNode;
413
414 });