source: imaps-frontend/node_modules/source-map-js/lib/source-map-generator.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 14.6 KB
RevLine 
[d565449]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
8var base64VLQ = require('./base64-vlq');
9var util = require('./util');
10var ArraySet = require('./array-set').ArraySet;
11var MappingList = require('./mapping-list').MappingList;
12
13/**
14 * An instance of the SourceMapGenerator represents a source map which is
15 * being built incrementally. You may pass an object with the following
16 * properties:
17 *
18 * - file: The filename of the generated source.
19 * - sourceRoot: A root for all relative URLs in this source map.
20 */
21function SourceMapGenerator(aArgs) {
22 if (!aArgs) {
23 aArgs = {};
24 }
25 this._file = util.getArg(aArgs, 'file', null);
26 this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
27 this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
28 this._ignoreInvalidMapping = util.getArg(aArgs, 'ignoreInvalidMapping', false);
29 this._sources = new ArraySet();
30 this._names = new ArraySet();
31 this._mappings = new MappingList();
32 this._sourcesContents = null;
33}
34
35SourceMapGenerator.prototype._version = 3;
36
37/**
38 * Creates a new SourceMapGenerator based on a SourceMapConsumer
39 *
40 * @param aSourceMapConsumer The SourceMap.
41 */
42SourceMapGenerator.fromSourceMap =
43 function SourceMapGenerator_fromSourceMap(aSourceMapConsumer, generatorOps) {
44 var sourceRoot = aSourceMapConsumer.sourceRoot;
45 var generator = new SourceMapGenerator(Object.assign(generatorOps || {}, {
46 file: aSourceMapConsumer.file,
47 sourceRoot: sourceRoot
48 }));
49 aSourceMapConsumer.eachMapping(function (mapping) {
50 var newMapping = {
51 generated: {
52 line: mapping.generatedLine,
53 column: mapping.generatedColumn
54 }
55 };
56
57 if (mapping.source != null) {
58 newMapping.source = mapping.source;
59 if (sourceRoot != null) {
60 newMapping.source = util.relative(sourceRoot, newMapping.source);
61 }
62
63 newMapping.original = {
64 line: mapping.originalLine,
65 column: mapping.originalColumn
66 };
67
68 if (mapping.name != null) {
69 newMapping.name = mapping.name;
70 }
71 }
72
73 generator.addMapping(newMapping);
74 });
75 aSourceMapConsumer.sources.forEach(function (sourceFile) {
76 var sourceRelative = sourceFile;
77 if (sourceRoot !== null) {
78 sourceRelative = util.relative(sourceRoot, sourceFile);
79 }
80
81 if (!generator._sources.has(sourceRelative)) {
82 generator._sources.add(sourceRelative);
83 }
84
85 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
86 if (content != null) {
87 generator.setSourceContent(sourceFile, content);
88 }
89 });
90 return generator;
91 };
92
93/**
94 * Add a single mapping from original source line and column to the generated
95 * source's line and column for this source map being created. The mapping
96 * object should have the following properties:
97 *
98 * - generated: An object with the generated line and column positions.
99 * - original: An object with the original line and column positions.
100 * - source: The original source file (relative to the sourceRoot).
101 * - name: An optional original token name for this mapping.
102 */
103SourceMapGenerator.prototype.addMapping =
104 function SourceMapGenerator_addMapping(aArgs) {
105 var generated = util.getArg(aArgs, 'generated');
106 var original = util.getArg(aArgs, 'original', null);
107 var source = util.getArg(aArgs, 'source', null);
108 var name = util.getArg(aArgs, 'name', null);
109
110 if (!this._skipValidation) {
111 if (this._validateMapping(generated, original, source, name) === false) {
112 return;
113 }
114 }
115
116 if (source != null) {
117 source = String(source);
118 if (!this._sources.has(source)) {
119 this._sources.add(source);
120 }
121 }
122
123 if (name != null) {
124 name = String(name);
125 if (!this._names.has(name)) {
126 this._names.add(name);
127 }
128 }
129
130 this._mappings.add({
131 generatedLine: generated.line,
132 generatedColumn: generated.column,
133 originalLine: original != null && original.line,
134 originalColumn: original != null && original.column,
135 source: source,
136 name: name
137 });
138 };
139
140/**
141 * Set the source content for a source file.
142 */
143SourceMapGenerator.prototype.setSourceContent =
144 function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
145 var source = aSourceFile;
146 if (this._sourceRoot != null) {
147 source = util.relative(this._sourceRoot, source);
148 }
149
150 if (aSourceContent != null) {
151 // Add the source content to the _sourcesContents map.
152 // Create a new _sourcesContents map if the property is null.
153 if (!this._sourcesContents) {
154 this._sourcesContents = Object.create(null);
155 }
156 this._sourcesContents[util.toSetString(source)] = aSourceContent;
157 } else if (this._sourcesContents) {
158 // Remove the source file from the _sourcesContents map.
159 // If the _sourcesContents map is empty, set the property to null.
160 delete this._sourcesContents[util.toSetString(source)];
161 if (Object.keys(this._sourcesContents).length === 0) {
162 this._sourcesContents = null;
163 }
164 }
165 };
166
167/**
168 * Applies the mappings of a sub-source-map for a specific source file to the
169 * source map being generated. Each mapping to the supplied source file is
170 * rewritten using the supplied source map. Note: The resolution for the
171 * resulting mappings is the minimium of this map and the supplied map.
172 *
173 * @param aSourceMapConsumer The source map to be applied.
174 * @param aSourceFile Optional. The filename of the source file.
175 * If omitted, SourceMapConsumer's file property will be used.
176 * @param aSourceMapPath Optional. The dirname of the path to the source map
177 * to be applied. If relative, it is relative to the SourceMapConsumer.
178 * This parameter is needed when the two source maps aren't in the same
179 * directory, and the source map to be applied contains relative source
180 * paths. If so, those relative source paths need to be rewritten
181 * relative to the SourceMapGenerator.
182 */
183SourceMapGenerator.prototype.applySourceMap =
184 function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
185 var sourceFile = aSourceFile;
186 // If aSourceFile is omitted, we will use the file property of the SourceMap
187 if (aSourceFile == null) {
188 if (aSourceMapConsumer.file == null) {
189 throw new Error(
190 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
191 'or the source map\'s "file" property. Both were omitted.'
192 );
193 }
194 sourceFile = aSourceMapConsumer.file;
195 }
196 var sourceRoot = this._sourceRoot;
197 // Make "sourceFile" relative if an absolute Url is passed.
198 if (sourceRoot != null) {
199 sourceFile = util.relative(sourceRoot, sourceFile);
200 }
201 // Applying the SourceMap can add and remove items from the sources and
202 // the names array.
203 var newSources = new ArraySet();
204 var newNames = new ArraySet();
205
206 // Find mappings for the "sourceFile"
207 this._mappings.unsortedForEach(function (mapping) {
208 if (mapping.source === sourceFile && mapping.originalLine != null) {
209 // Check if it can be mapped by the source map, then update the mapping.
210 var original = aSourceMapConsumer.originalPositionFor({
211 line: mapping.originalLine,
212 column: mapping.originalColumn
213 });
214 if (original.source != null) {
215 // Copy mapping
216 mapping.source = original.source;
217 if (aSourceMapPath != null) {
218 mapping.source = util.join(aSourceMapPath, mapping.source)
219 }
220 if (sourceRoot != null) {
221 mapping.source = util.relative(sourceRoot, mapping.source);
222 }
223 mapping.originalLine = original.line;
224 mapping.originalColumn = original.column;
225 if (original.name != null) {
226 mapping.name = original.name;
227 }
228 }
229 }
230
231 var source = mapping.source;
232 if (source != null && !newSources.has(source)) {
233 newSources.add(source);
234 }
235
236 var name = mapping.name;
237 if (name != null && !newNames.has(name)) {
238 newNames.add(name);
239 }
240
241 }, this);
242 this._sources = newSources;
243 this._names = newNames;
244
245 // Copy sourcesContents of applied map.
246 aSourceMapConsumer.sources.forEach(function (sourceFile) {
247 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
248 if (content != null) {
249 if (aSourceMapPath != null) {
250 sourceFile = util.join(aSourceMapPath, sourceFile);
251 }
252 if (sourceRoot != null) {
253 sourceFile = util.relative(sourceRoot, sourceFile);
254 }
255 this.setSourceContent(sourceFile, content);
256 }
257 }, this);
258 };
259
260/**
261 * A mapping can have one of the three levels of data:
262 *
263 * 1. Just the generated position.
264 * 2. The Generated position, original position, and original source.
265 * 3. Generated and original position, original source, as well as a name
266 * token.
267 *
268 * To maintain consistency, we validate that any new mapping being added falls
269 * in to one of these categories.
270 */
271SourceMapGenerator.prototype._validateMapping =
272 function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
273 aName) {
274 // When aOriginal is truthy but has empty values for .line and .column,
275 // it is most likely a programmer error. In this case we throw a very
276 // specific error message to try to guide them the right way.
277 // For example: https://github.com/Polymer/polymer-bundler/pull/519
278 if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
279 var message = 'original.line and original.column are not numbers -- you probably meant to omit ' +
280 'the original mapping entirely and only map the generated position. If so, pass ' +
281 'null for the original mapping instead of an object with empty or null values.'
282
283 if (this._ignoreInvalidMapping) {
284 if (typeof console !== 'undefined' && console.warn) {
285 console.warn(message);
286 }
287 return false;
288 } else {
289 throw new Error(message);
290 }
291 }
292
293 if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
294 && aGenerated.line > 0 && aGenerated.column >= 0
295 && !aOriginal && !aSource && !aName) {
296 // Case 1.
297 return;
298 }
299 else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
300 && aOriginal && 'line' in aOriginal && 'column' in aOriginal
301 && aGenerated.line > 0 && aGenerated.column >= 0
302 && aOriginal.line > 0 && aOriginal.column >= 0
303 && aSource) {
304 // Cases 2 and 3.
305 return;
306 }
307 else {
308 var message = 'Invalid mapping: ' + JSON.stringify({
309 generated: aGenerated,
310 source: aSource,
311 original: aOriginal,
312 name: aName
313 });
314
315 if (this._ignoreInvalidMapping) {
316 if (typeof console !== 'undefined' && console.warn) {
317 console.warn(message);
318 }
319 return false;
320 } else {
321 throw new Error(message)
322 }
323 }
324 };
325
326/**
327 * Serialize the accumulated mappings in to the stream of base 64 VLQs
328 * specified by the source map format.
329 */
330SourceMapGenerator.prototype._serializeMappings =
331 function SourceMapGenerator_serializeMappings() {
332 var previousGeneratedColumn = 0;
333 var previousGeneratedLine = 1;
334 var previousOriginalColumn = 0;
335 var previousOriginalLine = 0;
336 var previousName = 0;
337 var previousSource = 0;
338 var result = '';
339 var next;
340 var mapping;
341 var nameIdx;
342 var sourceIdx;
343
344 var mappings = this._mappings.toArray();
345 for (var i = 0, len = mappings.length; i < len; i++) {
346 mapping = mappings[i];
347 next = ''
348
349 if (mapping.generatedLine !== previousGeneratedLine) {
350 previousGeneratedColumn = 0;
351 while (mapping.generatedLine !== previousGeneratedLine) {
352 next += ';';
353 previousGeneratedLine++;
354 }
355 }
356 else {
357 if (i > 0) {
358 if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
359 continue;
360 }
361 next += ',';
362 }
363 }
364
365 next += base64VLQ.encode(mapping.generatedColumn
366 - previousGeneratedColumn);
367 previousGeneratedColumn = mapping.generatedColumn;
368
369 if (mapping.source != null) {
370 sourceIdx = this._sources.indexOf(mapping.source);
371 next += base64VLQ.encode(sourceIdx - previousSource);
372 previousSource = sourceIdx;
373
374 // lines are stored 0-based in SourceMap spec version 3
375 next += base64VLQ.encode(mapping.originalLine - 1
376 - previousOriginalLine);
377 previousOriginalLine = mapping.originalLine - 1;
378
379 next += base64VLQ.encode(mapping.originalColumn
380 - previousOriginalColumn);
381 previousOriginalColumn = mapping.originalColumn;
382
383 if (mapping.name != null) {
384 nameIdx = this._names.indexOf(mapping.name);
385 next += base64VLQ.encode(nameIdx - previousName);
386 previousName = nameIdx;
387 }
388 }
389
390 result += next;
391 }
392
393 return result;
394 };
395
396SourceMapGenerator.prototype._generateSourcesContent =
397 function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
398 return aSources.map(function (source) {
399 if (!this._sourcesContents) {
400 return null;
401 }
402 if (aSourceRoot != null) {
403 source = util.relative(aSourceRoot, source);
404 }
405 var key = util.toSetString(source);
406 return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
407 ? this._sourcesContents[key]
408 : null;
409 }, this);
410 };
411
412/**
413 * Externalize the source map.
414 */
415SourceMapGenerator.prototype.toJSON =
416 function SourceMapGenerator_toJSON() {
417 var map = {
418 version: this._version,
419 sources: this._sources.toArray(),
420 names: this._names.toArray(),
421 mappings: this._serializeMappings()
422 };
423 if (this._file != null) {
424 map.file = this._file;
425 }
426 if (this._sourceRoot != null) {
427 map.sourceRoot = this._sourceRoot;
428 }
429 if (this._sourcesContents) {
430 map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
431 }
432
433 return map;
434 };
435
436/**
437 * Render the source map being generated to a string.
438 */
439SourceMapGenerator.prototype.toString =
440 function SourceMapGenerator_toString() {
441 return JSON.stringify(this.toJSON());
442 };
443
444exports.SourceMapGenerator = SourceMapGenerator;
Note: See TracBrowser for help on using the repository browser.