Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 */
8 /**
9 * Define a module along with a payload.
10 * @param {string} moduleName Name for the payload
11 * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec
12 * @param {function} payload Function with (require, exports, module) params
13 */
14 function define(moduleName, deps, payload) {
15 if (typeof moduleName != "string") {
16 throw new TypeError('Expected string, got: ' + moduleName);
17 }
19 if (arguments.length == 2) {
20 payload = deps;
21 }
23 if (moduleName in define.modules) {
24 throw new Error("Module already defined: " + moduleName);
25 }
26 define.modules[moduleName] = payload;
27 };
29 /**
30 * The global store of un-instantiated modules
31 */
32 define.modules = {};
35 /**
36 * We invoke require() in the context of a Domain so we can have multiple
37 * sets of modules running separate from each other.
38 * This contrasts with JSMs which are singletons, Domains allows us to
39 * optionally load a CommonJS module twice with separate data each time.
40 * Perhaps you want 2 command lines with a different set of commands in each,
41 * for example.
42 */
43 function Domain() {
44 this.modules = {};
45 this._currentModule = null;
46 }
48 (function () {
50 /**
51 * Lookup module names and resolve them by calling the definition function if
52 * needed.
53 * There are 2 ways to call this, either with an array of dependencies and a
54 * callback to call when the dependencies are found (which can happen
55 * asynchronously in an in-page context) or with a single string an no callback
56 * where the dependency is resolved synchronously and returned.
57 * The API is designed to be compatible with the CommonJS AMD spec and
58 * RequireJS.
59 * @param {string[]|string} deps A name, or names for the payload
60 * @param {function|undefined} callback Function to call when the dependencies
61 * are resolved
62 * @return {undefined|object} The module required or undefined for
63 * array/callback method
64 */
65 Domain.prototype.require = function(deps, callback) {
66 if (Array.isArray(deps)) {
67 var params = deps.map(function(dep) {
68 return this.lookup(dep);
69 }, this);
70 if (callback) {
71 callback.apply(null, params);
72 }
73 return undefined;
74 }
75 else {
76 return this.lookup(deps);
77 }
78 };
80 function normalize(path) {
81 var bits = path.split('/');
82 var i = 1;
83 while (i < bits.length) {
84 if (bits[i] === '..') {
85 bits.splice(i-1, 1);
86 } else if (bits[i] === '.') {
87 bits.splice(i, 1);
88 } else {
89 i++;
90 }
91 }
92 return bits.join('/');
93 }
95 function join(a, b) {
96 a = a.trim();
97 b = b.trim();
98 if (/^\//.test(b)) {
99 return b;
100 } else {
101 return a.replace(/\/*$/, '/') + b;
102 }
103 }
105 function dirname(path) {
106 var bits = path.split('/');
107 bits.pop();
108 return bits.join('/');
109 }
111 /**
112 * Lookup module names and resolve them by calling the definition function if
113 * needed.
114 * @param {string} moduleName A name for the payload to lookup
115 * @return {object} The module specified by aModuleName or null if not found.
116 */
117 Domain.prototype.lookup = function(moduleName) {
118 if (/^\./.test(moduleName)) {
119 moduleName = normalize(join(dirname(this._currentModule), moduleName));
120 }
122 if (moduleName in this.modules) {
123 var module = this.modules[moduleName];
124 return module;
125 }
127 if (!(moduleName in define.modules)) {
128 throw new Error("Module not defined: " + moduleName);
129 }
131 var module = define.modules[moduleName];
133 if (typeof module == "function") {
134 var exports = {};
135 var previousModule = this._currentModule;
136 this._currentModule = moduleName;
137 module(this.require.bind(this), exports, { id: moduleName, uri: "" });
138 this._currentModule = previousModule;
139 module = exports;
140 }
142 // cache the resulting module object for next time
143 this.modules[moduleName] = module;
145 return module;
146 };
148 }());
150 define.Domain = Domain;
151 define.globalDomain = new Domain();
152 var require = define.globalDomain.require.bind(define.globalDomain);
153 /* -*- Mode: js; js-indent-level: 2; -*- */
154 /*
155 * Copyright 2011 Mozilla Foundation and contributors
156 * Licensed under the New BSD license. See LICENSE or:
157 * http://opensource.org/licenses/BSD-3-Clause
158 */
159 define('source-map/source-map-generator', ['require', 'exports', 'module' , 'source-map/base64-vlq', 'source-map/util', 'source-map/array-set'], function(require, exports, module) {
161 var base64VLQ = require('./base64-vlq');
162 var util = require('./util');
163 var ArraySet = require('./array-set').ArraySet;
165 /**
166 * An instance of the SourceMapGenerator represents a source map which is
167 * being built incrementally. To create a new one, you must pass an object
168 * with the following properties:
169 *
170 * - file: The filename of the generated source.
171 * - sourceRoot: An optional root for all URLs in this source map.
172 */
173 function SourceMapGenerator(aArgs) {
174 this._file = util.getArg(aArgs, 'file');
175 this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
176 this._sources = new ArraySet();
177 this._names = new ArraySet();
178 this._mappings = [];
179 this._sourcesContents = null;
180 }
182 SourceMapGenerator.prototype._version = 3;
184 /**
185 * Creates a new SourceMapGenerator based on a SourceMapConsumer
186 *
187 * @param aSourceMapConsumer The SourceMap.
188 */
189 SourceMapGenerator.fromSourceMap =
190 function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
191 var sourceRoot = aSourceMapConsumer.sourceRoot;
192 var generator = new SourceMapGenerator({
193 file: aSourceMapConsumer.file,
194 sourceRoot: sourceRoot
195 });
196 aSourceMapConsumer.eachMapping(function (mapping) {
197 var newMapping = {
198 generated: {
199 line: mapping.generatedLine,
200 column: mapping.generatedColumn
201 }
202 };
204 if (mapping.source) {
205 newMapping.source = mapping.source;
206 if (sourceRoot) {
207 newMapping.source = util.relative(sourceRoot, newMapping.source);
208 }
210 newMapping.original = {
211 line: mapping.originalLine,
212 column: mapping.originalColumn
213 };
215 if (mapping.name) {
216 newMapping.name = mapping.name;
217 }
218 }
220 generator.addMapping(newMapping);
221 });
222 aSourceMapConsumer.sources.forEach(function (sourceFile) {
223 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
224 if (content) {
225 generator.setSourceContent(sourceFile, content);
226 }
227 });
228 return generator;
229 };
231 /**
232 * Add a single mapping from original source line and column to the generated
233 * source's line and column for this source map being created. The mapping
234 * object should have the following properties:
235 *
236 * - generated: An object with the generated line and column positions.
237 * - original: An object with the original line and column positions.
238 * - source: The original source file (relative to the sourceRoot).
239 * - name: An optional original token name for this mapping.
240 */
241 SourceMapGenerator.prototype.addMapping =
242 function SourceMapGenerator_addMapping(aArgs) {
243 var generated = util.getArg(aArgs, 'generated');
244 var original = util.getArg(aArgs, 'original', null);
245 var source = util.getArg(aArgs, 'source', null);
246 var name = util.getArg(aArgs, 'name', null);
248 this._validateMapping(generated, original, source, name);
250 if (source && !this._sources.has(source)) {
251 this._sources.add(source);
252 }
254 if (name && !this._names.has(name)) {
255 this._names.add(name);
256 }
258 this._mappings.push({
259 generatedLine: generated.line,
260 generatedColumn: generated.column,
261 originalLine: original != null && original.line,
262 originalColumn: original != null && original.column,
263 source: source,
264 name: name
265 });
266 };
268 /**
269 * Set the source content for a source file.
270 */
271 SourceMapGenerator.prototype.setSourceContent =
272 function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
273 var source = aSourceFile;
274 if (this._sourceRoot) {
275 source = util.relative(this._sourceRoot, source);
276 }
278 if (aSourceContent !== null) {
279 // Add the source content to the _sourcesContents map.
280 // Create a new _sourcesContents map if the property is null.
281 if (!this._sourcesContents) {
282 this._sourcesContents = {};
283 }
284 this._sourcesContents[util.toSetString(source)] = aSourceContent;
285 } else {
286 // Remove the source file from the _sourcesContents map.
287 // If the _sourcesContents map is empty, set the property to null.
288 delete this._sourcesContents[util.toSetString(source)];
289 if (Object.keys(this._sourcesContents).length === 0) {
290 this._sourcesContents = null;
291 }
292 }
293 };
295 /**
296 * Applies the mappings of a sub-source-map for a specific source file to the
297 * source map being generated. Each mapping to the supplied source file is
298 * rewritten using the supplied source map. Note: The resolution for the
299 * resulting mappings is the minimium of this map and the supplied map.
300 *
301 * @param aSourceMapConsumer The source map to be applied.
302 * @param aSourceFile Optional. The filename of the source file.
303 * If omitted, SourceMapConsumer's file property will be used.
304 */
305 SourceMapGenerator.prototype.applySourceMap =
306 function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) {
307 // If aSourceFile is omitted, we will use the file property of the SourceMap
308 if (!aSourceFile) {
309 aSourceFile = aSourceMapConsumer.file;
310 }
311 var sourceRoot = this._sourceRoot;
312 // Make "aSourceFile" relative if an absolute Url is passed.
313 if (sourceRoot) {
314 aSourceFile = util.relative(sourceRoot, aSourceFile);
315 }
316 // Applying the SourceMap can add and remove items from the sources and
317 // the names array.
318 var newSources = new ArraySet();
319 var newNames = new ArraySet();
321 // Find mappings for the "aSourceFile"
322 this._mappings.forEach(function (mapping) {
323 if (mapping.source === aSourceFile && mapping.originalLine) {
324 // Check if it can be mapped by the source map, then update the mapping.
325 var original = aSourceMapConsumer.originalPositionFor({
326 line: mapping.originalLine,
327 column: mapping.originalColumn
328 });
329 if (original.source !== null) {
330 // Copy mapping
331 if (sourceRoot) {
332 mapping.source = util.relative(sourceRoot, original.source);
333 } else {
334 mapping.source = original.source;
335 }
336 mapping.originalLine = original.line;
337 mapping.originalColumn = original.column;
338 if (original.name !== null && mapping.name !== null) {
339 // Only use the identifier name if it's an identifier
340 // in both SourceMaps
341 mapping.name = original.name;
342 }
343 }
344 }
346 var source = mapping.source;
347 if (source && !newSources.has(source)) {
348 newSources.add(source);
349 }
351 var name = mapping.name;
352 if (name && !newNames.has(name)) {
353 newNames.add(name);
354 }
356 }, this);
357 this._sources = newSources;
358 this._names = newNames;
360 // Copy sourcesContents of applied map.
361 aSourceMapConsumer.sources.forEach(function (sourceFile) {
362 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
363 if (content) {
364 if (sourceRoot) {
365 sourceFile = util.relative(sourceRoot, sourceFile);
366 }
367 this.setSourceContent(sourceFile, content);
368 }
369 }, this);
370 };
372 /**
373 * A mapping can have one of the three levels of data:
374 *
375 * 1. Just the generated position.
376 * 2. The Generated position, original position, and original source.
377 * 3. Generated and original position, original source, as well as a name
378 * token.
379 *
380 * To maintain consistency, we validate that any new mapping being added falls
381 * in to one of these categories.
382 */
383 SourceMapGenerator.prototype._validateMapping =
384 function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
385 aName) {
386 if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
387 && aGenerated.line > 0 && aGenerated.column >= 0
388 && !aOriginal && !aSource && !aName) {
389 // Case 1.
390 return;
391 }
392 else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
393 && aOriginal && 'line' in aOriginal && 'column' in aOriginal
394 && aGenerated.line > 0 && aGenerated.column >= 0
395 && aOriginal.line > 0 && aOriginal.column >= 0
396 && aSource) {
397 // Cases 2 and 3.
398 return;
399 }
400 else {
401 throw new Error('Invalid mapping: ' + JSON.stringify({
402 generated: aGenerated,
403 source: aSource,
404 orginal: aOriginal,
405 name: aName
406 }));
407 }
408 };
410 /**
411 * Serialize the accumulated mappings in to the stream of base 64 VLQs
412 * specified by the source map format.
413 */
414 SourceMapGenerator.prototype._serializeMappings =
415 function SourceMapGenerator_serializeMappings() {
416 var previousGeneratedColumn = 0;
417 var previousGeneratedLine = 1;
418 var previousOriginalColumn = 0;
419 var previousOriginalLine = 0;
420 var previousName = 0;
421 var previousSource = 0;
422 var result = '';
423 var mapping;
425 // The mappings must be guaranteed to be in sorted order before we start
426 // serializing them or else the generated line numbers (which are defined
427 // via the ';' separators) will be all messed up. Note: it might be more
428 // performant to maintain the sorting as we insert them, rather than as we
429 // serialize them, but the big O is the same either way.
430 this._mappings.sort(util.compareByGeneratedPositions);
432 for (var i = 0, len = this._mappings.length; i < len; i++) {
433 mapping = this._mappings[i];
435 if (mapping.generatedLine !== previousGeneratedLine) {
436 previousGeneratedColumn = 0;
437 while (mapping.generatedLine !== previousGeneratedLine) {
438 result += ';';
439 previousGeneratedLine++;
440 }
441 }
442 else {
443 if (i > 0) {
444 if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) {
445 continue;
446 }
447 result += ',';
448 }
449 }
451 result += base64VLQ.encode(mapping.generatedColumn
452 - previousGeneratedColumn);
453 previousGeneratedColumn = mapping.generatedColumn;
455 if (mapping.source) {
456 result += base64VLQ.encode(this._sources.indexOf(mapping.source)
457 - previousSource);
458 previousSource = this._sources.indexOf(mapping.source);
460 // lines are stored 0-based in SourceMap spec version 3
461 result += base64VLQ.encode(mapping.originalLine - 1
462 - previousOriginalLine);
463 previousOriginalLine = mapping.originalLine - 1;
465 result += base64VLQ.encode(mapping.originalColumn
466 - previousOriginalColumn);
467 previousOriginalColumn = mapping.originalColumn;
469 if (mapping.name) {
470 result += base64VLQ.encode(this._names.indexOf(mapping.name)
471 - previousName);
472 previousName = this._names.indexOf(mapping.name);
473 }
474 }
475 }
477 return result;
478 };
480 SourceMapGenerator.prototype._generateSourcesContent =
481 function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
482 return aSources.map(function (source) {
483 if (!this._sourcesContents) {
484 return null;
485 }
486 if (aSourceRoot) {
487 source = util.relative(aSourceRoot, source);
488 }
489 var key = util.toSetString(source);
490 return Object.prototype.hasOwnProperty.call(this._sourcesContents,
491 key)
492 ? this._sourcesContents[key]
493 : null;
494 }, this);
495 };
497 /**
498 * Externalize the source map.
499 */
500 SourceMapGenerator.prototype.toJSON =
501 function SourceMapGenerator_toJSON() {
502 var map = {
503 version: this._version,
504 file: this._file,
505 sources: this._sources.toArray(),
506 names: this._names.toArray(),
507 mappings: this._serializeMappings()
508 };
509 if (this._sourceRoot) {
510 map.sourceRoot = this._sourceRoot;
511 }
512 if (this._sourcesContents) {
513 map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
514 }
516 return map;
517 };
519 /**
520 * Render the source map being generated to a string.
521 */
522 SourceMapGenerator.prototype.toString =
523 function SourceMapGenerator_toString() {
524 return JSON.stringify(this);
525 };
527 exports.SourceMapGenerator = SourceMapGenerator;
529 });
530 /* -*- Mode: js; js-indent-level: 2; -*- */
531 /*
532 * Copyright 2011 Mozilla Foundation and contributors
533 * Licensed under the New BSD license. See LICENSE or:
534 * http://opensource.org/licenses/BSD-3-Clause
535 *
536 * Based on the Base 64 VLQ implementation in Closure Compiler:
537 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
538 *
539 * Copyright 2011 The Closure Compiler Authors. All rights reserved.
540 * Redistribution and use in source and binary forms, with or without
541 * modification, are permitted provided that the following conditions are
542 * met:
543 *
544 * * Redistributions of source code must retain the above copyright
545 * notice, this list of conditions and the following disclaimer.
546 * * Redistributions in binary form must reproduce the above
547 * copyright notice, this list of conditions and the following
548 * disclaimer in the documentation and/or other materials provided
549 * with the distribution.
550 * * Neither the name of Google Inc. nor the names of its
551 * contributors may be used to endorse or promote products derived
552 * from this software without specific prior written permission.
553 *
554 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
555 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
556 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
557 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
558 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
559 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
560 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
561 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
562 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
563 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
564 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
565 */
566 define('source-map/base64-vlq', ['require', 'exports', 'module' , 'source-map/base64'], function(require, exports, module) {
568 var base64 = require('./base64');
570 // A single base 64 digit can contain 6 bits of data. For the base 64 variable
571 // length quantities we use in the source map spec, the first bit is the sign,
572 // the next four bits are the actual value, and the 6th bit is the
573 // continuation bit. The continuation bit tells us whether there are more
574 // digits in this value following this digit.
575 //
576 // Continuation
577 // | Sign
578 // | |
579 // V V
580 // 101011
582 var VLQ_BASE_SHIFT = 5;
584 // binary: 100000
585 var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
587 // binary: 011111
588 var VLQ_BASE_MASK = VLQ_BASE - 1;
590 // binary: 100000
591 var VLQ_CONTINUATION_BIT = VLQ_BASE;
593 /**
594 * Converts from a two-complement value to a value where the sign bit is
595 * is placed in the least significant bit. For example, as decimals:
596 * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
597 * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
598 */
599 function toVLQSigned(aValue) {
600 return aValue < 0
601 ? ((-aValue) << 1) + 1
602 : (aValue << 1) + 0;
603 }
605 /**
606 * Converts to a two-complement value from a value where the sign bit is
607 * is placed in the least significant bit. For example, as decimals:
608 * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
609 * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
610 */
611 function fromVLQSigned(aValue) {
612 var isNegative = (aValue & 1) === 1;
613 var shifted = aValue >> 1;
614 return isNegative
615 ? -shifted
616 : shifted;
617 }
619 /**
620 * Returns the base 64 VLQ encoded value.
621 */
622 exports.encode = function base64VLQ_encode(aValue) {
623 var encoded = "";
624 var digit;
626 var vlq = toVLQSigned(aValue);
628 do {
629 digit = vlq & VLQ_BASE_MASK;
630 vlq >>>= VLQ_BASE_SHIFT;
631 if (vlq > 0) {
632 // There are still more digits in this value, so we must make sure the
633 // continuation bit is marked.
634 digit |= VLQ_CONTINUATION_BIT;
635 }
636 encoded += base64.encode(digit);
637 } while (vlq > 0);
639 return encoded;
640 };
642 /**
643 * Decodes the next base 64 VLQ value from the given string and returns the
644 * value and the rest of the string.
645 */
646 exports.decode = function base64VLQ_decode(aStr) {
647 var i = 0;
648 var strLen = aStr.length;
649 var result = 0;
650 var shift = 0;
651 var continuation, digit;
653 do {
654 if (i >= strLen) {
655 throw new Error("Expected more digits in base 64 VLQ value.");
656 }
657 digit = base64.decode(aStr.charAt(i++));
658 continuation = !!(digit & VLQ_CONTINUATION_BIT);
659 digit &= VLQ_BASE_MASK;
660 result = result + (digit << shift);
661 shift += VLQ_BASE_SHIFT;
662 } while (continuation);
664 return {
665 value: fromVLQSigned(result),
666 rest: aStr.slice(i)
667 };
668 };
670 });
671 /* -*- Mode: js; js-indent-level: 2; -*- */
672 /*
673 * Copyright 2011 Mozilla Foundation and contributors
674 * Licensed under the New BSD license. See LICENSE or:
675 * http://opensource.org/licenses/BSD-3-Clause
676 */
677 define('source-map/base64', ['require', 'exports', 'module' , ], function(require, exports, module) {
679 var charToIntMap = {};
680 var intToCharMap = {};
682 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
683 .split('')
684 .forEach(function (ch, index) {
685 charToIntMap[ch] = index;
686 intToCharMap[index] = ch;
687 });
689 /**
690 * Encode an integer in the range of 0 to 63 to a single base 64 digit.
691 */
692 exports.encode = function base64_encode(aNumber) {
693 if (aNumber in intToCharMap) {
694 return intToCharMap[aNumber];
695 }
696 throw new TypeError("Must be between 0 and 63: " + aNumber);
697 };
699 /**
700 * Decode a single base 64 digit to an integer.
701 */
702 exports.decode = function base64_decode(aChar) {
703 if (aChar in charToIntMap) {
704 return charToIntMap[aChar];
705 }
706 throw new TypeError("Not a valid base 64 digit: " + aChar);
707 };
709 });
710 /* -*- Mode: js; js-indent-level: 2; -*- */
711 /*
712 * Copyright 2011 Mozilla Foundation and contributors
713 * Licensed under the New BSD license. See LICENSE or:
714 * http://opensource.org/licenses/BSD-3-Clause
715 */
716 define('source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) {
718 /**
719 * This is a helper function for getting values from parameter/options
720 * objects.
721 *
722 * @param args The object we are extracting values from
723 * @param name The name of the property we are getting.
724 * @param defaultValue An optional value to return if the property is missing
725 * from the object. If this is not specified and the property is missing, an
726 * error will be thrown.
727 */
728 function getArg(aArgs, aName, aDefaultValue) {
729 if (aName in aArgs) {
730 return aArgs[aName];
731 } else if (arguments.length === 3) {
732 return aDefaultValue;
733 } else {
734 throw new Error('"' + aName + '" is a required argument.');
735 }
736 }
737 exports.getArg = getArg;
739 var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/;
740 var dataUrlRegexp = /^data:.+\,.+/;
742 function urlParse(aUrl) {
743 var match = aUrl.match(urlRegexp);
744 if (!match) {
745 return null;
746 }
747 return {
748 scheme: match[1],
749 auth: match[3],
750 host: match[4],
751 port: match[6],
752 path: match[7]
753 };
754 }
755 exports.urlParse = urlParse;
757 function urlGenerate(aParsedUrl) {
758 var url = aParsedUrl.scheme + "://";
759 if (aParsedUrl.auth) {
760 url += aParsedUrl.auth + "@"
761 }
762 if (aParsedUrl.host) {
763 url += aParsedUrl.host;
764 }
765 if (aParsedUrl.port) {
766 url += ":" + aParsedUrl.port
767 }
768 if (aParsedUrl.path) {
769 url += aParsedUrl.path;
770 }
771 return url;
772 }
773 exports.urlGenerate = urlGenerate;
775 function join(aRoot, aPath) {
776 var url;
778 if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) {
779 return aPath;
780 }
782 if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) {
783 url.path = aPath;
784 return urlGenerate(url);
785 }
787 return aRoot.replace(/\/$/, '') + '/' + aPath;
788 }
789 exports.join = join;
791 /**
792 * Because behavior goes wacky when you set `__proto__` on objects, we
793 * have to prefix all the strings in our set with an arbitrary character.
794 *
795 * See https://github.com/mozilla/source-map/pull/31 and
796 * https://github.com/mozilla/source-map/issues/30
797 *
798 * @param String aStr
799 */
800 function toSetString(aStr) {
801 return '$' + aStr;
802 }
803 exports.toSetString = toSetString;
805 function fromSetString(aStr) {
806 return aStr.substr(1);
807 }
808 exports.fromSetString = fromSetString;
810 function relative(aRoot, aPath) {
811 aRoot = aRoot.replace(/\/$/, '');
813 var url = urlParse(aRoot);
814 if (aPath.charAt(0) == "/" && url && url.path == "/") {
815 return aPath.slice(1);
816 }
818 return aPath.indexOf(aRoot + '/') === 0
819 ? aPath.substr(aRoot.length + 1)
820 : aPath;
821 }
822 exports.relative = relative;
824 function strcmp(aStr1, aStr2) {
825 var s1 = aStr1 || "";
826 var s2 = aStr2 || "";
827 return (s1 > s2) - (s1 < s2);
828 }
830 /**
831 * Comparator between two mappings where the original positions are compared.
832 *
833 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
834 * mappings with the same original source/line/column, but different generated
835 * line and column the same. Useful when searching for a mapping with a
836 * stubbed out mapping.
837 */
838 function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
839 var cmp;
841 cmp = strcmp(mappingA.source, mappingB.source);
842 if (cmp) {
843 return cmp;
844 }
846 cmp = mappingA.originalLine - mappingB.originalLine;
847 if (cmp) {
848 return cmp;
849 }
851 cmp = mappingA.originalColumn - mappingB.originalColumn;
852 if (cmp || onlyCompareOriginal) {
853 return cmp;
854 }
856 cmp = strcmp(mappingA.name, mappingB.name);
857 if (cmp) {
858 return cmp;
859 }
861 cmp = mappingA.generatedLine - mappingB.generatedLine;
862 if (cmp) {
863 return cmp;
864 }
866 return mappingA.generatedColumn - mappingB.generatedColumn;
867 };
868 exports.compareByOriginalPositions = compareByOriginalPositions;
870 /**
871 * Comparator between two mappings where the generated positions are
872 * compared.
873 *
874 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
875 * mappings with the same generated line and column, but different
876 * source/name/original line and column the same. Useful when searching for a
877 * mapping with a stubbed out mapping.
878 */
879 function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) {
880 var cmp;
882 cmp = mappingA.generatedLine - mappingB.generatedLine;
883 if (cmp) {
884 return cmp;
885 }
887 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
888 if (cmp || onlyCompareGenerated) {
889 return cmp;
890 }
892 cmp = strcmp(mappingA.source, mappingB.source);
893 if (cmp) {
894 return cmp;
895 }
897 cmp = mappingA.originalLine - mappingB.originalLine;
898 if (cmp) {
899 return cmp;
900 }
902 cmp = mappingA.originalColumn - mappingB.originalColumn;
903 if (cmp) {
904 return cmp;
905 }
907 return strcmp(mappingA.name, mappingB.name);
908 };
909 exports.compareByGeneratedPositions = compareByGeneratedPositions;
911 });
912 /* -*- Mode: js; js-indent-level: 2; -*- */
913 /*
914 * Copyright 2011 Mozilla Foundation and contributors
915 * Licensed under the New BSD license. See LICENSE or:
916 * http://opensource.org/licenses/BSD-3-Clause
917 */
918 define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/util'], function(require, exports, module) {
920 var util = require('./util');
922 /**
923 * A data structure which is a combination of an array and a set. Adding a new
924 * member is O(1), testing for membership is O(1), and finding the index of an
925 * element is O(1). Removing elements from the set is not supported. Only
926 * strings are supported for membership.
927 */
928 function ArraySet() {
929 this._array = [];
930 this._set = {};
931 }
933 /**
934 * Static method for creating ArraySet instances from an existing array.
935 */
936 ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
937 var set = new ArraySet();
938 for (var i = 0, len = aArray.length; i < len; i++) {
939 set.add(aArray[i], aAllowDuplicates);
940 }
941 return set;
942 };
944 /**
945 * Add the given string to this set.
946 *
947 * @param String aStr
948 */
949 ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
950 var isDuplicate = this.has(aStr);
951 var idx = this._array.length;
952 if (!isDuplicate || aAllowDuplicates) {
953 this._array.push(aStr);
954 }
955 if (!isDuplicate) {
956 this._set[util.toSetString(aStr)] = idx;
957 }
958 };
960 /**
961 * Is the given string a member of this set?
962 *
963 * @param String aStr
964 */
965 ArraySet.prototype.has = function ArraySet_has(aStr) {
966 return Object.prototype.hasOwnProperty.call(this._set,
967 util.toSetString(aStr));
968 };
970 /**
971 * What is the index of the given string in the array?
972 *
973 * @param String aStr
974 */
975 ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
976 if (this.has(aStr)) {
977 return this._set[util.toSetString(aStr)];
978 }
979 throw new Error('"' + aStr + '" is not in the set.');
980 };
982 /**
983 * What is the element at the given index?
984 *
985 * @param Number aIdx
986 */
987 ArraySet.prototype.at = function ArraySet_at(aIdx) {
988 if (aIdx >= 0 && aIdx < this._array.length) {
989 return this._array[aIdx];
990 }
991 throw new Error('No element indexed by ' + aIdx);
992 };
994 /**
995 * Returns the array representation of this set (which has the proper indices
996 * indicated by indexOf). Note that this is a copy of the internal array used
997 * for storing the members so that no one can mess with internal state.
998 */
999 ArraySet.prototype.toArray = function ArraySet_toArray() {
1000 return this._array.slice();
1001 };
1003 exports.ArraySet = ArraySet;
1005 });
1006 /* -*- Mode: js; js-indent-level: 2; -*- */
1007 /*
1008 * Copyright 2011 Mozilla Foundation and contributors
1009 * Licensed under the New BSD license. See LICENSE or:
1010 * http://opensource.org/licenses/BSD-3-Clause
1011 */
1012 define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'source-map/util', 'source-map/binary-search', 'source-map/array-set', 'source-map/base64-vlq'], function(require, exports, module) {
1014 var util = require('./util');
1015 var binarySearch = require('./binary-search');
1016 var ArraySet = require('./array-set').ArraySet;
1017 var base64VLQ = require('./base64-vlq');
1019 /**
1020 * A SourceMapConsumer instance represents a parsed source map which we can
1021 * query for information about the original file positions by giving it a file
1022 * position in the generated source.
1023 *
1024 * The only parameter is the raw source map (either as a JSON string, or
1025 * already parsed to an object). According to the spec, source maps have the
1026 * following attributes:
1027 *
1028 * - version: Which version of the source map spec this map is following.
1029 * - sources: An array of URLs to the original source files.
1030 * - names: An array of identifiers which can be referrenced by individual mappings.
1031 * - sourceRoot: Optional. The URL root from which all sources are relative.
1032 * - sourcesContent: Optional. An array of contents of the original source files.
1033 * - mappings: A string of base64 VLQs which contain the actual mappings.
1034 * - file: The generated file this source map is associated with.
1035 *
1036 * Here is an example source map, taken from the source map spec[0]:
1037 *
1038 * {
1039 * version : 3,
1040 * file: "out.js",
1041 * sourceRoot : "",
1042 * sources: ["foo.js", "bar.js"],
1043 * names: ["src", "maps", "are", "fun"],
1044 * mappings: "AA,AB;;ABCDE;"
1045 * }
1046 *
1047 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
1048 */
1049 function SourceMapConsumer(aSourceMap) {
1050 var sourceMap = aSourceMap;
1051 if (typeof aSourceMap === 'string') {
1052 sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
1053 }
1055 var version = util.getArg(sourceMap, 'version');
1056 var sources = util.getArg(sourceMap, 'sources');
1057 var names = util.getArg(sourceMap, 'names');
1058 var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
1059 var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
1060 var mappings = util.getArg(sourceMap, 'mappings');
1061 var file = util.getArg(sourceMap, 'file', null);
1063 if (version !== this._version) {
1064 throw new Error('Unsupported version: ' + version);
1065 }
1067 // Pass `true` below to allow duplicate names and sources. While source maps
1068 // are intended to be compressed and deduplicated, the TypeScript compiler
1069 // sometimes generates source maps with duplicates in them. See Github issue
1070 // #72 and bugzil.la/889492.
1071 this._names = ArraySet.fromArray(names, true);
1072 this._sources = ArraySet.fromArray(sources, true);
1074 this.sourceRoot = sourceRoot;
1075 this.sourcesContent = sourcesContent;
1076 this._mappings = mappings;
1077 this.file = file;
1078 }
1080 /**
1081 * Create a SourceMapConsumer from a SourceMapGenerator.
1082 *
1083 * @param SourceMapGenerator aSourceMap
1084 * The source map that will be consumed.
1085 * @returns SourceMapConsumer
1086 */
1087 SourceMapConsumer.fromSourceMap =
1088 function SourceMapConsumer_fromSourceMap(aSourceMap) {
1089 var smc = Object.create(SourceMapConsumer.prototype);
1091 smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
1092 smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
1093 smc.sourceRoot = aSourceMap._sourceRoot;
1094 smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
1095 smc.sourceRoot);
1096 smc.file = aSourceMap._file;
1098 smc.__generatedMappings = aSourceMap._mappings.slice()
1099 .sort(util.compareByGeneratedPositions);
1100 smc.__originalMappings = aSourceMap._mappings.slice()
1101 .sort(util.compareByOriginalPositions);
1103 return smc;
1104 };
1106 /**
1107 * The version of the source mapping spec that we are consuming.
1108 */
1109 SourceMapConsumer.prototype._version = 3;
1111 /**
1112 * The list of original sources.
1113 */
1114 Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
1115 get: function () {
1116 return this._sources.toArray().map(function (s) {
1117 return this.sourceRoot ? util.join(this.sourceRoot, s) : s;
1118 }, this);
1119 }
1120 });
1122 // `__generatedMappings` and `__originalMappings` are arrays that hold the
1123 // parsed mapping coordinates from the source map's "mappings" attribute. They
1124 // are lazily instantiated, accessed via the `_generatedMappings` and
1125 // `_originalMappings` getters respectively, and we only parse the mappings
1126 // and create these arrays once queried for a source location. We jump through
1127 // these hoops because there can be many thousands of mappings, and parsing
1128 // them is expensive, so we only want to do it if we must.
1129 //
1130 // Each object in the arrays is of the form:
1131 //
1132 // {
1133 // generatedLine: The line number in the generated code,
1134 // generatedColumn: The column number in the generated code,
1135 // source: The path to the original source file that generated this
1136 // chunk of code,
1137 // originalLine: The line number in the original source that
1138 // corresponds to this chunk of generated code,
1139 // originalColumn: The column number in the original source that
1140 // corresponds to this chunk of generated code,
1141 // name: The name of the original symbol which generated this chunk of
1142 // code.
1143 // }
1144 //
1145 // All properties except for `generatedLine` and `generatedColumn` can be
1146 // `null`.
1147 //
1148 // `_generatedMappings` is ordered by the generated positions.
1149 //
1150 // `_originalMappings` is ordered by the original positions.
1152 SourceMapConsumer.prototype.__generatedMappings = null;
1153 Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {
1154 get: function () {
1155 if (!this.__generatedMappings) {
1156 this.__generatedMappings = [];
1157 this.__originalMappings = [];
1158 this._parseMappings(this._mappings, this.sourceRoot);
1159 }
1161 return this.__generatedMappings;
1162 }
1163 });
1165 SourceMapConsumer.prototype.__originalMappings = null;
1166 Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {
1167 get: function () {
1168 if (!this.__originalMappings) {
1169 this.__generatedMappings = [];
1170 this.__originalMappings = [];
1171 this._parseMappings(this._mappings, this.sourceRoot);
1172 }
1174 return this.__originalMappings;
1175 }
1176 });
1178 /**
1179 * Parse the mappings in a string in to a data structure which we can easily
1180 * query (the ordered arrays in the `this.__generatedMappings` and
1181 * `this.__originalMappings` properties).
1182 */
1183 SourceMapConsumer.prototype._parseMappings =
1184 function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
1185 var generatedLine = 1;
1186 var previousGeneratedColumn = 0;
1187 var previousOriginalLine = 0;
1188 var previousOriginalColumn = 0;
1189 var previousSource = 0;
1190 var previousName = 0;
1191 var mappingSeparator = /^[,;]/;
1192 var str = aStr;
1193 var mapping;
1194 var temp;
1196 while (str.length > 0) {
1197 if (str.charAt(0) === ';') {
1198 generatedLine++;
1199 str = str.slice(1);
1200 previousGeneratedColumn = 0;
1201 }
1202 else if (str.charAt(0) === ',') {
1203 str = str.slice(1);
1204 }
1205 else {
1206 mapping = {};
1207 mapping.generatedLine = generatedLine;
1209 // Generated column.
1210 temp = base64VLQ.decode(str);
1211 mapping.generatedColumn = previousGeneratedColumn + temp.value;
1212 previousGeneratedColumn = mapping.generatedColumn;
1213 str = temp.rest;
1215 if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
1216 // Original source.
1217 temp = base64VLQ.decode(str);
1218 mapping.source = this._sources.at(previousSource + temp.value);
1219 previousSource += temp.value;
1220 str = temp.rest;
1221 if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
1222 throw new Error('Found a source, but no line and column');
1223 }
1225 // Original line.
1226 temp = base64VLQ.decode(str);
1227 mapping.originalLine = previousOriginalLine + temp.value;
1228 previousOriginalLine = mapping.originalLine;
1229 // Lines are stored 0-based
1230 mapping.originalLine += 1;
1231 str = temp.rest;
1232 if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
1233 throw new Error('Found a source and line, but no column');
1234 }
1236 // Original column.
1237 temp = base64VLQ.decode(str);
1238 mapping.originalColumn = previousOriginalColumn + temp.value;
1239 previousOriginalColumn = mapping.originalColumn;
1240 str = temp.rest;
1242 if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
1243 // Original name.
1244 temp = base64VLQ.decode(str);
1245 mapping.name = this._names.at(previousName + temp.value);
1246 previousName += temp.value;
1247 str = temp.rest;
1248 }
1249 }
1251 this.__generatedMappings.push(mapping);
1252 if (typeof mapping.originalLine === 'number') {
1253 this.__originalMappings.push(mapping);
1254 }
1255 }
1256 }
1258 this.__originalMappings.sort(util.compareByOriginalPositions);
1259 };
1261 /**
1262 * Find the mapping that best matches the hypothetical "needle" mapping that
1263 * we are searching for in the given "haystack" of mappings.
1264 */
1265 SourceMapConsumer.prototype._findMapping =
1266 function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
1267 aColumnName, aComparator) {
1268 // To return the position we are searching for, we must first find the
1269 // mapping for the given position and then return the opposite position it
1270 // points to. Because the mappings are sorted, we can use binary search to
1271 // find the best mapping.
1273 if (aNeedle[aLineName] <= 0) {
1274 throw new TypeError('Line must be greater than or equal to 1, got '
1275 + aNeedle[aLineName]);
1276 }
1277 if (aNeedle[aColumnName] < 0) {
1278 throw new TypeError('Column must be greater than or equal to 0, got '
1279 + aNeedle[aColumnName]);
1280 }
1282 return binarySearch.search(aNeedle, aMappings, aComparator);
1283 };
1285 /**
1286 * Returns the original source, line, and column information for the generated
1287 * source's line and column positions provided. The only argument is an object
1288 * with the following properties:
1289 *
1290 * - line: The line number in the generated source.
1291 * - column: The column number in the generated source.
1292 *
1293 * and an object is returned with the following properties:
1294 *
1295 * - source: The original source file, or null.
1296 * - line: The line number in the original source, or null.
1297 * - column: The column number in the original source, or null.
1298 * - name: The original identifier, or null.
1299 */
1300 SourceMapConsumer.prototype.originalPositionFor =
1301 function SourceMapConsumer_originalPositionFor(aArgs) {
1302 var needle = {
1303 generatedLine: util.getArg(aArgs, 'line'),
1304 generatedColumn: util.getArg(aArgs, 'column')
1305 };
1307 var mapping = this._findMapping(needle,
1308 this._generatedMappings,
1309 "generatedLine",
1310 "generatedColumn",
1311 util.compareByGeneratedPositions);
1313 if (mapping) {
1314 var source = util.getArg(mapping, 'source', null);
1315 if (source && this.sourceRoot) {
1316 source = util.join(this.sourceRoot, source);
1317 }
1318 return {
1319 source: source,
1320 line: util.getArg(mapping, 'originalLine', null),
1321 column: util.getArg(mapping, 'originalColumn', null),
1322 name: util.getArg(mapping, 'name', null)
1323 };
1324 }
1326 return {
1327 source: null,
1328 line: null,
1329 column: null,
1330 name: null
1331 };
1332 };
1334 /**
1335 * Returns the original source content. The only argument is the url of the
1336 * original source file. Returns null if no original source content is
1337 * availible.
1338 */
1339 SourceMapConsumer.prototype.sourceContentFor =
1340 function SourceMapConsumer_sourceContentFor(aSource) {
1341 if (!this.sourcesContent) {
1342 return null;
1343 }
1345 if (this.sourceRoot) {
1346 aSource = util.relative(this.sourceRoot, aSource);
1347 }
1349 if (this._sources.has(aSource)) {
1350 return this.sourcesContent[this._sources.indexOf(aSource)];
1351 }
1353 var url;
1354 if (this.sourceRoot
1355 && (url = util.urlParse(this.sourceRoot))) {
1356 // XXX: file:// URIs and absolute paths lead to unexpected behavior for
1357 // many users. We can help them out when they expect file:// URIs to
1358 // behave like it would if they were running a local HTTP server. See
1359 // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
1360 var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
1361 if (url.scheme == "file"
1362 && this._sources.has(fileUriAbsPath)) {
1363 return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
1364 }
1366 if ((!url.path || url.path == "/")
1367 && this._sources.has("/" + aSource)) {
1368 return this.sourcesContent[this._sources.indexOf("/" + aSource)];
1369 }
1370 }
1372 throw new Error('"' + aSource + '" is not in the SourceMap.');
1373 };
1375 /**
1376 * Returns the generated line and column information for the original source,
1377 * line, and column positions provided. The only argument is an object with
1378 * the following properties:
1379 *
1380 * - source: The filename of the original source.
1381 * - line: The line number in the original source.
1382 * - column: The column number in the original source.
1383 *
1384 * and an object is returned with the following properties:
1385 *
1386 * - line: The line number in the generated source, or null.
1387 * - column: The column number in the generated source, or null.
1388 */
1389 SourceMapConsumer.prototype.generatedPositionFor =
1390 function SourceMapConsumer_generatedPositionFor(aArgs) {
1391 var needle = {
1392 source: util.getArg(aArgs, 'source'),
1393 originalLine: util.getArg(aArgs, 'line'),
1394 originalColumn: util.getArg(aArgs, 'column')
1395 };
1397 if (this.sourceRoot) {
1398 needle.source = util.relative(this.sourceRoot, needle.source);
1399 }
1401 var mapping = this._findMapping(needle,
1402 this._originalMappings,
1403 "originalLine",
1404 "originalColumn",
1405 util.compareByOriginalPositions);
1407 if (mapping) {
1408 return {
1409 line: util.getArg(mapping, 'generatedLine', null),
1410 column: util.getArg(mapping, 'generatedColumn', null)
1411 };
1412 }
1414 return {
1415 line: null,
1416 column: null
1417 };
1418 };
1420 SourceMapConsumer.GENERATED_ORDER = 1;
1421 SourceMapConsumer.ORIGINAL_ORDER = 2;
1423 /**
1424 * Iterate over each mapping between an original source/line/column and a
1425 * generated line/column in this source map.
1426 *
1427 * @param Function aCallback
1428 * The function that is called with each mapping.
1429 * @param Object aContext
1430 * Optional. If specified, this object will be the value of `this` every
1431 * time that `aCallback` is called.
1432 * @param aOrder
1433 * Either `SourceMapConsumer.GENERATED_ORDER` or
1434 * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
1435 * iterate over the mappings sorted by the generated file's line/column
1436 * order or the original's source/line/column order, respectively. Defaults to
1437 * `SourceMapConsumer.GENERATED_ORDER`.
1438 */
1439 SourceMapConsumer.prototype.eachMapping =
1440 function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
1441 var context = aContext || null;
1442 var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
1444 var mappings;
1445 switch (order) {
1446 case SourceMapConsumer.GENERATED_ORDER:
1447 mappings = this._generatedMappings;
1448 break;
1449 case SourceMapConsumer.ORIGINAL_ORDER:
1450 mappings = this._originalMappings;
1451 break;
1452 default:
1453 throw new Error("Unknown order of iteration.");
1454 }
1456 var sourceRoot = this.sourceRoot;
1457 mappings.map(function (mapping) {
1458 var source = mapping.source;
1459 if (source && sourceRoot) {
1460 source = util.join(sourceRoot, source);
1461 }
1462 return {
1463 source: source,
1464 generatedLine: mapping.generatedLine,
1465 generatedColumn: mapping.generatedColumn,
1466 originalLine: mapping.originalLine,
1467 originalColumn: mapping.originalColumn,
1468 name: mapping.name
1469 };
1470 }).forEach(aCallback, context);
1471 };
1473 exports.SourceMapConsumer = SourceMapConsumer;
1475 });
1476 /* -*- Mode: js; js-indent-level: 2; -*- */
1477 /*
1478 * Copyright 2011 Mozilla Foundation and contributors
1479 * Licensed under the New BSD license. See LICENSE or:
1480 * http://opensource.org/licenses/BSD-3-Clause
1481 */
1482 define('source-map/binary-search', ['require', 'exports', 'module' , ], function(require, exports, module) {
1484 /**
1485 * Recursive implementation of binary search.
1486 *
1487 * @param aLow Indices here and lower do not contain the needle.
1488 * @param aHigh Indices here and higher do not contain the needle.
1489 * @param aNeedle The element being searched for.
1490 * @param aHaystack The non-empty array being searched.
1491 * @param aCompare Function which takes two elements and returns -1, 0, or 1.
1492 */
1493 function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
1494 // This function terminates when one of the following is true:
1495 //
1496 // 1. We find the exact element we are looking for.
1497 //
1498 // 2. We did not find the exact element, but we can return the next
1499 // closest element that is less than that element.
1500 //
1501 // 3. We did not find the exact element, and there is no next-closest
1502 // element which is less than the one we are searching for, so we
1503 // return null.
1504 var mid = Math.floor((aHigh - aLow) / 2) + aLow;
1505 var cmp = aCompare(aNeedle, aHaystack[mid], true);
1506 if (cmp === 0) {
1507 // Found the element we are looking for.
1508 return aHaystack[mid];
1509 }
1510 else if (cmp > 0) {
1511 // aHaystack[mid] is greater than our needle.
1512 if (aHigh - mid > 1) {
1513 // The element is in the upper half.
1514 return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);
1515 }
1516 // We did not find an exact match, return the next closest one
1517 // (termination case 2).
1518 return aHaystack[mid];
1519 }
1520 else {
1521 // aHaystack[mid] is less than our needle.
1522 if (mid - aLow > 1) {
1523 // The element is in the lower half.
1524 return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);
1525 }
1526 // The exact needle element was not found in this haystack. Determine if
1527 // we are in termination case (2) or (3) and return the appropriate thing.
1528 return aLow < 0
1529 ? null
1530 : aHaystack[aLow];
1531 }
1532 }
1534 /**
1535 * This is an implementation of binary search which will always try and return
1536 * the next lowest value checked if there is no exact hit. This is because
1537 * mappings between original and generated line/col pairs are single points,
1538 * and there is an implicit region between each of them, so a miss just means
1539 * that you aren't on the very start of a region.
1540 *
1541 * @param aNeedle The element you are looking for.
1542 * @param aHaystack The array that is being searched.
1543 * @param aCompare A function which takes the needle and an element in the
1544 * array and returns -1, 0, or 1 depending on whether the needle is less
1545 * than, equal to, or greater than the element, respectively.
1546 */
1547 exports.search = function search(aNeedle, aHaystack, aCompare) {
1548 return aHaystack.length > 0
1549 ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)
1550 : null;
1551 };
1553 });
1554 /* -*- Mode: js; js-indent-level: 2; -*- */
1555 /*
1556 * Copyright 2011 Mozilla Foundation and contributors
1557 * Licensed under the New BSD license. See LICENSE or:
1558 * http://opensource.org/licenses/BSD-3-Clause
1559 */
1560 define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/source-map-generator', 'source-map/util'], function(require, exports, module) {
1562 var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
1563 var util = require('./util');
1565 /**
1566 * SourceNodes provide a way to abstract over interpolating/concatenating
1567 * snippets of generated JavaScript source code while maintaining the line and
1568 * column information associated with the original source code.
1569 *
1570 * @param aLine The original line number.
1571 * @param aColumn The original column number.
1572 * @param aSource The original source's filename.
1573 * @param aChunks Optional. An array of strings which are snippets of
1574 * generated JS, or other SourceNodes.
1575 * @param aName The original identifier.
1576 */
1577 function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
1578 this.children = [];
1579 this.sourceContents = {};
1580 this.line = aLine === undefined ? null : aLine;
1581 this.column = aColumn === undefined ? null : aColumn;
1582 this.source = aSource === undefined ? null : aSource;
1583 this.name = aName === undefined ? null : aName;
1584 if (aChunks != null) this.add(aChunks);
1585 }
1587 /**
1588 * Creates a SourceNode from generated code and a SourceMapConsumer.
1589 *
1590 * @param aGeneratedCode The generated code
1591 * @param aSourceMapConsumer The SourceMap for the generated code
1592 */
1593 SourceNode.fromStringWithSourceMap =
1594 function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) {
1595 // The SourceNode we want to fill with the generated code
1596 // and the SourceMap
1597 var node = new SourceNode();
1599 // The generated code
1600 // Processed fragments are removed from this array.
1601 var remainingLines = aGeneratedCode.split('\n');
1603 // We need to remember the position of "remainingLines"
1604 var lastGeneratedLine = 1, lastGeneratedColumn = 0;
1606 // The generate SourceNodes we need a code range.
1607 // To extract it current and last mapping is used.
1608 // Here we store the last mapping.
1609 var lastMapping = null;
1611 aSourceMapConsumer.eachMapping(function (mapping) {
1612 if (lastMapping === null) {
1613 // We add the generated code until the first mapping
1614 // to the SourceNode without any mapping.
1615 // Each line is added as separate string.
1616 while (lastGeneratedLine < mapping.generatedLine) {
1617 node.add(remainingLines.shift() + "\n");
1618 lastGeneratedLine++;
1619 }
1620 if (lastGeneratedColumn < mapping.generatedColumn) {
1621 var nextLine = remainingLines[0];
1622 node.add(nextLine.substr(0, mapping.generatedColumn));
1623 remainingLines[0] = nextLine.substr(mapping.generatedColumn);
1624 lastGeneratedColumn = mapping.generatedColumn;
1625 }
1626 } else {
1627 // We add the code from "lastMapping" to "mapping":
1628 // First check if there is a new line in between.
1629 if (lastGeneratedLine < mapping.generatedLine) {
1630 var code = "";
1631 // Associate full lines with "lastMapping"
1632 do {
1633 code += remainingLines.shift() + "\n";
1634 lastGeneratedLine++;
1635 lastGeneratedColumn = 0;
1636 } while (lastGeneratedLine < mapping.generatedLine);
1637 // When we reached the correct line, we add code until we
1638 // reach the correct column too.
1639 if (lastGeneratedColumn < mapping.generatedColumn) {
1640 var nextLine = remainingLines[0];
1641 code += nextLine.substr(0, mapping.generatedColumn);
1642 remainingLines[0] = nextLine.substr(mapping.generatedColumn);
1643 lastGeneratedColumn = mapping.generatedColumn;
1644 }
1645 // Create the SourceNode.
1646 addMappingWithCode(lastMapping, code);
1647 } else {
1648 // There is no new line in between.
1649 // Associate the code between "lastGeneratedColumn" and
1650 // "mapping.generatedColumn" with "lastMapping"
1651 var nextLine = remainingLines[0];
1652 var code = nextLine.substr(0, mapping.generatedColumn -
1653 lastGeneratedColumn);
1654 remainingLines[0] = nextLine.substr(mapping.generatedColumn -
1655 lastGeneratedColumn);
1656 lastGeneratedColumn = mapping.generatedColumn;
1657 addMappingWithCode(lastMapping, code);
1658 }
1659 }
1660 lastMapping = mapping;
1661 }, this);
1662 // We have processed all mappings.
1663 // Associate the remaining code in the current line with "lastMapping"
1664 // and add the remaining lines without any mapping
1665 addMappingWithCode(lastMapping, remainingLines.join("\n"));
1667 // Copy sourcesContent into SourceNode
1668 aSourceMapConsumer.sources.forEach(function (sourceFile) {
1669 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
1670 if (content) {
1671 node.setSourceContent(sourceFile, content);
1672 }
1673 });
1675 return node;
1677 function addMappingWithCode(mapping, code) {
1678 if (mapping === null || mapping.source === undefined) {
1679 node.add(code);
1680 } else {
1681 node.add(new SourceNode(mapping.originalLine,
1682 mapping.originalColumn,
1683 mapping.source,
1684 code,
1685 mapping.name));
1686 }
1687 }
1688 };
1690 /**
1691 * Add a chunk of generated JS to this source node.
1692 *
1693 * @param aChunk A string snippet of generated JS code, another instance of
1694 * SourceNode, or an array where each member is one of those things.
1695 */
1696 SourceNode.prototype.add = function SourceNode_add(aChunk) {
1697 if (Array.isArray(aChunk)) {
1698 aChunk.forEach(function (chunk) {
1699 this.add(chunk);
1700 }, this);
1701 }
1702 else if (aChunk instanceof SourceNode || typeof aChunk === "string") {
1703 if (aChunk) {
1704 this.children.push(aChunk);
1705 }
1706 }
1707 else {
1708 throw new TypeError(
1709 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
1710 );
1711 }
1712 return this;
1713 };
1715 /**
1716 * Add a chunk of generated JS to the beginning of this source node.
1717 *
1718 * @param aChunk A string snippet of generated JS code, another instance of
1719 * SourceNode, or an array where each member is one of those things.
1720 */
1721 SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
1722 if (Array.isArray(aChunk)) {
1723 for (var i = aChunk.length-1; i >= 0; i--) {
1724 this.prepend(aChunk[i]);
1725 }
1726 }
1727 else if (aChunk instanceof SourceNode || typeof aChunk === "string") {
1728 this.children.unshift(aChunk);
1729 }
1730 else {
1731 throw new TypeError(
1732 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
1733 );
1734 }
1735 return this;
1736 };
1738 /**
1739 * Walk over the tree of JS snippets in this node and its children. The
1740 * walking function is called once for each snippet of JS and is passed that
1741 * snippet and the its original associated source's line/column location.
1742 *
1743 * @param aFn The traversal function.
1744 */
1745 SourceNode.prototype.walk = function SourceNode_walk(aFn) {
1746 var chunk;
1747 for (var i = 0, len = this.children.length; i < len; i++) {
1748 chunk = this.children[i];
1749 if (chunk instanceof SourceNode) {
1750 chunk.walk(aFn);
1751 }
1752 else {
1753 if (chunk !== '') {
1754 aFn(chunk, { source: this.source,
1755 line: this.line,
1756 column: this.column,
1757 name: this.name });
1758 }
1759 }
1760 }
1761 };
1763 /**
1764 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
1765 * each of `this.children`.
1766 *
1767 * @param aSep The separator.
1768 */
1769 SourceNode.prototype.join = function SourceNode_join(aSep) {
1770 var newChildren;
1771 var i;
1772 var len = this.children.length;
1773 if (len > 0) {
1774 newChildren = [];
1775 for (i = 0; i < len-1; i++) {
1776 newChildren.push(this.children[i]);
1777 newChildren.push(aSep);
1778 }
1779 newChildren.push(this.children[i]);
1780 this.children = newChildren;
1781 }
1782 return this;
1783 };
1785 /**
1786 * Call String.prototype.replace on the very right-most source snippet. Useful
1787 * for trimming whitespace from the end of a source node, etc.
1788 *
1789 * @param aPattern The pattern to replace.
1790 * @param aReplacement The thing to replace the pattern with.
1791 */
1792 SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
1793 var lastChild = this.children[this.children.length - 1];
1794 if (lastChild instanceof SourceNode) {
1795 lastChild.replaceRight(aPattern, aReplacement);
1796 }
1797 else if (typeof lastChild === 'string') {
1798 this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
1799 }
1800 else {
1801 this.children.push(''.replace(aPattern, aReplacement));
1802 }
1803 return this;
1804 };
1806 /**
1807 * Set the source content for a source file. This will be added to the SourceMapGenerator
1808 * in the sourcesContent field.
1809 *
1810 * @param aSourceFile The filename of the source file
1811 * @param aSourceContent The content of the source file
1812 */
1813 SourceNode.prototype.setSourceContent =
1814 function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
1815 this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
1816 };
1818 /**
1819 * Walk over the tree of SourceNodes. The walking function is called for each
1820 * source file content and is passed the filename and source content.
1821 *
1822 * @param aFn The traversal function.
1823 */
1824 SourceNode.prototype.walkSourceContents =
1825 function SourceNode_walkSourceContents(aFn) {
1826 for (var i = 0, len = this.children.length; i < len; i++) {
1827 if (this.children[i] instanceof SourceNode) {
1828 this.children[i].walkSourceContents(aFn);
1829 }
1830 }
1832 var sources = Object.keys(this.sourceContents);
1833 for (var i = 0, len = sources.length; i < len; i++) {
1834 aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
1835 }
1836 };
1838 /**
1839 * Return the string representation of this source node. Walks over the tree
1840 * and concatenates all the various snippets together to one string.
1841 */
1842 SourceNode.prototype.toString = function SourceNode_toString() {
1843 var str = "";
1844 this.walk(function (chunk) {
1845 str += chunk;
1846 });
1847 return str;
1848 };
1850 /**
1851 * Returns the string representation of this source node along with a source
1852 * map.
1853 */
1854 SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
1855 var generated = {
1856 code: "",
1857 line: 1,
1858 column: 0
1859 };
1860 var map = new SourceMapGenerator(aArgs);
1861 var sourceMappingActive = false;
1862 var lastOriginalSource = null;
1863 var lastOriginalLine = null;
1864 var lastOriginalColumn = null;
1865 var lastOriginalName = null;
1866 this.walk(function (chunk, original) {
1867 generated.code += chunk;
1868 if (original.source !== null
1869 && original.line !== null
1870 && original.column !== null) {
1871 if(lastOriginalSource !== original.source
1872 || lastOriginalLine !== original.line
1873 || lastOriginalColumn !== original.column
1874 || lastOriginalName !== original.name) {
1875 map.addMapping({
1876 source: original.source,
1877 original: {
1878 line: original.line,
1879 column: original.column
1880 },
1881 generated: {
1882 line: generated.line,
1883 column: generated.column
1884 },
1885 name: original.name
1886 });
1887 }
1888 lastOriginalSource = original.source;
1889 lastOriginalLine = original.line;
1890 lastOriginalColumn = original.column;
1891 lastOriginalName = original.name;
1892 sourceMappingActive = true;
1893 } else if (sourceMappingActive) {
1894 map.addMapping({
1895 generated: {
1896 line: generated.line,
1897 column: generated.column
1898 }
1899 });
1900 lastOriginalSource = null;
1901 sourceMappingActive = false;
1902 }
1903 chunk.split('').forEach(function (ch) {
1904 if (ch === '\n') {
1905 generated.line++;
1906 generated.column = 0;
1907 } else {
1908 generated.column++;
1909 }
1910 });
1911 });
1912 this.walkSourceContents(function (sourceFile, sourceContent) {
1913 map.setSourceContent(sourceFile, sourceContent);
1914 });
1916 return { code: generated.code, map: map };
1917 };
1919 exports.SourceNode = SourceNode;
1921 });
1922 /* -*- Mode: js; js-indent-level: 2; -*- */
1923 ///////////////////////////////////////////////////////////////////////////////
1925 this.sourceMap = {
1926 SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer,
1927 SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator,
1928 SourceNode: require('source-map/source-node').SourceNode
1929 };