diff --git a/Makefile.dryice.js b/Makefile.dryice.js index d6fc26a7..ab42586a 100644 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -8,24 +8,27 @@ var path = require('path'); var fs = require('fs'); var copy = require('dryice').copy; -function removeAmdefine(src) { - src = String(src).replace( - /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, - ''); - src = src.replace( - /\b(define\(.*)('amdefine',?)/gm, - '$1'); - return src; -} -removeAmdefine.onRead = true; - function makeNonRelative(src) { - return src + return String(src) .replace(/require\('.\//g, 'require(\'source-map/') .replace(/\.\.\/\.\.\/lib\//g, ''); } makeNonRelative.onRead = true; +function wrapDefine(src, location) { + src = String(src); + if (/^build\//.test(location.path)) { + return src; + } else { + return ( + '\ndefine(function (require, exports, module) {\n' + + src.replace(/^(?=[^\n])/gm, ' ') + + '\n});\n\n' + ); + } +} +wrapDefine.onRead = true; + function buildBrowser() { console.log('\nCreating dist/source-map.js'); @@ -45,8 +48,8 @@ function buildBrowser() { 'build/suffix-browser.js' ], filter: [ - copy.filter.moduleDefines, - removeAmdefine + wrapDefine, + copy.filter.moduleDefines ], dest: 'dist/source-map.js' }); @@ -81,8 +84,8 @@ function buildFirefox() { 'build/suffix-source-map.jsm' ], filter: [ + wrapDefine, copy.filter.moduleDefines, - removeAmdefine, makeNonRelative ], dest: 'dist/SourceMap.jsm' @@ -106,8 +109,8 @@ function buildFirefox() { 'build/suffix-utils.jsm' ], filter: [ + wrapDefine, copy.filter.moduleDefines, - removeAmdefine, makeNonRelative ], dest: 'dist/test/Utils.jsm' @@ -129,7 +132,7 @@ function buildFirefox() { 'build/test-suffix.js' ], filter: [ - removeAmdefine, + wrapDefine, makeNonRelative, function (input, source) { return input.replace('define(', diff --git a/lib/source-map/array-set.js b/lib/source-map/array-set.js index fea20522..8de65c93 100644 --- a/lib/source-map/array-set.js +++ b/lib/source-map/array-set.js @@ -4,106 +4,99 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { +var util = require('./util'); - var util = require('./util'); +/** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ +function ArraySet() { + this._array = []; + this._set = {}; +} - /** - * A data structure which is a combination of an array and a set. Adding a new - * member is O(1), testing for membership is O(1), and finding the index of an - * element is O(1). Removing elements from the set is not supported. Only - * strings are supported for membership. - */ - function ArraySet() { - this._array = []; - this._set = {}; +/** + * Static method for creating ArraySet instances from an existing array. + */ +ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); } + return set; +}; - /** - * Static method for creating ArraySet instances from an existing array. - */ - ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { - var set = new ArraySet(); - for (var i = 0, len = aArray.length; i < len; i++) { - set.add(aArray[i], aAllowDuplicates); - } - return set; - }; - - /** - * Return how many unique items are in this ArraySet. If duplicates have been - * added, than those do not count towards the size. - * - * @returns Number - */ - ArraySet.prototype.size = function ArraySet_size() { - return Object.getOwnPropertyNames(this._set).length; - }; - - /** - * Add the given string to this set. - * - * @param String aStr - */ - ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { - var sStr = util.toSetString(aStr); - var isDuplicate = this._set.hasOwnProperty(sStr); - var idx = this._array.length; - if (!isDuplicate || aAllowDuplicates) { - this._array.push(aStr); - } - if (!isDuplicate) { - this._set[sStr] = idx; - } - }; +/** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ +ArraySet.prototype.size = function ArraySet_size() { + return Object.getOwnPropertyNames(this._set).length; +}; - /** - * Is the given string a member of this set? - * - * @param String aStr - */ - ArraySet.prototype.has = function ArraySet_has(aStr) { - var sStr = util.toSetString(aStr); - return this._set.hasOwnProperty(sStr); - }; +/** + * Add the given string to this set. + * + * @param String aStr + */ +ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = util.toSetString(aStr); + var isDuplicate = this._set.hasOwnProperty(sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[sStr] = idx; + } +}; - /** - * What is the index of the given string in the array? - * - * @param String aStr - */ - ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { - var sStr = util.toSetString(aStr); - if (this._set.hasOwnProperty(sStr)) { - return this._set[sStr]; - } - throw new Error('"' + aStr + '" is not in the set.'); - }; +/** + * Is the given string a member of this set? + * + * @param String aStr + */ +ArraySet.prototype.has = function ArraySet_has(aStr) { + var sStr = util.toSetString(aStr); + return this._set.hasOwnProperty(sStr); +}; - /** - * What is the element at the given index? - * - * @param Number aIdx - */ - ArraySet.prototype.at = function ArraySet_at(aIdx) { - if (aIdx >= 0 && aIdx < this._array.length) { - return this._array[aIdx]; - } - throw new Error('No element indexed by ' + aIdx); - }; +/** + * What is the index of the given string in the array? + * + * @param String aStr + */ +ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + var sStr = util.toSetString(aStr); + if (this._set.hasOwnProperty(sStr)) { + return this._set[sStr]; + } + throw new Error('"' + aStr + '" is not in the set.'); +}; - /** - * Returns the array representation of this set (which has the proper indices - * indicated by indexOf). Note that this is a copy of the internal array used - * for storing the members so that no one can mess with internal state. - */ - ArraySet.prototype.toArray = function ArraySet_toArray() { - return this._array.slice(); - }; +/** + * What is the element at the given index? + * + * @param Number aIdx + */ +ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); +}; - exports.ArraySet = ArraySet; +/** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ +ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); +}; -}); +exports.ArraySet = ArraySet; diff --git a/lib/source-map/base64-vlq.js b/lib/source-map/base64-vlq.js index bbe9a58e..3b22be6c 100644 --- a/lib/source-map/base64-vlq.js +++ b/lib/source-map/base64-vlq.js @@ -34,113 +34,106 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); +var base64 = require('./base64'); + +// A single base 64 digit can contain 6 bits of data. For the base 64 variable +// length quantities we use in the source map spec, the first bit is the sign, +// the next four bits are the actual value, and the 6th bit is the +// continuation bit. The continuation bit tells us whether there are more +// digits in this value following this digit. +// +// Continuation +// | Sign +// | | +// V V +// 101011 + +var VLQ_BASE_SHIFT = 5; + +// binary: 100000 +var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + +// binary: 011111 +var VLQ_BASE_MASK = VLQ_BASE - 1; + +// binary: 100000 +var VLQ_CONTINUATION_BIT = VLQ_BASE; + +/** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ +function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; +} + +/** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ +function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; } -define(function (require, exports, module) { - - var base64 = require('./base64'); - - // A single base 64 digit can contain 6 bits of data. For the base 64 variable - // length quantities we use in the source map spec, the first bit is the sign, - // the next four bits are the actual value, and the 6th bit is the - // continuation bit. The continuation bit tells us whether there are more - // digits in this value following this digit. - // - // Continuation - // | Sign - // | | - // V V - // 101011 - - var VLQ_BASE_SHIFT = 5; - - // binary: 100000 - var VLQ_BASE = 1 << VLQ_BASE_SHIFT; - - // binary: 011111 - var VLQ_BASE_MASK = VLQ_BASE - 1; - - // binary: 100000 - var VLQ_CONTINUATION_BIT = VLQ_BASE; - - /** - * Converts from a two-complement value to a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - */ - function toVLQSigned(aValue) { - return aValue < 0 - ? ((-aValue) << 1) + 1 - : (aValue << 1) + 0; - } - - /** - * Converts to a two-complement value from a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - */ - function fromVLQSigned(aValue) { - var isNegative = (aValue & 1) === 1; - var shifted = aValue >> 1; - return isNegative - ? -shifted - : shifted; - } - - /** - * Returns the base 64 VLQ encoded value. - */ - exports.encode = function base64VLQ_encode(aValue) { - var encoded = ""; - var digit; - - var vlq = toVLQSigned(aValue); - - do { - digit = vlq & VLQ_BASE_MASK; - vlq >>>= VLQ_BASE_SHIFT; - if (vlq > 0) { - // There are still more digits in this value, so we must make sure the - // continuation bit is marked. - digit |= VLQ_CONTINUATION_BIT; - } - encoded += base64.encode(digit); - } while (vlq > 0); - - return encoded; - }; - - /** - * Decodes the next base 64 VLQ value from the given string and returns the - * value and the rest of the string via the out parameter. - */ - exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { - var strLen = aStr.length; - var result = 0; - var shift = 0; - var continuation, digit; - - do { - if (aIndex >= strLen) { - throw new Error("Expected more digits in base 64 VLQ value."); - } - - digit = base64.decode(aStr.charCodeAt(aIndex++)); - if (digit === -1) { - throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); - } - - continuation = !!(digit & VLQ_CONTINUATION_BIT); - digit &= VLQ_BASE_MASK; - result = result + (digit << shift); - shift += VLQ_BASE_SHIFT; - } while (continuation); - - aOutParam.value = fromVLQSigned(result); - aOutParam.rest = aIndex; - }; - -}); + +/** + * Returns the base 64 VLQ encoded value. + */ +exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; +}; + +/** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ +exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; +}; diff --git a/lib/source-map/base64.js b/lib/source-map/base64.js index d0a61319..3a74cc64 100644 --- a/lib/source-map/base64.js +++ b/lib/source-map/base64.js @@ -4,70 +4,63 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { +var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); - var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); - - /** - * Encode an integer in the range of 0 to 63 to a single base 64 digit. - */ - exports.encode = function (number) { - if (0 <= number && number < intToCharMap.length) { - return intToCharMap[number]; - } - throw new TypeError("Must be between 0 and 63: " + number); - }; - - /** - * Decode a single base 64 character code digit to an integer. Returns -1 on - * failure. - */ - exports.decode = function (charCode) { - var bigA = 65; // 'A' - var bigZ = 90; // 'Z' +/** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ +exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); +}; - var littleA = 97; // 'a' - var littleZ = 122; // 'z' +/** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ +exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' - var zero = 48; // '0' - var nine = 57; // '9' + var littleA = 97; // 'a' + var littleZ = 122; // 'z' - var plus = 43; // '+' - var slash = 47; // '/' + var zero = 48; // '0' + var nine = 57; // '9' - var littleOffset = 26; - var numberOffset = 52; + var plus = 43; // '+' + var slash = 47; // '/' - // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ - if (bigA <= charCode && charCode <= bigZ) { - return (charCode - bigA); - } + var littleOffset = 26; + var numberOffset = 52; - // 26 - 51: abcdefghijklmnopqrstuvwxyz - if (littleA <= charCode && charCode <= littleZ) { - return (charCode - littleA + littleOffset); - } + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } - // 52 - 61: 0123456789 - if (zero <= charCode && charCode <= nine) { - return (charCode - zero + numberOffset); - } + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } - // 62: + - if (charCode == plus) { - return 62; - } + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } - // 63: / - if (charCode == slash) { - return 63; - } + // 62: + + if (charCode == plus) { + return 62; + } - // Invalid base64 digit. - return -1; - }; + // 63: / + if (charCode == slash) { + return 63; + } -}); + // Invalid base64 digit. + return -1; +}; diff --git a/lib/source-map/binary-search.js b/lib/source-map/binary-search.js index 7936f7e7..a23c5cd3 100644 --- a/lib/source-map/binary-search.js +++ b/lib/source-map/binary-search.js @@ -4,114 +4,107 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { +exports.GREATEST_LOWER_BOUND = 1; +exports.LEAST_UPPER_BOUND = 2; - exports.GREATEST_LOWER_BOUND = 1; - exports.LEAST_UPPER_BOUND = 2; +/** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ +function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } - /** - * Recursive implementation of binary search. - * - * @param aLow Indices here and lower do not contain the needle. - * @param aHigh Indices here and higher do not contain the needle. - * @param aNeedle The element being searched for. - * @param aHaystack The non-empty array being searched. - * @param aCompare Function which takes two elements and returns -1, 0, or 1. - * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or - * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - */ - function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { - // This function terminates when one of the following is true: - // - // 1. We find the exact element we are looking for. - // - // 2. We did not find the exact element, but we can return the index of - // the next-closest element. - // - // 3. We did not find the exact element, and there is no next-closest - // element than the one we are searching for, so we return -1. - var mid = Math.floor((aHigh - aLow) / 2) + aLow; - var cmp = aCompare(aNeedle, aHaystack[mid], true); - if (cmp === 0) { - // Found the element we are looking for. + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { return mid; } - else if (cmp > 0) { - // Our needle is greater than aHaystack[mid]. - if (aHigh - mid > 1) { - // The element is in the upper half. - return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); - } - - // The exact needle element was not found in this haystack. Determine if - // we are in termination case (3) or (2) and return the appropriate thing. - if (aBias == exports.LEAST_UPPER_BOUND) { - return aHigh < aHaystack.length ? aHigh : -1; - } else { - return mid; - } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); } - else { - // Our needle is less than aHaystack[mid]. - if (mid - aLow > 1) { - // The element is in the lower half. - return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); - } - // we are in termination case (3) or (2) and return the appropriate thing. - if (aBias == exports.LEAST_UPPER_BOUND) { - return mid; - } else { - return aLow < 0 ? -1 : aLow; - } + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; } } +} - /** - * This is an implementation of binary search which will always try and return - * the index of the closest element if there is no exact hit. This is because - * mappings between original and generated line/col pairs are single points, - * and there is an implicit region between each of them, so a miss just means - * that you aren't on the very start of a region. - * - * @param aNeedle The element you are looking for. - * @param aHaystack The array that is being searched. - * @param aCompare A function which takes the needle and an element in the - * array and returns -1, 0, or 1 depending on whether the needle is less - * than, equal to, or greater than the element, respectively. - * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or - * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. - */ - exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { - if (aHaystack.length === 0) { - return -1; - } +/** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ +exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } - var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, - aCompare, aBias || exports.GREATEST_LOWER_BOUND); - if (index < 0) { - return -1; - } + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } - // We have found either the exact element, or the next-closest element than - // the one we are searching for. However, there may be more than one such - // element. Make sure we always return the smallest of these. - while (index - 1 >= 0) { - if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { - break; - } - --index; + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; } + --index; + } - return index; - }; - -}); + return index; +}; diff --git a/lib/source-map/mapping-list.js b/lib/source-map/mapping-list.js index 6c5d3e4e..c9885e13 100644 --- a/lib/source-map/mapping-list.js +++ b/lib/source-map/mapping-list.js @@ -4,82 +4,75 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); +var util = require('./util'); + +/** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ +function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; +} + +/** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ +function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; } -define(function (require, exports, module) { - var util = require('./util'); +/** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ +MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; - /** - * Determine whether mappingB is after mappingA with respect to generated - * position. - */ - function generatedPositionAfter(mappingA, mappingB) { - // Optimized for most common case - var lineA = mappingA.generatedLine; - var lineB = mappingB.generatedLine; - var columnA = mappingA.generatedColumn; - var columnB = mappingB.generatedColumn; - return lineB > lineA || lineB == lineA && columnB >= columnA || - util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; +/** + * Add the given source mapping. + * + * @param Object aMapping + */ +MappingList.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); } +}; - /** - * A data structure to provide a sorted view of accumulated mappings in a - * performance conscious manner. It trades a neglibable overhead in general - * case for a large speedup in case of mappings being added in order. - */ - function MappingList() { - this._array = []; +/** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ +MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); this._sorted = true; - // Serves as infimum - this._last = {generatedLine: -1, generatedColumn: 0}; } + return this._array; +}; - /** - * Iterate through internal items. This method takes the same arguments that - * `Array.prototype.forEach` takes. - * - * NOTE: The order of the mappings is NOT guaranteed. - */ - MappingList.prototype.unsortedForEach = - function MappingList_forEach(aCallback, aThisArg) { - this._array.forEach(aCallback, aThisArg); - }; - - /** - * Add the given source mapping. - * - * @param Object aMapping - */ - MappingList.prototype.add = function MappingList_add(aMapping) { - if (generatedPositionAfter(this._last, aMapping)) { - this._last = aMapping; - this._array.push(aMapping); - } else { - this._sorted = false; - this._array.push(aMapping); - } - }; - - /** - * Returns the flat, sorted array of mappings. The mappings are sorted by - * generated position. - * - * WARNING: This method returns internal data without copying, for - * performance. The return value must NOT be mutated, and should be treated as - * an immutable borrow. If you want to take ownership, you must make your own - * copy. - */ - MappingList.prototype.toArray = function MappingList_toArray() { - if (!this._sorted) { - this._array.sort(util.compareByGeneratedPositionsInflated); - this._sorted = true; - } - return this._array; - }; - - exports.MappingList = MappingList; - -}); +exports.MappingList = MappingList; diff --git a/lib/source-map/quick-sort.js b/lib/source-map/quick-sort.js index e0551eda..aa19c223 100644 --- a/lib/source-map/quick-sort.js +++ b/lib/source-map/quick-sort.js @@ -4,117 +4,110 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - // It turns out that some (most?) JavaScript engines don't self-host - // `Array.prototype.sort`. This makes sense because C++ will likely remain - // faster than JS when doing raw CPU-intensive sorting. However, when using a - // custom comparator function, calling back and forth between the VM's C++ and - // JIT'd JS is rather slow *and* loses JIT type information, resulting in - // worse generated code for the comparator function than would be optimal. In - // fact, when sorting with a comparator, these costs outweigh the benefits of - // sorting in C++. By using our own JS-implemented Quick Sort (below), we get - // a ~3500ms mean speed-up in `bench/bench.html`. +// It turns out that some (most?) JavaScript engines don't self-host +// `Array.prototype.sort`. This makes sense because C++ will likely remain +// faster than JS when doing raw CPU-intensive sorting. However, when using a +// custom comparator function, calling back and forth between the VM's C++ and +// JIT'd JS is rather slow *and* loses JIT type information, resulting in +// worse generated code for the comparator function than would be optimal. In +// fact, when sorting with a comparator, these costs outweigh the benefits of +// sorting in C++. By using our own JS-implemented Quick Sort (below), we get +// a ~3500ms mean speed-up in `bench/bench.html`. - /** - * Swap the elements indexed by `x` and `y` in the array `ary`. - * - * @param {Array} ary - * The array. - * @param {Number} x - * The index of the first item. - * @param {Number} y - * The index of the second item. - */ - function swap(ary, x, y) { - var temp = ary[x]; - ary[x] = ary[y]; - ary[y] = temp; - } +/** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ +function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; +} - /** - * Returns a random integer within the range `low .. high` inclusive. - * - * @param {Number} low - * The lower bound on the range. - * @param {Number} high - * The upper bound on the range. - */ - function randomIntInRange(low, high) { - return Math.round(low + (Math.random() * (high - low))); - } +/** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ +function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); +} - /** - * The Quick Sort algorithm. - * - * @param {Array} ary - * An array to sort. - * @param {function} comparator - * Function to use to compare two items. - * @param {Number} p - * Start index of the array - * @param {Number} r - * End index of the array - */ - function doQuickSort(ary, comparator, p, r) { - // If our lower bound is less than our upper bound, we (1) partition the - // array into two pieces and (2) recurse on each half. If it is not, this is - // the empty array and our base case. +/** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ +function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. - if (p < r) { - // (1) Partitioning. - // - // The partitioning chooses a pivot between `p` and `r` and moves all - // elements that are less than or equal to the pivot to the before it, and - // all the elements that are greater than it after it. The effect is that - // once partition is done, the pivot is in the exact place it will be when - // the array is put in sorted order, and it will not need to be moved - // again. This runs in O(n) time. + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. - // Always choose a random pivot so that an input array which is reverse - // sorted does not cause O(n^2) running time. - var pivotIndex = randomIntInRange(p, r); - var i = p - 1; + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; - swap(ary, pivotIndex, r); - var pivot = ary[r]; + swap(ary, pivotIndex, r); + var pivot = ary[r]; - // Immediately after `j` is incremented in this loop, the following hold - // true: - // - // * Every element in `ary[p .. i]` is less than or equal to the pivot. - // - // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. - for (var j = p; j < r; j++) { - if (comparator(ary[j], pivot) <= 0) { - i += 1; - swap(ary, i, j); - } + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); } + } - swap(ary, i + 1, j); - var q = i + 1; + swap(ary, i + 1, j); + var q = i + 1; - // (2) Recurse on each half. + // (2) Recurse on each half. - doQuickSort(ary, comparator, p, q - 1); - doQuickSort(ary, comparator, q + 1, r); - } + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); } +} - /** - * Sort the given array in-place with the given comparator function. - * - * @param {Array} ary - * An array to sort. - * @param {function} comparator - * Function to use to compare two items. - */ - exports.quickSort = function (ary, comparator) { - doQuickSort(ary, comparator, 0, ary.length - 1); - }; - -}); +/** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ +exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); +}; diff --git a/lib/source-map/source-map-consumer.js b/lib/source-map/source-map-consumer.js index 99763388..7c8d74b0 100644 --- a/lib/source-map/source-map-consumer.js +++ b/lib/source-map/source-map-consumer.js @@ -4,1084 +4,1077 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); +var util = require('./util'); +var binarySearch = require('./binary-search'); +var ArraySet = require('./array-set').ArraySet; +var base64VLQ = require('./base64-vlq'); +var quickSort = require('./quick-sort').quickSort; + +function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); +} + +SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); } -define(function (require, exports, module) { - - var util = require('./util'); - var binarySearch = require('./binary-search'); - var ArraySet = require('./array-set').ArraySet; - var base64VLQ = require('./base64-vlq'); - var quickSort = require('./quick-sort').quickSort; - - function SourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + +/** + * The version of the source mapping spec that we are consuming. + */ +SourceMapConsumer.prototype._version = 3; + +// `__generatedMappings` and `__originalMappings` are arrays that hold the +// parsed mapping coordinates from the source map's "mappings" attribute. They +// are lazily instantiated, accessed via the `_generatedMappings` and +// `_originalMappings` getters respectively, and we only parse the mappings +// and create these arrays once queried for a source location. We jump through +// these hoops because there can be many thousands of mappings, and parsing +// them is expensive, so we only want to do it if we must. +// +// Each object in the arrays is of the form: +// +// { +// generatedLine: The line number in the generated code, +// generatedColumn: The column number in the generated code, +// source: The path to the original source file that generated this +// chunk of code, +// originalLine: The line number in the original source that +// corresponds to this chunk of generated code, +// originalColumn: The column number in the original source that +// corresponds to this chunk of generated code, +// name: The name of the original symbol which generated this chunk of +// code. +// } +// +// All properties except for `generatedLine` and `generatedColumn` can be +// `null`. +// +// `_generatedMappings` is ordered by the generated positions. +// +// `_originalMappings` is ordered by the original positions. + +SourceMapConsumer.prototype.__generatedMappings = null; +Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); } - return sourceMap.sections != null - ? new IndexedSourceMapConsumer(sourceMap) - : new BasicSourceMapConsumer(sourceMap); + return this.__generatedMappings; } +}); - SourceMapConsumer.fromSourceMap = function(aSourceMap) { - return BasicSourceMapConsumer.fromSourceMap(aSourceMap); +SourceMapConsumer.prototype.__originalMappings = null; +Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; } +}); - /** - * The version of the source mapping spec that we are consuming. - */ - SourceMapConsumer.prototype._version = 3; - - // `__generatedMappings` and `__originalMappings` are arrays that hold the - // parsed mapping coordinates from the source map's "mappings" attribute. They - // are lazily instantiated, accessed via the `_generatedMappings` and - // `_originalMappings` getters respectively, and we only parse the mappings - // and create these arrays once queried for a source location. We jump through - // these hoops because there can be many thousands of mappings, and parsing - // them is expensive, so we only want to do it if we must. - // - // Each object in the arrays is of the form: - // - // { - // generatedLine: The line number in the generated code, - // generatedColumn: The column number in the generated code, - // source: The path to the original source file that generated this - // chunk of code, - // originalLine: The line number in the original source that - // corresponds to this chunk of generated code, - // originalColumn: The column number in the original source that - // corresponds to this chunk of generated code, - // name: The name of the original symbol which generated this chunk of - // code. - // } - // - // All properties except for `generatedLine` and `generatedColumn` can be - // `null`. - // - // `_generatedMappings` is ordered by the generated positions. - // - // `_originalMappings` is ordered by the original positions. - - SourceMapConsumer.prototype.__generatedMappings = null; - Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { - get: function () { - if (!this.__generatedMappings) { - this._parseMappings(this._mappings, this.sourceRoot); - } +SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; - return this.__generatedMappings; +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + +SourceMapConsumer.GENERATED_ORDER = 1; +SourceMapConsumer.ORIGINAL_ORDER = 2; + +SourceMapConsumer.GREATEST_LOWER_BOUND = 1; +SourceMapConsumer.LEAST_UPPER_BOUND = 2; + +/** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ +SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); } - }); - SourceMapConsumer.prototype.__originalMappings = null; - Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { - get: function () { - if (!this.__originalMappings) { - this._parseMappings(this._mappings, this.sourceRoot); + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); } - - return this.__originalMappings; - } - }); - - SourceMapConsumer.prototype._charIsMappingSeparator = - function SourceMapConsumer_charIsMappingSeparator(aStr, index) { - var c = aStr.charAt(index); - return c === ";" || c === ","; - }; - - /** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ - SourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - throw new Error("Subclasses must implement _parseMappings"); + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; + +/** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) }; - SourceMapConsumer.GENERATED_ORDER = 1; - SourceMapConsumer.ORIGINAL_ORDER = 2; - - SourceMapConsumer.GREATEST_LOWER_BOUND = 1; - SourceMapConsumer.LEAST_UPPER_BOUND = 2; - - /** - * Iterate over each mapping between an original source/line/column and a - * generated line/column in this source map. - * - * @param Function aCallback - * The function that is called with each mapping. - * @param Object aContext - * Optional. If specified, this object will be the value of `this` every - * time that `aCallback` is called. - * @param aOrder - * Either `SourceMapConsumer.GENERATED_ORDER` or - * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to - * iterate over the mappings sorted by the generated file's line/column - * order or the original's source/line/column order, respectively. Defaults to - * `SourceMapConsumer.GENERATED_ORDER`. - */ - SourceMapConsumer.prototype.eachMapping = - function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { - var context = aContext || null; - var order = aOrder || SourceMapConsumer.GENERATED_ORDER; - - var mappings; - switch (order) { - case SourceMapConsumer.GENERATED_ORDER: - mappings = this._generatedMappings; - break; - case SourceMapConsumer.ORIGINAL_ORDER: - mappings = this._originalMappings; - break; - default: - throw new Error("Unknown order of iteration."); - } + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; + } + needle.source = this._sources.indexOf(needle.source); + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); - var sourceRoot = this.sourceRoot; - mappings.map(function (mapping) { - var source = mapping.source === null ? null : this._sources.at(mapping.source); - if (source != null && sourceRoot != null) { - source = util.join(sourceRoot, source); + mapping = this._originalMappings[++index]; } - return { - source: source, - generatedLine: mapping.generatedLine, - generatedColumn: mapping.generatedColumn, - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: mapping.name === null ? null : this._names.at(mapping.name) - }; - }, this).forEach(aCallback, context); - }; - - /** - * Returns all generated line and column information for the original source, - * line, and column provided. If no column is provided, returns all mappings - * corresponding to a either the line we are searching for or the next - * closest line that has any mappings. Otherwise, returns all mappings - * corresponding to the given line and either the column we are searching for - * or the next closest column that has any offsets. - * - * The only argument is an object with the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: Optional. the column number in the original source. - * - * and an array of objects is returned, each with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ - SourceMapConsumer.prototype.allGeneratedPositionsFor = - function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { - var line = util.getArg(aArgs, 'line'); - - // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping - // returns the index of the closest mapping less than the needle. By - // setting needle.originalColumn to 0, we thus find the last mapping for - // the given line, provided such a mapping exists. - var needle = { - source: util.getArg(aArgs, 'source'), - originalLine: line, - originalColumn: util.getArg(aArgs, 'column', 0) - }; + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); - if (this.sourceRoot != null) { - needle.source = util.relative(this.sourceRoot, needle.source); - } - if (!this._sources.has(needle.source)) { - return []; - } - needle.source = this._sources.indexOf(needle.source); - - var mappings = []; - - var index = this._findMapping(needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions, - binarySearch.LEAST_UPPER_BOUND); - if (index >= 0) { - var mapping = this._originalMappings[index]; - - if (aArgs.column === undefined) { - var originalLine = mapping.originalLine; - - // Iterate until either we run out of mappings, or we run into - // a mapping for a different line than the one we found. Since - // mappings are sorted, this is guaranteed to find all mappings for - // the line we found. - while (mapping && mapping.originalLine === originalLine) { - mappings.push({ - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }); - - mapping = this._originalMappings[++index]; - } - } else { - var originalColumn = mapping.originalColumn; - - // Iterate until either we run out of mappings, or we run into - // a mapping for a different line than the one we were searching for. - // Since mappings are sorted, this is guaranteed to find all mappings for - // the line we are searching for. - while (mapping && - mapping.originalLine === line && - mapping.originalColumn == originalColumn) { - mappings.push({ - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }); - - mapping = this._originalMappings[++index]; - } + mapping = this._originalMappings[++index]; } } - - return mappings; - }; - - exports.SourceMapConsumer = SourceMapConsumer; - - /** - * A BasicSourceMapConsumer instance represents a parsed source map which we can - * query for information about the original file positions by giving it a file - * position in the generated source. - * - * The only parameter is the raw source map (either as a JSON string, or - * already parsed to an object). According to the spec, source maps have the - * following attributes: - * - * - version: Which version of the source map spec this map is following. - * - sources: An array of URLs to the original source files. - * - names: An array of identifiers which can be referrenced by individual mappings. - * - sourceRoot: Optional. The URL root from which all sources are relative. - * - sourcesContent: Optional. An array of contents of the original source files. - * - mappings: A string of base64 VLQs which contain the actual mappings. - * - file: Optional. The generated file this source map is associated with. - * - * Here is an example source map, taken from the source map spec[0]: - * - * { - * version : 3, - * file: "out.js", - * sourceRoot : "", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AA,AB;;ABCDE;" - * } - * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# - */ - function BasicSourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } - - var version = util.getArg(sourceMap, 'version'); - var sources = util.getArg(sourceMap, 'sources'); - // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which - // requires the array) to play nice here. - var names = util.getArg(sourceMap, 'names', []); - var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); - var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); - var mappings = util.getArg(sourceMap, 'mappings'); - var file = util.getArg(sourceMap, 'file', null); - - // Once again, Sass deviates from the spec and supplies the version as a - // string rather than a number, so we use loose equality checking here. - if (version != this._version) { - throw new Error('Unsupported version: ' + version); } - sources = sources - // Some source maps produce relative source paths like "./foo.js" instead of - // "foo.js". Normalize these first so that future comparisons will succeed. - // See bugzil.la/1090768. - .map(util.normalize) - // Always ensure that absolute sources are internally stored relative to - // the source root, if the source root is absolute. Not doing this would - // be particularly problematic when the source root is a prefix of the - // source (valid, but why??). See github issue #199 and bugzil.la/1188982. - .map(function (source) { - return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) - ? util.relative(sourceRoot, source) - : source; - }); + return mappings; + }; + +exports.SourceMapConsumer = SourceMapConsumer; + +/** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ +function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } - // Pass `true` below to allow duplicate names and sources. While source maps - // are intended to be compressed and deduplicated, the TypeScript compiler - // sometimes generates source maps with duplicates in them. See Github issue - // #72 and bugzil.la/889492. - this._names = ArraySet.fromArray(names, true); - this._sources = ArraySet.fromArray(sources, true); - - this.sourceRoot = sourceRoot; - this.sourcesContent = sourcesContent; - this._mappings = mappings; - this.file = file; + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); } - BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); - BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; - - /** - * Create a BasicSourceMapConsumer from a SourceMapGenerator. - * - * @param SourceMapGenerator aSourceMap - * The source map that will be consumed. - * @returns BasicSourceMapConsumer - */ - BasicSourceMapConsumer.fromSourceMap = - function SourceMapConsumer_fromSourceMap(aSourceMap) { - var smc = Object.create(BasicSourceMapConsumer.prototype); - - var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); - var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); - smc.sourceRoot = aSourceMap._sourceRoot; - smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), - smc.sourceRoot); - smc.file = aSourceMap._file; - - // Because we are modifying the entries (by converting string sources and - // names to indices into the sources and names ArraySets), we have to make - // a copy of the entry or else bad things happen. Shared mutable state - // strikes again! See github issue #191. - - var generatedMappings = aSourceMap._mappings.toArray().slice(); - var destGeneratedMappings = smc.__generatedMappings = []; - var destOriginalMappings = smc.__originalMappings = []; - - for (var i = 0, length = generatedMappings.length; i < length; i++) { - var srcMapping = generatedMappings[i]; - var destMapping = new Mapping; - destMapping.generatedLine = srcMapping.generatedLine; - destMapping.generatedColumn = srcMapping.generatedColumn; - - if (srcMapping.source) { - destMapping.source = sources.indexOf(srcMapping.source); - destMapping.originalLine = srcMapping.originalLine; - destMapping.originalColumn = srcMapping.originalColumn; - - if (srcMapping.name) { - destMapping.name = names.indexOf(srcMapping.name); - } + sources = sources + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) + ? util.relative(sourceRoot, source) + : source; + }); - destOriginalMappings.push(destMapping); - } + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; +} - destGeneratedMappings.push(destMapping); - } +BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); +BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; - quickSort(smc.__originalMappings, util.compareByOriginalPositions); +/** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer + */ +BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } - return smc; - }; + destOriginalMappings.push(destMapping); + } - /** - * The version of the source mapping spec that we are consuming. - */ - BasicSourceMapConsumer.prototype._version = 3; - - /** - * The list of original sources. - */ - Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { - get: function () { - return this._sources.toArray().map(function (s) { - return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; - }, this); + destGeneratedMappings.push(destMapping); } - }); - /** - * Provide the JIT with a nice shape / hidden class. - */ - function Mapping() { - this.generatedLine = 0; - this.generatedColumn = 0; - this.source = null; - this.originalLine = null; - this.originalColumn = null; - this.name = null; - } + quickSort(smc.__originalMappings, util.compareByOriginalPositions); - /** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ - BasicSourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - var generatedLine = 1; - var previousGeneratedColumn = 0; - var previousOriginalLine = 0; - var previousOriginalColumn = 0; - var previousSource = 0; - var previousName = 0; - var length = aStr.length; - var index = 0; - var cachedSegments = {}; - var temp = {}; - var originalMappings = []; - var generatedMappings = []; - var mapping, str, segment, end, value; - - while (index < length) { - if (aStr.charAt(index) === ';') { - generatedLine++; - index++; - previousGeneratedColumn = 0; - } - else if (aStr.charAt(index) === ',') { - index++; - } - else { - mapping = new Mapping(); - mapping.generatedLine = generatedLine; - - // Because each offset is encoded relative to the previous one, - // many segments often have the same encoding. We can exploit this - // fact by caching the parsed variable length fields of each segment, - // allowing us to avoid a second parse if we encounter the same - // segment again. - for (end = index; end < length; end++) { - if (this._charIsMappingSeparator(aStr, end)) { - break; - } - } - str = aStr.slice(index, end); - - segment = cachedSegments[str]; - if (segment) { - index += str.length; - } else { - segment = []; - while (index < end) { - base64VLQ.decode(aStr, index, temp); - value = temp.value; - index = temp.rest; - segment.push(value); - } - - if (segment.length === 2) { - throw new Error('Found a source, but no line and column'); - } - - if (segment.length === 3) { - throw new Error('Found a source and line, but no column'); - } - - cachedSegments[str] = segment; - } - - // Generated column. - mapping.generatedColumn = previousGeneratedColumn + segment[0]; - previousGeneratedColumn = mapping.generatedColumn; - - if (segment.length > 1) { - // Original source. - mapping.source = previousSource + segment[1]; - previousSource += segment[1]; - - // Original line. - mapping.originalLine = previousOriginalLine + segment[2]; - previousOriginalLine = mapping.originalLine; - // Lines are stored 0-based - mapping.originalLine += 1; - - // Original column. - mapping.originalColumn = previousOriginalColumn + segment[3]; - previousOriginalColumn = mapping.originalColumn; - - if (segment.length > 4) { - // Original name. - mapping.name = previousName + segment[4]; - previousName += segment[4]; - } - } + return smc; + }; - generatedMappings.push(mapping); - if (typeof mapping.originalLine === 'number') { - originalMappings.push(mapping); - } - } - } +/** + * The version of the source mapping spec that we are consuming. + */ +BasicSourceMapConsumer.prototype._version = 3; - quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); - this.__generatedMappings = generatedMappings; +/** + * The list of original sources. + */ +Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } +}); - quickSort(originalMappings, util.compareByOriginalPositions); - this.__originalMappings = originalMappings; - }; +/** + * Provide the JIT with a nice shape / hidden class. + */ +function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; +} - /** - * Find the mapping that best matches the hypothetical "needle" mapping that - * we are searching for in the given "haystack" of mappings. - */ - BasicSourceMapConsumer.prototype._findMapping = - function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, - aColumnName, aComparator, aBias) { - // To return the position we are searching for, we must first find the - // mapping for the given position and then return the opposite position it - // points to. Because the mappings are sorted, we can use binary search to - // find the best mapping. - - if (aNeedle[aLineName] <= 0) { - throw new TypeError('Line must be greater than or equal to 1, got ' - + aNeedle[aLineName]); +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; } - if (aNeedle[aColumnName] < 0) { - throw new TypeError('Column must be greater than or equal to 0, got ' - + aNeedle[aColumnName]); + else if (aStr.charAt(index) === ',') { + index++; } - - return binarySearch.search(aNeedle, aMappings, aComparator, aBias); - }; - - /** - * Compute the last column for each generated mapping. The last column is - * inclusive. - */ - BasicSourceMapConsumer.prototype.computeColumnSpans = - function SourceMapConsumer_computeColumnSpans() { - for (var index = 0; index < this._generatedMappings.length; ++index) { - var mapping = this._generatedMappings[index]; - - // Mappings do not contain a field for the last generated columnt. We - // can come up with an optimistic estimate, however, by assuming that - // mappings are contiguous (i.e. given two consecutive mappings, the - // first mapping ends where the second one starts). - if (index + 1 < this._generatedMappings.length) { - var nextMapping = this._generatedMappings[index + 1]; - - if (mapping.generatedLine === nextMapping.generatedLine) { - mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; - continue; + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; } } + str = aStr.slice(index, end); - // The last mapping for each line spans the entire line. - mapping.lastGeneratedColumn = Infinity; - } - }; - - /** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: - * - * - line: The line number in the generated source. - * - column: The column number in the generated source. - * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or - * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. - * - * and an object is returned with the following properties: - * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. - */ - BasicSourceMapConsumer.prototype.originalPositionFor = - function SourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } - var index = this._findMapping( - needle, - this._generatedMappings, - "generatedLine", - "generatedColumn", - util.compareByGeneratedPositionsDeflated, - util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) - ); - - if (index >= 0) { - var mapping = this._generatedMappings[index]; - - if (mapping.generatedLine === needle.generatedLine) { - var source = util.getArg(mapping, 'source', null); - if (source !== null) { - source = this._sources.at(source); - if (this.sourceRoot != null) { - source = util.join(this.sourceRoot, source); - } + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); } - var name = util.getArg(mapping, 'name', null); - if (name !== null) { - name = this._names.at(name); + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); } - return { - source: source, - line: util.getArg(mapping, 'originalLine', null), - column: util.getArg(mapping, 'originalColumn', null), - name: name - }; + + cachedSegments[str] = segment; } - } - return { - source: null, - line: null, - column: null, - name: null - }; - }; + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } - /** - * Return true if we have the source content for every source in the source - * map, false otherwise. - */ - BasicSourceMapConsumer.prototype.hasContentsOfAllSources = - function BasicSourceMapConsumer_hasContentsOfAllSources() { - if (!this.sourcesContent) { - return false; + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } } - return this.sourcesContent.length >= this._sources.size() && - !this.sourcesContent.some(function (sc) { return sc == null; }); - }; + } - /** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * availible. - */ - BasicSourceMapConsumer.prototype.sourceContentFor = - function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { - if (!this.sourcesContent) { - return null; - } + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; - if (this.sourceRoot != null) { - aSource = util.relative(this.sourceRoot, aSource); - } + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; + }; - if (this._sources.has(aSource)) { - return this.sourcesContent[this._sources.indexOf(aSource)]; - } +/** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ +BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } - var url; - if (this.sourceRoot != null - && (url = util.urlParse(this.sourceRoot))) { - // XXX: file:// URIs and absolute paths lead to unexpected behavior for - // many users. We can help them out when they expect file:// URIs to - // behave like it would if they were running a local HTTP server. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. - var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); - if (url.scheme == "file" - && this._sources.has(fileUriAbsPath)) { - return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] - } + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; - if ((!url.path || url.path == "/") - && this._sources.has("/" + aSource)) { - return this.sourcesContent[this._sources.indexOf("/" + aSource)]; +/** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ +BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; } } - // This function is used recursively from - // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we - // don't want to throw if we can't find the source - we just want to - // return null, so we provide a flag to exit gracefully. - if (nullOnMissing) { - return null; - } - else { - throw new Error('"' + aSource + '" is not in the SourceMap.'); - } + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + +/** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ +BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') }; - /** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or - * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. - * - * and an object is returned with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ - BasicSourceMapConsumer.prototype.generatedPositionFor = - function SourceMapConsumer_generatedPositionFor(aArgs) { - var source = util.getArg(aArgs, 'source'); - if (this.sourceRoot != null) { - source = util.relative(this.sourceRoot, source); - } - if (!this._sources.has(source)) { + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } return { - line: null, - column: null, - lastColumn: null + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name }; } - source = this._sources.indexOf(source); + } - var needle = { - source: source, - originalLine: util.getArg(aArgs, 'line'), - originalColumn: util.getArg(aArgs, 'column') - }; + return { + source: null, + line: null, + column: null, + name: null + }; + }; + +/** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ +BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; + +/** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ +BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } - var index = this._findMapping( - needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions, - util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) - ); + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } - if (index >= 0) { - var mapping = this._originalMappings[index]; + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } - if (mapping.source === needle.source) { - return { - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }; - } + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] } + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + +/** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); + } + if (!this._sources.has(source)) { return { line: null, column: null, lastColumn: null }; + } + source = this._sources.indexOf(source); + + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') }; - exports.BasicSourceMapConsumer = BasicSourceMapConsumer; - - /** - * An IndexedSourceMapConsumer instance represents a parsed source map which - * we can query for information. It differs from BasicSourceMapConsumer in - * that it takes "indexed" source maps (i.e. ones with a "sections" field) as - * input. - * - * The only parameter is a raw source map (either as a JSON string, or already - * parsed to an object). According to the spec for indexed source maps, they - * have the following attributes: - * - * - version: Which version of the source map spec this map is following. - * - file: Optional. The generated file this source map is associated with. - * - sections: A list of section definitions. - * - * Each value under the "sections" field has two fields: - * - offset: The offset into the original specified at which this section - * begins to apply, defined as an object with a "line" and "column" - * field. - * - map: A source map definition. This source map could also be indexed, - * but doesn't have to be. - * - * Instead of the "map" field, it's also possible to have a "url" field - * specifying a URL to retrieve a source map from, but that's currently - * unsupported. - * - * Here's an example source map, taken from the source map spec[0], but - * modified to omit a section which uses the "url" field. - * - * { - * version : 3, - * file: "app.js", - * sections: [{ - * offset: {line:100, column:10}, - * map: { - * version : 3, - * file: "section.js", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AAAA,E;;ABCDE;" - * } - * }], - * } - * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt - */ - function IndexedSourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); - var version = util.getArg(sourceMap, 'version'); - var sections = util.getArg(sourceMap, 'sections'); + if (index >= 0) { + var mapping = this._originalMappings[index]; - if (version != this._version) { - throw new Error('Unsupported version: ' + version); + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } } - this._sources = new ArraySet(); - this._names = new ArraySet(); - - var lastOffset = { - line: -1, - column: 0 + return { + line: null, + column: null, + lastColumn: null }; - this._sections = sections.map(function (s) { - if (s.url) { - // The url field will require support for asynchronicity. - // See https://github.com/mozilla/source-map/issues/16 - throw new Error('Support for url field in sections not implemented.'); - } - var offset = util.getArg(s, 'offset'); - var offsetLine = util.getArg(offset, 'line'); - var offsetColumn = util.getArg(offset, 'column'); + }; + +exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + +/** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ +function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } - if (offsetLine < lastOffset.line || - (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { - throw new Error('Section offsets must be ordered and non-overlapping.'); - } - lastOffset = offset; + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); - return { - generatedOffset: { - // The offset fields are 0-based, but we use 1-based indices when - // encoding/decoding from VLQ. - generatedLine: offsetLine + 1, - generatedColumn: offsetColumn + 1 - }, - consumer: new SourceMapConsumer(util.getArg(s, 'map')) - } - }); + if (version != this._version) { + throw new Error('Unsupported version: ' + version); } - IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); - IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; - - /** - * The version of the source mapping spec that we are consuming. - */ - IndexedSourceMapConsumer.prototype._version = 3; - - /** - * The list of original sources. - */ - Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { - get: function () { - var sources = []; - for (var i = 0; i < this._sections.length; i++) { - for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { - sources.push(this._sections[i].consumer.sources[j]); - } - } - return sources; + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); } - }); + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); - /** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: - * - * - line: The line number in the generated source. - * - column: The column number in the generated source. - * - * and an object is returned with the following properties: - * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. - */ - IndexedSourceMapConsumer.prototype.originalPositionFor = - function IndexedSourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) + } + }); +} - // Find the section containing the generated position we're trying to map - // to an original position. - var sectionIndex = binarySearch.search(needle, this._sections, - function(needle, section) { - var cmp = needle.generatedLine - section.generatedOffset.generatedLine; - if (cmp) { - return cmp; - } +IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); +IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; - return (needle.generatedColumn - - section.generatedOffset.generatedColumn); - }); - var section = this._sections[sectionIndex]; +/** + * The version of the source mapping spec that we are consuming. + */ +IndexedSourceMapConsumer.prototype._version = 3; - if (!section) { - return { - source: null, - line: null, - column: null, - name: null - }; +/** + * The list of original sources. + */ +Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); } + } + return sources; + } +}); - return section.consumer.originalPositionFor({ - line: needle.generatedLine - - (section.generatedOffset.generatedLine - 1), - column: needle.generatedColumn - - (section.generatedOffset.generatedLine === needle.generatedLine - ? section.generatedOffset.generatedColumn - 1 - : 0), - bias: aArgs.bias - }); +/** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ +IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') }; - /** - * Return true if we have the source content for every source in the source - * map, false otherwise. - */ - IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = - function IndexedSourceMapConsumer_hasContentsOfAllSources() { - return this._sections.every(function (s) { - return s.consumer.hasContentsOfAllSources(); + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); }); - }; + var section = this._sections[sectionIndex]; - /** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * available. - */ - IndexedSourceMapConsumer.prototype.sourceContentFor = - function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - - var content = section.consumer.sourceContentFor(aSource, true); - if (content) { - return content; - } + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + +/** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ +IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + +/** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ +IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; } - if (nullOnMissing) { - return null; + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + +/** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; } - else { - throw new Error('"' + aSource + '" is not in the SourceMap.'); + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; } + } + + return { + line: null, + column: null }; + }; - /** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - * and an object is returned with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ - IndexedSourceMapConsumer.prototype.generatedPositionFor = - function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - - // Only consider this section if the requested source is in the list of - // sources of the consumer. - if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { - continue; - } - var generatedPosition = section.consumer.generatedPositionFor(aArgs); - if (generatedPosition) { - var ret = { - line: generatedPosition.line + - (section.generatedOffset.generatedLine - 1), - column: generatedPosition.column + - (section.generatedOffset.generatedLine === generatedPosition.line - ? section.generatedOffset.generatedColumn - 1 - : 0) - }; - return ret; +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[i]; + + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); } - } - - return { - line: null, - column: null - }; - }; + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.column + + (section.generatedOffset.generatedLine === mapping.generatedLine) + ? section.generatedOffset.generatedColumn - 1 + : 0, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; - /** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ - IndexedSourceMapConsumer.prototype._parseMappings = - function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { - this.__generatedMappings = []; - this.__originalMappings = []; - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - var sectionMappings = section.consumer._generatedMappings; - for (var j = 0; j < sectionMappings.length; j++) { - var mapping = sectionMappings[i]; - - var source = section.consumer._sources.at(mapping.source); - if (section.consumer.sourceRoot !== null) { - source = util.join(section.consumer.sourceRoot, source); - } - this._sources.add(source); - source = this._sources.indexOf(source); - - var name = section.consumer._names.at(mapping.name); - this._names.add(name); - name = this._names.indexOf(name); - - // The mappings coming from the consumer for the section have - // generated positions relative to the start of the section, so we - // need to offset them to be relative to the start of the concatenated - // generated file. - var adjustedMapping = { - source: source, - generatedLine: mapping.generatedLine + - (section.generatedOffset.generatedLine - 1), - generatedColumn: mapping.column + - (section.generatedOffset.generatedLine === mapping.generatedLine) - ? section.generatedOffset.generatedColumn - 1 - : 0, - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: name - }; - - this.__generatedMappings.push(adjustedMapping); - if (typeof adjustedMapping.originalLine === 'number') { - this.__originalMappings.push(adjustedMapping); - } + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); } } + } - quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); - quickSort(this.__originalMappings, util.compareByOriginalPositions); - }; - - exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; -}); +exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; diff --git a/lib/source-map/source-map-generator.js b/lib/source-map/source-map-generator.js index ad390845..5f13065a 100644 --- a/lib/source-map/source-map-generator.js +++ b/lib/source-map/source-map-generator.js @@ -4,398 +4,391 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var base64VLQ = require('./base64-vlq'); - var util = require('./util'); - var ArraySet = require('./array-set').ArraySet; - var MappingList = require('./mapping-list').MappingList; - - /** - * An instance of the SourceMapGenerator represents a source map which is - * being built incrementally. You may pass an object with the following - * properties: - * - * - file: The filename of the generated source. - * - sourceRoot: A root for all relative URLs in this source map. - */ - function SourceMapGenerator(aArgs) { - if (!aArgs) { - aArgs = {}; - } - this._file = util.getArg(aArgs, 'file', null); - this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); - this._skipValidation = util.getArg(aArgs, 'skipValidation', false); - this._sources = new ArraySet(); - this._names = new ArraySet(); - this._mappings = new MappingList(); - this._sourcesContents = null; +var base64VLQ = require('./base64-vlq'); +var util = require('./util'); +var ArraySet = require('./array-set').ArraySet; +var MappingList = require('./mapping-list').MappingList; + +/** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ +function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; +} - SourceMapGenerator.prototype._version = 3; - - /** - * Creates a new SourceMapGenerator based on a SourceMapConsumer - * - * @param aSourceMapConsumer The SourceMap. - */ - SourceMapGenerator.fromSourceMap = - function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { - var sourceRoot = aSourceMapConsumer.sourceRoot; - var generator = new SourceMapGenerator({ - file: aSourceMapConsumer.file, - sourceRoot: sourceRoot - }); - aSourceMapConsumer.eachMapping(function (mapping) { - var newMapping = { - generated: { - line: mapping.generatedLine, - column: mapping.generatedColumn - } - }; - - if (mapping.source != null) { - newMapping.source = mapping.source; - if (sourceRoot != null) { - newMapping.source = util.relative(sourceRoot, newMapping.source); - } - - newMapping.original = { - line: mapping.originalLine, - column: mapping.originalColumn - }; +SourceMapGenerator.prototype._version = 3; - if (mapping.name != null) { - newMapping.name = mapping.name; - } +/** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ +SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn } + }; - generator.addMapping(newMapping); - }); - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - generator.setSourceContent(sourceFile, content); + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); } - }); - return generator; - }; - /** - * Add a single mapping from original source line and column to the generated - * source's line and column for this source map being created. The mapping - * object should have the following properties: - * - * - generated: An object with the generated line and column positions. - * - original: An object with the original line and column positions. - * - source: The original source file (relative to the sourceRoot). - * - name: An optional original token name for this mapping. - */ - SourceMapGenerator.prototype.addMapping = - function SourceMapGenerator_addMapping(aArgs) { - var generated = util.getArg(aArgs, 'generated'); - var original = util.getArg(aArgs, 'original', null); - var source = util.getArg(aArgs, 'source', null); - var name = util.getArg(aArgs, 'name', null); - - if (!this._skipValidation) { - this._validateMapping(generated, original, source, name); - } + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; - if (source != null && !this._sources.has(source)) { - this._sources.add(source); + if (mapping.name != null) { + newMapping.name = mapping.name; + } } - if (name != null && !this._names.has(name)) { - this._names.add(name); + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); } + }); + return generator; + }; + +/** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ +SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } - this._mappings.add({ - generatedLine: generated.line, - generatedColumn: generated.column, - originalLine: original != null && original.line, - originalColumn: original != null && original.column, - source: source, - name: name - }); - }; + if (source != null && !this._sources.has(source)) { + this._sources.add(source); + } - /** - * Set the source content for a source file. - */ - SourceMapGenerator.prototype.setSourceContent = - function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { - var source = aSourceFile; - if (this._sourceRoot != null) { - source = util.relative(this._sourceRoot, source); - } + if (name != null && !this._names.has(name)) { + this._names.add(name); + } - if (aSourceContent != null) { - // Add the source content to the _sourcesContents map. - // Create a new _sourcesContents map if the property is null. - if (!this._sourcesContents) { - this._sourcesContents = {}; - } - this._sourcesContents[util.toSetString(source)] = aSourceContent; - } else if (this._sourcesContents) { - // Remove the source file from the _sourcesContents map. - // If the _sourcesContents map is empty, set the property to null. - delete this._sourcesContents[util.toSetString(source)]; - if (Object.keys(this._sourcesContents).length === 0) { - this._sourcesContents = null; - } - } - }; + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + +/** + * Set the source content for a source file. + */ +SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } - /** - * Applies the mappings of a sub-source-map for a specific source file to the - * source map being generated. Each mapping to the supplied source file is - * rewritten using the supplied source map. Note: The resolution for the - * resulting mappings is the minimium of this map and the supplied map. - * - * @param aSourceMapConsumer The source map to be applied. - * @param aSourceFile Optional. The filename of the source file. - * If omitted, SourceMapConsumer's file property will be used. - * @param aSourceMapPath Optional. The dirname of the path to the source map - * to be applied. If relative, it is relative to the SourceMapConsumer. - * This parameter is needed when the two source maps aren't in the same - * directory, and the source map to be applied contains relative source - * paths. If so, those relative source paths need to be rewritten - * relative to the SourceMapGenerator. - */ - SourceMapGenerator.prototype.applySourceMap = - function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { - var sourceFile = aSourceFile; - // If aSourceFile is omitted, we will use the file property of the SourceMap - if (aSourceFile == null) { - if (aSourceMapConsumer.file == null) { - throw new Error( - 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + - 'or the source map\'s "file" property. Both were omitted.' - ); - } - sourceFile = aSourceMapConsumer.file; + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; } - var sourceRoot = this._sourceRoot; - // Make "sourceFile" relative if an absolute Url is passed. - if (sourceRoot != null) { - sourceFile = util.relative(sourceRoot, sourceFile); + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; } - // Applying the SourceMap can add and remove items from the sources and - // the names array. - var newSources = new ArraySet(); - var newNames = new ArraySet(); - - // Find mappings for the "sourceFile" - this._mappings.unsortedForEach(function (mapping) { - if (mapping.source === sourceFile && mapping.originalLine != null) { - // Check if it can be mapped by the source map, then update the mapping. - var original = aSourceMapConsumer.originalPositionFor({ - line: mapping.originalLine, - column: mapping.originalColumn - }); - if (original.source != null) { - // Copy mapping - mapping.source = original.source; - if (aSourceMapPath != null) { - mapping.source = util.join(aSourceMapPath, mapping.source) - } - if (sourceRoot != null) { - mapping.source = util.relative(sourceRoot, mapping.source); - } - mapping.originalLine = original.line; - mapping.originalColumn = original.column; - if (original.name != null) { - mapping.name = original.name; - } - } - } - - var source = mapping.source; - if (source != null && !newSources.has(source)) { - newSources.add(source); - } - - var name = mapping.name; - if (name != null && !newNames.has(name)) { - newNames.add(name); - } - - }, this); - this._sources = newSources; - this._names = newNames; - - // Copy sourcesContents of applied map. - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { + } + }; + +/** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ +SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; if (aSourceMapPath != null) { - sourceFile = util.join(aSourceMapPath, sourceFile); + mapping.source = util.join(aSourceMapPath, mapping.source) } if (sourceRoot != null) { - sourceFile = util.relative(sourceRoot, sourceFile); + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; } - this.setSourceContent(sourceFile, content); } - }, this); - }; + } - /** - * A mapping can have one of the three levels of data: - * - * 1. Just the generated position. - * 2. The Generated position, original position, and original source. - * 3. Generated and original position, original source, as well as a name - * token. - * - * To maintain consistency, we validate that any new mapping being added falls - * in to one of these categories. - */ - SourceMapGenerator.prototype._validateMapping = - function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, - aName) { - if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aGenerated.line > 0 && aGenerated.column >= 0 - && !aOriginal && !aSource && !aName) { - // Case 1. - return; + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); } - else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aOriginal && 'line' in aOriginal && 'column' in aOriginal - && aGenerated.line > 0 && aGenerated.column >= 0 - && aOriginal.line > 0 && aOriginal.column >= 0 - && aSource) { - // Cases 2 and 3. - return; + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); } - else { - throw new Error('Invalid mapping: ' + JSON.stringify({ - generated: aGenerated, - source: aSource, - original: aOriginal, - name: aName - })); + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); } - }; + }, this); + }; + +/** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ +SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; - /** - * Serialize the accumulated mappings in to the stream of base 64 VLQs - * specified by the source map format. - */ - SourceMapGenerator.prototype._serializeMappings = - function SourceMapGenerator_serializeMappings() { - var previousGeneratedColumn = 0; - var previousGeneratedLine = 1; - var previousOriginalColumn = 0; - var previousOriginalLine = 0; - var previousName = 0; - var previousSource = 0; - var result = ''; - var mapping; - var nameIdx; - var sourceIdx; - - var mappings = this._mappings.toArray(); - for (var i = 0, len = mappings.length; i < len; i++) { - mapping = mappings[i]; - - if (mapping.generatedLine !== previousGeneratedLine) { - previousGeneratedColumn = 0; - while (mapping.generatedLine !== previousGeneratedLine) { - result += ';'; - previousGeneratedLine++; - } +/** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ +SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + var nameIdx; + var sourceIdx; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; } - else { - if (i > 0) { - if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { - continue; - } - result += ','; + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; } + result += ','; } + } - result += base64VLQ.encode(mapping.generatedColumn - - previousGeneratedColumn); - previousGeneratedColumn = mapping.generatedColumn; + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; - if (mapping.source != null) { - sourceIdx = this._sources.indexOf(mapping.source); - result += base64VLQ.encode(sourceIdx - previousSource); - previousSource = sourceIdx; + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + result += base64VLQ.encode(sourceIdx - previousSource); + previousSource = sourceIdx; - // lines are stored 0-based in SourceMap spec version 3 - result += base64VLQ.encode(mapping.originalLine - 1 - - previousOriginalLine); - previousOriginalLine = mapping.originalLine - 1; + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; - result += base64VLQ.encode(mapping.originalColumn - - previousOriginalColumn); - previousOriginalColumn = mapping.originalColumn; + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; - if (mapping.name != null) { - nameIdx = this._names.indexOf(mapping.name); - result += base64VLQ.encode(nameIdx - previousName); - previousName = nameIdx; - } + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + result += base64VLQ.encode(nameIdx - previousName); + previousName = nameIdx; } } + } - return result; - }; - - SourceMapGenerator.prototype._generateSourcesContent = - function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { - return aSources.map(function (source) { - if (!this._sourcesContents) { - return null; - } - if (aSourceRoot != null) { - source = util.relative(aSourceRoot, source); - } - var key = util.toSetString(source); - return Object.prototype.hasOwnProperty.call(this._sourcesContents, - key) - ? this._sourcesContents[key] - : null; - }, this); - }; + return result; + }; - /** - * Externalize the source map. - */ - SourceMapGenerator.prototype.toJSON = - function SourceMapGenerator_toJSON() { - var map = { - version: this._version, - sources: this._sources.toArray(), - names: this._names.toArray(), - mappings: this._serializeMappings() - }; - if (this._file != null) { - map.file = this._file; - } - if (this._sourceRoot != null) { - map.sourceRoot = this._sourceRoot; +SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; } - if (this._sourcesContents) { - map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); } - - return map; + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + +/** + * Externalize the source map. + */ +SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } - /** - * Render the source map being generated to a string. - */ - SourceMapGenerator.prototype.toString = - function SourceMapGenerator_toString() { - return JSON.stringify(this.toJSON()); - }; + return map; + }; - exports.SourceMapGenerator = SourceMapGenerator; +/** + * Render the source map being generated to a string. + */ +SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; -}); +exports.SourceMapGenerator = SourceMapGenerator; diff --git a/lib/source-map/source-node.js b/lib/source-map/source-node.js index 9ee90bd5..31288a32 100644 --- a/lib/source-map/source-node.js +++ b/lib/source-map/source-node.js @@ -4,349 +4,381 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; - var util = require('./util'); +var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; +var util = require('./util'); - // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other - // operating systems these days (capturing the result). - var REGEX_NEWLINE = /(\r?\n)/; +// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other +// operating systems these days (capturing the result). +var REGEX_NEWLINE = /(\r?\n)/; - // Newline character code for charCodeAt() comparisons - var NEWLINE_CODE = 10; +// Newline character code for charCodeAt() comparisons +var NEWLINE_CODE = 10; - // Private symbol for identifying `SourceNode`s when multiple versions of - // the source-map library are loaded. This MUST NOT CHANGE across - // versions! - var isSourceNode = "$$$isSourceNode$$$"; +// Private symbol for identifying `SourceNode`s when multiple versions of +// the source-map library are loaded. This MUST NOT CHANGE across +// versions! +var isSourceNode = "$$$isSourceNode$$$"; - /** - * SourceNodes provide a way to abstract over interpolating/concatenating - * snippets of generated JavaScript source code while maintaining the line and - * column information associated with the original source code. - * - * @param aLine The original line number. - * @param aColumn The original column number. - * @param aSource The original source's filename. - * @param aChunks Optional. An array of strings which are snippets of - * generated JS, or other SourceNodes. - * @param aName The original identifier. - */ - function SourceNode(aLine, aColumn, aSource, aChunks, aName) { - this.children = []; - this.sourceContents = {}; - this.line = aLine == null ? null : aLine; - this.column = aColumn == null ? null : aColumn; - this.source = aSource == null ? null : aSource; - this.name = aName == null ? null : aName; - this[isSourceNode] = true; - if (aChunks != null) this.add(aChunks); - } +/** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ +function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); +} - /** - * Creates a SourceNode from generated code and a SourceMapConsumer. - * - * @param aGeneratedCode The generated code - * @param aSourceMapConsumer The SourceMap for the generated code - * @param aRelativePath Optional. The path that relative sources in the - * SourceMapConsumer should be relative to. - */ - SourceNode.fromStringWithSourceMap = - function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { - // The SourceNode we want to fill with the generated code - // and the SourceMap - var node = new SourceNode(); +/** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ +SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); - // All even indices of this array are one line of the generated code, - // while all odd indices are the newlines between two adjacent lines - // (since `REGEX_NEWLINE` captures its match). - // Processed fragments are removed from this array, by calling `shiftNextLine`. - var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); - var shiftNextLine = function() { - var lineContents = remainingLines.shift(); - // The last line of a file might not have a newline. - var newLine = remainingLines.shift() || ""; - return lineContents + newLine; - }; + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are removed from this array, by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var shiftNextLine = function() { + var lineContents = remainingLines.shift(); + // The last line of a file might not have a newline. + var newLine = remainingLines.shift() || ""; + return lineContents + newLine; + }; - // We need to remember the position of "remainingLines" - var lastGeneratedLine = 1, lastGeneratedColumn = 0; + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; - // The generate SourceNodes we need a code range. - // To extract it current and last mapping is used. - // Here we store the last mapping. - var lastMapping = null; + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; - aSourceMapConsumer.eachMapping(function (mapping) { - if (lastMapping !== null) { - // We add the code from "lastMapping" to "mapping": - // First check if there is a new line in between. - if (lastGeneratedLine < mapping.generatedLine) { - var code = ""; - // Associate first line with "lastMapping" - addMappingWithCode(lastMapping, shiftNextLine()); - lastGeneratedLine++; - lastGeneratedColumn = 0; - // The remaining code is added without mapping - } else { - // There is no new line in between. - // Associate the code between "lastGeneratedColumn" and - // "mapping.generatedColumn" with "lastMapping" - var nextLine = remainingLines[0]; - var code = nextLine.substr(0, mapping.generatedColumn - - lastGeneratedColumn); - remainingLines[0] = nextLine.substr(mapping.generatedColumn - - lastGeneratedColumn); - lastGeneratedColumn = mapping.generatedColumn; - addMappingWithCode(lastMapping, code); - // No more remaining code, continue - lastMapping = mapping; - return; - } - } - // We add the generated code until the first mapping - // to the SourceNode without any mapping. - // Each line is added as separate string. - while (lastGeneratedLine < mapping.generatedLine) { - node.add(shiftNextLine()); + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); lastGeneratedLine++; - } - if (lastGeneratedColumn < mapping.generatedColumn) { + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" var nextLine = remainingLines[0]; - node.add(nextLine.substr(0, mapping.generatedColumn)); - remainingLines[0] = nextLine.substr(mapping.generatedColumn); + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; } - lastMapping = mapping; - }, this); - // We have processed all mappings. - if (remainingLines.length > 0) { - if (lastMapping) { - // Associate the remaining code in the current line with "lastMapping" - addMappingWithCode(lastMapping, shiftNextLine()); - } - // and add the remaining lines without any mapping - node.add(remainingLines.join("")); } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLines.length > 0) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.join("")); + } - // Copy sourcesContent into SourceNode - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - if (aRelativePath != null) { - sourceFile = util.join(aRelativePath, sourceFile); - } - node.setSourceContent(sourceFile, content); - } - }); - - return node; - - function addMappingWithCode(mapping, code) { - if (mapping === null || mapping.source === undefined) { - node.add(code); - } else { - var source = aRelativePath - ? util.join(aRelativePath, mapping.source) - : mapping.source; - node.add(new SourceNode(mapping.originalLine, - mapping.originalColumn, - source, - code, - mapping.name)); + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); } + node.setSourceContent(sourceFile, content); } - }; + }); - /** - * Add a chunk of generated JS to this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ - SourceNode.prototype.add = function SourceNode_add(aChunk) { - if (Array.isArray(aChunk)) { - aChunk.forEach(function (chunk) { - this.add(chunk); - }, this); - } - else if (aChunk[isSourceNode] || typeof aChunk === "string") { - if (aChunk) { - this.children.push(aChunk); + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); } } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); - } - return this; }; - /** - * Add a chunk of generated JS to the beginning of this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ - SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { - if (Array.isArray(aChunk)) { - for (var i = aChunk.length-1; i >= 0; i--) { - this.prepend(aChunk[i]); - } - } - else if (aChunk[isSourceNode] || typeof aChunk === "string") { - this.children.unshift(aChunk); +/** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ +SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; +}; + +/** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ +SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); } - return this; - }; + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; +}; - /** - * Walk over the tree of JS snippets in this node and its children. The - * walking function is called once for each snippet of JS and is passed that - * snippet and the its original associated source's line/column location. - * - * @param aFn The traversal function. - */ - SourceNode.prototype.walk = function SourceNode_walk(aFn) { - var chunk; - for (var i = 0, len = this.children.length; i < len; i++) { - chunk = this.children[i]; - if (chunk[isSourceNode]) { - chunk.walk(aFn); - } - else { - if (chunk !== '') { - aFn(chunk, { source: this.source, - line: this.line, - column: this.column, - name: this.name }); - } +/** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ +SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); } } - }; + } +}; - /** - * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between - * each of `this.children`. - * - * @param aSep The separator. - */ - SourceNode.prototype.join = function SourceNode_join(aSep) { - var newChildren; - var i; - var len = this.children.length; - if (len > 0) { - newChildren = []; - for (i = 0; i < len-1; i++) { - newChildren.push(this.children[i]); - newChildren.push(aSep); - } +/** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ +SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { newChildren.push(this.children[i]); - this.children = newChildren; + newChildren.push(aSep); } - return this; + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; +}; + +/** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ +SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; +}; + +/** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ +SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; }; - /** - * Call String.prototype.replace on the very right-most source snippet. Useful - * for trimming whitespace from the end of a source node, etc. - * - * @param aPattern The pattern to replace. - * @param aReplacement The thing to replace the pattern with. - */ - SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { - var lastChild = this.children[this.children.length - 1]; - if (lastChild[isSourceNode]) { - lastChild.replaceRight(aPattern, aReplacement); - } - else if (typeof lastChild === 'string') { - this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); +/** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ +SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } } - else { - this.children.push(''.replace(aPattern, aReplacement)); + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); } - return this; }; - /** - * Set the source content for a source file. This will be added to the SourceMapGenerator - * in the sourcesContent field. - * - * @param aSourceFile The filename of the source file - * @param aSourceContent The content of the source file - */ - SourceNode.prototype.setSourceContent = - function SourceNode_setSourceContent(aSourceFile, aSourceContent) { - this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; - }; - - /** - * Walk over the tree of SourceNodes. The walking function is called for each - * source file content and is passed the filename and source content. - * - * @param aFn The traversal function. - */ - SourceNode.prototype.walkSourceContents = - function SourceNode_walkSourceContents(aFn) { - for (var i = 0, len = this.children.length; i < len; i++) { - if (this.children[i][isSourceNode]) { - this.children[i].walkSourceContents(aFn); - } - } - - var sources = Object.keys(this.sourceContents); - for (var i = 0, len = sources.length; i < len; i++) { - aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); - } - }; +/** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ +SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; +}; - /** - * Return the string representation of this source node. Walks over the tree - * and concatenates all the various snippets together to one string. - */ - SourceNode.prototype.toString = function SourceNode_toString() { - var str = ""; - this.walk(function (chunk) { - str += chunk; - }); - return str; +/** + * Returns the string representation of this source node along with a source + * map. + */ +SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 }; - - /** - * Returns the string representation of this source node along with a source - * map. - */ - SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { - var generated = { - code: "", - line: 1, - column: 0 - }; - var map = new SourceMapGenerator(aArgs); - var sourceMappingActive = false; - var lastOriginalSource = null; - var lastOriginalLine = null; - var lastOriginalColumn = null; - var lastOriginalName = null; - this.walk(function (chunk, original) { - generated.code += chunk; - if (original.source !== null - && original.line !== null - && original.column !== null) { - if(lastOriginalSource !== original.source - || lastOriginalLine !== original.line - || lastOriginalColumn !== original.column - || lastOriginalName !== original.name) { + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { map.addMapping({ source: original.source, original: { @@ -360,55 +392,16 @@ define(function (require, exports, module) { name: original.name }); } - lastOriginalSource = original.source; - lastOriginalLine = original.line; - lastOriginalColumn = original.column; - lastOriginalName = original.name; - sourceMappingActive = true; - } else if (sourceMappingActive) { - map.addMapping({ - generated: { - line: generated.line, - column: generated.column - } - }); - lastOriginalSource = null; - sourceMappingActive = false; - } - for (var idx = 0, length = chunk.length; idx < length; idx++) { - if (chunk.charCodeAt(idx) === NEWLINE_CODE) { - generated.line++; - generated.column = 0; - // Mappings end at eol - if (idx + 1 === length) { - lastOriginalSource = null; - sourceMappingActive = false; - } else if (sourceMappingActive) { - map.addMapping({ - source: original.source, - original: { - line: original.line, - column: original.column - }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); - } - } else { - generated.column++; - } + } else { + generated.column++; } - }); - this.walkSourceContents(function (sourceFile, sourceContent) { - map.setSourceContent(sourceFile, sourceContent); - }); - - return { code: generated.code, map: map }; - }; + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); - exports.SourceNode = SourceNode; + return { code: generated.code, map: map }; +}; -}); +exports.SourceNode = SourceNode; diff --git a/lib/source-map/util.js b/lib/source-map/util.js index c16e70c3..4a59913d 100644 --- a/lib/source-map/util.js +++ b/lib/source-map/util.js @@ -4,371 +4,364 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - /** - * This is a helper function for getting values from parameter/options - * objects. - * - * @param args The object we are extracting values from - * @param name The name of the property we are getting. - * @param defaultValue An optional value to return if the property is missing - * from the object. If this is not specified and the property is missing, an - * error will be thrown. - */ - function getArg(aArgs, aName, aDefaultValue) { - if (aName in aArgs) { - return aArgs[aName]; - } else if (arguments.length === 3) { - return aDefaultValue; - } else { - throw new Error('"' + aName + '" is a required argument.'); - } +/** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ +function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); } - exports.getArg = getArg; +} +exports.getArg = getArg; - var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; - var dataUrlRegexp = /^data:.+\,.+$/; +var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; +var dataUrlRegexp = /^data:.+\,.+$/; - function urlParse(aUrl) { - var match = aUrl.match(urlRegexp); - if (!match) { - return null; - } - return { - scheme: match[1], - auth: match[2], - host: match[3], - port: match[4], - path: match[5] - }; - } - exports.urlParse = urlParse; - - function urlGenerate(aParsedUrl) { - var url = ''; - if (aParsedUrl.scheme) { - url += aParsedUrl.scheme + ':'; - } - url += '//'; - if (aParsedUrl.auth) { - url += aParsedUrl.auth + '@'; - } - if (aParsedUrl.host) { - url += aParsedUrl.host; - } - if (aParsedUrl.port) { - url += ":" + aParsedUrl.port - } - if (aParsedUrl.path) { - url += aParsedUrl.path; - } - return url; - } - exports.urlGenerate = urlGenerate; - - /** - * Normalizes a path, or the path portion of a URL: - * - * - Replaces consequtive slashes with one slash. - * - Removes unnecessary '.' parts. - * - Removes unnecessary '/..' parts. - * - * Based on code in the Node.js 'path' core module. - * - * @param aPath The path or url to normalize. - */ - function normalize(aPath) { - var path = aPath; - var url = urlParse(aPath); - if (url) { - if (!url.path) { - return aPath; - } - path = url.path; +function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; +} +exports.urlParse = urlParse; + +function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; +} +exports.urlGenerate = urlGenerate; + +/** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consequtive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ +function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; } - var isAbsolute = exports.isAbsolute(path); - - var parts = path.split(/\/+/); - for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { - part = parts[i]; - if (part === '.') { - parts.splice(i, 1); - } else if (part === '..') { - up++; - } else if (up > 0) { - if (part === '') { - // The first part is blank if the path is absolute. Trying to go - // above the root is a no-op. Therefore we can remove all '..' parts - // directly after the root. - parts.splice(i + 1, up); - up = 0; - } else { - parts.splice(i, 2); - up--; - } + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; } } - path = parts.join('/'); + } + path = parts.join('/'); - if (path === '') { - path = isAbsolute ? '/' : '.'; - } + if (path === '') { + path = isAbsolute ? '/' : '.'; + } - if (url) { - url.path = path; - return urlGenerate(url); - } - return path; - } - exports.normalize = normalize; - - /** - * Joins two paths/URLs. - * - * @param aRoot The root path or URL. - * @param aPath The path or URL to be joined with the root. - * - * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a - * scheme-relative URL: Then the scheme of aRoot, if any, is prepended - * first. - * - Otherwise aPath is a path. If aRoot is a URL, then its path portion - * is updated with the result and aRoot is returned. Otherwise the result - * is returned. - * - If aPath is absolute, the result is aPath. - * - Otherwise the two paths are joined with a slash. - * - Joining for example 'http://' and 'www.example.com' is also supported. - */ - function join(aRoot, aPath) { - if (aRoot === "") { - aRoot = "."; - } - if (aPath === "") { - aPath = "."; - } - var aPathUrl = urlParse(aPath); - var aRootUrl = urlParse(aRoot); - if (aRootUrl) { - aRoot = aRootUrl.path || '/'; - } + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; +} +exports.normalize = normalize; + +/** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ +function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } - // `join(foo, '//www.example.org')` - if (aPathUrl && !aPathUrl.scheme) { - if (aRootUrl) { - aPathUrl.scheme = aRootUrl.scheme; - } - return urlGenerate(aPathUrl); + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; } + return urlGenerate(aPathUrl); + } - if (aPathUrl || aPath.match(dataUrlRegexp)) { - return aPath; - } + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } - // `join('http://', 'www.example.com')` - if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { - aRootUrl.host = aPath; - return urlGenerate(aRootUrl); - } + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } - var joined = aPath.charAt(0) === '/' - ? aPath - : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); - if (aRootUrl) { - aRootUrl.path = joined; - return urlGenerate(aRootUrl); - } - return joined; + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); } - exports.join = join; - - exports.isAbsolute = function (aPath) { - return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); - }; + return joined; +} +exports.join = join; - /** - * Make a path relative to a URL or another path. - * - * @param aRoot The root path or URL. - * @param aPath The path or URL to be made relative to aRoot. - */ - function relative(aRoot, aPath) { - if (aRoot === "") { - aRoot = "."; - } +exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); +}; - aRoot = aRoot.replace(/\/$/, ''); - - // It is possible for the path to be above the root. In this case, simply - // checking whether the root is a prefix of the path won't work. Instead, we - // need to remove components from the root one by one, until either we find - // a prefix that fits, or we run out of components to remove. - var level = 0; - while (aPath.indexOf(aRoot + '/') !== 0) { - var index = aRoot.lastIndexOf("/"); - if (index < 0) { - return aPath; - } +/** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ +function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } - // If the only part of the root that is left is the scheme (i.e. http://, - // file:///, etc.), one or more slashes (/), or simply nothing at all, we - // have exhausted all components, so the path is not relative to the root. - aRoot = aRoot.slice(0, index); - if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { - return aPath; - } + aRoot = aRoot.replace(/\/$/, ''); - ++level; + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; } - // Make sure we add a "../" for each component we removed from the root. - return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); - } - exports.relative = relative; - - /** - * Because behavior goes wacky when you set `__proto__` on objects, we - * have to prefix all the strings in our set with an arbitrary character. - * - * See https://github.com/mozilla/source-map/pull/31 and - * https://github.com/mozilla/source-map/issues/30 - * - * @param String aStr - */ - function toSetString(aStr) { - return '$' + aStr; - } - exports.toSetString = toSetString; - - function fromSetString(aStr) { - return aStr.substr(1); - } - exports.fromSetString = fromSetString; - - /** - * Comparator between two mappings where the original positions are compared. - * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same original source/line/column, but different generated - * line and column the same. Useful when searching for a mapping with a - * stubbed out mapping. - */ - function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { - var cmp = mappingA.source - mappingB.source; - if (cmp !== 0) { - return cmp; + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; } - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } + ++level; + } - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0 || onlyCompareOriginal) { - return cmp; - } + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); +} +exports.relative = relative; + +/** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ +function toSetString(aStr) { + return '$' + aStr; +} +exports.toSetString = toSetString; - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0) { - return cmp; - } +function fromSetString(aStr) { + return aStr.substr(1); +} +exports.fromSetString = fromSetString; + +/** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ +function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } - cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } - return mappingA.name - mappingB.name; - } - exports.compareByOriginalPositions = compareByOriginalPositions; - - /** - * Comparator between two mappings with deflated source and name indices where - * the generated positions are compared. - * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same generated line and column, but different - * source/name/original line and column the same. Useful when searching for a - * mapping with a stubbed out mapping. - */ - function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { - var cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0 || onlyCompareGenerated) { - return cmp; - } + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } - cmp = mappingA.source - mappingB.source; - if (cmp !== 0) { - return cmp; - } + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } + return mappingA.name - mappingB.name; +} +exports.compareByOriginalPositions = compareByOriginalPositions; + +/** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ +function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0) { - return cmp; - } + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } - return mappingA.name - mappingB.name; + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; } - exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; - function strcmp(aStr1, aStr2) { - if (aStr1 === aStr2) { - return 0; - } + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } - if (aStr1 > aStr2) { - return 1; - } + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; +} +exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; - return -1; +function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; } - /** - * Comparator between two mappings with inflated source and name strings where - * the generated positions are compared. - */ - function compareByGeneratedPositionsInflated(mappingA, mappingB) { - var cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } + if (aStr1 > aStr2) { + return 1; + } - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0) { - return cmp; - } + return -1; +} - cmp = strcmp(mappingA.source, mappingB.source); - if (cmp !== 0) { - return cmp; - } +/** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ +function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0) { - return cmp; - } + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } - return strcmp(mappingA.name, mappingB.name); + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; } - exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; -}); + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); +} +exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; diff --git a/package.json b/package.json index 4962ab02..3347403e 100644 --- a/package.json +++ b/package.json @@ -55,9 +55,6 @@ "node": ">=0.8.0" }, "license": "BSD-3-Clause", - "dependencies": { - "amdefine": ">=0.0.4" - }, "devDependencies": { "dryice": ">=0.4.8" }, diff --git a/test/source-map/test-api.js b/test/source-map/test-api.js index de89d420..0783dda4 100644 --- a/test/source-map/test-api.js +++ b/test/source-map/test-api.js @@ -4,23 +4,16 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); +var sourceMap; +try { + sourceMap = require('../../lib/source-map'); +} catch (e) { + var loader = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {}); + sourceMap = loader.devtools.require("devtools/toolkit/sourcemap/source-map"); } -define(function (require, exports, module) { - var sourceMap; - try { - sourceMap = require('../../lib/source-map'); - } catch (e) { - var loader = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {}); - sourceMap = loader.devtools.require("devtools/toolkit/sourcemap/source-map"); - } - - exports['test that the api is properly exposed in the top level'] = function (assert, util) { - assert.equal(typeof sourceMap.SourceMapGenerator, "function"); - assert.equal(typeof sourceMap.SourceMapConsumer, "function"); - assert.equal(typeof sourceMap.SourceNode, "function"); - }; - -}); +exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); +}; diff --git a/test/source-map/test-array-set.js b/test/source-map/test-array-set.js index b513db93..769dc552 100644 --- a/test/source-map/test-array-set.js +++ b/test/source-map/test-array-set.js @@ -4,139 +4,132 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); +var ArraySet = require('../../lib/source-map/array-set').ArraySet; + +function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; } -define(function (require, exports, module) { - var ArraySet = require('../../lib/source-map/array-set').ArraySet; +exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } +}; - function makeTestSet() { - var set = new ArraySet(); - for (var i = 0; i < 100; i++) { - set.add(String(i)); - } - return set; +exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); } +}; - exports['test .has() membership'] = function (assert, util) { - var set = makeTestSet(); - for (var i = 0; i < 100; i++) { - assert.ok(set.has(String(i))); - } - }; - - exports['test .indexOf() elements'] = function (assert, util) { - var set = makeTestSet(); - for (var i = 0; i < 100; i++) { - assert.strictEqual(set.indexOf(String(i)), i); - } - }; - - exports['test .at() indexing'] = function (assert, util) { - var set = makeTestSet(); - for (var i = 0; i < 100; i++) { - assert.strictEqual(set.at(i), String(i)); - } - }; - - exports['test creating from an array'] = function (assert, util) { - var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); - - assert.ok(set.has('foo')); - assert.ok(set.has('bar')); - assert.ok(set.has('baz')); - assert.ok(set.has('quux')); - assert.ok(set.has('hasOwnProperty')); - - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.indexOf('bar'), 1); - assert.strictEqual(set.indexOf('baz'), 2); - assert.strictEqual(set.indexOf('quux'), 3); - - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.at(1), 'bar'); - assert.strictEqual(set.at(2), 'baz'); - assert.strictEqual(set.at(3), 'quux'); - }; - - exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { - var set = new ArraySet(); - set.add('__proto__'); - assert.ok(set.has('__proto__')); - assert.strictEqual(set.at(0), '__proto__'); - assert.strictEqual(set.indexOf('__proto__'), 0); - }; - - exports['test .fromArray() with duplicates'] = function (assert, util) { - var set = ArraySet.fromArray(['foo', 'foo']); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 1); - - set = ArraySet.fromArray(['foo', 'foo'], true); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.at(1), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 2); - }; - - exports['test .add() with duplicates'] = function (assert, util) { - var set = new ArraySet(); - set.add('foo'); - - set.add('foo'); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 1); - - set.add('foo', true); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.at(1), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 2); - }; - - exports['test .size()'] = function (assert, util) { - var set = new ArraySet(); - set.add('foo'); - set.add('bar'); - set.add('baz'); - assert.strictEqual(set.size(), 3); - }; - - exports['test .size() with disallowed duplicates'] = function (assert, util) { - var set = new ArraySet(); - - set.add('foo'); - set.add('foo'); - - set.add('bar'); - set.add('bar'); - - set.add('baz'); - set.add('baz'); - - assert.strictEqual(set.size(), 3); - }; - - exports['test .size() with allowed duplicates'] = function (assert, util) { - var set = new ArraySet(); - - set.add('foo'); - set.add('foo', true); - - set.add('bar'); - set.add('bar', true); - - set.add('baz'); - set.add('baz', true); - - assert.strictEqual(set.size(), 3); - }; - -}); +exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } +}; + +exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); +}; + +exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); +}; + +exports['test .fromArray() with duplicates'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'foo']); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set = ArraySet.fromArray(['foo', 'foo'], true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); +}; + +exports['test .add() with duplicates'] = function (assert, util) { + var set = new ArraySet(); + set.add('foo'); + + set.add('foo'); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set.add('foo', true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); +}; + +exports['test .size()'] = function (assert, util) { + var set = new ArraySet(); + set.add('foo'); + set.add('bar'); + set.add('baz'); + assert.strictEqual(set.size(), 3); +}; + +exports['test .size() with disallowed duplicates'] = function (assert, util) { + var set = new ArraySet(); + + set.add('foo'); + set.add('foo'); + + set.add('bar'); + set.add('bar'); + + set.add('baz'); + set.add('baz'); + + assert.strictEqual(set.size(), 3); +}; + +exports['test .size() with allowed duplicates'] = function (assert, util) { + var set = new ArraySet(); + + set.add('foo'); + set.add('foo', true); + + set.add('bar'); + set.add('bar', true); + + set.add('baz'); + set.add('baz', true); + + assert.strictEqual(set.size(), 3); +}; diff --git a/test/source-map/test-base64-vlq.js b/test/source-map/test-base64-vlq.js index e7b3749b..d976df62 100644 --- a/test/source-map/test-base64-vlq.js +++ b/test/source-map/test-base64-vlq.js @@ -4,21 +4,14 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { +var base64VLQ = require('../../lib/source-map/base64-vlq'); - var base64VLQ = require('../../lib/source-map/base64-vlq'); - - exports['test normal encoding and decoding'] = function (assert, util) { - var result = {}; - for (var i = -255; i < 256; i++) { - var str = base64VLQ.encode(i); - base64VLQ.decode(str, 0, result); - assert.equal(result.value, i); - assert.equal(result.rest, str.length); - } - }; - -}); +exports['test normal encoding and decoding'] = function (assert, util) { + var result = {}; + for (var i = -255; i < 256; i++) { + var str = base64VLQ.encode(i); + base64VLQ.decode(str, 0, result); + assert.equal(result.value, i); + assert.equal(result.rest, str.length); + } +}; diff --git a/test/source-map/test-base64.js b/test/source-map/test-base64.js index 6ade961e..9017b026 100644 --- a/test/source-map/test-base64.js +++ b/test/source-map/test-base64.js @@ -4,30 +4,23 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { +var base64 = require('../../lib/source-map/base64'); - var base64 = require('../../lib/source-map/base64'); +exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); +}; - exports['test out of range encoding'] = function (assert, util) { - assert.throws(function () { - base64.encode(-1); - }); - assert.throws(function () { - base64.encode(64); - }); - }; +exports['test out of range decoding'] = function (assert, util) { + assert.equal(base64.decode('='.charCodeAt(0)), -1); +}; - exports['test out of range decoding'] = function (assert, util) { - assert.equal(base64.decode('='.charCodeAt(0)), -1); - }; - - exports['test normal encoding and decoding'] = function (assert, util) { - for (var i = 0; i < 64; i++) { - assert.equal(base64.decode(base64.encode(i).charCodeAt(0)), i); - } - }; - -}); +exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i).charCodeAt(0)), i); + } +}; diff --git a/test/source-map/test-binary-search.js b/test/source-map/test-binary-search.js index 807fadef..5a12c9cd 100644 --- a/test/source-map/test-binary-search.js +++ b/test/source-map/test-binary-search.js @@ -4,99 +4,92 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var binarySearch = require('../../lib/source-map/binary-search'); +var binarySearch = require('../../lib/source-map/binary-search'); - function numberCompare(a, b) { - return a - b; - } - - exports['test too high with default (glb) bias'] = function (assert, util) { - var needle = 30; - var haystack = [2,4,6,8,10,12,14,16,18,20]; +function numberCompare(a, b) { + return a - b; +} - assert.doesNotThrow(function () { - binarySearch.search(needle, haystack, numberCompare); - }); +exports['test too high with default (glb) bias'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 20); - }; + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); - exports['test too low with default (glb) bias'] = function (assert, util) { - var needle = 1; - var haystack = [2,4,6,8,10,12,14,16,18,20]; + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 20); +}; - assert.doesNotThrow(function () { - binarySearch.search(needle, haystack, numberCompare); - }); +exports['test too low with default (glb) bias'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - assert.equal(binarySearch.search(needle, haystack, numberCompare), -1); - }; + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); - exports['test too high with lub bias'] = function (assert, util) { - var needle = 30; - var haystack = [2,4,6,8,10,12,14,16,18,20]; + assert.equal(binarySearch.search(needle, haystack, numberCompare), -1); +}; - assert.doesNotThrow(function () { - binarySearch.search(needle, haystack, numberCompare); - }); +exports['test too high with lub bias'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - assert.equal(binarySearch.search(needle, haystack, numberCompare, - binarySearch.LEAST_UPPER_BOUND), -1); - }; + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); - exports['test too low with lub bias'] = function (assert, util) { - var needle = 1; - var haystack = [2,4,6,8,10,12,14,16,18,20]; + assert.equal(binarySearch.search(needle, haystack, numberCompare, + binarySearch.LEAST_UPPER_BOUND), -1); +}; - assert.doesNotThrow(function () { - binarySearch.search(needle, haystack, numberCompare); - }); +exports['test too low with lub bias'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare, - binarySearch.LEAST_UPPER_BOUND)], 2); - }; + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); - exports['test exact search'] = function (assert, util) { - var needle = 4; - var haystack = [2,4,6,8,10,12,14,16,18,20]; + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare, + binarySearch.LEAST_UPPER_BOUND)], 2); +}; - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 4); - }; +exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - exports['test fuzzy search with default (glb) bias'] = function (assert, util) { - var needle = 19; - var haystack = [2,4,6,8,10,12,14,16,18,20]; + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 4); +}; - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 18); - }; +exports['test fuzzy search with default (glb) bias'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - exports['test fuzzy search with lub bias'] = function (assert, util) { - var needle = 19; - var haystack = [2,4,6,8,10,12,14,16,18,20]; + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 18); +}; - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare, - binarySearch.LEAST_UPPER_BOUND)], 20); - }; +exports['test fuzzy search with lub bias'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; - exports['test multiple matches'] = function (assert, util) { - var needle = 5; - var haystack = [1, 1, 2, 5, 5, 5, 13, 21]; + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare, + binarySearch.LEAST_UPPER_BOUND)], 20); +}; - assert.equal(binarySearch.search(needle, haystack, numberCompare, - binarySearch.LEAST_UPPER_BOUND), 3); - }; +exports['test multiple matches'] = function (assert, util) { + var needle = 5; + var haystack = [1, 1, 2, 5, 5, 5, 13, 21]; - exports['test multiple matches at the beginning'] = function (assert, util) { - var needle = 1; - var haystack = [1, 1, 2, 5, 5, 5, 13, 21]; + assert.equal(binarySearch.search(needle, haystack, numberCompare, + binarySearch.LEAST_UPPER_BOUND), 3); +}; - assert.equal(binarySearch.search(needle, haystack, numberCompare, - binarySearch.LEAST_UPPER_BOUND), 0); - }; +exports['test multiple matches at the beginning'] = function (assert, util) { + var needle = 1; + var haystack = [1, 1, 2, 5, 5, 5, 13, 21]; -}); + assert.equal(binarySearch.search(needle, haystack, numberCompare, + binarySearch.LEAST_UPPER_BOUND), 0); +}; diff --git a/test/source-map/test-dog-fooding.js b/test/source-map/test-dog-fooding.js index 1168ea52..1497de9e 100644 --- a/test/source-map/test-dog-fooding.js +++ b/test/source-map/test-dog-fooding.js @@ -4,102 +4,95 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { +var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; +var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; +exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); - exports['test eating our own dog food'] = function (assert, util) { - var smg = new SourceMapGenerator({ - file: 'testing.js', - sourceRoot: '/wu/tang' - }); + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); - smg.addMapping({ - source: 'gza.coffee', - original: { line: 1, column: 0 }, - generated: { line: 2, column: 2 } - }); + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); - smg.addMapping({ - source: 'gza.coffee', - original: { line: 2, column: 0 }, - generated: { line: 3, column: 2 } - }); + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); - smg.addMapping({ - source: 'gza.coffee', - original: { line: 3, column: 0 }, - generated: { line: 4, column: 2 } - }); + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); - smg.addMapping({ - source: 'gza.coffee', - original: { line: 4, column: 0 }, - generated: { line: 5, column: 2 } - }); + smg.addMapping({ + source: 'gza.coffee', + original: { line: 5, column: 10 }, + generated: { line: 6, column: 12 } + }); - smg.addMapping({ - source: 'gza.coffee', - original: { line: 5, column: 10 }, - generated: { line: 6, column: 12 } - }); + var smc = new SourceMapConsumer(smg.toString()); - var smc = new SourceMapConsumer(smg.toString()); + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, null, smc, assert); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 10, null, null, smc, assert); - // Exact - util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, null, smc, assert); - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, null, smc, assert); - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, null, smc, assert); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, null, smc, assert); - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 10, null, null, smc, assert); + // Fuzzy - // Fuzzy + // Generated to original with default (glb) bias. + util.assertMapping(2, 0, null, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, null, smc, assert, true); + util.assertMapping(3, 0, null, null, null, null, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, null, smc, assert, true); + util.assertMapping(4, 0, null, null, null, null, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, null, smc, assert, true); + util.assertMapping(5, 0, null, null, null, null, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, null, smc, assert, true); + util.assertMapping(6, 0, null, null, null, null, null, smc, assert, true); + util.assertMapping(6, 9, null, null, null, null, null, smc, assert, true); + util.assertMapping(6, 13, '/wu/tang/gza.coffee', 5, 10, null, null, smc, assert, true); - // Generated to original with default (glb) bias. - util.assertMapping(2, 0, null, null, null, null, null, smc, assert, true); - util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, null, smc, assert, true); - util.assertMapping(3, 0, null, null, null, null, null, smc, assert, true); - util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, null, smc, assert, true); - util.assertMapping(4, 0, null, null, null, null, null, smc, assert, true); - util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, null, smc, assert, true); - util.assertMapping(5, 0, null, null, null, null, null, smc, assert, true); - util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, null, smc, assert, true); - util.assertMapping(6, 0, null, null, null, null, null, smc, assert, true); - util.assertMapping(6, 9, null, null, null, null, null, smc, assert, true); - util.assertMapping(6, 13, '/wu/tang/gza.coffee', 5, 10, null, null, smc, assert, true); + // Generated to original with lub bias. + util.assertMapping(2, 0, '/wu/tang/gza.coffee', 1, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(2, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(3, 0, '/wu/tang/gza.coffee', 2, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(3, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(4, 0, '/wu/tang/gza.coffee', 3, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(4, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(5, 0, '/wu/tang/gza.coffee', 4, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(5, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(6, 0, '/wu/tang/gza.coffee', 5, 10, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(6, 9, '/wu/tang/gza.coffee', 5, 10, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + util.assertMapping(6, 13, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - // Generated to original with lub bias. - util.assertMapping(2, 0, '/wu/tang/gza.coffee', 1, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(2, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(3, 0, '/wu/tang/gza.coffee', 2, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(3, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(4, 0, '/wu/tang/gza.coffee', 3, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(4, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(5, 0, '/wu/tang/gza.coffee', 4, 0, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(5, 9, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(6, 0, '/wu/tang/gza.coffee', 5, 10, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(6, 9, '/wu/tang/gza.coffee', 5, 10, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); - util.assertMapping(6, 13, null, null, null, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, true); + // Original to generated with default (glb) bias + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 5, 9, null, null, smc, assert, null, true); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 6, 19, null, null, smc, assert, null, true); - // Original to generated with default (glb) bias - util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, null, smc, assert, null, true); - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, null, smc, assert, null, true); - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, null, smc, assert, null, true); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, null, smc, assert, null, true); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 5, 9, null, null, smc, assert, null, true); - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 6, 19, null, null, smc, assert, null, true); - - // Original to generated with lub bias. - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 1, 1, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 2, 3, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 3, 6, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 4, 9, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 9, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); - util.assertMapping(null, null, '/wu/tang/gza.coffee', 6, 19, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); - }; - -}); + // Original to generated with lub bias. + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 1, 1, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 2, 3, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 3, 6, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 4, 9, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 9, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); + util.assertMapping(null, null, '/wu/tang/gza.coffee', 6, 19, null, SourceMapConsumer.LEAST_UPPER_BOUND, smc, assert, null, true); +}; diff --git a/test/source-map/test-quick-sort.js b/test/source-map/test-quick-sort.js index 44587d74..340fb9a5 100644 --- a/test/source-map/test-quick-sort.js +++ b/test/source-map/test-quick-sort.js @@ -4,48 +4,41 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var quickSort = require('../../lib/source-map/quick-sort').quickSort; - - function numberCompare(a, b) { - return a - b; - } +var quickSort = require('../../lib/source-map/quick-sort').quickSort; - exports['test sorting sorted array'] = function (assert, util) { - var ary = [0,1,2,3,4,5,6,7,8,9]; +function numberCompare(a, b) { + return a - b; +} - var quickSorted = ary.slice(); - quickSort(quickSorted, numberCompare); +exports['test sorting sorted array'] = function (assert, util) { + var ary = [0,1,2,3,4,5,6,7,8,9]; - assert.equal(JSON.stringify(ary), - JSON.stringify(quickSorted)); - }; + var quickSorted = ary.slice(); + quickSort(quickSorted, numberCompare); - exports['test sorting reverse-sorted array'] = function (assert, util) { - var ary = [9,8,7,6,5,4,3,2,1,0]; + assert.equal(JSON.stringify(ary), + JSON.stringify(quickSorted)); +}; - var quickSorted = ary.slice(); - quickSort(quickSorted, numberCompare); +exports['test sorting reverse-sorted array'] = function (assert, util) { + var ary = [9,8,7,6,5,4,3,2,1,0]; - assert.equal(JSON.stringify(ary.sort(numberCompare)), - JSON.stringify(quickSorted)); - }; + var quickSorted = ary.slice(); + quickSort(quickSorted, numberCompare); - exports['test sorting unsorted array'] = function (assert, util) { - var ary = []; - for (var i = 0; i < 10; i++) { - ary.push(Math.random()); - } + assert.equal(JSON.stringify(ary.sort(numberCompare)), + JSON.stringify(quickSorted)); +}; - var quickSorted = ary.slice(); - quickSort(quickSorted, numberCompare); +exports['test sorting unsorted array'] = function (assert, util) { + var ary = []; + for (var i = 0; i < 10; i++) { + ary.push(Math.random()); + } - assert.equal(JSON.stringify(ary.sort(numberCompare)), - JSON.stringify(quickSorted)); - }; + var quickSorted = ary.slice(); + quickSort(quickSorted, numberCompare); -}); + assert.equal(JSON.stringify(ary.sort(numberCompare)), + JSON.stringify(quickSorted)); +}; diff --git a/test/source-map/test-source-map-consumer.js b/test/source-map/test-source-map-consumer.js index 9a39197b..d9730432 100644 --- a/test/source-map/test-source-map-consumer.js +++ b/test/source-map/test-source-map-consumer.js @@ -4,1122 +4,1115 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); +var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; +var IndexedSourceMapConsumer = require('../../lib/source-map/source-map-consumer').IndexedSourceMapConsumer; +var BasicSourceMapConsumer = require('../../lib/source-map/source-map-consumer').BasicSourceMapConsumer; +var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + +exports['test that we can instantiate with a string or an object'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); +}; + +exports['test that the object returned from new SourceMapConsumer inherits from SourceMapConsumer'] = function (assert, util) { + assert.ok(new SourceMapConsumer(util.testMap) instanceof SourceMapConsumer); } -define(function (require, exports, module) { - - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var IndexedSourceMapConsumer = require('../../lib/source-map/source-map-consumer').IndexedSourceMapConsumer; - var BasicSourceMapConsumer = require('../../lib/source-map/source-map-consumer').BasicSourceMapConsumer; - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - - exports['test that we can instantiate with a string or an object'] = function (assert, util) { - assert.doesNotThrow(function () { - var map = new SourceMapConsumer(util.testMap); - }); - assert.doesNotThrow(function () { - var map = new SourceMapConsumer(JSON.stringify(util.testMap)); - }); - }; - exports['test that the object returned from new SourceMapConsumer inherits from SourceMapConsumer'] = function (assert, util) { - assert.ok(new SourceMapConsumer(util.testMap) instanceof SourceMapConsumer); - } +exports['test that a BasicSourceMapConsumer is returned for sourcemaps without sections'] = function(assert, util) { + assert.ok(new SourceMapConsumer(util.testMap) instanceof BasicSourceMapConsumer); +}; - exports['test that a BasicSourceMapConsumer is returned for sourcemaps without sections'] = function(assert, util) { - assert.ok(new SourceMapConsumer(util.testMap) instanceof BasicSourceMapConsumer); - }; +exports['test that an IndexedSourceMapConsumer is returned for sourcemaps with sections'] = function(assert, util) { + assert.ok(new SourceMapConsumer(util.indexedTestMap) instanceof IndexedSourceMapConsumer); +}; - exports['test that an IndexedSourceMapConsumer is returned for sourcemaps with sections'] = function(assert, util) { - assert.ok(new SourceMapConsumer(util.indexedTestMap) instanceof IndexedSourceMapConsumer); - }; +exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map; + var sources; + + map = new SourceMapConsumer(util.testMap); + sources = map.sources; + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.indexedTestMap); + sources = map.sources; + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.indexedTestMapDifferentSourceRoots); + sources = map.sources; + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/different/root/two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + sources = map.sources; + assert.equal(sources[0], 'one.js'); + assert.equal(sources[1], 'two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + sources = map.sources; + assert.equal(sources[0], 'one.js'); + assert.equal(sources[1], 'two.js'); + assert.equal(sources.length, 2); +}; - exports['test that the `sources` field has the original sources'] = function (assert, util) { - var map; - var sources; - - map = new SourceMapConsumer(util.testMap); - sources = map.sources; - assert.equal(sources[0], '/the/root/one.js'); - assert.equal(sources[1], '/the/root/two.js'); - assert.equal(sources.length, 2); - - map = new SourceMapConsumer(util.indexedTestMap); - sources = map.sources; - assert.equal(sources[0], '/the/root/one.js'); - assert.equal(sources[1], '/the/root/two.js'); - assert.equal(sources.length, 2); - - map = new SourceMapConsumer(util.indexedTestMapDifferentSourceRoots); - sources = map.sources; - assert.equal(sources[0], '/the/root/one.js'); - assert.equal(sources[1], '/different/root/two.js'); - assert.equal(sources.length, 2); - - map = new SourceMapConsumer(util.testMapNoSourceRoot); - sources = map.sources; - assert.equal(sources[0], 'one.js'); - assert.equal(sources[1], 'two.js'); - assert.equal(sources.length, 2); - - map = new SourceMapConsumer(util.testMapEmptySourceRoot); - sources = map.sources; - assert.equal(sources[0], 'one.js'); - assert.equal(sources[1], 'two.js'); - assert.equal(sources.length, 2); - }; +exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map; + var mapping; - exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { - var map; - var mapping; + map = new SourceMapConsumer(util.testMap); - map = new SourceMapConsumer(util.testMap); + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); - mapping = map.originalPositionFor({ - line: 2, - column: 1 - }); - assert.equal(mapping.source, '/the/root/two.js'); + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); - mapping = map.originalPositionFor({ - line: 1, - column: 1 - }); - assert.equal(mapping.source, '/the/root/one.js'); + map = new SourceMapConsumer(util.testMapNoSourceRoot); - map = new SourceMapConsumer(util.testMapNoSourceRoot); + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, 'two.js'); - mapping = map.originalPositionFor({ - line: 2, - column: 1 - }); - assert.equal(mapping.source, 'two.js'); + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, 'one.js'); - mapping = map.originalPositionFor({ - line: 1, - column: 1 - }); - assert.equal(mapping.source, 'one.js'); + map = new SourceMapConsumer(util.testMapEmptySourceRoot); - map = new SourceMapConsumer(util.testMapEmptySourceRoot); + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, 'two.js'); - mapping = map.originalPositionFor({ - line: 2, - column: 1 - }); - assert.equal(mapping.source, 'two.js'); + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, 'one.js'); +}; - mapping = map.originalPositionFor({ - line: 1, - column: 1 - }); - assert.equal(mapping.source, 'one.js'); - }; +exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', null, map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', null, map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', null, map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', null, map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', null, map, assert); +}; - exports['test mapping tokens back exactly'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); +exports['test mapping tokens back exactly in indexed source map'] = function (assert, util) { + var map = new SourceMapConsumer(util.indexedTestMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', null, map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', null, map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', null, map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', null, map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', null, map, assert); +}; - util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, null, map, assert); - util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, null, map, assert); - util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, null, map, assert); - util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', null, map, assert); - util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, null, map, assert); - util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', null, map, assert); - util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', null, map, assert); - - util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, null, map, assert); - util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, null, map, assert); - util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, null, map, assert); - util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', null, map, assert); - util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, null, map, assert); - util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', null, map, assert); - }; - exports['test mapping tokens back exactly in indexed source map'] = function (assert, util) { - var map = new SourceMapConsumer(util.indexedTestMap); - - util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, null, map, assert); - util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, null, map, assert); - util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, null, map, assert); - util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', null, map, assert); - util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, null, map, assert); - util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', null, map, assert); - util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', null, map, assert); - - util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, null, map, assert); - util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, null, map, assert); - util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, null, map, assert); - util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', null, map, assert); - util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, null, map, assert); - util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', null, map, assert); - }; +exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', null, map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', null, map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', null, map, assert); - exports['test mapping tokens back exactly'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', null, map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', null, map, assert); +}; - util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, null, map, assert); - util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, null, map, assert); - util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, null, map, assert); - util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', null, map, assert); - util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, null, map, assert); - util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', null, map, assert); - util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', null, map, assert); - - util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, null, map, assert); - util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, null, map, assert); - util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, null, map, assert); - util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', null, map, assert); - util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, null, map, assert); - util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', null, map, assert); - }; +exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); - exports['test mapping tokens fuzzy'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); + // Finding original positions with default (glb) bias. + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', null, map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', null, map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, null, map, assert, true); - // Finding original positions with default (glb) bias. - util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', null, map, assert, true); - util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', null, map, assert, true); - util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, null, map, assert, true); - - // Finding original positions with lub bias. - util.assertMapping(1, 16, '/the/root/one.js', 1, 21, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - util.assertMapping(1, 26, '/the/root/one.js', 2, 10, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - util.assertMapping(2, 6, '/the/root/two.js', 1, 11, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - - // Finding generated positions with default (glb) bias. - util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', null, map, assert, null, true); - util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', null, map, assert, null, true); - util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, null, map, assert, null, true); - - // Finding generated positions with lub bias. - util.assertMapping(1, 18, '/the/root/one.js', 1, 20, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - util.assertMapping(1, 28, '/the/root/one.js', 2, 7, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - util.assertMapping(2, 9, '/the/root/two.js', 1, 6, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - }; + // Finding original positions with lub bias. + util.assertMapping(1, 16, '/the/root/one.js', 1, 21, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); + util.assertMapping(1, 26, '/the/root/one.js', 2, 10, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); + util.assertMapping(2, 6, '/the/root/two.js', 1, 11, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - exports['test mapping tokens fuzzy in indexed source map'] = function (assert, util) { - var map = new SourceMapConsumer(util.indexedTestMap); + // Finding generated positions with default (glb) bias. + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', null, map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', null, map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, null, map, assert, null, true); - // Finding original positions with default (glb) bias. - util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', null, map, assert, true); - util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', null, map, assert, true); - util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, null, map, assert, true); + // Finding generated positions with lub bias. + util.assertMapping(1, 18, '/the/root/one.js', 1, 20, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 7, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 6, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); +}; - // Finding original positions with lub bias. - util.assertMapping(1, 16, '/the/root/one.js', 1, 21, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - util.assertMapping(1, 26, '/the/root/one.js', 2, 10, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - util.assertMapping(2, 6, '/the/root/two.js', 1, 11, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); +exports['test mapping tokens fuzzy in indexed source map'] = function (assert, util) { + var map = new SourceMapConsumer(util.indexedTestMap); - // Finding generated positions with default (glb) bias. - util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', null, map, assert, null, true); - util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', null, map, assert, null, true); - util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, null, map, assert, null, true); + // Finding original positions with default (glb) bias. + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', null, map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', null, map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, null, map, assert, true); - // Finding generated positions with lub bias. - util.assertMapping(1, 18, '/the/root/one.js', 1, 20, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - util.assertMapping(1, 28, '/the/root/one.js', 2, 7, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - util.assertMapping(2, 9, '/the/root/two.js', 1, 6, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - }; + // Finding original positions with lub bias. + util.assertMapping(1, 16, '/the/root/one.js', 1, 21, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); + util.assertMapping(1, 26, '/the/root/one.js', 2, 10, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); + util.assertMapping(2, 6, '/the/root/two.js', 1, 11, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, true); - exports['test mappings and end of lines'] = function (assert, util) { - var smg = new SourceMapGenerator({ - file: 'foo.js' - }); - smg.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 1 }, - source: 'bar.js' - }); - smg.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 2, column: 2 }, - source: 'bar.js' - }); - smg.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 1 }, - source: 'baz.js' - }); - - var map = SourceMapConsumer.fromSourceMap(smg); - - // When finding original positions, mappings end at the end of the line. - util.assertMapping(2, 1, null, null, null, null, null, map, assert, true) - - // When finding generated positions, mappings do not end at the end of the line. - util.assertMapping(1, 1, 'bar.js', 2, 1, null, null, map, assert, null, true); - - // When finding generated positions with, mappings end at the end of the source. - util.assertMapping(null, null, 'bar.js', 3, 1, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); - }; + // Finding generated positions with default (glb) bias. + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', null, map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', null, map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, null, map, assert, null, true); - exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { - assert.doesNotThrow(function () { - var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); - }); - }; + // Finding generated positions with lub bias. + util.assertMapping(1, 18, '/the/root/one.js', 1, 20, 'bar', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 7, 'baz', SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 6, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); +}; - exports['test eachMapping'] = function (assert, util) { - var map; +exports['test mappings and end of lines'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'baz.js' + }); + + var map = SourceMapConsumer.fromSourceMap(smg); + + // When finding original positions, mappings end at the end of the line. + util.assertMapping(2, 1, null, null, null, null, null, map, assert, true) + + // When finding generated positions, mappings do not end at the end of the line. + util.assertMapping(1, 1, 'bar.js', 2, 1, null, null, map, assert, null, true); + + // When finding generated positions with, mappings end at the end of the source. + util.assertMapping(null, null, 'bar.js', 3, 1, null, SourceMapConsumer.LEAST_UPPER_BOUND, map, assert, null, true); +}; - map = new SourceMapConsumer(util.testMap); - var previousLine = -Infinity; - var previousColumn = -Infinity; - map.eachMapping(function (mapping) { - assert.ok(mapping.generatedLine >= previousLine); +exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); +}; - assert.ok(mapping.source === '/the/root/one.js' || mapping.source === '/the/root/two.js'); +exports['test eachMapping'] = function (assert, util) { + var map; - if (mapping.generatedLine === previousLine) { - assert.ok(mapping.generatedColumn >= previousColumn); - previousColumn = mapping.generatedColumn; - } - else { - previousLine = mapping.generatedLine; - previousColumn = -Infinity; - } - }); + map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); - map = new SourceMapConsumer(util.testMapNoSourceRoot); - map.eachMapping(function (mapping) { - assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); - }); + assert.ok(mapping.source === '/the/root/one.js' || mapping.source === '/the/root/two.js'); - map = new SourceMapConsumer(util.testMapEmptySourceRoot); - map.eachMapping(function (mapping) { - assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); - }); - }; + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); - exports['test eachMapping for indexed source maps'] = function(assert, util) { - var map = new SourceMapConsumer(util.indexedTestMap); - var previousLine = -Infinity; - var previousColumn = -Infinity; - map.eachMapping(function (mapping) { - assert.ok(mapping.generatedLine >= previousLine); + map = new SourceMapConsumer(util.testMapNoSourceRoot); + map.eachMapping(function (mapping) { + assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); + }); - if (mapping.source) { - assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); - } + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + map.eachMapping(function (mapping) { + assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); + }); +}; - if (mapping.generatedLine === previousLine) { - assert.ok(mapping.generatedColumn >= previousColumn); - previousColumn = mapping.generatedColumn; - } - else { - previousLine = mapping.generatedLine; - previousColumn = -Infinity; - } - }); - }; +exports['test eachMapping for indexed source maps'] = function(assert, util) { + var map = new SourceMapConsumer(util.indexedTestMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + if (mapping.source) { + assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); + } - exports['test iterating over mappings in a different order'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); - var previousLine = -Infinity; - var previousColumn = -Infinity; - var previousSource = ""; - map.eachMapping(function (mapping) { - assert.ok(mapping.source >= previousSource); - - if (mapping.source === previousSource) { - assert.ok(mapping.originalLine >= previousLine); - - if (mapping.originalLine === previousLine) { - assert.ok(mapping.originalColumn >= previousColumn); - previousColumn = mapping.originalColumn; - } - else { - previousLine = mapping.originalLine; - previousColumn = -Infinity; - } + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); +}; + + +exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; } else { - previousSource = mapping.source; - previousLine = -Infinity; + previousLine = mapping.originalLine; previousColumn = -Infinity; } - }, null, SourceMapConsumer.ORIGINAL_ORDER); - }; + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); +}; + +exports['test iterating over mappings in a different order in indexed source maps'] = function (assert, util) { + var map = new SourceMapConsumer(util.indexedTestMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); - exports['test iterating over mappings in a different order in indexed source maps'] = function (assert, util) { - var map = new SourceMapConsumer(util.indexedTestMap); - var previousLine = -Infinity; - var previousColumn = -Infinity; - var previousSource = ""; - map.eachMapping(function (mapping) { - assert.ok(mapping.source >= previousSource); - - if (mapping.source === previousSource) { - assert.ok(mapping.originalLine >= previousLine); - - if (mapping.originalLine === previousLine) { - assert.ok(mapping.originalColumn >= previousColumn); - previousColumn = mapping.originalColumn; - } - else { - previousLine = mapping.originalLine; - previousColumn = -Infinity; - } + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; } else { - previousSource = mapping.source; - previousLine = -Infinity; + previousLine = mapping.originalLine; previousColumn = -Infinity; } - }, null, SourceMapConsumer.ORIGINAL_ORDER); - }; - - exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); - var context = {}; - map.eachMapping(function () { - assert.equal(this, context); - }, context); - }; + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); +}; - exports['test that we can set the context for `this` in eachMapping in indexed source maps'] = function (assert, util) { - var map = new SourceMapConsumer(util.indexedTestMap); - var context = {}; - map.eachMapping(function () { - assert.equal(this, context); - }, context); - }; +exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); +}; - exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMapWithSourcesContent); - var sourcesContent = map.sourcesContent; +exports['test that we can set the context for `this` in eachMapping in indexed source maps'] = function (assert, util) { + var map = new SourceMapConsumer(util.indexedTestMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); +}; - assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(sourcesContent.length, 2); - }; +exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; - exports['test that we can get the original sources for the sources'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMapWithSourcesContent); - var sources = map.sources; - - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.throws(function () { - map.sourceContentFor(""); - }, Error); - assert.throws(function () { - map.sourceContentFor("/the/root/three.js"); - }, Error); - assert.throws(function () { - map.sourceContentFor("three.js"); - }, Error); - }; + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); +}; - exports['test that we can get the original source content with relative source paths'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMapRelativeSources); - var sources = map.sources; - - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.throws(function () { - map.sourceContentFor(""); - }, Error); - assert.throws(function () { - map.sourceContentFor("/the/root/three.js"); - }, Error); - assert.throws(function () { - map.sourceContentFor("three.js"); - }, Error); - }; +exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); +}; - exports['test that we can get the original source content for the sources on an indexed source map'] = function (assert, util) { - var map = new SourceMapConsumer(util.indexedTestMap); - var sources = map.sources; - - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.throws(function () { - map.sourceContentFor(""); - }, Error); - assert.throws(function () { - map.sourceContentFor("/the/root/three.js"); - }, Error); - assert.throws(function () { - map.sourceContentFor("three.js"); - }, Error); - }; +exports['test that we can get the original source content with relative source paths'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapRelativeSources); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); +}; - exports['test hasContentsOfAllSources, single source with contents'] = function (assert, util) { - // Has one source: foo.js (with contents). - var mapWithContents = new SourceMapGenerator(); - mapWithContents.addMapping({ source: 'foo.js', - original: { line: 1, column: 10 }, - generated: { line: 1, column: 10 } }); - mapWithContents.setSourceContent('foo.js', 'content of foo.js'); - var consumer = new SourceMapConsumer(mapWithContents.toJSON()); - assert.ok(consumer.hasContentsOfAllSources()); - }; +exports['test that we can get the original source content for the sources on an indexed source map'] = function (assert, util) { + var map = new SourceMapConsumer(util.indexedTestMap); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); +}; - exports['test hasContentsOfAllSources, single source without contents'] = function (assert, util) { - // Has one source: foo.js (without contents). - var mapWithoutContents = new SourceMapGenerator(); - mapWithoutContents.addMapping({ source: 'foo.js', - original: { line: 1, column: 10 }, - generated: { line: 1, column: 10 } }); - var consumer = new SourceMapConsumer(mapWithoutContents.toJSON()); - assert.ok(!consumer.hasContentsOfAllSources()); - }; +exports['test hasContentsOfAllSources, single source with contents'] = function (assert, util) { + // Has one source: foo.js (with contents). + var mapWithContents = new SourceMapGenerator(); + mapWithContents.addMapping({ source: 'foo.js', + original: { line: 1, column: 10 }, + generated: { line: 1, column: 10 } }); + mapWithContents.setSourceContent('foo.js', 'content of foo.js'); + var consumer = new SourceMapConsumer(mapWithContents.toJSON()); + assert.ok(consumer.hasContentsOfAllSources()); +}; - exports['test hasContentsOfAllSources, two sources with contents'] = function (assert, util) { - // Has two sources: foo.js (with contents) and bar.js (with contents). - var mapWithBothContents = new SourceMapGenerator(); - mapWithBothContents.addMapping({ source: 'foo.js', - original: { line: 1, column: 10 }, - generated: { line: 1, column: 10 } }); - mapWithBothContents.addMapping({ source: 'bar.js', - original: { line: 1, column: 10 }, - generated: { line: 1, column: 10 } }); - mapWithBothContents.setSourceContent('foo.js', 'content of foo.js'); - mapWithBothContents.setSourceContent('bar.js', 'content of bar.js'); - var consumer = new SourceMapConsumer(mapWithBothContents.toJSON()); - assert.ok(consumer.hasContentsOfAllSources()); - }; +exports['test hasContentsOfAllSources, single source without contents'] = function (assert, util) { + // Has one source: foo.js (without contents). + var mapWithoutContents = new SourceMapGenerator(); + mapWithoutContents.addMapping({ source: 'foo.js', + original: { line: 1, column: 10 }, + generated: { line: 1, column: 10 } }); + var consumer = new SourceMapConsumer(mapWithoutContents.toJSON()); + assert.ok(!consumer.hasContentsOfAllSources()); +}; - exports['test hasContentsOfAllSources, two sources one with and one without contents'] = function (assert, util) { - // Has two sources: foo.js (with contents) and bar.js (without contents). - var mapWithoutSomeContents = new SourceMapGenerator(); - mapWithoutSomeContents.addMapping({ source: 'foo.js', - original: { line: 1, column: 10 }, - generated: { line: 1, column: 10 } }); - mapWithoutSomeContents.addMapping({ source: 'bar.js', - original: { line: 1, column: 10 }, - generated: { line: 1, column: 10 } }); - mapWithoutSomeContents.setSourceContent('foo.js', 'content of foo.js'); - var consumer = new SourceMapConsumer(mapWithoutSomeContents.toJSON()); - assert.ok(!consumer.hasContentsOfAllSources()); +exports['test hasContentsOfAllSources, two sources with contents'] = function (assert, util) { + // Has two sources: foo.js (with contents) and bar.js (with contents). + var mapWithBothContents = new SourceMapGenerator(); + mapWithBothContents.addMapping({ source: 'foo.js', + original: { line: 1, column: 10 }, + generated: { line: 1, column: 10 } }); + mapWithBothContents.addMapping({ source: 'bar.js', + original: { line: 1, column: 10 }, + generated: { line: 1, column: 10 } }); + mapWithBothContents.setSourceContent('foo.js', 'content of foo.js'); + mapWithBothContents.setSourceContent('bar.js', 'content of bar.js'); + var consumer = new SourceMapConsumer(mapWithBothContents.toJSON()); + assert.ok(consumer.hasContentsOfAllSources()); }; - exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'foo/bar', - file: 'baz.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bang.coffee' - }); - map.addMapping({ - original: { line: 5, column: 5 }, - generated: { line: 6, column: 6 }, - source: 'bang.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - // Should handle without sourceRoot. - var pos = map.generatedPositionFor({ - line: 1, - column: 1, - source: 'bang.coffee' - }); - - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - - // Should handle with sourceRoot. - var pos = map.generatedPositionFor({ - line: 1, - column: 1, - source: 'foo/bar/bang.coffee' - }); - - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - }; +exports['test hasContentsOfAllSources, two sources one with and one without contents'] = function (assert, util) { + // Has two sources: foo.js (with contents) and bar.js (without contents). + var mapWithoutSomeContents = new SourceMapGenerator(); + mapWithoutSomeContents.addMapping({ source: 'foo.js', + original: { line: 1, column: 10 }, + generated: { line: 1, column: 10 } }); + mapWithoutSomeContents.addMapping({ source: 'bar.js', + original: { line: 1, column: 10 }, + generated: { line: 1, column: 10 } }); + mapWithoutSomeContents.setSourceContent('foo.js', 'content of foo.js'); + var consumer = new SourceMapConsumer(mapWithoutSomeContents.toJSON()); + assert.ok(!consumer.hasContentsOfAllSources()); +}; - exports['test sourceRoot + generatedPositionFor for path above the root'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'foo/bar', - file: 'baz.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: '../bang.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - // Should handle with sourceRoot. - var pos = map.generatedPositionFor({ - line: 1, - column: 1, - source: 'foo/bang.coffee' - }); - - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - }; +exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); +}; - exports['test allGeneratedPositionsFor for line'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 2, column: 1 }, - generated: { line: 3, column: 2 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 3, column: 3 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 3, column: 1 }, - generated: { line: 4, column: 2 }, - source: 'bar.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'bar.coffee' - }); - - assert.equal(mappings.length, 2); - assert.equal(mappings[0].line, 3); - assert.equal(mappings[0].column, 2); - assert.equal(mappings[1].line, 3); - assert.equal(mappings[1].column, 3); - }; +exports['test sourceRoot + generatedPositionFor for path above the root'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '../bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); +}; - exports['test allGeneratedPositionsFor for line fuzzy'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 3, column: 1 }, - generated: { line: 4, column: 2 }, - source: 'bar.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'bar.coffee' - }); - - assert.equal(mappings.length, 1); - assert.equal(mappings[0].line, 4); - assert.equal(mappings[0].column, 2); - }; +exports['test allGeneratedPositionsFor for line'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 3, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 3, column: 3 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 4, column: 2 }, + source: 'bar.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].line, 3); + assert.equal(mappings[0].column, 2); + assert.equal(mappings[1].line, 3); + assert.equal(mappings[1].column, 3); +}; - exports['test allGeneratedPositionsFor for empty source map'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map = new SourceMapConsumer(map.toString()); +exports['test allGeneratedPositionsFor for line fuzzy'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 4, column: 2 }, + source: 'bar.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 1); + assert.equal(mappings[0].line, 4); + assert.equal(mappings[0].column, 2); +}; - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'bar.coffee' - }); +exports['test allGeneratedPositionsFor for empty source map'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map = new SourceMapConsumer(map.toString()); - assert.equal(mappings.length, 0); - }; + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); - exports['test allGeneratedPositionsFor for column'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 3 }, - source: 'foo.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 1, - column: 1, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 2); - assert.equal(mappings[0].line, 1); - assert.equal(mappings[0].column, 2); - assert.equal(mappings[1].line, 1); - assert.equal(mappings[1].column, 3); - }; + assert.equal(mappings.length, 0); +}; - exports['test allGeneratedPositionsFor for column fuzzy'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 3 }, - source: 'foo.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 1, - column: 0, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 2); - assert.equal(mappings[0].line, 1); - assert.equal(mappings[0].column, 2); - assert.equal(mappings[1].line, 1); - assert.equal(mappings[1].column, 3); - }; +exports['test allGeneratedPositionsFor for column'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 3 }, + source: 'foo.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 1, + column: 1, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].line, 1); + assert.equal(mappings[0].column, 2); + assert.equal(mappings[1].line, 1); + assert.equal(mappings[1].column, 3); +}; - exports['test allGeneratedPositionsFor for column on different line fuzzy'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 2, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 1 }, - generated: { line: 2, column: 3 }, - source: 'foo.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 1, - column: 0, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 0); - }; +exports['test allGeneratedPositionsFor for column fuzzy'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 3 }, + source: 'foo.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 1, + column: 0, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].line, 1); + assert.equal(mappings[0].column, 2); + assert.equal(mappings[1].line, 1); + assert.equal(mappings[1].column, 3); +}; - exports['test computeColumnSpans'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 1 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 1 }, - generated: { line: 2, column: 1 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 2, column: 10 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 3 }, - generated: { line: 2, column: 20 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 3, column: 1 }, - generated: { line: 3, column: 1 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 3, column: 2 }, - generated: { line: 3, column: 2 }, - source: 'foo.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - map.computeColumnSpans(); - - var mappings = map.allGeneratedPositionsFor({ - line: 1, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 1); - assert.equal(mappings[0].lastColumn, Infinity); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 3); - assert.equal(mappings[0].lastColumn, 9); - assert.equal(mappings[1].lastColumn, 19); - assert.equal(mappings[2].lastColumn, Infinity); - - var mappings = map.allGeneratedPositionsFor({ - line: 3, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 2); - assert.equal(mappings[0].lastColumn, 1); - assert.equal(mappings[1].lastColumn, Infinity); - }; +exports['test allGeneratedPositionsFor for column on different line fuzzy'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 2, column: 3 }, + source: 'foo.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 1, + column: 0, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 0); +}; - exports['test sourceRoot + originalPositionFor'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'foo/bar', - file: 'baz.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bang.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var pos = map.originalPositionFor({ - line: 2, - column: 2, - }); - - // Should always have the prepended source root - assert.equal(pos.source, 'foo/bar/bang.coffee'); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - }; +exports['test computeColumnSpans'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 2, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 2, column: 10 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 3 }, + generated: { line: 2, column: 20 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 3, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 3, column: 2 }, + generated: { line: 3, column: 2 }, + source: 'foo.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + map.computeColumnSpans(); + + var mappings = map.allGeneratedPositionsFor({ + line: 1, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 1); + assert.equal(mappings[0].lastColumn, Infinity); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 3); + assert.equal(mappings[0].lastColumn, 9); + assert.equal(mappings[1].lastColumn, 19); + assert.equal(mappings[2].lastColumn, Infinity); + + var mappings = map.allGeneratedPositionsFor({ + line: 3, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].lastColumn, 1); + assert.equal(mappings[1].lastColumn, Infinity); +}; - exports['test github issue #56'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'http://', - file: 'www.example.com/foo.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'www.example.com/original.js' - }); - map = new SourceMapConsumer(map.toString()); - - var sources = map.sources; - assert.equal(sources.length, 1); - assert.equal(sources[0], 'http://www.example.com/original.js'); - }; +exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); +}; - exports['test github issue #43'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'http://example.com', - file: 'foo.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'http://cdn.example.com/original.js' - }); - map = new SourceMapConsumer(map.toString()); - - var sources = map.sources; - assert.equal(sources.length, 1, - 'Should only be one source.'); - assert.equal(sources[0], 'http://cdn.example.com/original.js', - 'Should not be joined with the sourceRoot.'); - }; +exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); +}; - exports['test absolute path, but same host sources'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'http://example.com/foo/bar', - file: 'foo.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: '/original.js' - }); - map = new SourceMapConsumer(map.toString()); - - var sources = map.sources; - assert.equal(sources.length, 1, - 'Should only be one source.'); - assert.equal(sources[0], 'http://example.com/original.js', - 'Source should be relative the host of the source root.'); - }; +exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); +}; - exports['test indexed source map errors when sections are out of order by line'] = function(assert, util) { - // Make a deep copy of the indexedTestMap - var misorderedIndexedTestMap = JSON.parse(JSON.stringify(util.indexedTestMap)); +exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); +}; - misorderedIndexedTestMap.sections[0].offset = { - line: 2, - column: 0 - }; +exports['test indexed source map errors when sections are out of order by line'] = function(assert, util) { + // Make a deep copy of the indexedTestMap + var misorderedIndexedTestMap = JSON.parse(JSON.stringify(util.indexedTestMap)); - assert.throws(function() { - new SourceMapConsumer(misorderedIndexedTestMap); - }, Error); + misorderedIndexedTestMap.sections[0].offset = { + line: 2, + column: 0 }; - exports['test github issue #64'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sourceRoot": "http://example.com/", - "sources": ["/a"], - "names": [], - "mappings": "AACA", - "sourcesContent": ["foo"] - }); - - assert.equal(map.sourceContentFor("a"), "foo"); - assert.equal(map.sourceContentFor("/a"), "foo"); - }; + assert.throws(function() { + new SourceMapConsumer(misorderedIndexedTestMap); + }, Error); +}; - exports['test bug 885597'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", - "sources": ["/a"], - "names": [], - "mappings": "AACA", - "sourcesContent": ["foo"] - }); - - var s = map.sources[0]; - assert.equal(map.sourceContentFor(s), "foo"); - }; +exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); +}; - exports['test github issue #72, duplicate sources'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sources": ["source1.js", "source1.js", "source3.js"], - "names": [], - "mappings": ";EAAC;;IAEE;;MEEE", - "sourceRoot": "http://example.com" - }); - - var pos = map.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(pos.source, 'http://example.com/source1.js'); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - - var pos = map.originalPositionFor({ - line: 4, - column: 4 - }); - assert.equal(pos.source, 'http://example.com/source1.js'); - assert.equal(pos.line, 3); - assert.equal(pos.column, 3); - - var pos = map.originalPositionFor({ - line: 6, - column: 6 - }); - assert.equal(pos.source, 'http://example.com/source3.js'); - assert.equal(pos.line, 5); - assert.equal(pos.column, 5); - }; +exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); +}; - exports['test github issue #72, duplicate names'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sources": ["source.js"], - "names": ["name1", "name1", "name3"], - "mappings": ";EAACA;;IAEEA;;MAEEE", - "sourceRoot": "http://example.com" - }); - - var pos = map.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(pos.name, 'name1'); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - - var pos = map.originalPositionFor({ - line: 4, - column: 4 - }); - assert.equal(pos.name, 'name1'); - assert.equal(pos.line, 3); - assert.equal(pos.column, 3); - - var pos = map.originalPositionFor({ - line: 6, - column: 6 - }); - assert.equal(pos.name, 'name3'); - assert.equal(pos.line, 5); - assert.equal(pos.column, 5); - }; +exports['test github issue #72, duplicate sources'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source1.js", "source1.js", "source3.js"], + "names": [], + "mappings": ";EAAC;;IAEE;;MEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.source, 'http://example.com/source3.js'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); +}; - exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { - var smg = new SourceMapGenerator({ - sourceRoot: 'http://example.com/', - file: 'foo.js' - }); - smg.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bar.js' - }); - smg.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 4, column: 4 }, - source: 'baz.js', - name: 'dirtMcGirt' - }); - smg.setSourceContent('baz.js', 'baz.js content'); - - var smc = SourceMapConsumer.fromSourceMap(smg); - assert.equal(smc.file, 'foo.js'); - assert.equal(smc.sourceRoot, 'http://example.com/'); - assert.equal(smc.sources.length, 2); - assert.equal(smc.sources[0], 'http://example.com/bar.js'); - assert.equal(smc.sources[1], 'http://example.com/baz.js'); - assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); - - var pos = smc.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - assert.equal(pos.source, 'http://example.com/bar.js'); - assert.equal(pos.name, null); - - pos = smc.generatedPositionFor({ - line: 1, - column: 1, - source: 'http://example.com/bar.js' - }); - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - - pos = smc.originalPositionFor({ - line: 4, - column: 4 - }); - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - assert.equal(pos.source, 'http://example.com/baz.js'); - assert.equal(pos.name, 'dirtMcGirt'); - - pos = smc.generatedPositionFor({ - line: 2, - column: 2, - source: 'http://example.com/baz.js' - }); - assert.equal(pos.line, 4); - assert.equal(pos.column, 4); - }; +exports['test github issue #72, duplicate names'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source.js"], + "names": ["name1", "name1", "name3"], + "mappings": ";EAACA;;IAEEA;;MAEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.name, 'name3'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); +}; - exports['test issue #191'] = function (assert, util) { - var generator = new SourceMapGenerator({ file: 'a.css' }); - generator.addMapping({ - source: 'b.css', - original: { - line: 1, - column: 0 - }, - generated: { - line: 1, - column: 0 - } - }); +exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { + var smg = new SourceMapGenerator({ + sourceRoot: 'http://example.com/', + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 4, column: 4 }, + source: 'baz.js', + name: 'dirtMcGirt' + }); + smg.setSourceContent('baz.js', 'baz.js content'); + + var smc = SourceMapConsumer.fromSourceMap(smg); + assert.equal(smc.file, 'foo.js'); + assert.equal(smc.sourceRoot, 'http://example.com/'); + assert.equal(smc.sources.length, 2); + assert.equal(smc.sources[0], 'http://example.com/bar.js'); + assert.equal(smc.sources[1], 'http://example.com/baz.js'); + assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); + + var pos = smc.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + assert.equal(pos.source, 'http://example.com/bar.js'); + assert.equal(pos.name, null); + + pos = smc.generatedPositionFor({ + line: 1, + column: 1, + source: 'http://example.com/bar.js' + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + pos = smc.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + assert.equal(pos.source, 'http://example.com/baz.js'); + assert.equal(pos.name, 'dirtMcGirt'); + + pos = smc.generatedPositionFor({ + line: 2, + column: 2, + source: 'http://example.com/baz.js' + }); + assert.equal(pos.line, 4); + assert.equal(pos.column, 4); +}; - // Create a SourceMapConsumer from the SourceMapGenerator, ... - var consumer = SourceMapConsumer.fromSourceMap(generator); - // ... and then try and use the SourceMapGenerator again. This should not - // throw. - generator.toJSON(); +exports['test issue #191'] = function (assert, util) { + var generator = new SourceMapGenerator({ file: 'a.css' }); + generator.addMapping({ + source: 'b.css', + original: { + line: 1, + column: 0 + }, + generated: { + line: 1, + column: 0 + } + }); - assert.ok(true, "Using a SourceMapGenerator again after creating a " + - "SourceMapConsumer from it should not throw"); - }; + // Create a SourceMapConsumer from the SourceMapGenerator, ... + var consumer = SourceMapConsumer.fromSourceMap(generator); + // ... and then try and use the SourceMapGenerator again. This should not + // throw. + generator.toJSON(); - exports['test sources where their prefix is the source root: issue #199'] = function (assert, util) { - var testSourceMap = { - "version": 3, - "sources": ["/source/app/app/app.js"], - "names": ["System"], - "mappings": "AAAAA", - "file": "app/app.js", - "sourcesContent": ["'use strict';"], - "sourceRoot":"/source/" - }; - - var consumer = new SourceMapConsumer(testSourceMap); - - function consumerHasSource(s) { - assert.ok(consumer.sourceContentFor(s)); - } + assert.ok(true, "Using a SourceMapGenerator again after creating a " + + "SourceMapConsumer from it should not throw"); +}; - consumer.sources.forEach(consumerHasSource); - testSourceMap.sources.forEach(consumerHasSource); +exports['test sources where their prefix is the source root: issue #199'] = function (assert, util) { + var testSourceMap = { + "version": 3, + "sources": ["/source/app/app/app.js"], + "names": ["System"], + "mappings": "AAAAA", + "file": "app/app.js", + "sourcesContent": ["'use strict';"], + "sourceRoot":"/source/" }; - exports['test sources where their prefix is the source root and the source root is a url: issue #199'] = function (assert, util) { - var testSourceMap = { - "version": 3, - "sources": ["http://example.com/source/app/app/app.js"], - "names": ["System"], - "mappings": "AAAAA", - "sourcesContent": ["'use strict';"], - "sourceRoot":"http://example.com/source/" - }; + var consumer = new SourceMapConsumer(testSourceMap); - var consumer = new SourceMapConsumer(testSourceMap); + function consumerHasSource(s) { + assert.ok(consumer.sourceContentFor(s)); + } - function consumerHasSource(s) { - assert.ok(consumer.sourceContentFor(s)); - } + consumer.sources.forEach(consumerHasSource); + testSourceMap.sources.forEach(consumerHasSource); +}; - consumer.sources.forEach(consumerHasSource); - testSourceMap.sources.forEach(consumerHasSource); +exports['test sources where their prefix is the source root and the source root is a url: issue #199'] = function (assert, util) { + var testSourceMap = { + "version": 3, + "sources": ["http://example.com/source/app/app/app.js"], + "names": ["System"], + "mappings": "AAAAA", + "sourcesContent": ["'use strict';"], + "sourceRoot":"http://example.com/source/" }; -}); + var consumer = new SourceMapConsumer(testSourceMap); + + function consumerHasSource(s) { + assert.ok(consumer.sourceContentFor(s)); + } + + consumer.sources.forEach(consumerHasSource); + testSourceMap.sources.forEach(consumerHasSource); +}; diff --git a/test/source-map/test-source-map-generator.js b/test/source-map/test-source-map-generator.js index e1cb8f0e..57c28fad 100644 --- a/test/source-map/test-source-map-generator.js +++ b/test/source-map/test-source-map-generator.js @@ -4,742 +4,735 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceNode = require('../../lib/source-map/source-node').SourceNode; - var util = require('./util'); - - exports['test some simple stuff'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'foo.js', - sourceRoot: '.' - }); - assert.ok(true); - - var map = new SourceMapGenerator().toJSON(); - assert.ok(!('file' in map)); - assert.ok(!('sourceRoot' in map)); - }; - - exports['test JSON serialization'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'foo.js', - sourceRoot: '.' - }); - assert.equal(map.toString(), JSON.stringify(map)); - }; - - exports['test adding mappings (case 1)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 } - }); - }); - }; - - exports['test adding mappings (case 2)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - source: 'bar.js', - original: { line: 1, column: 1 } - }); - }); - }; - - exports['test adding mappings (case 3)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - source: 'bar.js', - original: { line: 1, column: 1 }, - name: 'someToken' - }); - }); - }; - - exports['test adding mappings (invalid)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - // Not enough info. - assert.throws(function () { - map.addMapping({}); - }); - - // Original file position, but no source. - assert.throws(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 } - }); - }); - }; - - exports['test adding mappings with skipValidation'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.', - skipValidation: true - }); - - // Not enough info, caught by `util.getArgs` - assert.throws(function () { - map.addMapping({}); +var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; +var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; +var SourceNode = require('../../lib/source-map/source-node').SourceNode; +var util = require('./util'); + +exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + + var map = new SourceMapGenerator().toJSON(); + assert.ok(!('file' in map)); + assert.ok(!('sourceRoot' in map)); +}; + +exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); +}; + +exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } }); + }); +}; - // Original file position, but no source. Not checked. - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 } - }); - }); - }; - - exports['test that the correct mappings are being generated'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'min.js', - sourceRoot: '/the/root' - }); +exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + assert.doesNotThrow(function () { map.addMapping({ generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 5 }, - original: { line: 1, column: 5 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 9 }, - original: { line: 1, column: 11 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 18 }, - original: { line: 1, column: 21 }, - source: 'one.js', - name: 'bar' - }); - map.addMapping({ - generated: { line: 1, column: 21 }, - original: { line: 2, column: 3 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 28 }, - original: { line: 2, column: 10 }, - source: 'one.js', - name: 'baz' - }); - map.addMapping({ - generated: { line: 1, column: 32 }, - original: { line: 2, column: 14 }, - source: 'one.js', - name: 'bar' - }); - - map.addMapping({ - generated: { line: 2, column: 1 }, - original: { line: 1, column: 1 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 5 }, - original: { line: 1, column: 5 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 9 }, - original: { line: 1, column: 11 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 18 }, - original: { line: 1, column: 21 }, - source: 'two.js', - name: 'n' - }); - map.addMapping({ - generated: { line: 2, column: 21 }, - original: { line: 2, column: 3 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 28 }, - original: { line: 2, column: 10 }, - source: 'two.js', - name: 'n' + source: 'bar.js', + original: { line: 1, column: 1 } }); + }); +}; - map = JSON.parse(map.toString()); - - util.assertEqualMaps(assert, map, util.testMap); - }; - - exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); +exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + assert.doesNotThrow(function () { map.addMapping({ generated: { line: 1, column: 1 }, source: 'bar.js', original: { line: 1, column: 1 }, - name: '' + name: 'someToken' }); + }); +}; - assert.doesNotThrow(function () { - JSON.parse(map.toString()); - }); - }; +exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); - exports['test that source content can be set'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'min.js', - sourceRoot: '/the/root' - }); + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { map.addMapping({ generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 }, - source: 'one.js' + original: { line: 1, column: 1 } }); - map.addMapping({ - generated: { line: 2, column: 1 }, - original: { line: 1, column: 1 }, - source: 'two.js' - }); - map.setSourceContent('one.js', 'one file content'); - - map = JSON.parse(map.toString()); - assert.equal(map.sources[0], 'one.js'); - assert.equal(map.sources[1], 'two.js'); - assert.equal(map.sourcesContent[0], 'one file content'); - assert.equal(map.sourcesContent[1], null); - }; + }); +}; - exports['test .fromSourceMap'] = function (assert, util) { - var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); - util.assertEqualMaps(assert, map.toJSON(), util.testMap); - }; +exports['test adding mappings with skipValidation'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.', + skipValidation: true + }); - exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { - var map = SourceMapGenerator.fromSourceMap( - new SourceMapConsumer(util.testMapWithSourcesContent)); - util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); - }; + // Not enough info, caught by `util.getArgs` + assert.throws(function () { + map.addMapping({}); + }); - exports['test applySourceMap'] = function (assert, util) { - var node = new SourceNode(null, null, null, [ - new SourceNode(2, 0, 'fileX', 'lineX2\n'), - 'genA1\n', - new SourceNode(2, 0, 'fileY', 'lineY2\n'), - 'genA2\n', - new SourceNode(1, 0, 'fileX', 'lineX1\n'), - 'genA3\n', - new SourceNode(1, 0, 'fileY', 'lineY1\n') - ]); - var mapStep1 = node.toStringWithSourceMap({ - file: 'fileA' - }).map; - mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); - mapStep1 = mapStep1.toJSON(); - - node = new SourceNode(null, null, null, [ - 'gen1\n', - new SourceNode(1, 0, 'fileA', 'lineA1\n'), - new SourceNode(2, 0, 'fileA', 'lineA2\n'), - new SourceNode(3, 0, 'fileA', 'lineA3\n'), - new SourceNode(4, 0, 'fileA', 'lineA4\n'), - new SourceNode(1, 0, 'fileB', 'lineB1\n'), - new SourceNode(2, 0, 'fileB', 'lineB2\n'), - 'gen2\n' - ]); - var mapStep2 = node.toStringWithSourceMap({ - file: 'fileGen' - }).map; - mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); - mapStep2 = mapStep2.toJSON(); - - node = new SourceNode(null, null, null, [ - 'gen1\n', - new SourceNode(2, 0, 'fileX', 'lineA1\n'), - new SourceNode(2, 0, 'fileA', 'lineA2\n'), - new SourceNode(2, 0, 'fileY', 'lineA3\n'), - new SourceNode(4, 0, 'fileA', 'lineA4\n'), - new SourceNode(1, 0, 'fileB', 'lineB1\n'), - new SourceNode(2, 0, 'fileB', 'lineB2\n'), - 'gen2\n' - ]); - var expectedMap = node.toStringWithSourceMap({ - file: 'fileGen' - }).map; - expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); - expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); - expectedMap = expectedMap.toJSON(); - - // apply source map "mapStep1" to "mapStep2" - var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); - generator.applySourceMap(new SourceMapConsumer(mapStep1)); - var actualMap = generator.toJSON(); - - util.assertEqualMaps(assert, actualMap, expectedMap); - }; - - exports['test applySourceMap throws when file is missing'] = function (assert, util) { + // Original file position, but no source. Not checked. + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); +}; + +exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); +}; + +exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: '' + }); + + assert.doesNotThrow(function () { + JSON.parse(map.toString()); + }); +}; + +exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); +}; + +exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); +}; + +exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); +}; + +exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); +}; + +exports['test applySourceMap throws when file is missing'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + var map2 = new SourceMapGenerator(); + assert.throws(function() { + map.applySourceMap(new SourceMapConsumer(map2.toJSON())); + }); +}; + +exports['test the two additional parameters of applySourceMap'] = function (assert, util) { + // Assume the following directory structure: + // + // http://foo.org/ + // bar.coffee + // app/ + // coffee/ + // foo.coffee + // temp/ + // bundle.js + // temp_maps/ + // bundle.js.map + // public/ + // bundle.min.js + // bundle.min.js.map + // + // http://www.example.com/ + // baz.coffee + + var bundleMap = new SourceMapGenerator({ + file: 'bundle.js' + }); + bundleMap.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 2, column: 2 }, + source: '../../coffee/foo.coffee' + }); + bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee'); + bundleMap.addMapping({ + generated: { line: 13, column: 13 }, + original: { line: 12, column: 12 }, + source: '/bar.coffee' + }); + bundleMap.setSourceContent('/bar.coffee', 'bar coffee'); + bundleMap.addMapping({ + generated: { line: 23, column: 23 }, + original: { line: 22, column: 22 }, + source: 'http://www.example.com/baz.coffee' + }); + bundleMap.setSourceContent( + 'http://www.example.com/baz.coffee', + 'baz coffee' + ); + bundleMap = new SourceMapConsumer(bundleMap.toJSON()); + + var minifiedMap = new SourceMapGenerator({ + file: 'bundle.min.js', + sourceRoot: '..' + }); + minifiedMap.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 3, column: 3 }, + source: 'temp/bundle.js' + }); + minifiedMap.addMapping({ + generated: { line: 11, column: 11 }, + original: { line: 13, column: 13 }, + source: 'temp/bundle.js' + }); + minifiedMap.addMapping({ + generated: { line: 21, column: 21 }, + original: { line: 23, column: 23 }, + source: 'temp/bundle.js' + }); + minifiedMap = new SourceMapConsumer(minifiedMap.toJSON()); + + var expectedMap = function (sources) { var map = new SourceMapGenerator({ - file: 'test.js' - }); - var map2 = new SourceMapGenerator(); - assert.throws(function() { - map.applySourceMap(new SourceMapConsumer(map2.toJSON())); - }); - }; - - exports['test the two additional parameters of applySourceMap'] = function (assert, util) { - // Assume the following directory structure: - // - // http://foo.org/ - // bar.coffee - // app/ - // coffee/ - // foo.coffee - // temp/ - // bundle.js - // temp_maps/ - // bundle.js.map - // public/ - // bundle.min.js - // bundle.min.js.map - // - // http://www.example.com/ - // baz.coffee - - var bundleMap = new SourceMapGenerator({ - file: 'bundle.js' + file: 'bundle.min.js', + sourceRoot: '..' }); - bundleMap.addMapping({ - generated: { line: 3, column: 3 }, + map.addMapping({ + generated: { line: 1, column: 1 }, original: { line: 2, column: 2 }, - source: '../../coffee/foo.coffee' + source: sources[0] }); - bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee'); - bundleMap.addMapping({ - generated: { line: 13, column: 13 }, + map.setSourceContent(sources[0], 'foo coffee'); + map.addMapping({ + generated: { line: 11, column: 11 }, original: { line: 12, column: 12 }, - source: '/bar.coffee' + source: sources[1] }); - bundleMap.setSourceContent('/bar.coffee', 'bar coffee'); - bundleMap.addMapping({ - generated: { line: 23, column: 23 }, + map.setSourceContent(sources[1], 'bar coffee'); + map.addMapping({ + generated: { line: 21, column: 21 }, original: { line: 22, column: 22 }, - source: 'http://www.example.com/baz.coffee' - }); - bundleMap.setSourceContent( - 'http://www.example.com/baz.coffee', - 'baz coffee' - ); - bundleMap = new SourceMapConsumer(bundleMap.toJSON()); - + source: sources[2] + }); + map.setSourceContent(sources[2], 'baz coffee'); + return map.toJSON(); + } + + var actualMap = function (aSourceMapPath) { + var map = SourceMapGenerator.fromSourceMap(minifiedMap); + // Note that relying on `bundleMap.file` (which is simply 'bundle.js') + // instead of supplying the second parameter wouldn't work here. + map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath); + return map.toJSON(); + } + + util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([ + 'coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([ + '/app/coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([ + 'http://foo.org/app/coffee/foo.coffee', + 'http://foo.org/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + // If the third parameter is omitted or set to the current working + // directory we get incorrect source paths: + + util.assertEqualMaps(assert, actualMap(), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap(''), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('.'), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('./'), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); +}; + +exports['test applySourceMap name handling'] = function (assert, util) { + // Imagine some CoffeeScript code being compiled into JavaScript and then + // minified. + + var assertName = function(coffeeName, jsName, expectedName) { var minifiedMap = new SourceMapGenerator({ - file: 'bundle.min.js', - sourceRoot: '..' - }); - minifiedMap.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 3, column: 3 }, - source: 'temp/bundle.js' + file: 'test.js.min' }); minifiedMap.addMapping({ - generated: { line: 11, column: 11 }, - original: { line: 13, column: 13 }, - source: 'temp/bundle.js' - }); - minifiedMap.addMapping({ - generated: { line: 21, column: 21 }, - original: { line: 23, column: 23 }, - source: 'temp/bundle.js' + generated: { line: 1, column: 4 }, + original: { line: 1, column: 4 }, + source: 'test.js', + name: jsName }); - minifiedMap = new SourceMapConsumer(minifiedMap.toJSON()); - - var expectedMap = function (sources) { - var map = new SourceMapGenerator({ - file: 'bundle.min.js', - sourceRoot: '..' - }); - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 2, column: 2 }, - source: sources[0] - }); - map.setSourceContent(sources[0], 'foo coffee'); - map.addMapping({ - generated: { line: 11, column: 11 }, - original: { line: 12, column: 12 }, - source: sources[1] - }); - map.setSourceContent(sources[1], 'bar coffee'); - map.addMapping({ - generated: { line: 21, column: 21 }, - original: { line: 22, column: 22 }, - source: sources[2] - }); - map.setSourceContent(sources[2], 'baz coffee'); - return map.toJSON(); - } - - var actualMap = function (aSourceMapPath) { - var map = SourceMapGenerator.fromSourceMap(minifiedMap); - // Note that relying on `bundleMap.file` (which is simply 'bundle.js') - // instead of supplying the second parameter wouldn't work here. - map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath); - return map.toJSON(); - } - - util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([ - 'coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([ - '/app/coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([ - 'http://foo.org/app/coffee/foo.coffee', - 'http://foo.org/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - // If the third parameter is omitted or set to the current working - // directory we get incorrect source paths: - - util.assertEqualMaps(assert, actualMap(), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap(''), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('.'), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('./'), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - }; - - exports['test applySourceMap name handling'] = function (assert, util) { - // Imagine some CoffeeScript code being compiled into JavaScript and then - // minified. - - var assertName = function(coffeeName, jsName, expectedName) { - var minifiedMap = new SourceMapGenerator({ - file: 'test.js.min' - }); - minifiedMap.addMapping({ - generated: { line: 1, column: 4 }, - original: { line: 1, column: 4 }, - source: 'test.js', - name: jsName - }); - - var coffeeMap = new SourceMapGenerator({ - file: 'test.js' - }); - coffeeMap.addMapping({ - generated: { line: 1, column: 4 }, - original: { line: 1, column: 0 }, - source: 'test.coffee', - name: coffeeName - }); - - minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON())); - - new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) { - assert.equal(mapping.name, expectedName); - }); - }; - - // `foo = 1` -> `var foo = 1;` -> `var a=1` - // CoffeeScript doesn’t rename variables, so there’s no need for it to - // provide names in its source maps. Minifiers do rename variables and - // therefore do provide names in their source maps. So that name should be - // retained if the original map lacks names. - assertName(null, 'foo', 'foo'); - - // `foo = 1` -> `var coffee$foo = 1;` -> `var a=1` - // Imagine that CoffeeScript prefixed all variables with `coffee$`. Even - // though the minifier then also provides a name, the original name is - // what corresponds to the source. - assertName('foo', 'coffee$foo', 'foo'); - - // `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1` - // Minifiers can turn off variable mangling. Then there’s no need to - // provide names in the source map, but the names from the original map are - // still needed. - assertName('foo', null, 'foo'); - - // `foo = 1` -> `var foo = 1;` -> `var foo=1` - // No renaming at all. - assertName(null, null, null); - }; - exports['test sorting with duplicate generated mappings'] = function (assert, util) { - var map = new SourceMapGenerator({ + var coffeeMap = new SourceMapGenerator({ file: 'test.js' }); - map.addMapping({ - generated: { line: 3, column: 0 }, - original: { line: 2, column: 0 }, - source: 'a.js' - }); - map.addMapping({ - generated: { line: 2, column: 0 } - }); - map.addMapping({ - generated: { line: 2, column: 0 } - }); - map.addMapping({ - generated: { line: 1, column: 0 }, + coffeeMap.addMapping({ + generated: { line: 1, column: 4 }, original: { line: 1, column: 0 }, - source: 'a.js' + source: 'test.coffee', + name: coffeeName }); - util.assertEqualMaps(assert, map.toJSON(), { - version: 3, - file: 'test.js', - sources: ['a.js'], - names: [], - mappings: 'AAAA;A;AACA' + minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON())); + + new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) { + assert.equal(mapping.name, expectedName); }); }; - exports['test ignore duplicate mappings.'] = function (assert, util) { - var init = { file: 'min.js', sourceRoot: '/the/root' }; - var map1, map2; - - // null original source location - var nullMapping1 = { - generated: { line: 1, column: 0 } - }; - var nullMapping2 = { - generated: { line: 2, column: 2 } - }; - - map1 = new SourceMapGenerator(init); - map2 = new SourceMapGenerator(init); - - map1.addMapping(nullMapping1); - map1.addMapping(nullMapping1); - - map2.addMapping(nullMapping1); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - - map1.addMapping(nullMapping2); - map1.addMapping(nullMapping1); - - map2.addMapping(nullMapping2); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + // `foo = 1` -> `var foo = 1;` -> `var a=1` + // CoffeeScript doesn’t rename variables, so there’s no need for it to + // provide names in its source maps. Minifiers do rename variables and + // therefore do provide names in their source maps. So that name should be + // retained if the original map lacks names. + assertName(null, 'foo', 'foo'); + + // `foo = 1` -> `var coffee$foo = 1;` -> `var a=1` + // Imagine that CoffeeScript prefixed all variables with `coffee$`. Even + // though the minifier then also provides a name, the original name is + // what corresponds to the source. + assertName('foo', 'coffee$foo', 'foo'); + + // `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1` + // Minifiers can turn off variable mangling. Then there’s no need to + // provide names in the source map, but the names from the original map are + // still needed. + assertName('foo', null, 'foo'); + + // `foo = 1` -> `var foo = 1;` -> `var foo=1` + // No renaming at all. + assertName(null, null, null); +}; + +exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); +}; + +exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; - // original source location - var srcMapping1 = { - generated: { line: 1, column: 0 }, - original: { line: 11, column: 0 }, - source: 'srcMapping1.js' - }; - var srcMapping2 = { - generated: { line: 2, column: 2 }, - original: { line: 11, column: 0 }, - source: 'srcMapping2.js' - }; + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); - map1 = new SourceMapGenerator(init); - map2 = new SourceMapGenerator(init); + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); - map1.addMapping(srcMapping1); - map1.addMapping(srcMapping1); + map2.addMapping(nullMapping1); - map2.addMapping(srcMapping1); + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); - map1.addMapping(srcMapping2); - map1.addMapping(srcMapping1); + map2.addMapping(nullMapping2); - map2.addMapping(srcMapping2); + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; - // full original source and name information - var fullMapping1 = { - generated: { line: 1, column: 0 }, - original: { line: 11, column: 0 }, - source: 'fullMapping1.js', - name: 'fullMapping1' - }; - var fullMapping2 = { - generated: { line: 2, column: 2 }, - original: { line: 11, column: 0 }, - source: 'fullMapping2.js', - name: 'fullMapping2' - }; + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); - map1 = new SourceMapGenerator(init); - map2 = new SourceMapGenerator(init); + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); - map1.addMapping(fullMapping1); - map1.addMapping(fullMapping1); + map2.addMapping(srcMapping1); - map2.addMapping(fullMapping1); + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); - map1.addMapping(fullMapping2); - map1.addMapping(fullMapping1); + map2.addMapping(srcMapping2); - map2.addMapping(fullMapping2); + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' }; - - exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'test.js' - }); - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 2, column: 2 }, - source: 'a.js', - name: 'foo' - }); - map.addMapping({ - generated: { line: 3, column: 3 }, - original: { line: 4, column: 4 }, - source: 'a.js', - name: 'foo' - }); - util.assertEqualMaps(assert, map.toJSON(), { - version: 3, - file: 'test.js', - sources: ['a.js'], - names: ['foo'], - mappings: 'CACEA;;GAEEA' - }); + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' }; - exports['test setting sourcesContent to null when already null'] = function (assert, util) { - var smg = new SourceMapGenerator({ file: "foo.js" }); - assert.doesNotThrow(function() { - smg.setSourceContent("bar.js", null); + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); +}; + +exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: 'a.js', + name: 'foo' + }); + map.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 4, column: 4 }, + source: 'a.js', + name: 'foo' + }); + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: ['foo'], + mappings: 'CACEA;;GAEEA' + }); +}; + +exports['test setting sourcesContent to null when already null'] = function (assert, util) { + var smg = new SourceMapGenerator({ file: "foo.js" }); + assert.doesNotThrow(function() { + smg.setSourceContent("bar.js", null); + }); +}; + +exports['test applySourceMap with unexact match'] = function (assert, util) { + var map1 = new SourceMapGenerator({ + file: 'bundled-source' + }); + map1.addMapping({ + generated: { line: 1, column: 4 }, + original: { line: 1, column: 4 }, + source: 'transformed-source' + }); + map1.addMapping({ + generated: { line: 2, column: 4 }, + original: { line: 2, column: 4 }, + source: 'transformed-source' + }); + + var map2 = new SourceMapGenerator({ + file: 'transformed-source' + }); + map2.addMapping({ + generated: { line: 2, column: 0 }, + original: { line: 1, column: 0 }, + source: 'original-source' }); - }; - exports['test applySourceMap with unexact match'] = function (assert, util) { - var map1 = new SourceMapGenerator({ - file: 'bundled-source' - }); - map1.addMapping({ - generated: { line: 1, column: 4 }, - original: { line: 1, column: 4 }, - source: 'transformed-source' - }); - map1.addMapping({ - generated: { line: 2, column: 4 }, - original: { line: 2, column: 4 }, - source: 'transformed-source' - }); - - var map2 = new SourceMapGenerator({ - file: 'transformed-source' - }); - map2.addMapping({ - generated: { line: 2, column: 0 }, - original: { line: 1, column: 0 }, - source: 'original-source' - }); - - var expectedMap = new SourceMapGenerator({ - file: 'bundled-source' - }); - expectedMap.addMapping({ - generated: { line: 1, column: 4 }, - original: { line: 1, column: 4 }, - source: 'transformed-source' - }); - expectedMap.addMapping({ - generated: { line: 2, column: 4 }, - original: { line: 1, column: 0 }, - source: 'original-source' - }); - - map1.applySourceMap(new SourceMapConsumer(map2.toJSON())); - - util.assertEqualMaps(assert, map1.toJSON(), expectedMap.toJSON()); - }; - - exports['test issue #192'] = function (assert, util) { - var generator = new SourceMapGenerator(); - generator.addMapping({ - source: 'a.js', - generated: { line: 1, column: 10 }, - original: { line: 1, column: 10 }, + var expectedMap = new SourceMapGenerator({ + file: 'bundled-source' }); - generator.addMapping({ - source: 'b.js', - generated: { line: 1, column: 10 }, - original: { line: 2, column: 20 }, + expectedMap.addMapping({ + generated: { line: 1, column: 4 }, + original: { line: 1, column: 4 }, + source: 'transformed-source' + }); + expectedMap.addMapping({ + generated: { line: 2, column: 4 }, + original: { line: 1, column: 0 }, + source: 'original-source' }); - var consumer = new SourceMapConsumer(generator.toJSON()); - - var n = 0; - consumer.eachMapping(function () { n++ }); + map1.applySourceMap(new SourceMapConsumer(map2.toJSON())); - assert.equal(n, 2, - "Should not de-duplicate mappings that have the same " + - "generated positions, but different original positions."); + util.assertEqualMaps(assert, map1.toJSON(), expectedMap.toJSON()); }; -}); +exports['test issue #192'] = function (assert, util) { + var generator = new SourceMapGenerator(); + generator.addMapping({ + source: 'a.js', + generated: { line: 1, column: 10 }, + original: { line: 1, column: 10 }, + }); + generator.addMapping({ + source: 'b.js', + generated: { line: 1, column: 10 }, + original: { line: 2, column: 20 }, + }); + + var consumer = new SourceMapConsumer(generator.toJSON()); + + var n = 0; + consumer.eachMapping(function () { n++ }); + + assert.equal(n, 2, + "Should not de-duplicate mappings that have the same " + + "generated positions, but different original positions."); +}; diff --git a/test/source-map/test-source-node.js b/test/source-map/test-source-node.js index 139af4e4..9ae3fbf6 100644 --- a/test/source-map/test-source-node.js +++ b/test/source-map/test-source-node.js @@ -4,609 +4,603 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceNode = require('../../lib/source-map/source-node').SourceNode; +var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; +var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; +var SourceNode = require('../../lib/source-map/source-node').SourceNode; - function forEachNewline(fn) { - return function (assert, util) { - ['\n', '\r\n'].forEach(fn.bind(null, assert, util)); - } +function forEachNewline(fn) { + return function (assert, util) { + ['\n', '\r\n'].forEach(fn.bind(null, assert, util)); } +} - exports['test .add()'] = function (assert, util) { - var node = new SourceNode(null, null, null); - - // Adding a string works. - node.add('function noop() {}'); - - // Adding another source node works. - node.add(new SourceNode(null, null, null)); +exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); - // Adding an array works. - node.add(['function foo() {', - new SourceNode(null, null, null, - 'return 10;'), - '}']); + // Adding a string works. + node.add('function noop() {}'); - // Adding other stuff doesn't. - assert.throws(function () { - node.add({}); - }); - assert.throws(function () { - node.add(function () {}); - }); - }; + // Adding another source node works. + node.add(new SourceNode(null, null, null)); - exports['test .prepend()'] = function (assert, util) { - var node = new SourceNode(null, null, null); - - // Prepending a string works. - node.prepend('function noop() {}'); - assert.equal(node.children[0], 'function noop() {}'); - assert.equal(node.children.length, 1); - - // Prepending another source node works. - node.prepend(new SourceNode(null, null, null)); - assert.equal(node.children[0], ''); - assert.equal(node.children[1], 'function noop() {}'); - assert.equal(node.children.length, 2); - - // Prepending an array works. - node.prepend(['function foo() {', - new SourceNode(null, null, null, - 'return 10;'), - '}']); - assert.equal(node.children[0], 'function foo() {'); - assert.equal(node.children[1], 'return 10;'); - assert.equal(node.children[2], '}'); - assert.equal(node.children[3], ''); - assert.equal(node.children[4], 'function noop() {}'); - assert.equal(node.children.length, 5); - - // Prepending other stuff doesn't. - assert.throws(function () { - node.prepend({}); - }); - assert.throws(function () { - node.prepend(function () {}); - }); - }; + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); - exports['test .toString()'] = function (assert, util) { - assert.equal((new SourceNode(null, null, null, - ['function foo() {', - new SourceNode(null, null, null, 'return 10;'), - '}'])).toString(), - 'function foo() {return 10;}'); - }; + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); +}; + +exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); +}; + +exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); +}; + +exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); +}; + +exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); +}; + +exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); +}; + +exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { + var node = new SourceNode(null, null, null, + ['(function () {' + nl, + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';' + nl, + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl, + '}());']); + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); - exports['test .join()'] = function (assert, util) { - assert.equal((new SourceNode(null, null, null, - ['a', 'b', 'c', 'd'])).join(', ').toString(), - 'a, b, c, d'); - }; + assert.equal(result.code, [ + '(function () {', + ' someCall();', + ' if (foo) bar();', + '}());' + ].join(nl)); - exports['test .walk()'] = function (assert, util) { - var node = new SourceNode(null, null, null, - ['(function () {\n', - ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', - ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', - '}());']); - var expected = [ - { str: '(function () {\n', source: null, line: null, column: null }, - { str: ' ', source: null, line: null, column: null }, - { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, - { str: ';\n', source: null, line: null, column: null }, - { str: ' ', source: null, line: null, column: null }, - { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, - { str: ';\n', source: null, line: null, column: null }, - { str: '}());', source: null, line: null, column: null }, - ]; - var i = 0; - node.walk(function (chunk, loc) { - assert.equal(expected[i].str, chunk); - assert.equal(expected[i].source, loc.source); - assert.equal(expected[i].line, loc.line); - assert.equal(expected[i].column, loc.column); - i++; - }); - }; + var map = result.map; + var mapWithoutOptions = node.toStringWithSourceMap().map; - exports['test .replaceRight'] = function (assert, util) { - var node; + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator'); + assert.ok(!('file' in mapWithoutOptions)); + mapWithoutOptions._file = 'foo.js'; + util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON()); - // Not nested - node = new SourceNode(null, null, null, 'hello world'); - node.replaceRight(/world/, 'universe'); - assert.equal(node.toString(), 'hello universe'); + map = new SourceMapConsumer(map.toString()); - // Nested - node = new SourceNode(null, null, null, - [new SourceNode(null, null, null, 'hey sexy mama, '), - new SourceNode(null, null, null, 'want to kill all humans?')]); - node.replaceRight(/kill all humans/, 'watch Futurama'); - assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); - }; + var actual; - exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { - var node = new SourceNode(null, null, null, - ['(function () {' + nl, - ' ', - new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), - new SourceNode(1, 8, 'a.js', '()'), - ';' + nl, - ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl, - '}());']); - var result = node.toStringWithSourceMap({ - file: 'foo.js' - }); + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); - assert.equal(result.code, [ - '(function () {', - ' someCall();', - ' if (foo) bar();', - '}());' - ].join(nl)); + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); - var map = result.map; - var mapWithoutOptions = node.toStringWithSourceMap().map; + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator'); - assert.ok(!('file' in mapWithoutOptions)); - mapWithoutOptions._file = 'foo.js'; - util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON()); + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); +}); - map = new SourceMapConsumer(map.toString()); +exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { + var testCode = util.testGeneratedCode.replace(/\n/g, nl); + var node = SourceNode.fromStringWithSourceMap( + testCode, + new SourceMapConsumer(util.testMap)); - var actual; + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, testCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); +}); - actual = map.originalPositionFor({ - line: 1, - column: 4 - }); - assert.equal(actual.source, null); - assert.equal(actual.line, null); - assert.equal(actual.column, null); +exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode.replace(/\n/g, nl), + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl)); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); +}); - actual = map.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(actual.source, 'a.js'); - assert.equal(actual.line, 1); - assert.equal(actual.column, 0); - assert.equal(actual.name, 'originalCall'); - - actual = map.originalPositionFor({ - line: 3, - column: 2 - }); - assert.equal(actual.source, 'b.js'); - assert.equal(actual.line, 2); - assert.equal(actual.column, 0); +exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + "(function() {" + nl, + " var Test = {};" + nl, + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl, + "}());" + nl, + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); - actual = map.originalPositionFor({ - line: 3, - column: 16 - }); - assert.equal(actual.source, null); - assert.equal(actual.line, null); - assert.equal(actual.column, null); + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); - actual = map.originalPositionFor({ - line: 4, - column: 2 - }); - assert.equal(actual.source, null); - assert.equal(actual.line, null); - assert.equal(actual.column, null); + var result = node.toStringWithSourceMap({ + file: 'foo.js' }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); +}); - exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { - var testCode = util.testGeneratedCode.replace(/\n/g, nl); - var node = SourceNode.fromStringWithSourceMap( - testCode, - new SourceMapConsumer(util.testMap)); - - var result = node.toStringWithSourceMap({ - file: 'min.js' - }); - var map = result.map; - var code = result.code; - - assert.equal(code, testCode); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = map.toJSON(); - assert.equal(map.version, util.testMap.version); - assert.equal(map.file, util.testMap.file); - assert.equal(map.mappings, util.testMap.mappings); - }); - - exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) { - var node = SourceNode.fromStringWithSourceMap( - util.testGeneratedCode.replace(/\n/g, nl), - new SourceMapConsumer(util.emptyMap)); - var result = node.toStringWithSourceMap({ - file: 'min.js' - }); - var map = result.map; - var code = result.code; - - assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl)); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = map.toJSON(); - assert.equal(map.version, util.emptyMap.version); - assert.equal(map.file, util.emptyMap.file); - assert.equal(map.mappings.length, util.emptyMap.mappings.length); - assert.equal(map.mappings, util.emptyMap.mappings); - }); - - exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - "(function() {" + nl, - " var Test = {};" + nl, - " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl), - " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl, - "}());" + nl, - "/* Generated Source */"]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); +exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) { + // Assume the following directory structure: + // + // http://foo.org/ + // bar.coffee + // app/ + // coffee/ + // foo.coffee + // coffeeBundle.js # Made from {foo,bar,baz}.coffee + // maps/ + // coffeeBundle.js.map + // js/ + // foo.js + // public/ + // app.js # Made from {foo,coffeeBundle}.js + // app.js.map + // + // http://www.example.com/ + // baz.coffee + + var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n'); + coffeeBundle.setSourceContent('foo.coffee', 'foo coffee'); + coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n')); + coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);')); + coffeeBundle = coffeeBundle.toStringWithSourceMap({ + file: 'foo.js', + sourceRoot: '..' + }); - var node = SourceNode.fromStringWithSourceMap( - input.code, - new SourceMapConsumer(input.map.toString())); + var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);'); - var result = node.toStringWithSourceMap({ - file: 'foo.js' - }); - var map = result.map; - var code = result.code; - - assert.equal(code, input.code); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = map.toJSON(); - var inputMap = input.map.toJSON(); - util.assertEqualMaps(assert, map, inputMap); - }); - - exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) { - // Assume the following directory structure: - // - // http://foo.org/ - // bar.coffee - // app/ - // coffee/ - // foo.coffee - // coffeeBundle.js # Made from {foo,bar,baz}.coffee - // maps/ - // coffeeBundle.js.map - // js/ - // foo.js - // public/ - // app.js # Made from {foo,coffeeBundle}.js - // app.js.map - // - // http://www.example.com/ - // baz.coffee - - var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n'); - coffeeBundle.setSourceContent('foo.coffee', 'foo coffee'); - coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n')); - coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);')); - coffeeBundle = coffeeBundle.toStringWithSourceMap({ - file: 'foo.js', - sourceRoot: '..' + var test = function(relativePath, expectedSources) { + var app = new SourceNode(); + app.add(SourceNode.fromStringWithSourceMap( + coffeeBundle.code, + new SourceMapConsumer(coffeeBundle.map.toString()), + relativePath)); + app.add(foo); + var i = 0; + app.walk(function (chunk, loc) { + assert.equal(loc.source, expectedSources[i]); + i++; }); - - var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);'); - - var test = function(relativePath, expectedSources) { - var app = new SourceNode(); - app.add(SourceNode.fromStringWithSourceMap( - coffeeBundle.code, - new SourceMapConsumer(coffeeBundle.map.toString()), - relativePath)); - app.add(foo); - var i = 0; - app.walk(function (chunk, loc) { - assert.equal(loc.source, expectedSources[i]); - i++; - }); - app.walkSourceContents(function (sourceFile, sourceContent) { - assert.equal(sourceFile, expectedSources[0]); - assert.equal(sourceContent, 'foo coffee'); - }) - }; - - test('../coffee/maps', [ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - // If the third parameter is omitted or set to the current working - // directory we get incorrect source paths: - - test(undefined, [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - test('', [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - test('.', [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - test('./', [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); + app.walkSourceContents(function (sourceFile, sourceContent) { + assert.equal(sourceFile, expectedSources[0]); + assert.equal(sourceContent, 'foo coffee'); + }) }; - exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - new SourceNode(1, 0, "a.js", "(function"), - new SourceNode(1, 0, "a.js", "() {" + nl), - " ", - new SourceNode(1, 0, "a.js", "var Test = "), - new SourceNode(1, 0, "b.js", "{};" + nl), - new SourceNode(2, 0, "b.js", "Test"), - new SourceNode(2, 0, "b.js", ".A", "A"), - new SourceNode(2, 20, "b.js", " = { value: ", "A"), - "1234", - new SourceNode(2, 40, "b.js", " };" + nl, "A"), - "}());" + nl, - "/* Generated Source */" - ]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); + test('../coffee/maps', [ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + // If the third parameter is omitted or set to the current working + // directory we get incorrect source paths: + + test(undefined, [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('.', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('./', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); +}; + +exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function"), + new SourceNode(1, 0, "a.js", "() {" + nl), + " ", + new SourceNode(1, 0, "a.js", "var Test = "), + new SourceNode(1, 0, "b.js", "{};" + nl), + new SourceNode(2, 0, "b.js", "Test"), + new SourceNode(2, 0, "b.js", ".A", "A"), + new SourceNode(2, 20, "b.js", " = { value: ", "A"), + "1234", + new SourceNode(2, 40, "b.js", " };" + nl, "A"), + "}());" + nl, + "/* Generated Source */" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); - assert.equal(input.code, [ - "(function() {", - " var Test = {};", - "Test.A = { value: 1234 };", - "}());", - "/* Generated Source */" - ].join(nl)) + assert.equal(input.code, [ + "(function() {", + " var Test = {};", + "Test.A = { value: 1234 };", + "}());", + "/* Generated Source */" + ].join(nl)) - var correctMap = new SourceMapGenerator({ - file: 'foo.js' - }); - correctMap.addMapping({ - generated: { line: 1, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - // Here is no need for a empty mapping, - // because mappings ends at eol - correctMap.addMapping({ - generated: { line: 2, column: 2 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 2, column: 13 }, - source: 'b.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 0 }, - source: 'b.js', - original: { line: 2, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 4 }, - source: 'b.js', - name: 'A', - original: { line: 2, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 6 }, - source: 'b.js', - name: 'A', - original: { line: 2, column: 20 } - }); - // This empty mapping is required, - // because there is a hole in the middle of the line - correctMap.addMapping({ - generated: { line: 3, column: 18 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 22 }, - source: 'b.js', - name: 'A', - original: { line: 2, column: 40 } - }); - // Here is no need for a empty mapping, - // because mappings ends at eol - - var inputMap = input.map.toJSON(); - correctMap = correctMap.toJSON(); - util.assertEqualMaps(assert, inputMap, correctMap); - }); - - exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl), - new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl), - new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl), - new SourceNode(2, 2, "b.js", "anotherLine();" + nl), - "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl, - new SourceNode(3, 4, "c.js", "anotherLine();" + nl), - "/*" + nl + "Generated" + nl + "Source" + nl + "*/" - ]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + // Here is no need for a empty mapping, + // because mappings ends at eol + correctMap.addMapping({ + generated: { line: 2, column: 2 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 13 }, + source: 'b.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'b.js', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 4 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 6 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 20 } + }); + // This empty mapping is required, + // because there is a hole in the middle of the line + correctMap.addMapping({ + generated: { line: 3, column: 18 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 22 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 40 } + }); + // Here is no need for a empty mapping, + // because mappings ends at eol - assert.equal(input.code, [ - "(function() {", - "var nextLine = 1;", - "anotherLine();", - "Test.call(this, 123);", - "this['stuff'] = 'v';", - "anotherLine();", - "/*", - "Generated", - "Source", - "*/", - "anotherLine();", - "/*", - "Generated", - "Source", - "*/" - ].join(nl)); - - var correctMap = new SourceMapGenerator({ - file: 'foo.js' - }); - correctMap.addMapping({ - generated: { line: 1, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 2, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 4, column: 0 }, - source: 'b.js', - original: { line: 2, column: 2 } - }); - correctMap.addMapping({ - generated: { line: 5, column: 0 }, - source: 'b.js', - original: { line: 2, column: 2 } - }); - correctMap.addMapping({ - generated: { line: 6, column: 0 }, - source: 'b.js', - original: { line: 2, column: 2 } - }); - correctMap.addMapping({ - generated: { line: 11, column: 0 }, - source: 'c.js', - original: { line: 3, column: 4 } - }); + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); +}); - var inputMap = input.map.toJSON(); - correctMap = correctMap.toJSON(); - util.assertEqualMaps(assert, inputMap, correctMap); +exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl), + new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl), + new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl), + new SourceNode(2, 2, "b.js", "anotherLine();" + nl), + "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl, + new SourceNode(3, 4, "c.js", "anotherLine();" + nl), + "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' }); - exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) { - var node = new SourceNode(1, 0, 'empty.js', ''); - var result = node.toStringWithSourceMap(); - assert.equal(result.code, ''); - }; + assert.equal(input.code, [ + "(function() {", + "var nextLine = 1;", + "anotherLine();", + "Test.call(this, 123);", + "this['stuff'] = 'v';", + "anotherLine();", + "/*", + "Generated", + "Source", + "*/", + "anotherLine();", + "/*", + "Generated", + "Source", + "*/" + ].join(nl)); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 5, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 6, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 11, column: 0 }, + source: 'c.js', + original: { line: 3, column: 4 } + }); - exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - "/***/" + nl + nl, - new SourceNode(1, 0, "a.js", "'use strict';" + nl), - new SourceNode(2, 0, "a.js", "a();"), - ]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); +}); - assert.equal(input.code, [ - "/***/", - "", - "'use strict';", - "a();", - ].join(nl)); +exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) { + var node = new SourceNode(1, 0, 'empty.js', ''); + var result = node.toStringWithSourceMap(); + assert.equal(result.code, ''); +}; + +exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + "/***/" + nl + nl, + new SourceNode(1, 0, "a.js", "'use strict';" + nl), + new SourceNode(2, 0, "a.js", "a();"), + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); - var correctMap = new SourceMapGenerator({ - file: 'foo.js' - }); - correctMap.addMapping({ - generated: { line: 3, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 4, column: 0 }, - source: 'a.js', - original: { line: 2, column: 0 } - }); + assert.equal(input.code, [ + "/***/", + "", + "'use strict';", + "a();", + ].join(nl)); - var inputMap = input.map.toJSON(); - correctMap = correctMap.toJSON(); - util.assertEqualMaps(assert, inputMap, correctMap); - }); - - exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { - var aNode = new SourceNode(1, 1, 'a.js', 'a'); - aNode.setSourceContent('a.js', 'someContent'); - var node = new SourceNode(null, null, null, - ['(function () {\n', - ' ', aNode, - ' ', new SourceNode(1, 1, 'b.js', 'b'), - '}());']); - node.setSourceContent('b.js', 'otherContent'); - var map = node.toStringWithSourceMap({ - file: 'foo.js' - }).map; - - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = new SourceMapConsumer(map.toString()); - - assert.equal(map.sources.length, 2); - assert.equal(map.sources[0], 'a.js'); - assert.equal(map.sources[1], 'b.js'); - assert.equal(map.sourcesContent.length, 2); - assert.equal(map.sourcesContent[0], 'someContent'); - assert.equal(map.sourcesContent[1], 'otherContent'); - }; + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 }, + source: 'a.js', + original: { line: 2, column: 0 } + }); - exports['test walkSourceContents'] = function (assert, util) { - var aNode = new SourceNode(1, 1, 'a.js', 'a'); - aNode.setSourceContent('a.js', 'someContent'); - var node = new SourceNode(null, null, null, - ['(function () {\n', - ' ', aNode, - ' ', new SourceNode(1, 1, 'b.js', 'b'), - '}());']); - node.setSourceContent('b.js', 'otherContent'); - var results = []; - node.walkSourceContents(function (sourceFile, sourceContent) { - results.push([sourceFile, sourceContent]); - }); - assert.equal(results.length, 2); - assert.equal(results[0][0], 'a.js'); - assert.equal(results[0][1], 'someContent'); - assert.equal(results[1][0], 'b.js'); - assert.equal(results[1][1], 'otherContent'); - }; + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); }); + +exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); +}; + +exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); +}; diff --git a/test/source-map/test-util.js b/test/source-map/test-util.js index 530dbdbc..15f97267 100644 --- a/test/source-map/test-util.js +++ b/test/source-map/test-util.js @@ -4,217 +4,210 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var libUtil = require('../../lib/source-map/util'); - - exports['test urls'] = function (assert, util) { - var assertUrl = function (url) { - assert.equal(url, libUtil.urlGenerate(libUtil.urlParse(url))); - }; - assertUrl('http://'); - assertUrl('http://www.example.com'); - assertUrl('http://user:pass@www.example.com'); - assertUrl('http://www.example.com:80'); - assertUrl('http://www.example.com/'); - assertUrl('http://www.example.com/foo/bar'); - assertUrl('http://www.example.com/foo/bar/'); - assertUrl('http://user:pass@www.example.com:80/foo/bar/'); - - assertUrl('//'); - assertUrl('//www.example.com'); - assertUrl('file:///www.example.com'); - - assert.equal(libUtil.urlParse(''), null); - assert.equal(libUtil.urlParse('.'), null); - assert.equal(libUtil.urlParse('..'), null); - assert.equal(libUtil.urlParse('a'), null); - assert.equal(libUtil.urlParse('a/b'), null); - assert.equal(libUtil.urlParse('a//b'), null); - assert.equal(libUtil.urlParse('/a'), null); - assert.equal(libUtil.urlParse('data:foo,bar'), null); - }; - - exports['test normalize()'] = function (assert, util) { - assert.equal(libUtil.normalize('/..'), '/'); - assert.equal(libUtil.normalize('/../'), '/'); - assert.equal(libUtil.normalize('/../../../..'), '/'); - assert.equal(libUtil.normalize('/../../../../a/b/c'), '/a/b/c'); - assert.equal(libUtil.normalize('/a/b/c/../../../d/../../e'), '/e'); - - assert.equal(libUtil.normalize('..'), '..'); - assert.equal(libUtil.normalize('../'), '../'); - assert.equal(libUtil.normalize('../../a/'), '../../a/'); - assert.equal(libUtil.normalize('a/..'), '.'); - assert.equal(libUtil.normalize('a/../../..'), '../..'); - - assert.equal(libUtil.normalize('/.'), '/'); - assert.equal(libUtil.normalize('/./'), '/'); - assert.equal(libUtil.normalize('/./././.'), '/'); - assert.equal(libUtil.normalize('/././././a/b/c'), '/a/b/c'); - assert.equal(libUtil.normalize('/a/b/c/./././d/././e'), '/a/b/c/d/e'); - - assert.equal(libUtil.normalize(''), '.'); - assert.equal(libUtil.normalize('.'), '.'); - assert.equal(libUtil.normalize('./'), '.'); - assert.equal(libUtil.normalize('././a'), 'a'); - assert.equal(libUtil.normalize('a/./'), 'a/'); - assert.equal(libUtil.normalize('a/././.'), 'a'); - - assert.equal(libUtil.normalize('/a/b//c////d/////'), '/a/b/c/d/'); - assert.equal(libUtil.normalize('///a/b//c////d/////'), '///a/b/c/d/'); - assert.equal(libUtil.normalize('a/b//c////d'), 'a/b/c/d'); - - assert.equal(libUtil.normalize('.///.././../a/b//./..'), '../../a') - - assert.equal(libUtil.normalize('http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.normalize('http://www.example.com/'), 'http://www.example.com/'); - assert.equal(libUtil.normalize('http://www.example.com/./..//a/b/c/.././d//'), 'http://www.example.com/a/b/d/'); - }; - - exports['test join()'] = function (assert, util) { - assert.equal(libUtil.join('a', 'b'), 'a/b'); - assert.equal(libUtil.join('a/', 'b'), 'a/b'); - assert.equal(libUtil.join('a//', 'b'), 'a/b'); - assert.equal(libUtil.join('a', 'b/'), 'a/b/'); - assert.equal(libUtil.join('a', 'b//'), 'a/b/'); - assert.equal(libUtil.join('a/', '/b'), '/b'); - assert.equal(libUtil.join('a//', '//b'), '//b'); - - assert.equal(libUtil.join('a', '..'), '.'); - assert.equal(libUtil.join('a', '../b'), 'b'); - assert.equal(libUtil.join('a/b', '../c'), 'a/c'); - - assert.equal(libUtil.join('a', '.'), 'a'); - assert.equal(libUtil.join('a', './b'), 'a/b'); - assert.equal(libUtil.join('a/b', './c'), 'a/b/c'); - - assert.equal(libUtil.join('a', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('a', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('', 'b'), 'b'); - assert.equal(libUtil.join('.', 'b'), 'b'); - assert.equal(libUtil.join('', 'b/'), 'b/'); - assert.equal(libUtil.join('.', 'b/'), 'b/'); - assert.equal(libUtil.join('', 'b//'), 'b/'); - assert.equal(libUtil.join('.', 'b//'), 'b/'); - - assert.equal(libUtil.join('', '..'), '..'); - assert.equal(libUtil.join('.', '..'), '..'); - assert.equal(libUtil.join('', '../b'), '../b'); - assert.equal(libUtil.join('.', '../b'), '../b'); - - assert.equal(libUtil.join('', '.'), '.'); - assert.equal(libUtil.join('.', '.'), '.'); - assert.equal(libUtil.join('', './b'), 'b'); - assert.equal(libUtil.join('.', './b'), 'b'); - - assert.equal(libUtil.join('', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('.', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('', 'data:foo,bar'), 'data:foo,bar'); - assert.equal(libUtil.join('.', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('..', 'b'), '../b'); - assert.equal(libUtil.join('..', 'b/'), '../b/'); - assert.equal(libUtil.join('..', 'b//'), '../b/'); - - assert.equal(libUtil.join('..', '..'), '../..'); - assert.equal(libUtil.join('..', '../b'), '../../b'); - - assert.equal(libUtil.join('..', '.'), '..'); - assert.equal(libUtil.join('..', './b'), '../b'); - - assert.equal(libUtil.join('..', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('..', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('a', ''), 'a'); - assert.equal(libUtil.join('a', '.'), 'a'); - assert.equal(libUtil.join('a/', ''), 'a'); - assert.equal(libUtil.join('a/', '.'), 'a'); - assert.equal(libUtil.join('a//', ''), 'a'); - assert.equal(libUtil.join('a//', '.'), 'a'); - assert.equal(libUtil.join('/a', ''), '/a'); - assert.equal(libUtil.join('/a', '.'), '/a'); - assert.equal(libUtil.join('', ''), '.'); - assert.equal(libUtil.join('.', ''), '.'); - assert.equal(libUtil.join('.', ''), '.'); - assert.equal(libUtil.join('.', '.'), '.'); - assert.equal(libUtil.join('..', ''), '..'); - assert.equal(libUtil.join('..', '.'), '..'); - assert.equal(libUtil.join('http://foo.org/a', ''), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a/', ''), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a/', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a//', ''), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a//', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org', ''), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org', '.'), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org/', ''), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org/', '.'), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org//', ''), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org//', '.'), 'http://foo.org/'); - assert.equal(libUtil.join('//www.example.com', ''), '//www.example.com/'); - assert.equal(libUtil.join('//www.example.com', '.'), '//www.example.com/'); - - - assert.equal(libUtil.join('http://foo.org/a', 'b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a/', 'b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a//', 'b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a', 'b/'), 'http://foo.org/a/b/'); - assert.equal(libUtil.join('http://foo.org/a', 'b//'), 'http://foo.org/a/b/'); - assert.equal(libUtil.join('http://foo.org/a/', '/b'), 'http://foo.org/b'); - assert.equal(libUtil.join('http://foo.org/a//', '//b'), 'http://b'); - - assert.equal(libUtil.join('http://foo.org/a', '..'), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org/a', '../b'), 'http://foo.org/b'); - assert.equal(libUtil.join('http://foo.org/a/b', '../c'), 'http://foo.org/a/c'); - - assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a', './b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a/b', './c'), 'http://foo.org/a/b/c'); - - assert.equal(libUtil.join('http://foo.org/a', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('http://foo.org/a', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('http://foo.org', 'a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/', 'a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org//', 'a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org', '/a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/', '/a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org//', '/a'), 'http://foo.org/a'); - - - assert.equal(libUtil.join('http://', 'www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('file:///', 'www.example.com'), 'file:///www.example.com'); - assert.equal(libUtil.join('http://', 'ftp://example.com'), 'ftp://example.com'); - - assert.equal(libUtil.join('http://www.example.com', '//foo.org/bar'), 'http://foo.org/bar'); - assert.equal(libUtil.join('//www.example.com', '//foo.org/bar'), '//foo.org/bar'); - }; - - // TODO Issue #128: Define and test this function properly. - exports['test relative()'] = function (assert, util) { - assert.equal(libUtil.relative('/the/root', '/the/root/one.js'), 'one.js'); - assert.equal(libUtil.relative('http://the/root', 'http://the/root/one.js'), 'one.js'); - assert.equal(libUtil.relative('/the/root', '/the/rootone.js'), '../rootone.js'); - assert.equal(libUtil.relative('http://the/root', 'http://the/rootone.js'), '../rootone.js'); - assert.equal(libUtil.relative('/the/root', '/therootone.js'), '/therootone.js'); - assert.equal(libUtil.relative('http://the/root', '/therootone.js'), '/therootone.js'); - - assert.equal(libUtil.relative('', '/the/root/one.js'), '/the/root/one.js'); - assert.equal(libUtil.relative('.', '/the/root/one.js'), '/the/root/one.js'); - assert.equal(libUtil.relative('', 'the/root/one.js'), 'the/root/one.js'); - assert.equal(libUtil.relative('.', 'the/root/one.js'), 'the/root/one.js'); - - assert.equal(libUtil.relative('/', '/the/root/one.js'), 'the/root/one.js'); - assert.equal(libUtil.relative('/', 'the/root/one.js'), 'the/root/one.js'); - }; - -}); +var libUtil = require('../../lib/source-map/util'); + +exports['test urls'] = function (assert, util) { +var assertUrl = function (url) { + assert.equal(url, libUtil.urlGenerate(libUtil.urlParse(url))); +}; +assertUrl('http://'); +assertUrl('http://www.example.com'); +assertUrl('http://user:pass@www.example.com'); +assertUrl('http://www.example.com:80'); +assertUrl('http://www.example.com/'); +assertUrl('http://www.example.com/foo/bar'); +assertUrl('http://www.example.com/foo/bar/'); +assertUrl('http://user:pass@www.example.com:80/foo/bar/'); + +assertUrl('//'); +assertUrl('//www.example.com'); +assertUrl('file:///www.example.com'); + +assert.equal(libUtil.urlParse(''), null); +assert.equal(libUtil.urlParse('.'), null); +assert.equal(libUtil.urlParse('..'), null); +assert.equal(libUtil.urlParse('a'), null); +assert.equal(libUtil.urlParse('a/b'), null); +assert.equal(libUtil.urlParse('a//b'), null); +assert.equal(libUtil.urlParse('/a'), null); +assert.equal(libUtil.urlParse('data:foo,bar'), null); +}; + +exports['test normalize()'] = function (assert, util) { +assert.equal(libUtil.normalize('/..'), '/'); +assert.equal(libUtil.normalize('/../'), '/'); +assert.equal(libUtil.normalize('/../../../..'), '/'); +assert.equal(libUtil.normalize('/../../../../a/b/c'), '/a/b/c'); +assert.equal(libUtil.normalize('/a/b/c/../../../d/../../e'), '/e'); + +assert.equal(libUtil.normalize('..'), '..'); +assert.equal(libUtil.normalize('../'), '../'); +assert.equal(libUtil.normalize('../../a/'), '../../a/'); +assert.equal(libUtil.normalize('a/..'), '.'); +assert.equal(libUtil.normalize('a/../../..'), '../..'); + +assert.equal(libUtil.normalize('/.'), '/'); +assert.equal(libUtil.normalize('/./'), '/'); +assert.equal(libUtil.normalize('/./././.'), '/'); +assert.equal(libUtil.normalize('/././././a/b/c'), '/a/b/c'); +assert.equal(libUtil.normalize('/a/b/c/./././d/././e'), '/a/b/c/d/e'); + +assert.equal(libUtil.normalize(''), '.'); +assert.equal(libUtil.normalize('.'), '.'); +assert.equal(libUtil.normalize('./'), '.'); +assert.equal(libUtil.normalize('././a'), 'a'); +assert.equal(libUtil.normalize('a/./'), 'a/'); +assert.equal(libUtil.normalize('a/././.'), 'a'); + +assert.equal(libUtil.normalize('/a/b//c////d/////'), '/a/b/c/d/'); +assert.equal(libUtil.normalize('///a/b//c////d/////'), '///a/b/c/d/'); +assert.equal(libUtil.normalize('a/b//c////d'), 'a/b/c/d'); + +assert.equal(libUtil.normalize('.///.././../a/b//./..'), '../../a') + +assert.equal(libUtil.normalize('http://www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.normalize('http://www.example.com/'), 'http://www.example.com/'); +assert.equal(libUtil.normalize('http://www.example.com/./..//a/b/c/.././d//'), 'http://www.example.com/a/b/d/'); +}; + +exports['test join()'] = function (assert, util) { +assert.equal(libUtil.join('a', 'b'), 'a/b'); +assert.equal(libUtil.join('a/', 'b'), 'a/b'); +assert.equal(libUtil.join('a//', 'b'), 'a/b'); +assert.equal(libUtil.join('a', 'b/'), 'a/b/'); +assert.equal(libUtil.join('a', 'b//'), 'a/b/'); +assert.equal(libUtil.join('a/', '/b'), '/b'); +assert.equal(libUtil.join('a//', '//b'), '//b'); + +assert.equal(libUtil.join('a', '..'), '.'); +assert.equal(libUtil.join('a', '../b'), 'b'); +assert.equal(libUtil.join('a/b', '../c'), 'a/c'); + +assert.equal(libUtil.join('a', '.'), 'a'); +assert.equal(libUtil.join('a', './b'), 'a/b'); +assert.equal(libUtil.join('a/b', './c'), 'a/b/c'); + +assert.equal(libUtil.join('a', 'http://www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.join('a', 'data:foo,bar'), 'data:foo,bar'); + + +assert.equal(libUtil.join('', 'b'), 'b'); +assert.equal(libUtil.join('.', 'b'), 'b'); +assert.equal(libUtil.join('', 'b/'), 'b/'); +assert.equal(libUtil.join('.', 'b/'), 'b/'); +assert.equal(libUtil.join('', 'b//'), 'b/'); +assert.equal(libUtil.join('.', 'b//'), 'b/'); + +assert.equal(libUtil.join('', '..'), '..'); +assert.equal(libUtil.join('.', '..'), '..'); +assert.equal(libUtil.join('', '../b'), '../b'); +assert.equal(libUtil.join('.', '../b'), '../b'); + +assert.equal(libUtil.join('', '.'), '.'); +assert.equal(libUtil.join('.', '.'), '.'); +assert.equal(libUtil.join('', './b'), 'b'); +assert.equal(libUtil.join('.', './b'), 'b'); + +assert.equal(libUtil.join('', 'http://www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.join('.', 'http://www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.join('', 'data:foo,bar'), 'data:foo,bar'); +assert.equal(libUtil.join('.', 'data:foo,bar'), 'data:foo,bar'); + + +assert.equal(libUtil.join('..', 'b'), '../b'); +assert.equal(libUtil.join('..', 'b/'), '../b/'); +assert.equal(libUtil.join('..', 'b//'), '../b/'); + +assert.equal(libUtil.join('..', '..'), '../..'); +assert.equal(libUtil.join('..', '../b'), '../../b'); + +assert.equal(libUtil.join('..', '.'), '..'); +assert.equal(libUtil.join('..', './b'), '../b'); + +assert.equal(libUtil.join('..', 'http://www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.join('..', 'data:foo,bar'), 'data:foo,bar'); + + +assert.equal(libUtil.join('a', ''), 'a'); +assert.equal(libUtil.join('a', '.'), 'a'); +assert.equal(libUtil.join('a/', ''), 'a'); +assert.equal(libUtil.join('a/', '.'), 'a'); +assert.equal(libUtil.join('a//', ''), 'a'); +assert.equal(libUtil.join('a//', '.'), 'a'); +assert.equal(libUtil.join('/a', ''), '/a'); +assert.equal(libUtil.join('/a', '.'), '/a'); +assert.equal(libUtil.join('', ''), '.'); +assert.equal(libUtil.join('.', ''), '.'); +assert.equal(libUtil.join('.', ''), '.'); +assert.equal(libUtil.join('.', '.'), '.'); +assert.equal(libUtil.join('..', ''), '..'); +assert.equal(libUtil.join('..', '.'), '..'); +assert.equal(libUtil.join('http://foo.org/a', ''), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/a/', ''), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/a/', '.'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/a//', ''), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/a//', '.'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org', ''), 'http://foo.org/'); +assert.equal(libUtil.join('http://foo.org', '.'), 'http://foo.org/'); +assert.equal(libUtil.join('http://foo.org/', ''), 'http://foo.org/'); +assert.equal(libUtil.join('http://foo.org/', '.'), 'http://foo.org/'); +assert.equal(libUtil.join('http://foo.org//', ''), 'http://foo.org/'); +assert.equal(libUtil.join('http://foo.org//', '.'), 'http://foo.org/'); +assert.equal(libUtil.join('//www.example.com', ''), '//www.example.com/'); +assert.equal(libUtil.join('//www.example.com', '.'), '//www.example.com/'); + + +assert.equal(libUtil.join('http://foo.org/a', 'b'), 'http://foo.org/a/b'); +assert.equal(libUtil.join('http://foo.org/a/', 'b'), 'http://foo.org/a/b'); +assert.equal(libUtil.join('http://foo.org/a//', 'b'), 'http://foo.org/a/b'); +assert.equal(libUtil.join('http://foo.org/a', 'b/'), 'http://foo.org/a/b/'); +assert.equal(libUtil.join('http://foo.org/a', 'b//'), 'http://foo.org/a/b/'); +assert.equal(libUtil.join('http://foo.org/a/', '/b'), 'http://foo.org/b'); +assert.equal(libUtil.join('http://foo.org/a//', '//b'), 'http://b'); + +assert.equal(libUtil.join('http://foo.org/a', '..'), 'http://foo.org/'); +assert.equal(libUtil.join('http://foo.org/a', '../b'), 'http://foo.org/b'); +assert.equal(libUtil.join('http://foo.org/a/b', '../c'), 'http://foo.org/a/c'); + +assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/a', './b'), 'http://foo.org/a/b'); +assert.equal(libUtil.join('http://foo.org/a/b', './c'), 'http://foo.org/a/b/c'); + +assert.equal(libUtil.join('http://foo.org/a', 'http://www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.join('http://foo.org/a', 'data:foo,bar'), 'data:foo,bar'); + + +assert.equal(libUtil.join('http://foo.org', 'a'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/', 'a'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org//', 'a'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org', '/a'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org/', '/a'), 'http://foo.org/a'); +assert.equal(libUtil.join('http://foo.org//', '/a'), 'http://foo.org/a'); + + +assert.equal(libUtil.join('http://', 'www.example.com'), 'http://www.example.com'); +assert.equal(libUtil.join('file:///', 'www.example.com'), 'file:///www.example.com'); +assert.equal(libUtil.join('http://', 'ftp://example.com'), 'ftp://example.com'); + +assert.equal(libUtil.join('http://www.example.com', '//foo.org/bar'), 'http://foo.org/bar'); +assert.equal(libUtil.join('//www.example.com', '//foo.org/bar'), '//foo.org/bar'); +}; + +// TODO Issue #128: Define and test this function properly. +exports['test relative()'] = function (assert, util) { +assert.equal(libUtil.relative('/the/root', '/the/root/one.js'), 'one.js'); +assert.equal(libUtil.relative('http://the/root', 'http://the/root/one.js'), 'one.js'); +assert.equal(libUtil.relative('/the/root', '/the/rootone.js'), '../rootone.js'); +assert.equal(libUtil.relative('http://the/root', 'http://the/rootone.js'), '../rootone.js'); +assert.equal(libUtil.relative('/the/root', '/therootone.js'), '/therootone.js'); +assert.equal(libUtil.relative('http://the/root', '/therootone.js'), '/therootone.js'); + +assert.equal(libUtil.relative('', '/the/root/one.js'), '/the/root/one.js'); +assert.equal(libUtil.relative('.', '/the/root/one.js'), '/the/root/one.js'); +assert.equal(libUtil.relative('', 'the/root/one.js'), 'the/root/one.js'); +assert.equal(libUtil.relative('.', 'the/root/one.js'), 'the/root/one.js'); + +assert.equal(libUtil.relative('/', '/the/root/one.js'), 'the/root/one.js'); +assert.equal(libUtil.relative('/', 'the/root/one.js'), 'the/root/one.js'); +}; diff --git a/test/source-map/util.js b/test/source-map/util.js index f48703bc..9e0c67e1 100644 --- a/test/source-map/util.js +++ b/test/source-map/util.js @@ -4,298 +4,291 @@ * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var util = require('../../lib/source-map/util'); +var util = require('../../lib/source-map/util'); - // This is a test mapping which maps functions from two different files - // (one.js and two.js) to a minified generated source. - // - // Here is one.js: - // - // ONE.foo = function (bar) { - // return baz(bar); - // }; - // - // Here is two.js: - // - // TWO.inc = function (n) { - // return n + 1; - // }; - // - // And here is the generated code (min.js): - // - // ONE.foo=function(a){return baz(a);}; - // TWO.inc=function(a){return a+1;}; - exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ - " TWO.inc=function(a){return a+1;};"; - exports.testMap = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourceRoot: '/the/root', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapNoSourceRoot = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapEmptySourceRoot = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourceRoot: '', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - // This mapping is identical to above, but uses the indexed format instead. - exports.indexedTestMap = { - version: 3, - file: 'min.js', - sections: [ - { - offset: { - line: 0, - column: 0 - }, - map: { - version: 3, - sources: [ - "one.js" - ], - sourcesContent: [ - ' ONE.foo = function (bar) {\n' + - ' return baz(bar);\n' + - ' };', - ], - names: [ - "bar", - "baz" - ], - mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID", - file: "min.js", - sourceRoot: "/the/root" - } +// This is a test mapping which maps functions from two different files +// (one.js and two.js) to a minified generated source. +// +// Here is one.js: +// +// ONE.foo = function (bar) { +// return baz(bar); +// }; +// +// Here is two.js: +// +// TWO.inc = function (n) { +// return n + 1; +// }; +// +// And here is the generated code (min.js): +// +// ONE.foo=function(a){return baz(a);}; +// TWO.inc=function(a){return a+1;}; +exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; +exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; +exports.testMapNoSourceRoot = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; +exports.testMapEmptySourceRoot = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; +// This mapping is identical to above, but uses the indexed format instead. +exports.indexedTestMap = { + version: 3, + file: 'min.js', + sections: [ + { + offset: { + line: 0, + column: 0 }, - { - offset: { - line: 1, - column: 0 - }, - map: { - version: 3, - sources: [ - "two.js" - ], - sourcesContent: [ - ' TWO.inc = function (n) {\n' + - ' return n + 1;\n' + - ' };' - ], - names: [ - "n" - ], - mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA", - file: "min.js", - sourceRoot: "/the/root" - } + map: { + version: 3, + sources: [ + "one.js" + ], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ], + names: [ + "bar", + "baz" + ], + mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID", + file: "min.js", + sourceRoot: "/the/root" } - ] - }; - exports.indexedTestMapDifferentSourceRoots = { - version: 3, - file: 'min.js', - sections: [ - { - offset: { - line: 0, - column: 0 - }, - map: { - version: 3, - sources: [ - "one.js" - ], - sourcesContent: [ - ' ONE.foo = function (bar) {\n' + - ' return baz(bar);\n' + - ' };', - ], - names: [ - "bar", - "baz" - ], - mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID", - file: "min.js", - sourceRoot: "/the/root" - } + }, + { + offset: { + line: 1, + column: 0 }, - { - offset: { - line: 1, - column: 0 - }, - map: { - version: 3, - sources: [ - "two.js" - ], - sourcesContent: [ - ' TWO.inc = function (n) {\n' + - ' return n + 1;\n' + - ' };' - ], - names: [ - "n" - ], - mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA", - file: "min.js", - sourceRoot: "/different/root" - } + map: { + version: 3, + sources: [ + "two.js" + ], + sourcesContent: [ + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + names: [ + "n" + ], + mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA", + file: "min.js", + sourceRoot: "/the/root" } - ] - }; - exports.testMapWithSourcesContent = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourcesContent: [ - ' ONE.foo = function (bar) {\n' + - ' return baz(bar);\n' + - ' };', - ' TWO.inc = function (n) {\n' + - ' return n + 1;\n' + - ' };' - ], - sourceRoot: '/the/root', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapRelativeSources = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['./one.js', './two.js'], - sourcesContent: [ - ' ONE.foo = function (bar) {\n' + - ' return baz(bar);\n' + - ' };', - ' TWO.inc = function (n) {\n' + - ' return n + 1;\n' + - ' };' - ], - sourceRoot: '/the/root', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.emptyMap = { - version: 3, - file: 'min.js', - names: [], - sources: [], - mappings: '' - }; - + } + ] +}; +exports.indexedTestMapDifferentSourceRoots = { + version: 3, + file: 'min.js', + sections: [ + { + offset: { + line: 0, + column: 0 + }, + map: { + version: 3, + sources: [ + "one.js" + ], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ], + names: [ + "bar", + "baz" + ], + mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID", + file: "min.js", + sourceRoot: "/the/root" + } + }, + { + offset: { + line: 1, + column: 0 + }, + map: { + version: 3, + sources: [ + "two.js" + ], + sourcesContent: [ + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + names: [ + "n" + ], + mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA", + file: "min.js", + sourceRoot: "/different/root" + } + } + ] +}; +exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; +exports.testMapRelativeSources = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['./one.js', './two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; +exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' +}; - function assertMapping(generatedLine, generatedColumn, originalSource, - originalLine, originalColumn, name, bias, map, assert, - dontTestGenerated, dontTestOriginal) { - if (!dontTestOriginal) { - var origMapping = map.originalPositionFor({ - line: generatedLine, - column: generatedColumn, - bias: bias - }); - assert.equal(origMapping.name, name, - 'Incorrect name, expected ' + JSON.stringify(name) - + ', got ' + JSON.stringify(origMapping.name)); - assert.equal(origMapping.line, originalLine, - 'Incorrect line, expected ' + JSON.stringify(originalLine) - + ', got ' + JSON.stringify(origMapping.line)); - assert.equal(origMapping.column, originalColumn, - 'Incorrect column, expected ' + JSON.stringify(originalColumn) - + ', got ' + JSON.stringify(origMapping.column)); - var expectedSource; +function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, bias, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn, + bias: bias + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); - if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { - expectedSource = originalSource; - } else if (originalSource) { - expectedSource = map.sourceRoot - ? util.join(map.sourceRoot, originalSource) - : originalSource; - } else { - expectedSource = null; - } + var expectedSource; - assert.equal(origMapping.source, expectedSource, - 'Incorrect source, expected ' + JSON.stringify(expectedSource) - + ', got ' + JSON.stringify(origMapping.source)); + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; } - if (!dontTestGenerated) { - var genMapping = map.generatedPositionFor({ - source: originalSource, - line: originalLine, - column: originalColumn, - bias: bias - }); - assert.equal(genMapping.line, generatedLine, - 'Incorrect line, expected ' + JSON.stringify(generatedLine) - + ', got ' + JSON.stringify(genMapping.line)); - assert.equal(genMapping.column, generatedColumn, - 'Incorrect column, expected ' + JSON.stringify(generatedColumn) - + ', got ' + JSON.stringify(genMapping.column)); - } + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); } - exports.assertMapping = assertMapping; - function assertEqualMaps(assert, actualMap, expectedMap) { - assert.equal(actualMap.version, expectedMap.version, "version mismatch"); - assert.equal(actualMap.file, expectedMap.file, "file mismatch"); - assert.equal(actualMap.names.length, - expectedMap.names.length, - "names length mismatch: " + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn, + bias: bias + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } +} +exports.assertMapping = assertMapping; + +function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); - for (var i = 0; i < actualMap.names.length; i++) { - assert.equal(actualMap.names[i], - expectedMap.names[i], - "names[" + i + "] mismatch: " + - actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); - } - assert.equal(actualMap.sources.length, - expectedMap.sources.length, - "sources length mismatch: " + - actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); - for (var i = 0; i < actualMap.sources.length; i++) { - assert.equal(actualMap.sources[i], - expectedMap.sources[i], - "sources[" + i + "] length mismatch: " + - actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); - } - assert.equal(actualMap.sourceRoot, - expectedMap.sourceRoot, - "sourceRoot mismatch: " + - actualMap.sourceRoot + " != " + expectedMap.sourceRoot); - assert.equal(actualMap.mappings, expectedMap.mappings, - "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); - if (actualMap.sourcesContent) { - assert.equal(actualMap.sourcesContent.length, - expectedMap.sourcesContent.length, - "sourcesContent length mismatch"); - for (var i = 0; i < actualMap.sourcesContent.length; i++) { - assert.equal(actualMap.sourcesContent[i], - expectedMap.sourcesContent[i], - "sourcesContent[" + i + "] mismatch"); - } + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, + "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); } } - exports.assertEqualMaps = assertEqualMaps; - -}); +} +exports.assertEqualMaps = assertEqualMaps;