| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 | /* -*- Mode: js; js-indent-level: 2; -*- *//* * Copyright 2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause *//** * 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;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 consecutive slashes with one slash. * - Removes unnecessary '.' parts. * - Removes unnecessary '<dir>/..' 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;  }  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('/');  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 || '/';  }  // `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;  }  // `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);  if (aRootUrl) {    aRootUrl.path = joined;    return urlGenerate(aRootUrl);  }  return joined;}exports.join = join;exports.isAbsolute = function (aPath) {  return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp);};/** * 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 = ".";  }  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;    }    // 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;    }    ++level;  }  // 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;var supportsNullProto = (function () {  var obj = Object.create(null);  return !('__proto__' in obj);}());function identity (s) {  return s;}/** * 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) {  if (isProtoString(aStr)) {    return '$' + aStr;  }  return aStr;}exports.toSetString = supportsNullProto ? identity : toSetString;function fromSetString(aStr) {  if (isProtoString(aStr)) {    return aStr.slice(1);  }  return aStr;}exports.fromSetString = supportsNullProto ? identity : fromSetString;function isProtoString(s) {  if (!s) {    return false;  }  var length = s.length;  if (length < 9 /* "__proto__".length */) {    return false;  }  if (s.charCodeAt(length - 1) !== 95  /* '_' */ ||      s.charCodeAt(length - 2) !== 95  /* '_' */ ||      s.charCodeAt(length - 3) !== 111 /* 'o' */ ||      s.charCodeAt(length - 4) !== 116 /* 't' */ ||      s.charCodeAt(length - 5) !== 111 /* 'o' */ ||      s.charCodeAt(length - 6) !== 114 /* 'r' */ ||      s.charCodeAt(length - 7) !== 112 /* 'p' */ ||      s.charCodeAt(length - 8) !== 95  /* '_' */ ||      s.charCodeAt(length - 9) !== 95  /* '_' */) {    return false;  }  for (var i = length - 10; i >= 0; i--) {    if (s.charCodeAt(i) !== 36 /* '$' */) {      return false;    }  }  return true;}/** * 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.originalLine - mappingB.originalLine;  if (cmp !== 0) {    return cmp;  }  cmp = mappingA.originalColumn - mappingB.originalColumn;  if (cmp !== 0 || onlyCompareOriginal) {    return cmp;  }  cmp = mappingA.generatedColumn - mappingB.generatedColumn;  if (cmp !== 0) {    return cmp;  }  cmp = mappingA.generatedLine - mappingB.generatedLine;  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.generatedColumn - mappingB.generatedColumn;  if (cmp !== 0 || onlyCompareGenerated) {    return cmp;  }  cmp = mappingA.source - mappingB.source;  if (cmp !== 0) {    return cmp;  }  cmp = mappingA.originalLine - mappingB.originalLine;  if (cmp !== 0) {    return cmp;  }  cmp = mappingA.originalColumn - mappingB.originalColumn;  if (cmp !== 0) {    return cmp;  }  return mappingA.name - mappingB.name;}exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;function strcmp(aStr1, aStr2) {  if (aStr1 === aStr2) {    return 0;  }  if (aStr1 > aStr2) {    return 1;  }  return -1;}/** * 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.generatedColumn - mappingB.generatedColumn;  if (cmp !== 0) {    return cmp;  }  cmp = strcmp(mappingA.source, mappingB.source);  if (cmp !== 0) {    return cmp;  }  cmp = mappingA.originalLine - mappingB.originalLine;  if (cmp !== 0) {    return cmp;  }  cmp = mappingA.originalColumn - mappingB.originalColumn;  if (cmp !== 0) {    return cmp;  }  return strcmp(mappingA.name, mappingB.name);}exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
 |