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!!