Best Python code snippet using ATX
SourceMap.js
Source:SourceMap.js  
1/**2 * Copyright (c) 2015-present, Facebook, Inc.3 * All rights reserved.4 *5 * This source code is licensed under the BSD-style license found in the6 * LICENSE file in the root directory of this source tree. An additional grant7 * of patent rights can be found in the PATENTS file in the same directory.8 *9 * @providesModule SourceMap10 * @generated11 * @extern12 *13 * This module was generated from `node_modules/source-map` by running14 *15 *   $ npm install dryice16 *   $ node Makefile.dryice.js17 *   $ cat dist/source-map.js18 *19 * and wrapping resulting file into `wrapper` function.20 *21 */22/*eslint-disable */23var scope = {};24wrapper.call(scope);25module.exports = scope.sourceMap;26function wrapper() {27/* -*- Mode: js; js-indent-level: 2; -*- */28/*29 * Copyright 2011 Mozilla Foundation and contributors30 * Licensed under the New BSD license. See LICENSE or:31 * http://opensource.org/licenses/BSD-3-Clause32 */33/**34 * Define a module along with a payload.35 * @param {string} moduleName Name for the payload36 * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec37 * @param {function} payload Function with (require, exports, module) params38 */39function define(moduleName, deps, payload) {40  if (typeof moduleName != "string") {41    throw new TypeError('Expected string, got: ' + moduleName);42  }43  if (arguments.length == 2) {44    payload = deps;45  }46  if (moduleName in define.modules) {47    throw new Error("Module already defined: " + moduleName);48  }49  define.modules[moduleName] = payload;50};51/**52 * The global store of un-instantiated modules53 */54define.modules = {};55/**56 * We invoke require() in the context of a Domain so we can have multiple57 * sets of modules running separate from each other.58 * This contrasts with JSMs which are singletons, Domains allows us to59 * optionally load a CommonJS module twice with separate data each time.60 * Perhaps you want 2 command lines with a different set of commands in each,61 * for example.62 */63function Domain() {64  this.modules = {};65  this._currentModule = null;66}67(function () {68  /**69   * Lookup module names and resolve them by calling the definition function if70   * needed.71   * There are 2 ways to call this, either with an array of dependencies and a72   * callback to call when the dependencies are found (which can happen73   * asynchronously in an in-page context) or with a single string an no callback74   * where the dependency is resolved synchronously and returned.75   * The API is designed to be compatible with the CommonJS AMD spec and76   * RequireJS.77   * @param {string[]|string} deps A name, or names for the payload78   * @param {function|undefined} callback Function to call when the dependencies79   * are resolved80   * @return {undefined|object} The module required or undefined for81   * array/callback method82   */83  Domain.prototype.require = function(deps, callback) {84    if (Array.isArray(deps)) {85      var params = deps.map(function(dep) {86        return this.lookup(dep);87      }, this);88      if (callback) {89        callback.apply(null, params);90      }91      return undefined;92    }93    else {94      return this.lookup(deps);95    }96  };97  function normalize(path) {98    var bits = path.split('/');99    var i = 1;100    while (i < bits.length) {101      if (bits[i] === '..') {102        bits.splice(i-1, 1);103      } else if (bits[i] === '.') {104        bits.splice(i, 1);105      } else {106        i++;107      }108    }109    return bits.join('/');110  }111  function join(a, b) {112    a = a.trim();113    b = b.trim();114    if (/^\//.test(b)) {115      return b;116    } else {117      return a.replace(/\/*$/, '/') + b;118    }119  }120  function dirname(path) {121    var bits = path.split('/');122    bits.pop();123    return bits.join('/');124  }125  /**126   * Lookup module names and resolve them by calling the definition function if127   * needed.128   * @param {string} moduleName A name for the payload to lookup129   * @return {object} The module specified by aModuleName or null if not found.130   */131  Domain.prototype.lookup = function(moduleName) {132    if (/^\./.test(moduleName)) {133      moduleName = normalize(join(dirname(this._currentModule), moduleName));134    }135    if (moduleName in this.modules) {136      var module = this.modules[moduleName];137      return module;138    }139    if (!(moduleName in define.modules)) {140      throw new Error("Module not defined: " + moduleName);141    }142    var module = define.modules[moduleName];143    if (typeof module == "function") {144      var exports = {};145      var previousModule = this._currentModule;146      this._currentModule = moduleName;147      module(this.require.bind(this), exports, { id: moduleName, uri: "" });148      this._currentModule = previousModule;149      module = exports;150    }151    // cache the resulting module object for next time152    this.modules[moduleName] = module;153    return module;154  };155}());156define.Domain = Domain;157define.globalDomain = new Domain();158var require = define.globalDomain.require.bind(define.globalDomain);159/* -*- Mode: js; js-indent-level: 2; -*- */160/*161 * Copyright 2011 Mozilla Foundation and contributors162 * Licensed under the New BSD license. See LICENSE or:163 * http://opensource.org/licenses/BSD-3-Clause164 */165define('source-map/source-map-generator', ['require', 'exports', 'module' ,  'source-map/base64-vlq', 'source-map/util', 'source-map/array-set'], function(require, exports, module) {166  var base64VLQ = require('./base64-vlq');167  var util = require('./util');168  var ArraySet = require('./array-set').ArraySet;169  /**170   * An instance of the SourceMapGenerator represents a source map which is171   * being built incrementally. To create a new one, you must pass an object172   * with the following properties:173   *174   *   - file: The filename of the generated source.175   *   - sourceRoot: An optional root for all URLs in this source map.176   */177  function SourceMapGenerator(aArgs) {178    this._file = util.getArg(aArgs, 'file');179    this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);180    this._sources = new ArraySet();181    this._names = new ArraySet();182    this._mappings = [];183    this._sourcesContents = null;184  }185  SourceMapGenerator.prototype._version = 3;186  /**187   * Creates a new SourceMapGenerator based on a SourceMapConsumer188   *189   * @param aSourceMapConsumer The SourceMap.190   */191  SourceMapGenerator.fromSourceMap =192    function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {193      var sourceRoot = aSourceMapConsumer.sourceRoot;194      var generator = new SourceMapGenerator({195        file: aSourceMapConsumer.file,196        sourceRoot: sourceRoot197      });198      aSourceMapConsumer.eachMapping(function (mapping) {199        var newMapping = {200          generated: {201            line: mapping.generatedLine,202            column: mapping.generatedColumn203          }204        };205        if (mapping.source) {206          newMapping.source = mapping.source;207          if (sourceRoot) {208            newMapping.source = util.relative(sourceRoot, newMapping.source);209          }210          newMapping.original = {211            line: mapping.originalLine,212            column: mapping.originalColumn213          };214          if (mapping.name) {215            newMapping.name = mapping.name;216          }217        }218        generator.addMapping(newMapping);219      });220      aSourceMapConsumer.sources.forEach(function (sourceFile) {221        var content = aSourceMapConsumer.sourceContentFor(sourceFile);222        if (content) {223          generator.setSourceContent(sourceFile, content);224        }225      });226      return generator;227    };228  /**229   * Add a single mapping from original source line and column to the generated230   * source's line and column for this source map being created. The mapping231   * object should have the following properties:232   *233   *   - generated: An object with the generated line and column positions.234   *   - original: An object with the original line and column positions.235   *   - source: The original source file (relative to the sourceRoot).236   *   - name: An optional original token name for this mapping.237   */238  SourceMapGenerator.prototype.addMapping =239    function SourceMapGenerator_addMapping(aArgs) {240      var generated = util.getArg(aArgs, 'generated');241      var original = util.getArg(aArgs, 'original', null);242      var source = util.getArg(aArgs, 'source', null);243      var name = util.getArg(aArgs, 'name', null);244      this._validateMapping(generated, original, source, name);245      if (source && !this._sources.has(source)) {246        this._sources.add(source);247      }248      if (name && !this._names.has(name)) {249        this._names.add(name);250      }251      this._mappings.push({252        generatedLine: generated.line,253        generatedColumn: generated.column,254        originalLine: original != null && original.line,255        originalColumn: original != null && original.column,256        source: source,257        name: name258      });259    };260  /**261   * Set the source content for a source file.262   */263  SourceMapGenerator.prototype.setSourceContent =264    function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {265      var source = aSourceFile;266      if (this._sourceRoot) {267        source = util.relative(this._sourceRoot, source);268      }269      if (aSourceContent !== null) {270        // Add the source content to the _sourcesContents map.271        // Create a new _sourcesContents map if the property is null.272        if (!this._sourcesContents) {273          this._sourcesContents = {};274        }275        this._sourcesContents[util.toSetString(source)] = aSourceContent;276      } else {277        // Remove the source file from the _sourcesContents map.278        // If the _sourcesContents map is empty, set the property to null.279        delete this._sourcesContents[util.toSetString(source)];280        if (Object.keys(this._sourcesContents).length === 0) {281          this._sourcesContents = null;282        }283      }284    };285  /**286   * Applies the mappings of a sub-source-map for a specific source file to the287   * source map being generated. Each mapping to the supplied source file is288   * rewritten using the supplied source map. Note: The resolution for the289   * resulting mappings is the minimium of this map and the supplied map.290   *291   * @param aSourceMapConsumer The source map to be applied.292   * @param aSourceFile Optional. The filename of the source file.293   *        If omitted, SourceMapConsumer's file property will be used.294   */295  SourceMapGenerator.prototype.applySourceMap =296    function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) {297      // If aSourceFile is omitted, we will use the file property of the SourceMap298      if (!aSourceFile) {299        aSourceFile = aSourceMapConsumer.file;300      }301      var sourceRoot = this._sourceRoot;302      // Make "aSourceFile" relative if an absolute Url is passed.303      if (sourceRoot) {304        aSourceFile = util.relative(sourceRoot, aSourceFile);305      }306      // Applying the SourceMap can add and remove items from the sources and307      // the names array.308      var newSources = new ArraySet();309      var newNames = new ArraySet();310      // Find mappings for the "aSourceFile"311      this._mappings.forEach(function (mapping) {312        if (mapping.source === aSourceFile && mapping.originalLine) {313          // Check if it can be mapped by the source map, then update the mapping.314          var original = aSourceMapConsumer.originalPositionFor({315            line: mapping.originalLine,316            column: mapping.originalColumn317          });318          if (original.source !== null) {319            // Copy mapping320            if (sourceRoot) {321              mapping.source = util.relative(sourceRoot, original.source);322            } else {323              mapping.source = original.source;324            }325            mapping.originalLine = original.line;326            mapping.originalColumn = original.column;327            if (original.name !== null && mapping.name !== null) {328              // Only use the identifier name if it's an identifier329              // in both SourceMaps330              mapping.name = original.name;331            }332          }333        }334        var source = mapping.source;335        if (source && !newSources.has(source)) {336          newSources.add(source);337        }338        var name = mapping.name;339        if (name && !newNames.has(name)) {340          newNames.add(name);341        }342      }, this);343      this._sources = newSources;344      this._names = newNames;345      // Copy sourcesContents of applied map.346      aSourceMapConsumer.sources.forEach(function (sourceFile) {347        var content = aSourceMapConsumer.sourceContentFor(sourceFile);348        if (content) {349          if (sourceRoot) {350            sourceFile = util.relative(sourceRoot, sourceFile);351          }352          this.setSourceContent(sourceFile, content);353        }354      }, this);355    };356  /**357   * A mapping can have one of the three levels of data:358   *359   *   1. Just the generated position.360   *   2. The Generated position, original position, and original source.361   *   3. Generated and original position, original source, as well as a name362   *      token.363   *364   * To maintain consistency, we validate that any new mapping being added falls365   * in to one of these categories.366   */367  SourceMapGenerator.prototype._validateMapping =368    function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,369                                                aName) {370      if (aGenerated && 'line' in aGenerated && 'column' in aGenerated371          && aGenerated.line > 0 && aGenerated.column >= 0372          && !aOriginal && !aSource && !aName) {373        // Case 1.374        return;375      }376      else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated377               && aOriginal && 'line' in aOriginal && 'column' in aOriginal378               && aGenerated.line > 0 && aGenerated.column >= 0379               && aOriginal.line > 0 && aOriginal.column >= 0380               && aSource) {381        // Cases 2 and 3.382        return;383      }384      else {385        throw new Error('Invalid mapping: ' + JSON.stringify({386          generated: aGenerated,387          source: aSource,388          orginal: aOriginal,389          name: aName390        }));391      }392    };393  /**394   * Serialize the accumulated mappings in to the stream of base 64 VLQs395   * specified by the source map format.396   */397  SourceMapGenerator.prototype._serializeMappings =398    function SourceMapGenerator_serializeMappings() {399      var previousGeneratedColumn = 0;400      var previousGeneratedLine = 1;401      var previousOriginalColumn = 0;402      var previousOriginalLine = 0;403      var previousName = 0;404      var previousSource = 0;405      var result = '';406      var mapping;407      // The mappings must be guaranteed to be in sorted order before we start408      // serializing them or else the generated line numbers (which are defined409      // via the ';' separators) will be all messed up. Note: it might be more410      // performant to maintain the sorting as we insert them, rather than as we411      // serialize them, but the big O is the same either way.412      this._mappings.sort(util.compareByGeneratedPositions);413      for (var i = 0, len = this._mappings.length; i < len; i++) {414        mapping = this._mappings[i];415        if (mapping.generatedLine !== previousGeneratedLine) {416          previousGeneratedColumn = 0;417          while (mapping.generatedLine !== previousGeneratedLine) {418            result += ';';419            previousGeneratedLine++;420          }421        }422        else {423          if (i > 0) {424            if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) {425              continue;426            }427            result += ',';428          }429        }430        result += base64VLQ.encode(mapping.generatedColumn431                                   - previousGeneratedColumn);432        previousGeneratedColumn = mapping.generatedColumn;433        if (mapping.source) {434          result += base64VLQ.encode(this._sources.indexOf(mapping.source)435                                     - previousSource);436          previousSource = this._sources.indexOf(mapping.source);437          // lines are stored 0-based in SourceMap spec version 3438          result += base64VLQ.encode(mapping.originalLine - 1439                                     - previousOriginalLine);440          previousOriginalLine = mapping.originalLine - 1;441          result += base64VLQ.encode(mapping.originalColumn442                                     - previousOriginalColumn);443          previousOriginalColumn = mapping.originalColumn;444          if (mapping.name) {445            result += base64VLQ.encode(this._names.indexOf(mapping.name)446                                       - previousName);447            previousName = this._names.indexOf(mapping.name);448          }449        }450      }451      return result;452    };453  SourceMapGenerator.prototype._generateSourcesContent =454    function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {455      return aSources.map(function (source) {456        if (!this._sourcesContents) {457          return null;458        }459        if (aSourceRoot) {460          source = util.relative(aSourceRoot, source);461        }462        var key = util.toSetString(source);463        return Object.prototype.hasOwnProperty.call(this._sourcesContents,464                                                    key)465          ? this._sourcesContents[key]466          : null;467      }, this);468    };469  /**470   * Externalize the source map.471   */472  SourceMapGenerator.prototype.toJSON =473    function SourceMapGenerator_toJSON() {474      var map = {475        version: this._version,476        file: this._file,477        sources: this._sources.toArray(),478        names: this._names.toArray(),479        mappings: this._serializeMappings()480      };481      if (this._sourceRoot) {482        map.sourceRoot = this._sourceRoot;483      }484      if (this._sourcesContents) {485        map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);486      }487      return map;488    };489  /**490   * Render the source map being generated to a string.491   */492  SourceMapGenerator.prototype.toString =493    function SourceMapGenerator_toString() {494      return JSON.stringify(this);495    };496  exports.SourceMapGenerator = SourceMapGenerator;497});498/* -*- Mode: js; js-indent-level: 2; -*- */499/*500 * Copyright 2011 Mozilla Foundation and contributors501 * Licensed under the New BSD license. See LICENSE or:502 * http://opensource.org/licenses/BSD-3-Clause503 *504 * Based on the Base 64 VLQ implementation in Closure Compiler:505 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java506 *507 * Copyright 2011 The Closure Compiler Authors. All rights reserved.508 * Redistribution and use in source and binary forms, with or without509 * modification, are permitted provided that the following conditions are510 * met:511 *512 *  * Redistributions of source code must retain the above copyright513 *    notice, this list of conditions and the following disclaimer.514 *  * Redistributions in binary form must reproduce the above515 *    copyright notice, this list of conditions and the following516 *    disclaimer in the documentation and/or other materials provided517 *    with the distribution.518 *  * Neither the name of Google Inc. nor the names of its519 *    contributors may be used to endorse or promote products derived520 *    from this software without specific prior written permission.521 *522 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS523 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT524 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR525 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT526 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,527 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT528 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,529 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY530 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT531 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE532 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.533 */534define('source-map/base64-vlq', ['require', 'exports', 'module' ,  'source-map/base64'], function(require, exports, module) {535  var base64 = require('./base64');536  // A single base 64 digit can contain 6 bits of data. For the base 64 variable537  // length quantities we use in the source map spec, the first bit is the sign,538  // the next four bits are the actual value, and the 6th bit is the539  // continuation bit. The continuation bit tells us whether there are more540  // digits in this value following this digit.541  //542  //   Continuation543  //   |    Sign544  //   |    |545  //   V    V546  //   101011547  var VLQ_BASE_SHIFT = 5;548  // binary: 100000549  var VLQ_BASE = 1 << VLQ_BASE_SHIFT;550  // binary: 011111551  var VLQ_BASE_MASK = VLQ_BASE - 1;552  // binary: 100000553  var VLQ_CONTINUATION_BIT = VLQ_BASE;554  /**555   * Converts from a two-complement value to a value where the sign bit is556   * is placed in the least significant bit.  For example, as decimals:557   *   1 becomes 2 (10 binary), -1 becomes 3 (11 binary)558   *   2 becomes 4 (100 binary), -2 becomes 5 (101 binary)559   */560  function toVLQSigned(aValue) {561    return aValue < 0562      ? ((-aValue) << 1) + 1563      : (aValue << 1) + 0;564  }565  /**566   * Converts to a two-complement value from a value where the sign bit is567   * is placed in the least significant bit.  For example, as decimals:568   *   2 (10 binary) becomes 1, 3 (11 binary) becomes -1569   *   4 (100 binary) becomes 2, 5 (101 binary) becomes -2570   */571  function fromVLQSigned(aValue) {572    var isNegative = (aValue & 1) === 1;573    var shifted = aValue >> 1;574    return isNegative575      ? -shifted576      : shifted;577  }578  /**579   * Returns the base 64 VLQ encoded value.580   */581  exports.encode = function base64VLQ_encode(aValue) {582    var encoded = "";583    var digit;584    var vlq = toVLQSigned(aValue);585    do {586      digit = vlq & VLQ_BASE_MASK;587      vlq >>>= VLQ_BASE_SHIFT;588      if (vlq > 0) {589        // There are still more digits in this value, so we must make sure the590        // continuation bit is marked.591        digit |= VLQ_CONTINUATION_BIT;592      }593      encoded += base64.encode(digit);594    } while (vlq > 0);595    return encoded;596  };597  /**598   * Decodes the next base 64 VLQ value from the given string and returns the599   * value and the rest of the string.600   */601  exports.decode = function base64VLQ_decode(aStr) {602    var i = 0;603    var strLen = aStr.length;604    var result = 0;605    var shift = 0;606    var continuation, digit;607    do {608      if (i >= strLen) {609        throw new Error("Expected more digits in base 64 VLQ value.");610      }611      digit = base64.decode(aStr.charAt(i++));612      continuation = !!(digit & VLQ_CONTINUATION_BIT);613      digit &= VLQ_BASE_MASK;614      result = result + (digit << shift);615      shift += VLQ_BASE_SHIFT;616    } while (continuation);617    return {618      value: fromVLQSigned(result),619      rest: aStr.slice(i)620    };621  };622});623/* -*- Mode: js; js-indent-level: 2; -*- */624/*625 * Copyright 2011 Mozilla Foundation and contributors626 * Licensed under the New BSD license. See LICENSE or:627 * http://opensource.org/licenses/BSD-3-Clause628 */629define('source-map/base64', ['require', 'exports', 'module' , ], function(require, exports, module) {630  var charToIntMap = {};631  var intToCharMap = {};632  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'633    .split('')634    .forEach(function (ch, index) {635      charToIntMap[ch] = index;636      intToCharMap[index] = ch;637    });638  /**639   * Encode an integer in the range of 0 to 63 to a single base 64 digit.640   */641  exports.encode = function base64_encode(aNumber) {642    if (aNumber in intToCharMap) {643      return intToCharMap[aNumber];644    }645    throw new TypeError("Must be between 0 and 63: " + aNumber);646  };647  /**648   * Decode a single base 64 digit to an integer.649   */650  exports.decode = function base64_decode(aChar) {651    if (aChar in charToIntMap) {652      return charToIntMap[aChar];653    }654    throw new TypeError("Not a valid base 64 digit: " + aChar);655  };656});657/* -*- Mode: js; js-indent-level: 2; -*- */658/*659 * Copyright 2011 Mozilla Foundation and contributors660 * Licensed under the New BSD license. See LICENSE or:661 * http://opensource.org/licenses/BSD-3-Clause662 */663define('source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) {664  /**665   * This is a helper function for getting values from parameter/options666   * objects.667   *668   * @param args The object we are extracting values from669   * @param name The name of the property we are getting.670   * @param defaultValue An optional value to return if the property is missing671   * from the object. If this is not specified and the property is missing, an672   * error will be thrown.673   */674  function getArg(aArgs, aName, aDefaultValue) {675    if (aName in aArgs) {676      return aArgs[aName];677    } else if (arguments.length === 3) {678      return aDefaultValue;679    } else {680      throw new Error('"' + aName + '" is a required argument.');681    }682  }683  exports.getArg = getArg;684  var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/;685  var dataUrlRegexp = /^data:.+\,.+/;686  function urlParse(aUrl) {687    var match = aUrl.match(urlRegexp);688    if (!match) {689      return null;690    }691    return {692      scheme: match[1],693      auth: match[3],694      host: match[4],695      port: match[6],696      path: match[7]697    };698  }699  exports.urlParse = urlParse;700  function urlGenerate(aParsedUrl) {701    var url = aParsedUrl.scheme + "://";702    if (aParsedUrl.auth) {703      url += aParsedUrl.auth + "@"704    }705    if (aParsedUrl.host) {706      url += aParsedUrl.host;707    }708    if (aParsedUrl.port) {709      url += ":" + aParsedUrl.port710    }711    if (aParsedUrl.path) {712      url += aParsedUrl.path;713    }714    return url;715  }716  exports.urlGenerate = urlGenerate;717  function join(aRoot, aPath) {718    var url;719    if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) {720      return aPath;721    }722    if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) {723      url.path = aPath;724      return urlGenerate(url);725    }726    return aRoot.replace(/\/$/, '') + '/' + aPath;727  }728  exports.join = join;729  /**730   * Because behavior goes wacky when you set `__proto__` on objects, we731   * have to prefix all the strings in our set with an arbitrary character.732   *733   * See https://github.com/mozilla/source-map/pull/31 and734   * https://github.com/mozilla/source-map/issues/30735   *736   * @param String aStr737   */738  function toSetString(aStr) {739    return '$' + aStr;740  }741  exports.toSetString = toSetString;742  function fromSetString(aStr) {743    return aStr.substr(1);744  }745  exports.fromSetString = fromSetString;746  function relative(aRoot, aPath) {747    aRoot = aRoot.replace(/\/$/, '');748    var url = urlParse(aRoot);749    if (aPath.charAt(0) == "/" && url && url.path == "/") {750      return aPath.slice(1);751    }752    return aPath.indexOf(aRoot + '/') === 0753      ? aPath.substr(aRoot.length + 1)754      : aPath;755  }756  exports.relative = relative;757  function strcmp(aStr1, aStr2) {758    var s1 = aStr1 || "";759    var s2 = aStr2 || "";760    return (s1 > s2) - (s1 < s2);761  }762  /**763   * Comparator between two mappings where the original positions are compared.764   *765   * Optionally pass in `true` as `onlyCompareGenerated` to consider two766   * mappings with the same original source/line/column, but different generated767   * line and column the same. Useful when searching for a mapping with a768   * stubbed out mapping.769   */770  function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {771    var cmp;772    cmp = strcmp(mappingA.source, mappingB.source);773    if (cmp) {774      return cmp;775    }776    cmp = mappingA.originalLine - mappingB.originalLine;777    if (cmp) {778      return cmp;779    }780    cmp = mappingA.originalColumn - mappingB.originalColumn;781    if (cmp || onlyCompareOriginal) {782      return cmp;783    }784    cmp = strcmp(mappingA.name, mappingB.name);785    if (cmp) {786      return cmp;787    }788    cmp = mappingA.generatedLine - mappingB.generatedLine;789    if (cmp) {790      return cmp;791    }792    return mappingA.generatedColumn - mappingB.generatedColumn;793  };794  exports.compareByOriginalPositions = compareByOriginalPositions;795  /**796   * Comparator between two mappings where the generated positions are797   * compared.798   *799   * Optionally pass in `true` as `onlyCompareGenerated` to consider two800   * mappings with the same generated line and column, but different801   * source/name/original line and column the same. Useful when searching for a802   * mapping with a stubbed out mapping.803   */804  function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) {805    var cmp;806    cmp = mappingA.generatedLine - mappingB.generatedLine;807    if (cmp) {808      return cmp;809    }810    cmp = mappingA.generatedColumn - mappingB.generatedColumn;811    if (cmp || onlyCompareGenerated) {812      return cmp;813    }814    cmp = strcmp(mappingA.source, mappingB.source);815    if (cmp) {816      return cmp;817    }818    cmp = mappingA.originalLine - mappingB.originalLine;819    if (cmp) {820      return cmp;821    }822    cmp = mappingA.originalColumn - mappingB.originalColumn;823    if (cmp) {824      return cmp;825    }826    return strcmp(mappingA.name, mappingB.name);827  };828  exports.compareByGeneratedPositions = compareByGeneratedPositions;829});830/* -*- Mode: js; js-indent-level: 2; -*- */831/*832 * Copyright 2011 Mozilla Foundation and contributors833 * Licensed under the New BSD license. See LICENSE or:834 * http://opensource.org/licenses/BSD-3-Clause835 */836define('source-map/array-set', ['require', 'exports', 'module' ,  'source-map/util'], function(require, exports, module) {837  var util = require('./util');838  /**839   * A data structure which is a combination of an array and a set. Adding a new840   * member is O(1), testing for membership is O(1), and finding the index of an841   * element is O(1). Removing elements from the set is not supported. Only842   * strings are supported for membership.843   */844  function ArraySet() {845    this._array = [];846    this._set = {};847  }848  /**849   * Static method for creating ArraySet instances from an existing array.850   */851  ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {852    var set = new ArraySet();853    for (var i = 0, len = aArray.length; i < len; i++) {854      set.add(aArray[i], aAllowDuplicates);855    }856    return set;857  };858  /**859   * Add the given string to this set.860   *861   * @param String aStr862   */863  ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {864    var isDuplicate = this.has(aStr);865    var idx = this._array.length;866    if (!isDuplicate || aAllowDuplicates) {867      this._array.push(aStr);868    }869    if (!isDuplicate) {870      this._set[util.toSetString(aStr)] = idx;871    }872  };873  /**874   * Is the given string a member of this set?875   *876   * @param String aStr877   */878  ArraySet.prototype.has = function ArraySet_has(aStr) {879    return Object.prototype.hasOwnProperty.call(this._set,880                                                util.toSetString(aStr));881  };882  /**883   * What is the index of the given string in the array?884   *885   * @param String aStr886   */887  ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {888    if (this.has(aStr)) {889      return this._set[util.toSetString(aStr)];890    }891    throw new Error('"' + aStr + '" is not in the set.');892  };893  /**894   * What is the element at the given index?895   *896   * @param Number aIdx897   */898  ArraySet.prototype.at = function ArraySet_at(aIdx) {899    if (aIdx >= 0 && aIdx < this._array.length) {900      return this._array[aIdx];901    }902    throw new Error('No element indexed by ' + aIdx);903  };904  /**905   * Returns the array representation of this set (which has the proper indices906   * indicated by indexOf). Note that this is a copy of the internal array used907   * for storing the members so that no one can mess with internal state.908   */909  ArraySet.prototype.toArray = function ArraySet_toArray() {910    return this._array.slice();911  };912  exports.ArraySet = ArraySet;913});914/* -*- Mode: js; js-indent-level: 2; -*- */915/*916 * Copyright 2011 Mozilla Foundation and contributors917 * Licensed under the New BSD license. See LICENSE or:918 * http://opensource.org/licenses/BSD-3-Clause919 */920define('source-map/source-map-consumer', ['require', 'exports', 'module' ,  'source-map/util', 'source-map/binary-search', 'source-map/array-set', 'source-map/base64-vlq'], function(require, exports, module) {921  var util = require('./util');922  var binarySearch = require('./binary-search');923  var ArraySet = require('./array-set').ArraySet;924  var base64VLQ = require('./base64-vlq');925  /**926   * A SourceMapConsumer instance represents a parsed source map which we can927   * query for information about the original file positions by giving it a file928   * position in the generated source.929   *930   * The only parameter is the raw source map (either as a JSON string, or931   * already parsed to an object). According to the spec, source maps have the932   * following attributes:933   *934   *   - version: Which version of the source map spec this map is following.935   *   - sources: An array of URLs to the original source files.936   *   - names: An array of identifiers which can be referrenced by individual mappings.937   *   - sourceRoot: Optional. The URL root from which all sources are relative.938   *   - sourcesContent: Optional. An array of contents of the original source files.939   *   - mappings: A string of base64 VLQs which contain the actual mappings.940   *   - file: The generated file this source map is associated with.941   *942   * Here is an example source map, taken from the source map spec[0]:943   *944   *     {945   *       version : 3,946   *       file: "out.js",947   *       sourceRoot : "",948   *       sources: ["foo.js", "bar.js"],949   *       names: ["src", "maps", "are", "fun"],950   *       mappings: "AA,AB;;ABCDE;"951   *     }952   *953   * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#954   */955  function SourceMapConsumer(aSourceMap) {956    var sourceMap = aSourceMap;957    if (typeof aSourceMap === 'string') {958      sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));959    }960    var version = util.getArg(sourceMap, 'version');961    var sources = util.getArg(sourceMap, 'sources');962    // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which963    // requires the array) to play nice here.964    var names = util.getArg(sourceMap, 'names', []);965    var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);966    var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);967    var mappings = util.getArg(sourceMap, 'mappings');968    var file = util.getArg(sourceMap, 'file', null);969    // Once again, Sass deviates from the spec and supplies the version as a970    // string rather than a number, so we use loose equality checking here.971    if (version != this._version) {972      throw new Error('Unsupported version: ' + version);973    }974    // Pass `true` below to allow duplicate names and sources. While source maps975    // are intended to be compressed and deduplicated, the TypeScript compiler976    // sometimes generates source maps with duplicates in them. See Github issue977    // #72 and bugzil.la/889492.978    this._names = ArraySet.fromArray(names, true);979    this._sources = ArraySet.fromArray(sources, true);980    this.sourceRoot = sourceRoot;981    this.sourcesContent = sourcesContent;982    this._mappings = mappings;983    this.file = file;984  }985  /**986   * Create a SourceMapConsumer from a SourceMapGenerator.987   *988   * @param SourceMapGenerator aSourceMap989   *        The source map that will be consumed.990   * @returns SourceMapConsumer991   */992  SourceMapConsumer.fromSourceMap =993    function SourceMapConsumer_fromSourceMap(aSourceMap) {994      var smc = Object.create(SourceMapConsumer.prototype);995      smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);996      smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);997      smc.sourceRoot = aSourceMap._sourceRoot;998      smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),999                                                              smc.sourceRoot);1000      smc.file = aSourceMap._file;1001      smc.__generatedMappings = aSourceMap._mappings.slice()1002        .sort(util.compareByGeneratedPositions);1003      smc.__originalMappings = aSourceMap._mappings.slice()1004        .sort(util.compareByOriginalPositions);1005      return smc;1006    };1007  /**1008   * The version of the source mapping spec that we are consuming.1009   */1010  SourceMapConsumer.prototype._version = 3;1011  /**1012   * The list of original sources.1013   */1014  Object.defineProperty(SourceMapConsumer.prototype, 'sources', {1015    get: function () {1016      return this._sources.toArray().map(function (s) {1017        return this.sourceRoot ? util.join(this.sourceRoot, s) : s;1018      }, this);1019    }1020  });1021  // `__generatedMappings` and `__originalMappings` are arrays that hold the1022  // parsed mapping coordinates from the source map's "mappings" attribute. They1023  // are lazily instantiated, accessed via the `_generatedMappings` and1024  // `_originalMappings` getters respectively, and we only parse the mappings1025  // and create these arrays once queried for a source location. We jump through1026  // these hoops because there can be many thousands of mappings, and parsing1027  // them is expensive, so we only want to do it if we must.1028  //1029  // Each object in the arrays is of the form:1030  //1031  //     {1032  //       generatedLine: The line number in the generated code,1033  //       generatedColumn: The column number in the generated code,1034  //       source: The path to the original source file that generated this1035  //               chunk of code,1036  //       originalLine: The line number in the original source that1037  //                     corresponds to this chunk of generated code,1038  //       originalColumn: The column number in the original source that1039  //                       corresponds to this chunk of generated code,1040  //       name: The name of the original symbol which generated this chunk of1041  //             code.1042  //     }1043  //1044  // All properties except for `generatedLine` and `generatedColumn` can be1045  // `null`.1046  //1047  // `_generatedMappings` is ordered by the generated positions.1048  //1049  // `_originalMappings` is ordered by the original positions.1050  SourceMapConsumer.prototype.__generatedMappings = null;1051  Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {1052    get: function () {1053      if (!this.__generatedMappings) {1054        this.__generatedMappings = [];1055        this.__originalMappings = [];1056        this._parseMappings(this._mappings, this.sourceRoot);1057      }1058      return this.__generatedMappings;1059    }1060  });1061  SourceMapConsumer.prototype.__originalMappings = null;1062  Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {1063    get: function () {1064      if (!this.__originalMappings) {1065        this.__generatedMappings = [];1066        this.__originalMappings = [];1067        this._parseMappings(this._mappings, this.sourceRoot);1068      }1069      return this.__originalMappings;1070    }1071  });1072  /**1073   * Parse the mappings in a string in to a data structure which we can easily1074   * query (the ordered arrays in the `this.__generatedMappings` and1075   * `this.__originalMappings` properties).1076   */1077  SourceMapConsumer.prototype._parseMappings =1078    function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {1079      var generatedLine = 1;1080      var previousGeneratedColumn = 0;1081      var previousOriginalLine = 0;1082      var previousOriginalColumn = 0;1083      var previousSource = 0;1084      var previousName = 0;1085      var mappingSeparator = /^[,;]/;1086      var str = aStr;1087      var mapping;1088      var temp;1089      while (str.length > 0) {1090        if (str.charAt(0) === ';') {1091          generatedLine++;1092          str = str.slice(1);1093          previousGeneratedColumn = 0;1094        }1095        else if (str.charAt(0) === ',') {1096          str = str.slice(1);1097        }1098        else {1099          mapping = {};1100          mapping.generatedLine = generatedLine;1101          // Generated column.1102          temp = base64VLQ.decode(str);1103          mapping.generatedColumn = previousGeneratedColumn + temp.value;1104          previousGeneratedColumn = mapping.generatedColumn;1105          str = temp.rest;1106          if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {1107            // Original source.1108            temp = base64VLQ.decode(str);1109            mapping.source = this._sources.at(previousSource + temp.value);1110            previousSource += temp.value;1111            str = temp.rest;1112            if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {1113              throw new Error('Found a source, but no line and column');1114            }1115            // Original line.1116            temp = base64VLQ.decode(str);1117            mapping.originalLine = previousOriginalLine + temp.value;1118            previousOriginalLine = mapping.originalLine;1119            // Lines are stored 0-based1120            mapping.originalLine += 1;1121            str = temp.rest;1122            if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {1123              throw new Error('Found a source and line, but no column');1124            }1125            // Original column.1126            temp = base64VLQ.decode(str);1127            mapping.originalColumn = previousOriginalColumn + temp.value;1128            previousOriginalColumn = mapping.originalColumn;1129            str = temp.rest;1130            if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {1131              // Original name.1132              temp = base64VLQ.decode(str);1133              mapping.name = this._names.at(previousName + temp.value);1134              previousName += temp.value;1135              str = temp.rest;1136            }1137          }1138          this.__generatedMappings.push(mapping);1139          if (typeof mapping.originalLine === 'number') {1140            this.__originalMappings.push(mapping);1141          }1142        }1143      }1144      this.__originalMappings.sort(util.compareByOriginalPositions);1145    };1146  /**1147   * Find the mapping that best matches the hypothetical "needle" mapping that1148   * we are searching for in the given "haystack" of mappings.1149   */1150  SourceMapConsumer.prototype._findMapping =1151    function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,1152                                           aColumnName, aComparator) {1153      // To return the position we are searching for, we must first find the1154      // mapping for the given position and then return the opposite position it1155      // points to. Because the mappings are sorted, we can use binary search to1156      // find the best mapping.1157      if (aNeedle[aLineName] <= 0) {1158        throw new TypeError('Line must be greater than or equal to 1, got '1159                            + aNeedle[aLineName]);1160      }1161      if (aNeedle[aColumnName] < 0) {1162        throw new TypeError('Column must be greater than or equal to 0, got '1163                            + aNeedle[aColumnName]);1164      }1165      return binarySearch.search(aNeedle, aMappings, aComparator);1166    };1167  /**1168   * Returns the original source, line, and column information for the generated1169   * source's line and column positions provided. The only argument is an object1170   * with the following properties:1171   *1172   *   - line: The line number in the generated source.1173   *   - column: The column number in the generated source.1174   *1175   * and an object is returned with the following properties:1176   *1177   *   - source: The original source file, or null.1178   *   - line: The line number in the original source, or null.1179   *   - column: The column number in the original source, or null.1180   *   - name: The original identifier, or null.1181   */1182  SourceMapConsumer.prototype.originalPositionFor =1183    function SourceMapConsumer_originalPositionFor(aArgs) {1184      var needle = {1185        generatedLine: util.getArg(aArgs, 'line'),1186        generatedColumn: util.getArg(aArgs, 'column')1187      };1188      var mapping = this._findMapping(needle,1189                                      this._generatedMappings,1190                                      "generatedLine",1191                                      "generatedColumn",1192                                      util.compareByGeneratedPositions);1193      if (mapping) {1194        var source = util.getArg(mapping, 'source', null);1195        if (source && this.sourceRoot) {1196          source = util.join(this.sourceRoot, source);1197        }1198        return {1199          source: source,1200          line: util.getArg(mapping, 'originalLine', null),1201          column: util.getArg(mapping, 'originalColumn', null),1202          name: util.getArg(mapping, 'name', null)1203        };1204      }1205      return {1206        source: null,1207        line: null,1208        column: null,1209        name: null1210      };1211    };1212  /**1213   * Returns the original source content. The only argument is the url of the1214   * original source file. Returns null if no original source content is1215   * availible.1216   */1217  SourceMapConsumer.prototype.sourceContentFor =1218    function SourceMapConsumer_sourceContentFor(aSource) {1219      if (!this.sourcesContent) {1220        return null;1221      }1222      if (this.sourceRoot) {1223        aSource = util.relative(this.sourceRoot, aSource);1224      }1225      if (this._sources.has(aSource)) {1226        return this.sourcesContent[this._sources.indexOf(aSource)];1227      }1228      var url;1229      if (this.sourceRoot1230          && (url = util.urlParse(this.sourceRoot))) {1231        // XXX: file:// URIs and absolute paths lead to unexpected behavior for1232        // many users. We can help them out when they expect file:// URIs to1233        // behave like it would if they were running a local HTTP server. See1234        // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.1235        var fileUriAbsPath = aSource.replace(/^file:\/\//, "");1236        if (url.scheme == "file"1237            && this._sources.has(fileUriAbsPath)) {1238          return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]1239        }1240        if ((!url.path || url.path == "/")1241            && this._sources.has("/" + aSource)) {1242          return this.sourcesContent[this._sources.indexOf("/" + aSource)];1243        }1244      }1245      throw new Error('"' + aSource + '" is not in the SourceMap.');1246    };1247  /**1248   * Returns the generated line and column information for the original source,1249   * line, and column positions provided. The only argument is an object with1250   * the following properties:1251   *1252   *   - source: The filename of the original source.1253   *   - line: The line number in the original source.1254   *   - column: The column number in the original source.1255   *1256   * and an object is returned with the following properties:1257   *1258   *   - line: The line number in the generated source, or null.1259   *   - column: The column number in the generated source, or null.1260   */1261  SourceMapConsumer.prototype.generatedPositionFor =1262    function SourceMapConsumer_generatedPositionFor(aArgs) {1263      var needle = {1264        source: util.getArg(aArgs, 'source'),1265        originalLine: util.getArg(aArgs, 'line'),1266        originalColumn: util.getArg(aArgs, 'column')1267      };1268      if (this.sourceRoot) {1269        needle.source = util.relative(this.sourceRoot, needle.source);1270      }1271      var mapping = this._findMapping(needle,1272                                      this._originalMappings,1273                                      "originalLine",1274                                      "originalColumn",1275                                      util.compareByOriginalPositions);1276      if (mapping) {1277        return {1278          line: util.getArg(mapping, 'generatedLine', null),1279          column: util.getArg(mapping, 'generatedColumn', null)1280        };1281      }1282      return {1283        line: null,1284        column: null1285      };1286    };1287  SourceMapConsumer.GENERATED_ORDER = 1;1288  SourceMapConsumer.ORIGINAL_ORDER = 2;1289  /**1290   * Iterate over each mapping between an original source/line/column and a1291   * generated line/column in this source map.1292   *1293   * @param Function aCallback1294   *        The function that is called with each mapping.1295   * @param Object aContext1296   *        Optional. If specified, this object will be the value of `this` every1297   *        time that `aCallback` is called.1298   * @param aOrder1299   *        Either `SourceMapConsumer.GENERATED_ORDER` or1300   *        `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to1301   *        iterate over the mappings sorted by the generated file's line/column1302   *        order or the original's source/line/column order, respectively. Defaults to1303   *        `SourceMapConsumer.GENERATED_ORDER`.1304   */1305  SourceMapConsumer.prototype.eachMapping =1306    function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {1307      var context = aContext || null;1308      var order = aOrder || SourceMapConsumer.GENERATED_ORDER;1309      var mappings;1310      switch (order) {1311      case SourceMapConsumer.GENERATED_ORDER:1312        mappings = this._generatedMappings;1313        break;1314      case SourceMapConsumer.ORIGINAL_ORDER:1315        mappings = this._originalMappings;1316        break;1317      default:1318        throw new Error("Unknown order of iteration.");1319      }1320      var sourceRoot = this.sourceRoot;1321      mappings.map(function (mapping) {1322        var source = mapping.source;1323        if (source && sourceRoot) {1324          source = util.join(sourceRoot, source);1325        }1326        return {1327          source: source,1328          generatedLine: mapping.generatedLine,1329          generatedColumn: mapping.generatedColumn,1330          originalLine: mapping.originalLine,1331          originalColumn: mapping.originalColumn,1332          name: mapping.name1333        };1334      }).forEach(aCallback, context);1335    };1336  exports.SourceMapConsumer = SourceMapConsumer;1337});1338/* -*- Mode: js; js-indent-level: 2; -*- */1339/*1340 * Copyright 2011 Mozilla Foundation and contributors1341 * Licensed under the New BSD license. See LICENSE or:1342 * http://opensource.org/licenses/BSD-3-Clause1343 */1344define('source-map/binary-search', ['require', 'exports', 'module' , ], function(require, exports, module) {1345  /**1346   * Recursive implementation of binary search.1347   *1348   * @param aLow Indices here and lower do not contain the needle.1349   * @param aHigh Indices here and higher do not contain the needle.1350   * @param aNeedle The element being searched for.1351   * @param aHaystack The non-empty array being searched.1352   * @param aCompare Function which takes two elements and returns -1, 0, or 1.1353   */1354  function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {1355    // This function terminates when one of the following is true:1356    //1357    //   1. We find the exact element we are looking for.1358    //1359    //   2. We did not find the exact element, but we can return the next1360    //      closest element that is less than that element.1361    //1362    //   3. We did not find the exact element, and there is no next-closest1363    //      element which is less than the one we are searching for, so we1364    //      return null.1365    var mid = Math.floor((aHigh - aLow) / 2) + aLow;1366    var cmp = aCompare(aNeedle, aHaystack[mid], true);1367    if (cmp === 0) {1368      // Found the element we are looking for.1369      return aHaystack[mid];1370    }1371    else if (cmp > 0) {1372      // aHaystack[mid] is greater than our needle.1373      if (aHigh - mid > 1) {1374        // The element is in the upper half.1375        return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);1376      }1377      // We did not find an exact match, return the next closest one1378      // (termination case 2).1379      return aHaystack[mid];1380    }1381    else {1382      // aHaystack[mid] is less than our needle.1383      if (mid - aLow > 1) {1384        // The element is in the lower half.1385        return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);1386      }1387      // The exact needle element was not found in this haystack. Determine if1388      // we are in termination case (2) or (3) and return the appropriate thing.1389      return aLow < 01390        ? null1391        : aHaystack[aLow];1392    }1393  }1394  /**1395   * This is an implementation of binary search which will always try and return1396   * the next lowest value checked if there is no exact hit. This is because1397   * mappings between original and generated line/col pairs are single points,1398   * and there is an implicit region between each of them, so a miss just means1399   * that you aren't on the very start of a region.1400   *1401   * @param aNeedle The element you are looking for.1402   * @param aHaystack The array that is being searched.1403   * @param aCompare A function which takes the needle and an element in the1404   *     array and returns -1, 0, or 1 depending on whether the needle is less1405   *     than, equal to, or greater than the element, respectively.1406   */1407  exports.search = function search(aNeedle, aHaystack, aCompare) {1408    return aHaystack.length > 01409      ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)1410      : null;1411  };1412});1413/* -*- Mode: js; js-indent-level: 2; -*- */1414/*1415 * Copyright 2011 Mozilla Foundation and contributors1416 * Licensed under the New BSD license. See LICENSE or:1417 * http://opensource.org/licenses/BSD-3-Clause1418 */1419define('source-map/source-node', ['require', 'exports', 'module' ,  'source-map/source-map-generator', 'source-map/util'], function(require, exports, module) {1420  var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;1421  var util = require('./util');1422  /**1423   * SourceNodes provide a way to abstract over interpolating/concatenating1424   * snippets of generated JavaScript source code while maintaining the line and1425   * column information associated with the original source code.1426   *1427   * @param aLine The original line number.1428   * @param aColumn The original column number.1429   * @param aSource The original source's filename.1430   * @param aChunks Optional. An array of strings which are snippets of1431   *        generated JS, or other SourceNodes.1432   * @param aName The original identifier.1433   */1434  function SourceNode(aLine, aColumn, aSource, aChunks, aName) {1435    this.children = [];1436    this.sourceContents = {};1437    this.line = aLine === undefined ? null : aLine;1438    this.column = aColumn === undefined ? null : aColumn;1439    this.source = aSource === undefined ? null : aSource;1440    this.name = aName === undefined ? null : aName;1441    if (aChunks != null) this.add(aChunks);1442  }1443  /**1444   * Creates a SourceNode from generated code and a SourceMapConsumer.1445   *1446   * @param aGeneratedCode The generated code1447   * @param aSourceMapConsumer The SourceMap for the generated code1448   */1449  SourceNode.fromStringWithSourceMap =1450    function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) {1451      // The SourceNode we want to fill with the generated code1452      // and the SourceMap1453      var node = new SourceNode();1454      // The generated code1455      // Processed fragments are removed from this array.1456      var remainingLines = aGeneratedCode.split('\n');1457      // We need to remember the position of "remainingLines"1458      var lastGeneratedLine = 1, lastGeneratedColumn = 0;1459      // The generate SourceNodes we need a code range.1460      // To extract it current and last mapping is used.1461      // Here we store the last mapping.1462      var lastMapping = null;1463      aSourceMapConsumer.eachMapping(function (mapping) {1464        if (lastMapping === null) {1465          // We add the generated code until the first mapping1466          // to the SourceNode without any mapping.1467          // Each line is added as separate string.1468          while (lastGeneratedLine < mapping.generatedLine) {1469            node.add(remainingLines.shift() + "\n");1470            lastGeneratedLine++;1471          }1472          if (lastGeneratedColumn < mapping.generatedColumn) {1473            var nextLine = remainingLines[0];1474            node.add(nextLine.substr(0, mapping.generatedColumn));1475            remainingLines[0] = nextLine.substr(mapping.generatedColumn);1476            lastGeneratedColumn = mapping.generatedColumn;1477          }1478        } else {1479          // We add the code from "lastMapping" to "mapping":1480          // First check if there is a new line in between.1481          if (lastGeneratedLine < mapping.generatedLine) {1482            var code = "";1483            // Associate full lines with "lastMapping"1484            do {1485              code += remainingLines.shift() + "\n";1486              lastGeneratedLine++;1487              lastGeneratedColumn = 0;1488            } while (lastGeneratedLine < mapping.generatedLine);1489            // When we reached the correct line, we add code until we1490            // reach the correct column too.1491            if (lastGeneratedColumn < mapping.generatedColumn) {1492              var nextLine = remainingLines[0];1493              code += nextLine.substr(0, mapping.generatedColumn);1494              remainingLines[0] = nextLine.substr(mapping.generatedColumn);1495              lastGeneratedColumn = mapping.generatedColumn;1496            }1497            // Create the SourceNode.1498            addMappingWithCode(lastMapping, code);1499          } else {1500            // There is no new line in between.1501            // Associate the code between "lastGeneratedColumn" and1502            // "mapping.generatedColumn" with "lastMapping"1503            var nextLine = remainingLines[0];1504            var code = nextLine.substr(0, mapping.generatedColumn -1505                                          lastGeneratedColumn);1506            remainingLines[0] = nextLine.substr(mapping.generatedColumn -1507                                                lastGeneratedColumn);1508            lastGeneratedColumn = mapping.generatedColumn;1509            addMappingWithCode(lastMapping, code);1510          }1511        }1512        lastMapping = mapping;1513      }, this);1514      // We have processed all mappings.1515      // Associate the remaining code in the current line with "lastMapping"1516      // and add the remaining lines without any mapping1517      addMappingWithCode(lastMapping, remainingLines.join("\n"));1518      // Copy sourcesContent into SourceNode1519      aSourceMapConsumer.sources.forEach(function (sourceFile) {1520        var content = aSourceMapConsumer.sourceContentFor(sourceFile);1521        if (content) {1522          node.setSourceContent(sourceFile, content);1523        }1524      });1525      return node;1526      function addMappingWithCode(mapping, code) {1527        if (mapping === null || mapping.source === undefined) {1528          node.add(code);1529        } else {1530          node.add(new SourceNode(mapping.originalLine,1531                                  mapping.originalColumn,1532                                  mapping.source,1533                                  code,1534                                  mapping.name));1535        }1536      }1537    };1538  /**1539   * Add a chunk of generated JS to this source node.1540   *1541   * @param aChunk A string snippet of generated JS code, another instance of1542   *        SourceNode, or an array where each member is one of those things.1543   */1544  SourceNode.prototype.add = function SourceNode_add(aChunk) {1545    if (Array.isArray(aChunk)) {1546      aChunk.forEach(function (chunk) {1547        this.add(chunk);1548      }, this);1549    }1550    else if (aChunk instanceof SourceNode || typeof aChunk === "string") {1551      if (aChunk) {1552        this.children.push(aChunk);1553      }1554    }1555    else {1556      throw new TypeError(1557        "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk1558      );1559    }1560    return this;1561  };1562  /**1563   * Add a chunk of generated JS to the beginning of this source node.1564   *1565   * @param aChunk A string snippet of generated JS code, another instance of1566   *        SourceNode, or an array where each member is one of those things.1567   */1568  SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {1569    if (Array.isArray(aChunk)) {1570      for (var i = aChunk.length-1; i >= 0; i--) {1571        this.prepend(aChunk[i]);1572      }1573    }1574    else if (aChunk instanceof SourceNode || typeof aChunk === "string") {1575      this.children.unshift(aChunk);1576    }1577    else {1578      throw new TypeError(1579        "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk1580      );1581    }1582    return this;1583  };1584  /**1585   * Walk over the tree of JS snippets in this node and its children. The1586   * walking function is called once for each snippet of JS and is passed that1587   * snippet and the its original associated source's line/column location.1588   *1589   * @param aFn The traversal function.1590   */1591  SourceNode.prototype.walk = function SourceNode_walk(aFn) {1592    var chunk;1593    for (var i = 0, len = this.children.length; i < len; i++) {1594      chunk = this.children[i];1595      if (chunk instanceof SourceNode) {1596        chunk.walk(aFn);1597      }1598      else {1599        if (chunk !== '') {1600          aFn(chunk, { source: this.source,1601                       line: this.line,1602                       column: this.column,1603                       name: this.name });1604        }1605      }1606    }1607  };1608  /**1609   * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between1610   * each of `this.children`.1611   *1612   * @param aSep The separator.1613   */1614  SourceNode.prototype.join = function SourceNode_join(aSep) {1615    var newChildren;1616    var i;1617    var len = this.children.length;1618    if (len > 0) {1619      newChildren = [];1620      for (i = 0; i < len-1; i++) {1621        newChildren.push(this.children[i]);1622        newChildren.push(aSep);1623      }1624      newChildren.push(this.children[i]);1625      this.children = newChildren;1626    }1627    return this;1628  };1629  /**1630   * Call String.prototype.replace on the very right-most source snippet. Useful1631   * for trimming whitespace from the end of a source node, etc.1632   *1633   * @param aPattern The pattern to replace.1634   * @param aReplacement The thing to replace the pattern with.1635   */1636  SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {1637    var lastChild = this.children[this.children.length - 1];1638    if (lastChild instanceof SourceNode) {1639      lastChild.replaceRight(aPattern, aReplacement);1640    }1641    else if (typeof lastChild === 'string') {1642      this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);1643    }1644    else {1645      this.children.push(''.replace(aPattern, aReplacement));1646    }1647    return this;1648  };1649  /**1650   * Set the source content for a source file. This will be added to the SourceMapGenerator1651   * in the sourcesContent field.1652   *1653   * @param aSourceFile The filename of the source file1654   * @param aSourceContent The content of the source file1655   */1656  SourceNode.prototype.setSourceContent =1657    function SourceNode_setSourceContent(aSourceFile, aSourceContent) {1658      this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;1659    };1660  /**1661   * Walk over the tree of SourceNodes. The walking function is called for each1662   * source file content and is passed the filename and source content.1663   *1664   * @param aFn The traversal function.1665   */1666  SourceNode.prototype.walkSourceContents =1667    function SourceNode_walkSourceContents(aFn) {1668      for (var i = 0, len = this.children.length; i < len; i++) {1669        if (this.children[i] instanceof SourceNode) {1670          this.children[i].walkSourceContents(aFn);1671        }1672      }1673      var sources = Object.keys(this.sourceContents);1674      for (var i = 0, len = sources.length; i < len; i++) {1675        aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);1676      }1677    };1678  /**1679   * Return the string representation of this source node. Walks over the tree1680   * and concatenates all the various snippets together to one string.1681   */1682  SourceNode.prototype.toString = function SourceNode_toString() {1683    var str = "";1684    this.walk(function (chunk) {1685      str += chunk;1686    });1687    return str;1688  };1689  /**1690   * Returns the string representation of this source node along with a source1691   * map.1692   */1693  SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {1694    var generated = {1695      code: "",1696      line: 1,1697      column: 01698    };1699    var map = new SourceMapGenerator(aArgs);1700    var sourceMappingActive = false;1701    var lastOriginalSource = null;1702    var lastOriginalLine = null;1703    var lastOriginalColumn = null;1704    var lastOriginalName = null;1705    this.walk(function (chunk, original) {1706      generated.code += chunk;1707      if (original.source !== null1708          && original.line !== null1709          && original.column !== null) {1710        if(lastOriginalSource !== original.source1711           || lastOriginalLine !== original.line1712           || lastOriginalColumn !== original.column1713           || lastOriginalName !== original.name) {1714          map.addMapping({1715            source: original.source,1716            original: {1717              line: original.line,1718              column: original.column1719            },1720            generated: {1721              line: generated.line,1722              column: generated.column1723            },1724            name: original.name1725          });1726        }1727        lastOriginalSource = original.source;1728        lastOriginalLine = original.line;1729        lastOriginalColumn = original.column;1730        lastOriginalName = original.name;1731        sourceMappingActive = true;1732      } else if (sourceMappingActive) {1733        map.addMapping({1734          generated: {1735            line: generated.line,1736            column: generated.column1737          }1738        });1739        lastOriginalSource = null;1740        sourceMappingActive = false;1741      }1742      chunk.split('').forEach(function (ch) {1743        if (ch === '\n') {1744          generated.line++;1745          generated.column = 0;1746        } else {1747          generated.column++;1748        }1749      });1750    });1751    this.walkSourceContents(function (sourceFile, sourceContent) {1752      map.setSourceContent(sourceFile, sourceContent);1753    });1754    return { code: generated.code, map: map };1755  };1756  exports.SourceNode = SourceNode;1757});1758/* -*- Mode: js; js-indent-level: 2; -*- */1759///////////////////////////////////////////////////////////////////////////////1760this.sourceMap = {1761  SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer,1762  SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator,1763  SourceNode: require('source-map/source-node').SourceNode1764};...SearchSourceSettings.js
Source:SearchSourceSettings.js  
1///////////////////////////////////////////////////////////////////////////2// Copyright © Esri. All Rights Reserved.3//4// Licensed under the Apache License Version 2.0 (the 'License');5// you may not use this file except in compliance with the License.6// You may obtain a copy of the License at7//8//    http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing, software11// distributed under the License is distributed on an 'AS IS' BASIS,12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13// See the License for the specific language governing permissions and14// limitations under the License.15///////////////////////////////////////////////////////////////////////////16define([17  'dojo/_base/declare',18  'jimu/BaseWidgetSetting',19  'dijit/_WidgetsInTemplateMixin',20  'dojo/Evented',21  'dojo/text!./SearchSourceSettings.html',22  'dojo/_base/html',23  'jimu/dijit/SimpleTable',24  './QuerySourceSetting',25  './LocatorSourceSetting',26  'jimu/LayerInfos/LayerInfos',27  '../searchSourceUtils',28  'jimu/utils',29  'dojo/when',30  'esri/lang',31  'dojo/_base/lang',32  'dojo/_base/array',33  'dojo/query',34  'dojo/on',35  'dojo/dom-class',36  'jimu/dijit/CheckBox',37  'dojo/domReady!'38], function (39  declare,40  BaseWidgetSetting,41  _WidgetsInTemplateMixin,42  Evented,43  SearchSourceSettingsTemplate,44  html,45  SimpleTable,46  QuerySourceSetting,47  LocatorSourceSetting,48  LayerInfos,49  utils,50  jimuUtils,51  when,52  esriLang,53  lang,54  array,55  query,56  on,57  domClass,58  CheckBox59) {60  return declare([BaseWidgetSetting, _WidgetsInTemplateMixin, Evented], {61    baseClass: 'jimu-widget-screening-search-source-settings',62    templateString: SearchSourceSettingsTemplate,63    startup: function () {64      this.inherited(arguments);65    },66    postCreate: function () {67      this.inherited(arguments);68      this.own(on(this.menuItemClickNode, 'click', lang.hitch(this, this._onMenuItemClick)));69      this._createSourceListTable();70      //create checkbox for show infoWindow on select71      this.showInfoWindowOnSelect = new CheckBox({72        checked: false,73        label: this.nls.searchSourceSetting.generalSettingCheckboxLabel74      }, this.showInfoWindowOnSelectNode);75      if (!(this.config && this.config.sources)) {76        this.config.sources = [];77      }78      LayerInfos.getInstance(this.map, this.map.itemInfo)79        .then(lang.hitch(this, function (layerInfosObj) {80          this.layerInfosObj = layerInfosObj;81          utils.setMap(this.map);82          utils.setLayerInfosObj(this.layerInfosObj);83          utils.setAppConfig(this.appConfig);84          when(utils.getConfigInfo(this.config)).then(lang.hitch(this, this._loadConfig));85        }));86    },87    /**88     * This function is to load configuration89     * @param{object} contains config90     * @memberOf Screening/setting/SearchSourceSettings91     */92    _loadConfig: function (config) {93      if (!this.domNode) {94        return;95      }96      this.setConfig(config);97    },98    /**99     * This function is to set configured values to respective components100     * @param{object} contains config101     * @memberOf Screening/setting/SearchSourceSettings102     */103    setConfig: function (config) {104      this.config = config;105      var sources = config.sources;106      this.allPlaceholder.set('value', jimuUtils.stripHTML(this.config.allPlaceholder));107      this.showInfoWindowOnSelect.setValue(108        esriLang.isDefined(this.config.showInfoWindowOnSelect) ?109          !!this.config.showInfoWindowOnSelect : true);110      array.forEach(sources, lang.hitch(this, function (source, index) {111        var addResult = this.sourceList.addRow({112          name: source.name || ""113        });114        if (addResult && addResult.success) {115          this._setRelatedConfig(addResult.tr, source);116          if (index === 0) {117            var firstTr = addResult.tr;118            setTimeout(lang.hitch(this, function () {119              this.sourceList.selectRow(addResult.tr);120              firstTr = null;121            }), 100);122          }123        } else {124          console.error("add row failed ", addResult);125        }126      }));127    },128    /**129     * Gets the config updates by user, validates and returns the config object130     * @memberOf Screening/setting/SearchSourceSettings131     */132    getConfig: function () {133      if (this._currentSourceSetting) {134        if (this._currentSourceSetting.isValidConfig()) {135          this._closeSourceSetting();136        } else {137          return null;138        }139      }140      var config = {141        allPlaceholder: jimuUtils.stripHTML(this.allPlaceholder.get('value')),142        showInfoWindowOnSelect: this.showInfoWindowOnSelect.checked143      };144      var trs = this.sourceList.getRows();145      var sources = [];146      array.forEach(trs, lang.hitch(this, function (tr) {147        var source = this._getRelatedConfig(tr);148        delete source._definition;149        this._removeRelatedConfig(tr);150        sources.push(source);151      }));152      config.sources = sources;153      return config;154    },155    /**156     * Reset search configuration UI157     * @memberOf Screening/setting/SearchSourceSettings158     */159    destroy: function () {160      utils.setMap(null);161      utils.setLayerInfosObj(null);162      utils.setAppConfig(null);163      this.inherited(arguments);164    },165    /**166     * Set value of placeholder on blur167     * @memberOf Screening/setting/SearchSourceSettings168     */169    _onAllPlaceholderBlur: function () {170      this.allPlaceholder.set('value', jimuUtils.stripHTML(this.allPlaceholder.get('value')));171    },172    /**173     * Create source list table174     * @memberOf Screening/setting/SearchSourceSettings175     */176    _createSourceListTable: function () {177      this.sourceList = new SimpleTable({178        autoHeight: false,179        selectable: true,180        fields: [{181          name: "name",182          title: this.nls.common.name,183          width: "auto",184          type: "text",185          editable: false186        }, {187          name: "actions",188          title: "",189          width: "70px",190          type: "actions",191          actions: ["up", "down", "delete"]192        }]193      }, this.sourceList);194      html.setStyle(this.sourceList.domNode, 'height', '100%');195      this.sourceList.startup();196      this.own(on(this.sourceList, 'row-select', lang.hitch(this, this._onSourceItemSelected)));197      this.own(on(this.sourceList, 'row-delete', lang.hitch(this, this._onSourceItemRemoved)));198    },199    /**200     * on row delete from source list table201     * @param{node} contains table row202     * @memberOf Screening/setting/SearchSourceSettings203     */204    _onSourceItemRemoved: function (tr) {205      if (!this._currentSourceSetting) {206        return;207      }208      var currentTr = this._currentSourceSetting.getRelatedTr();209      if (currentTr === tr) {210        this._currentSourceSetting.destroy();211        this._currentSourceSetting = null;212      }213    },214    /**215     * on row selection of source list table216     * @param{node} contains table row217     * @memberOf Screening/setting/SearchSourceSettings218     */219    _onSourceItemSelected: function (tr) {220      var config = this._getRelatedConfig(tr);221      var currentTr = this._currentSourceSetting && this._currentSourceSetting.tr;222      if (!config || tr === currentTr) {223        return;224      }225      // check fields226      if (this._currentSourceSetting && !this._currentSourceSetting.isValidConfig()) {227        this._currentSourceSetting.showValidationTip();228        this.sourceList.selectRow(currentTr);229        return;230      }231      //Remove extra height required for localSearch.232      //This will required when prev selected locator has local search enable233      domClass.remove(this.searchSources, "esriCTSourcesExtraHeight");234      if (config.type === "query") {235        this._createNewQuerySourceSettingFromSourceList(config, config._definition || {}, tr);236      } else if (config.type === "locator") {237        this._createNewLocatorSourceSettingFromSourceList(config, config._definition || {}, tr);238      }239    },240    /**241     * Set related configuration to widget configuration242     * @param{node} contains table row243     * @param{object} contains table source244     * @memberOf Screening/setting/SearchSourceSettings245     */246    _setRelatedConfig: function (tr, source) {247      query(tr).data('config', lang.clone(source));248    },249    /**250     * Get related configuration from widget configuration251     * @param{node} contains table row252     * @memberOf Screening/setting/SearchSourceSettings253     */254    _getRelatedConfig: function (tr) {255      return query(tr).data('config')[0];256    },257    /**258     * Remove related configuration from widget configuration259     * @param{node} contains table row260     * @memberOf Screening/setting/SearchSourceSettings261     */262    _removeRelatedConfig: function (tr) {263      return query(tr).removeData('config');264    },265    /**266     * On menu item click267     * @param{object} contains event information268     * @memberOf Screening/setting/SearchSourceSettings269     */270    _onMenuItemClick: function (evt) {271      var itemType = evt && evt.target && html.getAttr(evt.target, "type");272      //if current settings are not valid then emit invalid settings event else create new source273      if (this._currentSourceSetting && !this._currentSourceSetting.isValidConfig()) {274        this.emit("invalid-source-setting");275      } else {276        //Remove extra height required for localSearch.277        //This will required when prev selected locator has local search enable278        domClass.remove(this.searchSources, "esriCTSourcesExtraHeight");279        if (itemType === "locator") {280          this._addNewLocator();281        } else if (itemType === "query") {282          this._addNewQuerySource();283        }284      }285    },286    /**287     * Add new locator288     * @memberOf Screening/setting/SearchSourceSettings289     */290    _addNewLocator: function () {291      this._createNewLocatorSourceSettingFromMenuItem({}, {});292    },293    /**294     * Add new query source295     * @memberOf Screening/setting/SearchSourceSettings296     */297    _addNewQuerySource: function () {298      this._createNewQuerySourceSettingFromMenuItem({}, {});299    },300    /**301     * Create new locator source setting from menu item302     * @param{object} contains setting303     * @param{string} contains definition304     * @memberOf Screening/setting/SearchSourceSettings305     */306    _createNewLocatorSourceSettingFromMenuItem: function (setting, definition) {307      var locatorSetting = new LocatorSourceSetting({308        nls: lang.mixin(this.nls.searchSourceSetting, window.jimuNls.units),309        map: this.map310      });311      locatorSetting.setDefinition(definition);312      locatorSetting.setConfig({313        url: setting.url || "",314        name: setting.name || "",315        singleLineFieldName: setting.singleLineFieldName || "",316        placeholder: setting.placeholder || "",317        countryCode: setting.countryCode || "",318        maxSuggestions: setting.maxSuggestions || 6,319        maxResults: setting.maxResults || 6,320        searchInCurrentMapExtent: !!setting.searchInCurrentMapExtent,321        type: "locator"322      });323      locatorSetting._openLocatorChooser();324      locatorSetting.own(325        on(locatorSetting, 'select-locator-url-ok', lang.hitch(this, function (item) {326          var addResult = this.sourceList.addRow({327            name: item.name || "New Geocoder"328          }, this.sourceList.getRows().length);329          if (addResult && addResult.success) {330            if (this._currentSourceSetting) {331              this._closeSourceSetting();332            }333            locatorSetting.setRelatedTr(addResult.tr);334            locatorSetting.placeAt(this.sourceSettingNode);335            this.sourceList.selectRow(addResult.tr);336            this._currentSourceSetting = locatorSetting;337          }338        }))339      );340      locatorSetting.own(341        on(locatorSetting, 'reselect-locator-url-ok', lang.hitch(this, function (item) {342          var tr = this._currentSourceSetting.getRelatedTr();343          this.sourceList.editRow(tr, {344            name: item.name345          });346        }))347      );348      locatorSetting.own(349        on(locatorSetting, 'select-locator-url-cancel', lang.hitch(this, function () {350          if (this._currentSourceSetting !== locatorSetting) {// locator doesn't display in UI351            locatorSetting.destroy();352            locatorSetting = null;353          }354        }))355      );356    },357    /**358     * Create new locator source setting from Source List359     * @param{object} contains setting360     * @param{string} contains definition361     * @param{node} contains relatedTr362     * @memberOf Screening/setting/SearchSourceSettings363     */364    _createNewLocatorSourceSettingFromSourceList: function (setting, definition, relatedTr) {365      if (this._currentSourceSetting) {366        this._closeSourceSetting();367      }368      this._currentSourceSetting = new LocatorSourceSetting({369        nls: lang.mixin(this.nls.searchSourceSetting, window.jimuNls.units),370        map: this.map371      });372      this._currentSourceSetting.own(373        on(this._currentSourceSetting, 'enable-local-search', lang.hitch(this, function () {374          domClass.add(this.searchSources, "esriCTSourcesExtraHeight");375        }))376      );377      this._currentSourceSetting.own(378        on(this._currentSourceSetting, 'disable-local-search', lang.hitch(this, function () {379          domClass.remove(this.searchSources, "esriCTSourcesExtraHeight");380        }))381      );382      this._currentSourceSetting.setDefinition(definition);383      this._currentSourceSetting.setConfig({384        url: setting.url || "",385        name: setting.name || "",386        singleLineFieldName: setting.singleLineFieldName || "",387        placeholder: setting.placeholder || "",388        countryCode: setting.countryCode || "",389        maxSuggestions: setting.maxSuggestions || 6,390        maxResults: setting.maxResults || 6,391        searchInCurrentMapExtent: !!setting.searchInCurrentMapExtent,392        enableLocalSearch: !!setting.enableLocalSearch,393        localSearchMinScale: setting.localSearchMinScale,394        localSearchDistance: setting.localSearchDistance,395        type: "locator"396      });397      this._currentSourceSetting.setRelatedTr(relatedTr);398      this._currentSourceSetting.placeAt(this.sourceSettingNode);399      this._currentSourceSetting.own(400        on(this._currentSourceSetting,401          'reselect-locator-url-ok',402          lang.hitch(this, function (item) {403            var tr = this._currentSourceSetting.getRelatedTr();404            this.sourceList.editRow(tr, {405              name: item.name406            });407          }))408      );409    },410    /**411     * Close source setting412     * @memberOf Screening/setting/SearchSourceSettings413     */414    _closeSourceSetting: function () {415      var tr = this._currentSourceSetting.getRelatedTr();416      var source = this._currentSourceSetting.getConfig();417      source._definition = this._currentSourceSetting.getDefinition();418      this._setRelatedConfig(tr, source);419      this.sourceList.editRow(tr, {420        name: source.name421      });422      this._currentSourceSetting.destroy();423    },424    /**425     * Create new query source setting from menu item426     * @param{object} contains setting427     * @param{string} contains definition428     * @memberOf Screening/setting/SearchSourceSettings429     */430    _createNewQuerySourceSettingFromMenuItem: function (setting, definition) {431      var querySetting = new QuerySourceSetting({432        nls: this.nls.searchSourceSetting,433        map: this.map,434        appConfig: this.appConfig435      });436      querySetting.setDefinition(definition);437      querySetting.setConfig({438        url: setting.url,439        name: setting.name || "",440        layerId: setting.layerId,441        placeholder: setting.placeholder || "",442        searchFields: setting.searchFields || [],443        displayField: setting.displayField || definition.displayField || "",444        exactMatch: !!setting.exactMatch,445        maxSuggestions: setting.maxSuggestions || 6,446        maxResults: setting.maxResults || 6,447        searchInCurrentMapExtent: !!setting.searchInCurrentMapExtent,448        type: "query"449      });450      querySetting._openQuerySourceChooser();451      querySetting.own(452        on(querySetting, 'select-query-source-ok', lang.hitch(this, function (item) {453          var addResult = this.sourceList.addRow({454            name: item.name455          }, 0);456          if (addResult && addResult.success) {457            if (this._currentSourceSetting) {458              this._closeSourceSetting();459            }460            querySetting.setRelatedTr(addResult.tr);461            querySetting.placeAt(this.sourceSettingNode);462            this.sourceList.selectRow(addResult.tr);463            this._currentSourceSetting = querySetting;464          }465        }))466      );467      querySetting.own(468        on(querySetting, 'reselect-query-source-ok', lang.hitch(this, function (item) {469          var tr = this._currentSourceSetting.getRelatedTr();470          this.sourceList.editRow(tr, {471            name: item.name472          });473        }))474      );475      querySetting.own(476        on(querySetting, 'select-query-source-cancel', lang.hitch(this, function () {477          if (this._currentSourceSetting !== querySetting) {// query source doesn't display in UI478            querySetting.destroy();479            querySetting = null;480          }481        }))482      );483    },484    /**485     * Create new query source setting from source list486     * @param{object} contains setting487     * @param{string} contains definition488     * @param{node} contains relatedTr489     * @memberOf Screening/setting/SearchSourceSettings490     */491    _createNewQuerySourceSettingFromSourceList: function (setting, definition, relatedTr) {492      if (this._currentSourceSetting) {493        this._closeSourceSetting();494      }495      this._currentSourceSetting = new QuerySourceSetting({496        nls: this.nls.searchSourceSetting,497        map: this.map,498        appConfig: this.appConfig499      });500      this._currentSourceSetting.placeAt(this.sourceSettingNode);501      this._currentSourceSetting.setDefinition(definition);502      this._currentSourceSetting.setConfig({503        url: setting.url,504        name: setting.name || "",505        layerId: setting.layerId,506        placeholder: setting.placeholder || "",507        searchFields: setting.searchFields || [],508        displayField: setting.displayField || definition.displayField || "",509        exactMatch: !!setting.exactMatch,510        maxSuggestions: setting.maxSuggestions || 6,511        maxResults: setting.maxResults || 6,512        searchInCurrentMapExtent: !!setting.searchInCurrentMapExtent,513        type: "query"514      });515      this._currentSourceSetting.setRelatedTr(relatedTr);516      this._currentSourceSetting.own(517        on(this._currentSourceSetting, 'reselect-query-source', lang.hitch(this, function (item) {518          var tr = this._currentSourceSetting.getRelatedTr();519          this.sourceList.editRow(tr, {520            name: item.name521          });522        }))523      );524    }525  });...MeasurementService.js
Source:MeasurementService.js  
1import log from '../../log';2import guid from '../../utils/guid';3import pubSubServiceInterface from '../_shared/pubSubServiceInterface';4/**5 * Measurement source schema6 *7 * @typedef {Object} MeasurementSource8 * @property {number} id -9 * @property {string} name -10 * @property {string} version -11 */12/**13 * Measurement schema14 *15 * @typedef {Object} Measurement16 * @property {number} id -17 * @property {string} SOPInstanceUID -18 * @property {string} FrameOfReferenceUID -19 * @property {string} referenceSeriesUID -20 * @property {string} label -21 * @property {string} description -22 * @property {string} type -23 * @property {string} unit -24 * @property {number} area -25 * @property {Array} points -26 * @property {MeasurementSource} source -27 */28/* Measurement schema keys for object validation. */29const MEASUREMENT_SCHEMA_KEYS = [30  'id',31  'SOPInstanceUID',32  'FrameOfReferenceUID',33  'referenceStudyUID',34  'referenceSeriesUID',35  'label',36  'description',37  'type',38  'unit',39  'area', // TODO: Add concept names instead (descriptor)40  'mean',41  'stdDev',42  'length',43  'shortestDiameter',44  'longestDiameter',45  'text', // NOTE: There is nothing like this in SR.46  'points',47  'source',48];49const EVENTS = {50  MEASUREMENT_UPDATED: 'event::measurement_updated',51  INTERNAL_MEASUREMENT_UPDATED: 'event:internal_measurement_updated',52  MEASUREMENT_ADDED: 'event::measurement_added',53  MEASUREMENT_REMOVED: 'event::measurement_removed',54  MEASUREMENTS_CLEARED: 'event::measurements_cleared',55  JUMP_TO_MEASUREMENT: 'event:jump_to_measurement',56};57const VALUE_TYPES = {58  POLYLINE: 'value_type::polyline',59  POINT: 'value_type::point',60  BIDIRECTIONAL: 'value_type::shortAxisLongAxis', // TODO -> Discuss with Danny. => just using SCOORD values isn't enough here.61  ELLIPSE: 'value_type::ellipse',62  MULTIPOINT: 'value_type::multipoint',63  CIRCLE: 'value_type::circle',64};65class MeasurementService {66  constructor() {67    this.sources = {};68    this.mappings = {};69    this.measurements = {};70    this.listeners = {};71    this._jumpToMeasurementCache = {};72    Object.defineProperty(this, 'EVENTS', {73      value: EVENTS,74      writable: false,75      enumerable: true,76      configurable: false,77    });78    Object.defineProperty(this, 'VALUE_TYPES', {79      value: VALUE_TYPES,80      writable: false,81      enumerable: true,82      configurable: false,83    });84    Object.assign(this, pubSubServiceInterface);85  }86  /**87   * Get all measurements.88   *89   * @return {Measurement[]} Array of measurements90   */91  getMeasurements() {92    const measurements = this._arrayOfObjects(this.measurements);93    return (94      measurements &&95      measurements.map(m => this.measurements[Object.keys(m)[0]])96    );97  }98  /**99   * Get specific measurement by its id.100   *101   * @param {string} id If of the measurement102   * @return {Measurement} Measurement instance103   */104  getMeasurement(id) {105    let measurement = null;106    const measurements = this.measurements[id];107    if (measurements && Object.keys(measurements).length > 0) {108      measurement = this.measurements[id];109    }110    return measurement;111  }112  /**113   * Create a new source.114   *115   * @param {string} name Name of the source116   * @param {string} version Source name117   * @return {MeasurementSource} Measurement source instance118   */119  createSource(name, version) {120    if (!name) {121      throw new Error('Source name not provided.');122    }123    if (!version) {124      throw new Error('Source version not provided.');125    }126    const id = guid();127    const source = {128      id,129      name,130      version,131    };132    source.addOrUpdate = (definition, measurement) => {133      return this.addOrUpdate(source, definition, measurement);134    };135    source.remove = id => {136      return this.remove(id, source);137    };138    source.getAnnotation = (definition, measurementId) => {139      return this.getAnnotation(source, definition, measurementId);140    };141    log.info(`New '${name}@${version}' source added.`);142    this.sources[id] = source;143    return source;144  }145  getSource(name, version) {146    const { sources } = this;147    const id = this._getSourceId(name, version);148    return sources[id];149  }150  getSourceMappings(name, version) {151    const { mappings } = this;152    const id = this._getSourceId(name, version);153    return mappings[id];154  }155  _getSourceId(name, version) {156    const { sources } = this;157    const sourceId = Object.keys(sources).find(sourceId => {158      const source = sources[sourceId];159      return source.name === name && source.version === version;160    });161    return sourceId;162  }163  /**164   * Add a new measurement matching criteria along with mapping functions.165   *166   * @param {MeasurementSource} source Measurement source instance167   * @param {string} definition Definition of the measurement (Annotation Type)168   * @param {MatchingCriteria} matchingCriteria The matching criteria169   * @param {Function} toSourceSchema Mapping function to source schema170   * @param {Function} toMeasurementSchema Mapping function to measurement schema171   * @return void172   */173  addMapping(174    source,175    definition,176    matchingCriteria,177    toSourceSchema,178    toMeasurementSchema179  ) {180    if (!this._isValidSource(source)) {181      throw new Error('Invalid source.');182    }183    if (!matchingCriteria) {184      throw new Error('Matching criteria not provided.');185    }186    if (!definition) {187      throw new Error('Definition not provided.');188    }189    if (!toSourceSchema) {190      throw new Error('Mapping function to source schema not provided.');191    }192    if (!toMeasurementSchema) {193      throw new Error('Measurement mapping function not provided.');194    }195    const mapping = {196      matchingCriteria,197      definition,198      toSourceSchema,199      toMeasurementSchema,200    };201    if (Array.isArray(this.mappings[source.id])) {202      this.mappings[source.id].push(mapping);203    } else {204      this.mappings[source.id] = [mapping];205    }206    log.info(207      `New measurement mapping added to source '${this._getSourceInfo(208        source209      )}'.`210    );211  }212  /**213   * Get annotation for specific source.214   *215   * @param {MeasurementSource} source Measurement source instance216   * @param {string} definition The source definition217   * @param {string} measurementId The measurement service measurement id218   * @return {Object} Source measurement schema219   */220  getAnnotation(source, definition, measurementId) {221    if (!this._isValidSource(source)) {222      log.warn('Invalid source. Exiting early.');223      return;224    }225    if (!definition) {226      log.warn('No source definition provided. Exiting early.');227      return;228    }229    const mapping = this._getMappingByMeasurementSource(230      measurementId,231      definition232    );233    const measurement = this.getMeasurement(measurementId);234    if (mapping) return mapping.toSourceSchema(measurement, definition);235    const matchingMapping = this._getMatchingMapping(236      source,237      definition,238      measurement239    );240    if (matchingMapping) {241      log.info('Matching mapping found:', matchingMapping);242      const { toSourceSchema, definition } = matchingMapping;243      return toSourceSchema(measurement, definition);244    }245  }246  update(id, measurement, notYetUpdatedAtSource = false) {247    if (this.measurements[id]) {248      const updatedMeasurement = {249        ...measurement,250        modifiedTimestamp: Math.floor(Date.now() / 1000),251      };252      log.info(253        `Updating internal measurement representation...`,254        updatedMeasurement255      );256      this.measurements[id] = updatedMeasurement;257      this._broadcastEvent(258        // Add an internal flag to say the measurement has not yet been updated at source.259        this.EVENTS.MEASUREMENT_UPDATED,260        {261          source: measurement.source,262          measurement: updatedMeasurement,263          notYetUpdatedAtSource,264        }265      );266      return updatedMeasurement.id;267    }268  }269  /**270   * Add a raw measurement into a source so that it may be271   * Converted to/from annotation in the same way. E.g. import serialized data272   * Of the same form as the measurement source.273   * @param {MeasurementSource} source The measurement source instance.274   * @param {string} definition The source definition you want to add the measuremnet to.275   * @param {object} data The data you wish to add to the source.276   * @param {function} toMeasurementSchema A function to get the `data` into the same shape as the source definition.277   */278  addRawMeasurement(source, definition, data, toMeasurementSchema) {279    if (!this._isValidSource(source)) {280      log.warn('Invalid source. Exiting early.');281      return;282    }283    const sourceInfo = this._getSourceInfo(source);284    if (!definition) {285      log.warn('No source definition provided. Exiting early.');286      return;287    }288    if (!this._sourceHasMappings(source)) {289      log.warn(290        `No measurement mappings found for '${sourceInfo}' source. Exiting early.`291      );292      return;293    }294    let measurement = {};295    try {296      /* Convert measurement */297      measurement = toMeasurementSchema(data);298      /* Assign measurement source instance */299      measurement.source = source;300    } catch (error) {301      log.warn(302        `Failed to map '${sourceInfo}' measurement for definition ${definition}:`,303        error.message304      );305      return;306    }307    if (!this._isValidMeasurement(measurement)) {308      log.warn(309        `Attempting to add or update a invalid measurement provided by '${sourceInfo}'. Exiting early.`310      );311      return;312    }313    let internalId = data.id;314    if (!internalId) {315      internalId = guid();316      log.warn(`Measurement ID not found. Generating UID: ${internalId}`);317    }318    const newMeasurement = {319      ...measurement,320      modifiedTimestamp: Math.floor(Date.now() / 1000),321      id: internalId,322    };323    if (this.measurements[internalId]) {324      log.info(325        `Measurement already defined. Updating measurement.`,326        newMeasurement327      );328      this.measurements[internalId] = newMeasurement;329      this._broadcastEvent(this.EVENTS.MEASUREMENT_UPDATED, {330        source,331        measurement: newMeasurement,332      });333    } else {334      log.info(`Measurement added.`, newMeasurement);335      this.measurements[internalId] = newMeasurement;336      this._broadcastEvent(this.EVENTS.MEASUREMENT_ADDED, {337        source,338        measurement: newMeasurement,339      });340    }341    return newMeasurement.id;342  }343  /**344   * Adds or update persisted measurements.345   *346   * @param {MeasurementSource} source The measurement source instance347   * @param {string} definition The source definition348   * @param {Measurement} measurement The source measurement349   * @return {string} A measurement id350   */351  addOrUpdate(source, definition, sourceMeasurement) {352    if (!this._isValidSource(source)) {353      throw new Error('Invalid source.');354    }355    if (!definition) {356      throw new Error('No source definition provided.');357    }358    const sourceInfo = this._getSourceInfo(source);359    if (!this._sourceHasMappings(source)) {360      throw new Error(361        `No measurement mappings found for '${sourceInfo}' source. Exiting early.`362      );363    }364    let measurement = {};365    try {366      const sourceMappings = this.mappings[source.id];367      const { toMeasurementSchema } = sourceMappings.find(368        mapping => mapping.definition === definition369      );370      /* Convert measurement */371      measurement = toMeasurementSchema(sourceMeasurement);372      /* Assign measurement source instance */373      measurement.source = source;374    } catch (error) {375      throw new Error(376        `Failed to map '${sourceInfo}' measurement for definition ${definition}:`,377        error.message378      );379    }380    if (!this._isValidMeasurement(measurement)) {381      throw new Error(382        `Attempting to add or update a invalid measurement provided by '${sourceInfo}'. Exiting early.`383      );384    }385    let internalId = sourceMeasurement.id;386    if (!internalId) {387      internalId = guid();388      log.info(`Measurement ID not found. Generating UID: ${internalId}`);389    }390    const newMeasurement = {391      ...measurement,392      modifiedTimestamp: Math.floor(Date.now() / 1000),393      id: internalId,394    };395    if (this.measurements[internalId]) {396      log.info(397        `Measurement already defined. Updating measurement.`,398        newMeasurement399      );400      this.measurements[internalId] = newMeasurement;401      this._broadcastEvent(this.EVENTS.MEASUREMENT_UPDATED, {402        source,403        measurement: newMeasurement,404        notYetUpdatedAtSource: false,405      });406    } else {407      log.info('Measurement added.', newMeasurement);408      this.measurements[internalId] = newMeasurement;409      this._broadcastEvent(this.EVENTS.MEASUREMENT_ADDED, {410        source,411        measurement: newMeasurement,412      });413    }414    return newMeasurement.id;415  }416  /**417   * Removes a measurement and broadcasts the removed event.418   *419   * @param {string} id The measurement id420   * @param {MeasurementSource} source The measurement source instance421   * @return {string} The removed measurement id422   */423  remove(id, source) {424    if (!id || !this.measurements[id]) {425      log.warn(`No id provided, or unable to find measurement by id.`);426      return;427    }428    delete this.measurements[id];429    this._broadcastEvent(this.EVENTS.MEASUREMENT_REMOVED, {430      source,431      measurement: id, // This is weird :shrug:432    });433  }434  clearMeasurements() {435    this.measurements = {};436    this._broadcastEvent(this.EVENTS.MEASUREMENTS_CLEARED);437  }438  jumpToMeasurement(viewportIndex, id) {439    const measurement = this.measurements[id];440    if (!measurement) {441      log.warn(`No id provided, or unable to find measurement by id.`);442      return;443    }444    this._addJumpToMeasurement(viewportIndex, id);445    const eventName = this.EVENTS.JUMP_TO_MEASUREMENT;446    const hasListeners = Object.keys(this.listeners).length > 0;447    const hasCallbacks = Array.isArray(this.listeners[eventName]);448    if (hasListeners && hasCallbacks) {449      this.listeners[eventName].forEach(listener => {450        listener.callback({ viewportIndex, measurement });451      });452    }453  }454  _addJumpToMeasurement(viewportIndex, id) {455    this._jumpToMeasurementCache[viewportIndex] = id;456  }457  getJumpToMeasurement(viewportIndex) {458    return this._jumpToMeasurementCache[viewportIndex];459  }460  removeJumpToMeasurement(viewportIndex) {461    delete this._jumpToMeasurementCache[viewportIndex];462  }463  _getMappingByMeasurementSource(measurementId, definition) {464    const measurement = this.getMeasurement(measurementId);465    if (this._isValidSource(measurement.source)) {466      return this.mappings[measurement.source.id].find(467        m => m.definition === definition468      );469    }470  }471  /**472   * Clear all measurements and broadcasts cleared event.473   */474  clear() {475    this.measurements = {};476    this._broadcastEvent(this.EVENTS.MEASUREMENTS_CLEARED);477  }478  /**479   * Get measurement mapping function if matching criteria.480   *481   * @param {MeasurementSource} source Measurement source instance482   * @param {string} definition The source definition483   * @param {Measurement} measurement The measurement service measurement484   * @return {Object} The mapping based on matched criteria485   */486  _getMatchingMapping(source, definition, measurement) {487    const sourceMappings = this.mappings[source.id];488    const sourceMappingsByDefinition = sourceMappings.filter(489      mapping => mapping.definition === definition490    );491    /* Criteria Matching */492    return sourceMappingsByDefinition.find(({ matchingCriteria }) => {493      return (494        measurement.points &&495        measurement.points.length === matchingCriteria.points496      );497    });498  }499  /**500   * Returns formatted string with source info.501   *502   * @param {MeasurementSource} source Measurement source503   * @return {string} Source information504   */505  _getSourceInfo(source) {506    return `${source.name}@${source.version}`;507  }508  /**509   * Checks if given source is valid.510   *511   * @param {MeasurementSource} source Measurement source512   * @return {boolean} Measurement source validation513   */514  _isValidSource(source) {515    return source && this.sources[source.id];516  }517  /**518   * Checks if a given source has mappings.519   *520   * @param {MeasurementSource} source The measurement source521   * @return {boolean} Validation if source has mappings522   */523  _sourceHasMappings(source) {524    return (525      Array.isArray(this.mappings[source.id]) && this.mappings[source.id].length526    );527  }528  /**529   * Check if a given measurement data is valid.530   *531   * @param {Measurement} measurementData Measurement data532   * @return {boolean} Measurement validation533   */534  _isValidMeasurement(measurementData) {535    Object.keys(measurementData).forEach(key => {536      if (!MEASUREMENT_SCHEMA_KEYS.includes(key)) {537        log.warn(`Invalid measurement key: ${key}`);538        return false;539      }540    });541    return true;542  }543  /**544   * Check if a given measurement service event is valid.545   *546   * @param {string} eventName The name of the event547   * @return {boolean} Event name validation548  //  */549  // _isValidEvent(eventName) {550  //   return Object.values(this.EVENTS).includes(eventName);551  // }552  /**553   * Converts object of objects to array.554   *555   * @return {Array} Array of objects556   */557  _arrayOfObjects = obj => {558    return Object.entries(obj).map(e => ({ [e[0]]: e[1] }));559  };560}561export default MeasurementService;...s2sTesting_spec.js
Source:s2sTesting_spec.js  
1import s2sTesting from 'modules/s2sTesting';2import { config } from 'src/config';3import find from 'core-js/library/fn/array/find';4var events = require('src/events');5var CONSTANTS = require('src/constants.json');6const BID_ADJUSTMENT = CONSTANTS.EVENTS.BID_ADJUSTMENT;7var expect = require('chai').expect;8describe('s2sTesting', function () {9  let mathRandomStub;10  let randomNumber = 0;11  beforeEach(function () {12    mathRandomStub = sinon.stub(Math, 'random').callsFake(() => { return randomNumber; });13  });14  afterEach(function () {15    mathRandomStub.restore();16  });17  describe('s2sTesting.getSource', function () {18    // helper function to set random number and get the source19    function getExpectedSource(randNumber, sourceWeights, sources) {20      // set random number for testing21      randomNumber = randNumber;22      return s2sTesting.getSource(sourceWeights, sources);23    }24    it('returns undefined if no sources', function () {25      expect(getExpectedSource(0, {})).to.be.undefined;26      expect(getExpectedSource(0.5, {})).to.be.undefined;27      expect(getExpectedSource(0.9999, {})).to.be.undefined;28    });29    it('returns undefined if no weights', function () {30      expect(getExpectedSource(0, {server: 0, client: 0})).to.be.undefined;31      expect(getExpectedSource(0.5, {client: 0})).to.be.undefined;32    });33    it('gets the expected source from 3 sources', function () {34      var sources = ['server', 'client', 'both'];35      expect(getExpectedSource(0, {server: 1, client: 1, both: 2}, sources)).to.equal('server');36      expect(getExpectedSource(0.2499999, {server: 1, client: 1, both: 2}, sources)).to.equal('server');37      expect(getExpectedSource(0.25, {server: 1, client: 1, both: 2}, sources)).to.equal('client');38      expect(getExpectedSource(0.49999, {server: 1, client: 1, both: 2}, sources)).to.equal('client');39      expect(getExpectedSource(0.5, {server: 1, client: 1, both: 2}, sources)).to.equal('both');40      expect(getExpectedSource(0.99999, {server: 1, client: 1, both: 2}, sources)).to.equal('both');41    });42    it('gets the expected source from 2 sources', function () {43      expect(getExpectedSource(0, {server: 2, client: 3})).to.equal('server');44      expect(getExpectedSource(0.39999, {server: 2, client: 3})).to.equal('server');45      expect(getExpectedSource(0.4, {server: 2, client: 3})).to.equal('client');46      expect(getExpectedSource(0.9, {server: 2, client: 3})).to.equal('client');47      var sources = ['server', 'client', 'both'];48      expect(getExpectedSource(0, {server: 2, client: 3}, sources)).to.equal('server');49      expect(getExpectedSource(0.39999, {server: 2, client: 3}, sources)).to.equal('server');50      expect(getExpectedSource(0.4, {server: 2, client: 3}, sources)).to.equal('client');51      expect(getExpectedSource(0.9, {server: 2, client: 3}, sources)).to.equal('client');52    });53    it('gets the expected source from 1 source', function () {54      expect(getExpectedSource(0, {client: 2})).to.equal('client');55      expect(getExpectedSource(0.5, {client: 2})).to.equal('client');56      expect(getExpectedSource(0.99999, {client: 2})).to.equal('client');57    });58    it('ignores an invalid source', function () {59      expect(getExpectedSource(0, {client: 2, cache: 2})).to.equal('client');60      expect(getExpectedSource(0.3333, {server: 1, cache: 1, client: 2})).to.equal('server');61      expect(getExpectedSource(0.34, {server: 1, cache: 1, client: 2})).to.equal('client');62    });63    it('ignores order of sources', function () {64      var sources = ['server', 'client', 'both'];65      expect(getExpectedSource(0, {client: 1, server: 1, both: 2}, sources)).to.equal('server');66      expect(getExpectedSource(0.2499999, {both: 2, client: 1, server: 1}, sources)).to.equal('server');67      expect(getExpectedSource(0.25, {client: 1, both: 2, server: 1}, sources)).to.equal('client');68      expect(getExpectedSource(0.49999, {server: 1, both: 2, client: 1}, sources)).to.equal('client');69      expect(getExpectedSource(0.5, {both: 2, server: 1, client: 1}, sources)).to.equal('both');70    });71    it('accepts an array of sources', function () {72      expect(getExpectedSource(0.3333, {second: 2, first: 1}, ['first', 'second'])).to.equal('first');73      expect(getExpectedSource(0.34, {second: 2, first: 1}, ['first', 'second'])).to.equal('second');74      expect(getExpectedSource(0.9999, {second: 2, first: 1}, ['first', 'second'])).to.equal('second');75    });76  });77  describe('s2sTesting.getSourceBidderMap', function () {78    describe('setting source through s2sConfig', function () {79      beforeEach(function () {80        // set random number for testing81        randomNumber = 0.7;82      });83      it('does not work if testing is "false"', function () {84        config.setConfig({s2sConfig: {85          bidders: ['rubicon'],86          testing: false,87          bidderControl: {rubicon: {bidSource: {server: 1, client: 1}}}88        }});89        expect(s2sTesting.getSourceBidderMap()).to.eql({90          server: [],91          client: []92        });93      });94      it('sets one client bidder', function () {95        config.setConfig({s2sConfig: {96          bidders: ['rubicon'],97          testing: true,98          bidderControl: {rubicon: {bidSource: {server: 1, client: 1}}}99        }});100        expect(s2sTesting.getSourceBidderMap()).to.eql({101          server: [],102          client: ['rubicon']103        });104      });105      it('sets one server bidder', function () {106        config.setConfig({s2sConfig: {107          bidders: ['rubicon'],108          testing: true,109          bidderControl: {rubicon: {bidSource: {server: 4, client: 1}}}110        }});111        expect(s2sTesting.getSourceBidderMap()).to.eql({112          server: ['rubicon'],113          client: []114        });115      });116      it('defaults to server', function () {117        config.setConfig({s2sConfig: {118          bidders: ['rubicon'],119          testing: true120        }});121        expect(s2sTesting.getSourceBidderMap()).to.eql({122          server: ['rubicon'],123          client: []124        });125      });126      it('sets two bidders', function () {127        config.setConfig({s2sConfig: {128          bidders: ['rubicon', 'appnexus'],129          testing: true,130          bidderControl: {131            rubicon: {bidSource: {server: 3, client: 1}},132            appnexus: {bidSource: {server: 1, client: 1}}133          }}});134        var serverClientBidders = s2sTesting.getSourceBidderMap();135        expect(serverClientBidders.server).to.eql(['rubicon']);136        expect(serverClientBidders.client).to.have.members(['appnexus']);137      });138    });139    describe('setting source through adUnits', function () {140      beforeEach(function () {141        // reset s2sconfig bid sources142        config.setConfig({s2sConfig: {testing: true}});143        // set random number for testing144        randomNumber = 0.7;145      });146      it('sets one bidder source from one adUnit', function () {147        var adUnits = [148          {bids: [149            {bidder: 'rubicon', bidSource: {server: 4, client: 1}}150          ]}151        ];152        expect(s2sTesting.getSourceBidderMap(adUnits)).to.eql({153          server: ['rubicon'],154          client: []155        });156        // should have saved the source on the bid157        expect(adUnits[0].bids[0].calcSource).to.equal('server');158        expect(adUnits[0].bids[0].finalSource).to.equal('server');159        adUnits = [160          {bids: [161            {bidder: 'rubicon', bidSource: {server: 1, client: 1}}162          ]}163        ];164        expect(s2sTesting.getSourceBidderMap(adUnits)).to.eql({165          server: [],166          client: ['rubicon']167        });168        // should have saved the source on the bid169        expect(adUnits[0].bids[0].calcSource).to.equal('client');170        expect(adUnits[0].bids[0].finalSource).to.equal('client');171      });172      it('defaults to client if no bidSource', function () {173        var adUnits = [174          {bids: [175            {bidder: 'rubicon', bidSource: {}}176          ]}177        ];178        expect(s2sTesting.getSourceBidderMap(adUnits)).to.eql({179          server: [],180          client: ['rubicon']181        });182        // should have saved the source on the bid183        expect(adUnits[0].bids[0].calcSource).to.be.undefined;184        expect(adUnits[0].bids[0].finalSource).to.equal('client');185      });186      it('sets multiple bidders sources from one adUnit', function () {187        var adUnits = [188          {bids: [189            {bidder: 'rubicon', bidSource: {server: 2, client: 1}},190            {bidder: 'appnexus', bidSource: {server: 3, client: 1}}191          ]}192        ];193        var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits);194        expect(serverClientBidders.server).to.eql(['appnexus']);195        expect(serverClientBidders.client).to.have.members(['rubicon']);196        // should have saved the source on the bid197        expect(adUnits[0].bids[0].calcSource).to.equal('client');198        expect(adUnits[0].bids[0].finalSource).to.equal('client');199        expect(adUnits[0].bids[1].calcSource).to.equal('server');200        expect(adUnits[0].bids[1].finalSource).to.equal('server');201      });202      it('sets multiple bidders sources from multiple adUnits', function () {203        var adUnits = [204          {bids: [205            {bidder: 'rubicon', bidSource: {server: 2, client: 1}},206            {bidder: 'appnexus', bidSource: {server: 1, client: 1}}207          ]},208          {bids: [209            {bidder: 'rubicon', bidSource: {server: 4, client: 1}},210            {bidder: 'bidder3', bidSource: {client: 1}}211          ]}212        ];213        var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits);214        expect(serverClientBidders.server).to.have.members(['rubicon']);215        expect(serverClientBidders.server).to.not.have.members(['appnexus', 'bidder3']);216        expect(serverClientBidders.client).to.have.members(['rubicon', 'appnexus', 'bidder3']);217        // should have saved the source on the bid218        expect(adUnits[0].bids[0].calcSource).to.equal('client');219        expect(adUnits[0].bids[0].finalSource).to.equal('client');220        expect(adUnits[0].bids[1].calcSource).to.equal('client');221        expect(adUnits[0].bids[1].finalSource).to.equal('client');222        expect(adUnits[1].bids[0].calcSource).to.equal('server');223        expect(adUnits[1].bids[0].finalSource).to.equal('server');224        expect(adUnits[1].bids[1].calcSource).to.equal('client');225        expect(adUnits[1].bids[1].finalSource).to.equal('client');226      });227      it('should reuse calculated sources', function () {228        var adUnits = [229          {bids: [230            {bidder: 'rubicon', calcSource: 'client', bidSource: {server: 4, client: 1}},231            {bidder: 'appnexus', calcSource: 'server', bidSource: {server: 1, client: 1}},232            {bidder: 'bidder3', calcSource: 'server', bidSource: {client: 1}}233          ]}234        ];235        var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits);236        expect(serverClientBidders.server).to.have.members(['appnexus', 'bidder3']);237        expect(serverClientBidders.server).to.not.have.members(['rubicon']);238        expect(serverClientBidders.client).to.have.members(['rubicon']);239        expect(serverClientBidders.client).to.not.have.members(['appnexus', 'bidder3']);240        // should have saved the source on the bid241        expect(adUnits[0].bids[0].calcSource).to.equal('client');242        expect(adUnits[0].bids[0].finalSource).to.equal('client');243        expect(adUnits[0].bids[1].calcSource).to.equal('server');244        expect(adUnits[0].bids[1].finalSource).to.equal('server');245        expect(adUnits[0].bids[2].calcSource).to.equal('server');246        expect(adUnits[0].bids[2].finalSource).to.equal('server');247      });248    });249    describe('setting source through s2sconfig and adUnits', function () {250      beforeEach(function () {251        // reset s2sconfig bid sources252        config.setConfig({s2sConfig: {testing: true}});253        // set random number for testing254        randomNumber = 0.7;255      });256      it('should get sources from  both', function () {257        // set rubicon: server and appnexus: client258        var adUnits = [259          {bids: [260            {bidder: 'rubicon', bidSource: {server: 4, client: 1}},261            {bidder: 'appnexus', bidSource: {client: 1}}262          ]}263        ];264        // set rubicon: client and appnexus: server265        config.setConfig({s2sConfig: {266          bidders: ['rubicon', 'appnexus'],267          testing: true,268          bidderControl: {269            rubicon: {bidSource: {server: 2, client: 1}},270            appnexus: {bidSource: {server: 1}}271          }272        }});273        var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits);274        expect(serverClientBidders.server).to.have.members(['rubicon', 'appnexus']);275        expect(serverClientBidders.client).to.have.members(['rubicon', 'appnexus']);276      });277    });278  });...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
