提交 1706a5c5f658db9930462826623031fd9d87ab81

作者 guanh
0 个父辈

feat: 指纹

  1 +Copyright (c) 2020 FingerprintJS, Inc
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in all
  11 +copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19 +SOFTWARE.
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +'use strict';
  10 +(function(window) {
  11 + Object.defineProperty(exports, '__esModule', { value: true });
  12 +
  13 + var tslib = require('tslib');
  14 +
  15 + /*
  16 + * Taken from https://github.com/karanlyons/murmurHash3.js/blob/a33d0723127e2e5415056c455f8aed2451ace208/murmurHash3.js
  17 + */
  18 + //
  19 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  20 + // added together as a 64bit int (as an array of two 32bit ints).
  21 + //
  22 + function x64Add(m, n) {
  23 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  24 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  25 + var o = [0, 0, 0, 0];
  26 + o[3] += m[3] + n[3];
  27 + o[2] += o[3] >>> 16;
  28 + o[3] &= 0xffff;
  29 + o[2] += m[2] + n[2];
  30 + o[1] += o[2] >>> 16;
  31 + o[2] &= 0xffff;
  32 + o[1] += m[1] + n[1];
  33 + o[0] += o[1] >>> 16;
  34 + o[1] &= 0xffff;
  35 + o[0] += m[0] + n[0];
  36 + o[0] &= 0xffff;
  37 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  38 + }
  39 + //
  40 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  41 + // multiplied together as a 64bit int (as an array of two 32bit ints).
  42 + //
  43 + function x64Multiply(m, n) {
  44 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  45 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  46 + var o = [0, 0, 0, 0];
  47 + o[3] += m[3] * n[3];
  48 + o[2] += o[3] >>> 16;
  49 + o[3] &= 0xffff;
  50 + o[2] += m[2] * n[3];
  51 + o[1] += o[2] >>> 16;
  52 + o[2] &= 0xffff;
  53 + o[2] += m[3] * n[2];
  54 + o[1] += o[2] >>> 16;
  55 + o[2] &= 0xffff;
  56 + o[1] += m[1] * n[3];
  57 + o[0] += o[1] >>> 16;
  58 + o[1] &= 0xffff;
  59 + o[1] += m[2] * n[2];
  60 + o[0] += o[1] >>> 16;
  61 + o[1] &= 0xffff;
  62 + o[1] += m[3] * n[1];
  63 + o[0] += o[1] >>> 16;
  64 + o[1] &= 0xffff;
  65 + o[0] += m[0] * n[3] + m[1] * n[2] + m[2] * n[1] + m[3] * n[0];
  66 + o[0] &= 0xffff;
  67 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  68 + }
  69 + //
  70 + // Given a 64bit int (as an array of two 32bit ints) and an int
  71 + // representing a number of bit positions, returns the 64bit int (as an
  72 + // array of two 32bit ints) rotated left by that number of positions.
  73 + //
  74 + function x64Rotl(m, n) {
  75 + n %= 64;
  76 + if (n === 32) {
  77 + return [m[1], m[0]];
  78 + }
  79 + else if (n < 32) {
  80 + return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))];
  81 + }
  82 + else {
  83 + n -= 32;
  84 + return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))];
  85 + }
  86 + }
  87 + //
  88 + // Given a 64bit int (as an array of two 32bit ints) and an int
  89 + // representing a number of bit positions, returns the 64bit int (as an
  90 + // array of two 32bit ints) shifted left by that number of positions.
  91 + //
  92 + function x64LeftShift(m, n) {
  93 + n %= 64;
  94 + if (n === 0) {
  95 + return m;
  96 + }
  97 + else if (n < 32) {
  98 + return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
  99 + }
  100 + else {
  101 + return [m[1] << (n - 32), 0];
  102 + }
  103 + }
  104 + //
  105 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  106 + // xored together as a 64bit int (as an array of two 32bit ints).
  107 + //
  108 + function x64Xor(m, n) {
  109 + return [m[0] ^ n[0], m[1] ^ n[1]];
  110 + }
  111 + //
  112 + // Given a block, returns murmurHash3's final x64 mix of that block.
  113 + // (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
  114 + // only place where we need to right shift 64bit ints.)
  115 + //
  116 + function x64Fmix(h) {
  117 + h = x64Xor(h, [0, h[0] >>> 1]);
  118 + h = x64Multiply(h, [0xff51afd7, 0xed558ccd]);
  119 + h = x64Xor(h, [0, h[0] >>> 1]);
  120 + h = x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
  121 + h = x64Xor(h, [0, h[0] >>> 1]);
  122 + return h;
  123 + }
  124 + //
  125 + // Given a string and an optional seed as an int, returns a 128 bit
  126 + // hash using the x64 flavor of MurmurHash3, as an unsigned hex.
  127 + //
  128 + function x64hash128(key, seed) {
  129 + key = key || '';
  130 + seed = seed || 0;
  131 + var remainder = key.length % 16;
  132 + var bytes = key.length - remainder;
  133 + var h1 = [0, seed];
  134 + var h2 = [0, seed];
  135 + var k1 = [0, 0];
  136 + var k2 = [0, 0];
  137 + var c1 = [0x87c37b91, 0x114253d5];
  138 + var c2 = [0x4cf5ad43, 0x2745937f];
  139 + var i;
  140 + for (i = 0; i < bytes; i = i + 16) {
  141 + k1 = [
  142 + (key.charCodeAt(i + 4) & 0xff) |
  143 + ((key.charCodeAt(i + 5) & 0xff) << 8) |
  144 + ((key.charCodeAt(i + 6) & 0xff) << 16) |
  145 + ((key.charCodeAt(i + 7) & 0xff) << 24),
  146 + (key.charCodeAt(i) & 0xff) |
  147 + ((key.charCodeAt(i + 1) & 0xff) << 8) |
  148 + ((key.charCodeAt(i + 2) & 0xff) << 16) |
  149 + ((key.charCodeAt(i + 3) & 0xff) << 24),
  150 + ];
  151 + k2 = [
  152 + (key.charCodeAt(i + 12) & 0xff) |
  153 + ((key.charCodeAt(i + 13) & 0xff) << 8) |
  154 + ((key.charCodeAt(i + 14) & 0xff) << 16) |
  155 + ((key.charCodeAt(i + 15) & 0xff) << 24),
  156 + (key.charCodeAt(i + 8) & 0xff) |
  157 + ((key.charCodeAt(i + 9) & 0xff) << 8) |
  158 + ((key.charCodeAt(i + 10) & 0xff) << 16) |
  159 + ((key.charCodeAt(i + 11) & 0xff) << 24),
  160 + ];
  161 + k1 = x64Multiply(k1, c1);
  162 + k1 = x64Rotl(k1, 31);
  163 + k1 = x64Multiply(k1, c2);
  164 + h1 = x64Xor(h1, k1);
  165 + h1 = x64Rotl(h1, 27);
  166 + h1 = x64Add(h1, h2);
  167 + h1 = x64Add(x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
  168 + k2 = x64Multiply(k2, c2);
  169 + k2 = x64Rotl(k2, 33);
  170 + k2 = x64Multiply(k2, c1);
  171 + h2 = x64Xor(h2, k2);
  172 + h2 = x64Rotl(h2, 31);
  173 + h2 = x64Add(h2, h1);
  174 + h2 = x64Add(x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
  175 + }
  176 + k1 = [0, 0];
  177 + k2 = [0, 0];
  178 + switch (remainder) {
  179 + case 15:
  180 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 14)], 48));
  181 + // fallthrough
  182 + case 14:
  183 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 13)], 40));
  184 + // fallthrough
  185 + case 13:
  186 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 12)], 32));
  187 + // fallthrough
  188 + case 12:
  189 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 11)], 24));
  190 + // fallthrough
  191 + case 11:
  192 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 10)], 16));
  193 + // fallthrough
  194 + case 10:
  195 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 9)], 8));
  196 + // fallthrough
  197 + case 9:
  198 + k2 = x64Xor(k2, [0, key.charCodeAt(i + 8)]);
  199 + k2 = x64Multiply(k2, c2);
  200 + k2 = x64Rotl(k2, 33);
  201 + k2 = x64Multiply(k2, c1);
  202 + h2 = x64Xor(h2, k2);
  203 + // fallthrough
  204 + case 8:
  205 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 7)], 56));
  206 + // fallthrough
  207 + case 7:
  208 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 6)], 48));
  209 + // fallthrough
  210 + case 6:
  211 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 5)], 40));
  212 + // fallthrough
  213 + case 5:
  214 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 4)], 32));
  215 + // fallthrough
  216 + case 4:
  217 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 3)], 24));
  218 + // fallthrough
  219 + case 3:
  220 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 2)], 16));
  221 + // fallthrough
  222 + case 2:
  223 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 1)], 8));
  224 + // fallthrough
  225 + case 1:
  226 + k1 = x64Xor(k1, [0, key.charCodeAt(i)]);
  227 + k1 = x64Multiply(k1, c1);
  228 + k1 = x64Rotl(k1, 31);
  229 + k1 = x64Multiply(k1, c2);
  230 + h1 = x64Xor(h1, k1);
  231 + // fallthrough
  232 + }
  233 + h1 = x64Xor(h1, [0, key.length]);
  234 + h2 = x64Xor(h2, [0, key.length]);
  235 + h1 = x64Add(h1, h2);
  236 + h2 = x64Add(h2, h1);
  237 + h1 = x64Fmix(h1);
  238 + h2 = x64Fmix(h2);
  239 + h1 = x64Add(h1, h2);
  240 + h2 = x64Add(h2, h1);
  241 + return (('00000000' + (h1[0] >>> 0).toString(16)).slice(-8) +
  242 + ('00000000' + (h1[1] >>> 0).toString(16)).slice(-8) +
  243 + ('00000000' + (h2[0] >>> 0).toString(16)).slice(-8) +
  244 + ('00000000' + (h2[1] >>> 0).toString(16)).slice(-8));
  245 + }
  246 +
  247 + var version = "3.0.3";
  248 +
  249 + function requestIdleCallbackIfAvailable(fallbackTimeout) {
  250 + return new Promise(function (resolve) {
  251 + if (window.requestIdleCallback) {
  252 + window.requestIdleCallback(function () { return resolve(); });
  253 + }
  254 + else {
  255 + setTimeout(resolve, fallbackTimeout);
  256 + }
  257 + });
  258 + }
  259 +
  260 + /*
  261 + * This file contains functions to work with pure data only (no browser features, DOM, side effects, etc).
  262 + */
  263 + /**
  264 + * Does the same as Array.prototype.includes but has better typing
  265 + */
  266 + function includes(haystack, needle) {
  267 + for (var i = 0, l = haystack.length; i < l; ++i) {
  268 + if (haystack[i] === needle) {
  269 + return true;
  270 + }
  271 + }
  272 + return false;
  273 + }
  274 + /**
  275 + * Like `!includes()` but with proper typing
  276 + */
  277 + function excludes(haystack, needle) {
  278 + return !includes(haystack, needle);
  279 + }
  280 + /**
  281 + * Be careful, NaN can return
  282 + */
  283 + function toInt(value) {
  284 + if (typeof value === 'number') {
  285 + return value | 0;
  286 + }
  287 + return parseInt(value);
  288 + }
  289 + /**
  290 + * Be careful, NaN can return
  291 + */
  292 + function toFloat(value) {
  293 + if (typeof value === 'number') {
  294 + return value;
  295 + }
  296 + return parseFloat(value);
  297 + }
  298 + function countTruthy(values) {
  299 + return values.reduce(function (sum, value) { return sum + (value ? 1 : 0); }, 0);
  300 + }
  301 +
  302 + /*
  303 + * Functions to help with browser features
  304 + */
  305 + var w = window;
  306 + var n = window.navigator;
  307 + var d = window.document;
  308 + /**
  309 + * Checks whether the browser is based on Trident (the Internet Explorer engine) without using user-agent.
  310 + *
  311 + * Warning for package users:
  312 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  313 + */
  314 + function isTrident() {
  315 + // The properties are checked to be in IE 10, IE 11 and not to be in other browsers in October 2020
  316 + return (countTruthy([
  317 + 'MSCSSMatrix' in w,
  318 + 'msSetImmediate' in w,
  319 + 'msIndexedDB' in w,
  320 + 'msMaxTouchPoints' in n,
  321 + 'msPointerEnabled' in n,
  322 + ]) >= 4);
  323 + }
  324 + /**
  325 + * Checks whether the browser is based on EdgeHTML (the pre-Chromium Edge engine) without using user-agent.
  326 + *
  327 + * Warning for package users:
  328 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  329 + */
  330 + function isEdgeHTML() {
  331 + // Based on research in October 2020
  332 + return (countTruthy(['msWriteProfilerMark' in w, 'MSStream' in w, 'msLaunchUri' in n, 'msSaveBlob' in n]) >= 3 &&
  333 + !isTrident());
  334 + }
  335 + /**
  336 + * Checks whether the browser is based on Chromium without using user-agent.
  337 + *
  338 + * Warning for package users:
  339 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  340 + */
  341 + function isChromium() {
  342 + // Based on research in October 2020. Tested to detect Chromium 42-86.
  343 + return (countTruthy([
  344 + 'webkitPersistentStorage' in n,
  345 + 'webkitTemporaryStorage' in n,
  346 + n.vendor.indexOf('Google') === 0,
  347 + 'webkitResolveLocalFileSystemURL' in w,
  348 + 'BatteryManager' in w,
  349 + 'webkitMediaStream' in w,
  350 + 'webkitSpeechGrammar' in w,
  351 + ]) >= 5);
  352 + }
  353 + /**
  354 + * Checks whether the browser is based on mobile or desktop Safari without using user-agent.
  355 + * All iOS browsers use WebKit (the Safari engine).
  356 + *
  357 + * Warning for package users:
  358 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  359 + */
  360 + function isWebKit() {
  361 + // Based on research in September 2020
  362 + return (countTruthy([
  363 + 'ApplePayError' in w,
  364 + 'CSSPrimitiveValue' in w,
  365 + 'Counter' in w,
  366 + n.vendor.indexOf('Apple') === 0,
  367 + 'getStorageUpdates' in n,
  368 + 'WebKitMediaKeys' in w,
  369 + ]) >= 4);
  370 + }
  371 + /**
  372 + * Checks whether the WebKit browser is a desktop Safari.
  373 + *
  374 + * Warning for package users:
  375 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  376 + */
  377 + function isDesktopSafari() {
  378 + return (countTruthy([
  379 + 'safari' in w,
  380 + !('DeviceMotionEvent' in w),
  381 + !('ongestureend' in w),
  382 + !('standalone' in n),
  383 + ]) >= 3);
  384 + }
  385 + /**
  386 + * Checks whether the browser is based on Gecko (Firefox engine) without using user-agent.
  387 + *
  388 + * Warning for package users:
  389 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  390 + */
  391 + function isGecko() {
  392 + var _a;
  393 + // Based on research in September 2020
  394 + return (countTruthy([
  395 + 'buildID' in n,
  396 + ((_a = d.window.documentElement) === null || _a === void 0 ? void 0 : _a.style) && 'MozAppearance' in d.window.documentElement.style,
  397 + 'MediaRecorderErrorEvent' in w,
  398 + 'mozInnerScreenX' in w,
  399 + 'CSSMozDocumentRule' in w,
  400 + 'CanvasCaptureMediaStream' in w,
  401 + ]) >= 4);
  402 + }
  403 + /**
  404 + * Checks whether the browser is based on Chromium version ≥86 without using user-agent.
  405 + * It doesn't check that the browser is based on Chromium, there is a separate function for this.
  406 + */
  407 + function isChromium86OrNewer() {
  408 + // Checked in Chrome 85 vs Chrome 86 both on desktop and Android
  409 + return (countTruthy([
  410 + !('MediaSettingsRange' in w),
  411 + 'RTCEncodedAudioFrame' in w,
  412 + '' + w.Intl === '[object Intl]',
  413 + '' + w.Reflect === '[object Reflect]',
  414 + ]) >= 3);
  415 + }
  416 + /**
  417 + * Checks whether the browser is based on WebKit version ≥606 (Safari ≥12) without using user-agent.
  418 + * It doesn't check that the browser is based on WebKit, there is a separate function for this.
  419 + *
  420 + * @link https://en.wikipedia.org/wiki/Safari_version_history#Release_history Safari-WebKit versions map
  421 + */
  422 + function isWebKit606OrNewer() {
  423 + // Checked in Safari 9–14
  424 + return (countTruthy([
  425 + 'DOMRectList' in w,
  426 + 'RTCPeerConnectionIceEvent' in w,
  427 + 'SVGGeometryElement' in w,
  428 + 'ontransitioncancel' in w,
  429 + ]) >= 3);
  430 + }
  431 +
  432 + var w$1 = window;
  433 + var d$1 = window.document;
  434 + // Inspired by and based on https://github.com/cozylife/audio-fingerprint
  435 + function getAudioFingerprint() {
  436 + return tslib.__awaiter(this, void 0, void 0, function () {
  437 + var AudioContext, context, oscillator, compressor, buffer, error_1;
  438 + return tslib.__generator(this, function (_a) {
  439 + switch (_a.label) {
  440 + case 0:
  441 + // In some browsers, audio context always stays suspended unless the context is started in response to a user action
  442 + // (e.g. a click or a tap). It prevents audio fingerprint from being taken at an arbitrary moment of time.
  443 + // Such browsers are old and unpopular, so the audio fingerprinting is just skipped in them.
  444 + // See a similar case explanation at https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088
  445 + if (doesCurrentBrowserSuspendAudioContext()) {
  446 + return [2 /*return*/, -1];
  447 + }
  448 + AudioContext = w$1.OfflineAudioContext || w$1.webkitOfflineAudioContext;
  449 + if (!AudioContext) {
  450 + return [2 /*return*/, -2];
  451 + }
  452 + context = new AudioContext(1, 44100, 44100);
  453 + oscillator = context.createOscillator();
  454 + oscillator.type = 'triangle';
  455 + setAudioParam(context, oscillator.frequency, 10000);
  456 + compressor = context.createDynamicsCompressor();
  457 + setAudioParam(context, compressor.threshold, -50);
  458 + setAudioParam(context, compressor.knee, 40);
  459 + setAudioParam(context, compressor.ratio, 12);
  460 + setAudioParam(context, compressor.reduction, -20);
  461 + setAudioParam(context, compressor.attack, 0);
  462 + setAudioParam(context, compressor.release, 0.25);
  463 + oscillator.connect(compressor);
  464 + compressor.connect(context.destination);
  465 + oscillator.start(0);
  466 + _a.label = 1;
  467 + case 1:
  468 + _a.trys.push([1, 3, 4, 5]);
  469 + return [4 /*yield*/, renderAudio(context)];
  470 + case 2:
  471 + buffer = _a.sent();
  472 + return [3 /*break*/, 5];
  473 + case 3:
  474 + error_1 = _a.sent();
  475 + if (error_1.name === "timeout" /* Timeout */ || error_1.name === "suspended" /* Suspended */) {
  476 + return [2 /*return*/, -3];
  477 + }
  478 + throw error_1;
  479 + case 4:
  480 + oscillator.disconnect();
  481 + compressor.disconnect();
  482 + return [7 /*endfinally*/];
  483 + case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))];
  484 + }
  485 + });
  486 + });
  487 + }
  488 + /**
  489 + * Checks if the current browser is known to always suspend audio context
  490 + */
  491 + function doesCurrentBrowserSuspendAudioContext() {
  492 + return isWebKit() && !isDesktopSafari() && !isWebKit606OrNewer();
  493 + }
  494 + function setAudioParam(context, param, value) {
  495 + var isAudioParam = function (value) {
  496 + return value && typeof value.setValueAtTime === 'function';
  497 + };
  498 + if (isAudioParam(param)) {
  499 + param.setValueAtTime(value, context.currentTime);
  500 + }
  501 + }
  502 + function renderAudio(context) {
  503 + var resumeTriesMaxCount = 3;
  504 + var resumeRetryDelay = 500;
  505 + var runningTimeout = 1000;
  506 + return new Promise(function (resolve, reject) {
  507 + context.oncomplete = function (event) { return resolve(event.renderedBuffer); };
  508 + var resumeTriesLeft = resumeTriesMaxCount;
  509 + var tryResume = function () {
  510 + context.startRendering();
  511 + switch (context.state) {
  512 + case 'running':
  513 + setTimeout(function () { return reject(makeInnerError("timeout" /* Timeout */)); }, runningTimeout);
  514 + break;
  515 + // Sometimes the audio context doesn't start after calling `startRendering` (in addition to the cases where
  516 + // audio context doesn't start at all). A known case is starting an audio context when the browser tab is in
  517 + // background on iPhone. Retries usually help in this case.
  518 + case 'suspended':
  519 + // The audio context can reject starting until the tab is in foreground. Long fingerprint duration
  520 + // in background isn't a problem, therefore the retry attempts don't count in background. It can lead to
  521 + // a situation when a fingerprint takes very long time and finishes successfully. FYI, the audio context
  522 + // can be suspended when `window.document.hidden === false` and start running after a retry.
  523 + if (!d$1.hidden) {
  524 + resumeTriesLeft--;
  525 + }
  526 + if (resumeTriesLeft > 0) {
  527 + setTimeout(tryResume, resumeRetryDelay);
  528 + }
  529 + else {
  530 + reject(makeInnerError("suspended" /* Suspended */));
  531 + }
  532 + break;
  533 + }
  534 + };
  535 + tryResume();
  536 + });
  537 + }
  538 + function getHash(signal) {
  539 + var hash = 0;
  540 + for (var i = 4500; i < 5000; ++i) {
  541 + hash += Math.abs(signal[i]);
  542 + }
  543 + return hash;
  544 + }
  545 + function makeInnerError(name) {
  546 + var error = new Error(name);
  547 + error.name = name;
  548 + return error;
  549 + }
  550 +
  551 + var d$2 = window.document;
  552 + // We use m or w because these two characters take up the maximum width.
  553 + // And we use a LLi so that the same matching fonts can get separated.
  554 + var testString = 'mmMwWLliI0O&1';
  555 + // We test using 48px font size, we may use any size. I guess larger the better.
  556 + var testSize = '48px';
  557 + // A font will be compared against all the three default fonts.
  558 + // And if it doesn't match all 3 then that font is not available.
  559 + var baseFonts = ['monospace', 'sans-serif', 'serif'];
  560 + var fontList = [
  561 + // This is android-specific font from "Roboto" family
  562 + 'sans-serif-thin',
  563 + 'ARNO PRO',
  564 + 'Agency FB',
  565 + 'Arabic Typesetting',
  566 + 'Arial Unicode MS',
  567 + 'AvantGarde Bk BT',
  568 + 'BankGothic Md BT',
  569 + 'Batang',
  570 + 'Bitstream Vera Sans Mono',
  571 + 'Calibri',
  572 + 'Century',
  573 + 'Century Gothic',
  574 + 'Clarendon',
  575 + 'EUROSTILE',
  576 + 'Franklin Gothic',
  577 + 'Futura Bk BT',
  578 + 'Futura Md BT',
  579 + 'GOTHAM',
  580 + 'Gill Sans',
  581 + 'HELV',
  582 + 'Haettenschweiler',
  583 + 'Helvetica Neue',
  584 + 'Humanst521 BT',
  585 + 'Leelawadee',
  586 + 'Letter Gothic',
  587 + 'Levenim MT',
  588 + 'Lucida Bright',
  589 + 'Lucida Sans',
  590 + 'Menlo',
  591 + 'MS Mincho',
  592 + 'MS Outlook',
  593 + 'MS Reference Specialty',
  594 + 'MS UI Gothic',
  595 + 'MT Extra',
  596 + 'MYRIAD PRO',
  597 + 'Marlett',
  598 + 'Meiryo UI',
  599 + 'Microsoft Uighur',
  600 + 'Minion Pro',
  601 + 'Monotype Corsiva',
  602 + 'PMingLiU',
  603 + 'Pristina',
  604 + 'SCRIPTINA',
  605 + 'Segoe UI Light',
  606 + 'Serifa',
  607 + 'SimHei',
  608 + 'Small Fonts',
  609 + 'Staccato222 BT',
  610 + 'TRAJAN PRO',
  611 + 'Univers CE 55 Medium',
  612 + 'Vrinda',
  613 + 'ZWAdobeF',
  614 + ];
  615 + var fontSpanStyle = {
  616 + // CSS font reset to reset external styles
  617 + fontStyle: 'normal',
  618 + fontWeight: 'normal',
  619 + letterSpacing: 'normal',
  620 + lineBreak: 'auto',
  621 + lineHeight: 'normal',
  622 + textTransform: 'none',
  623 + textAlign: 'left',
  624 + textDecoration: 'none',
  625 + textShadow: 'none',
  626 + whiteSpace: 'normal',
  627 + wordBreak: 'normal',
  628 + wordSpacing: 'normal',
  629 + // We need this css as in some weird browser this span elements shows up for a microSec which creates
  630 + // a bad user experience
  631 + position: 'absolute',
  632 + left: '-9999px',
  633 + fontSize: testSize,
  634 + };
  635 + // kudos to http://www.lalit.org/lab/javascript-css-font-detect/
  636 + function getFonts() {
  637 + var h = d$2.body;
  638 + // div to load spans for the base fonts
  639 + var baseFontsDiv = d$2.createElement('div');
  640 + // div to load spans for the fonts to detect
  641 + var fontsDiv = d$2.createElement('div');
  642 + var defaultWidth = {};
  643 + var defaultHeight = {};
  644 + // creates a span where the fonts will be loaded
  645 + var createSpan = function () {
  646 + var span = d$2.createElement('span');
  647 + span.textContent = testString;
  648 + for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) {
  649 + var prop = _a[_i];
  650 + span.style[prop] = fontSpanStyle[prop];
  651 + }
  652 + return span;
  653 + };
  654 + // creates a span and load the font to detect and a base font for fallback
  655 + var createSpanWithFonts = function (fontToDetect, baseFont) {
  656 + var s = createSpan();
  657 + s.style.fontFamily = "'" + fontToDetect + "'," + baseFont;
  658 + return s;
  659 + };
  660 + // creates spans for the base fonts and adds them to baseFontsDiv
  661 + var initializeBaseFontsSpans = function () {
  662 + return baseFonts.map(function (baseFont) {
  663 + var s = createSpan();
  664 + s.style.fontFamily = baseFont;
  665 + baseFontsDiv.appendChild(s);
  666 + return s;
  667 + });
  668 + };
  669 + // creates spans for the fonts to detect and adds them to fontsDiv
  670 + var initializeFontsSpans = function () {
  671 + // Stores {fontName : [spans for that font]}
  672 + var spans = {};
  673 + var _loop_1 = function (font) {
  674 + spans[font] = baseFonts.map(function (baseFont) {
  675 + var s = createSpanWithFonts(font, baseFont);
  676 + fontsDiv.appendChild(s);
  677 + return s;
  678 + });
  679 + };
  680 + for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) {
  681 + var font = fontList_1[_i];
  682 + _loop_1(font);
  683 + }
  684 + return spans;
  685 + };
  686 + // checks if a font is available
  687 + var isFontAvailable = function (fontSpans) {
  688 + return baseFonts.some(function (baseFont, baseFontIndex) {
  689 + return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] ||
  690 + fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont];
  691 + });
  692 + };
  693 + // create spans for base fonts
  694 + var baseFontsSpans = initializeBaseFontsSpans();
  695 + // add the spans to the DOM
  696 + h.appendChild(baseFontsDiv);
  697 + // get the default width for the three base fonts
  698 + for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) {
  699 + defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font
  700 + defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font
  701 + }
  702 + // create spans for fonts to detect
  703 + var fontsSpans = initializeFontsSpans();
  704 + // add all the spans to the DOM
  705 + h.appendChild(fontsDiv);
  706 + // check available fonts
  707 + var available = [];
  708 + for (var i = 0, l = fontList.length; i < l; i++) {
  709 + if (isFontAvailable(fontsSpans[fontList[i]])) {
  710 + available.push(fontList[i]);
  711 + }
  712 + }
  713 + // remove spans from DOM
  714 + h.removeChild(fontsDiv);
  715 + h.removeChild(baseFontsDiv);
  716 + return available;
  717 + }
  718 +
  719 + function getPlugins() {
  720 + if (isTrident()) {
  721 + return [];
  722 + }
  723 + if (!window.navigator.plugins) {
  724 + return undefined;
  725 + }
  726 + var plugins = [];
  727 + // Safari 10 doesn't support iterating window.navigator.plugins with for...of
  728 + for (var i = 0; i < window.navigator.plugins.length; ++i) {
  729 + var plugin = window.navigator.plugins[i];
  730 + if (!plugin) {
  731 + continue;
  732 + }
  733 + var mimeTypes = [];
  734 + for (var j = 0; j < plugin.length; ++j) {
  735 + var mimeType = plugin[j];
  736 + mimeTypes.push({
  737 + type: mimeType.type,
  738 + suffixes: mimeType.suffixes,
  739 + });
  740 + }
  741 + plugins.push({
  742 + name: plugin.name,
  743 + description: plugin.description,
  744 + mimeTypes: mimeTypes,
  745 + });
  746 + }
  747 + return plugins;
  748 + }
  749 +
  750 + function makeCanvasContext() {
  751 + var canvas = window.document.createElement('canvas');
  752 + canvas.width = 240;
  753 + canvas.height = 140;
  754 + canvas.style.display = 'inline';
  755 + return [canvas, canvas.getContext('2d')];
  756 + }
  757 + function isSupported(canvas, context) {
  758 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  759 + return !!(context && canvas.toDataURL);
  760 + }
  761 + function save(canvas) {
  762 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  763 + return canvas.toDataURL();
  764 + }
  765 + // https://www.browserleaks.com/canvas#how-does-it-work
  766 + function getCanvasFingerprint() {
  767 + var _a = makeCanvasContext(), canvas = _a[0], context = _a[1];
  768 + if (!isSupported(canvas, context)) {
  769 + return { winding: false, data: '' };
  770 + }
  771 + // detect browser support of canvas winding
  772 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  773 + // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js
  774 + context.rect(0, 0, 10, 10);
  775 + context.rect(2, 2, 6, 6);
  776 + var winding = !context.isPointInPath(5, 5, 'evenodd');
  777 + context.textBaseline = 'alphabetic';
  778 + context.fillStyle = '#f60';
  779 + context.fillRect(125, 1, 62, 20);
  780 + context.fillStyle = '#069';
  781 + // https://github.com/Valve/fingerprintjs2/issues/66
  782 + // this can affect FP generation when applying different CSS on different websites
  783 + context.font = '11pt no-real-font-123';
  784 + // the choice of emojis has a gigantic impact on rendering performance (especially in FF)
  785 + // some newer emojis cause it to slow down 50-200 times
  786 + // context.fillText("Cw爨m fjordbank \ud83d\ude03 gly", 2, 15)
  787 + var printedText = 'Cwm fjordbank \ud83d\ude03 gly';
  788 + context.fillText(printedText, 2, 15);
  789 + context.fillStyle = 'rgba(102, 204, 0, 0.2)';
  790 + context.font = '18pt Arial';
  791 + context.fillText(printedText, 4, 45);
  792 + // canvas blending
  793 + // http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
  794 + // http://jsfiddle.net/NDYV8/16/
  795 + context.globalCompositeOperation = 'multiply';
  796 + context.fillStyle = 'rgb(255,0,255)';
  797 + context.beginPath();
  798 + context.arc(50, 50, 50, 0, Math.PI * 2, true);
  799 + context.closePath();
  800 + context.fill();
  801 + context.fillStyle = 'rgb(0,255,255)';
  802 + context.beginPath();
  803 + context.arc(100, 50, 50, 0, Math.PI * 2, true);
  804 + context.closePath();
  805 + context.fill();
  806 + context.fillStyle = 'rgb(255,255,0)';
  807 + context.beginPath();
  808 + context.arc(75, 100, 50, 0, Math.PI * 2, true);
  809 + context.closePath();
  810 + context.fill();
  811 + context.fillStyle = 'rgb(255,0,255)';
  812 + // canvas winding
  813 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  814 + // http://jsfiddle.net/NDYV8/19/
  815 + context.arc(75, 75, 75, 0, Math.PI * 2, true);
  816 + context.arc(75, 75, 25, 0, Math.PI * 2, true);
  817 + context.fill('evenodd');
  818 + return {
  819 + winding: winding,
  820 + data: save(canvas),
  821 + };
  822 + }
  823 +
  824 + var n$1 = window.navigator;
  825 + var w$2 = window;
  826 + /**
  827 + * This is a crude and primitive touch screen detection. It's not possible to currently reliably detect the availability
  828 + * of a touch screen with a JS, without actually subscribing to a touch event.
  829 + *
  830 + * @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
  831 + * @see https://github.com/Modernizr/Modernizr/issues/548
  832 + */
  833 + function getTouchSupport() {
  834 + var maxTouchPoints = 0;
  835 + var touchEvent;
  836 + if (n$1.maxTouchPoints !== undefined) {
  837 + maxTouchPoints = toInt(n$1.maxTouchPoints);
  838 + }
  839 + else if (n$1.msMaxTouchPoints !== undefined) {
  840 + maxTouchPoints = n$1.msMaxTouchPoints;
  841 + }
  842 + try {
  843 + window.document.createEvent('TouchEvent');
  844 + touchEvent = true;
  845 + }
  846 + catch (_) {
  847 + touchEvent = false;
  848 + }
  849 + var touchStart = 'ontouchstart' in w$2;
  850 + return {
  851 + maxTouchPoints: maxTouchPoints,
  852 + touchEvent: touchEvent,
  853 + touchStart: touchStart,
  854 + };
  855 + }
  856 +
  857 + function getOsCpu() {
  858 + return window.navigator.oscpu;
  859 + }
  860 +
  861 + var n$2 = window.navigator;
  862 + function getLanguages() {
  863 + var result = [];
  864 + var language = n$2.language || n$2.userLanguage || n$2.browserLanguage || n$2.systemLanguage;
  865 + if (language !== undefined) {
  866 + result.push([language]);
  867 + }
  868 + if (Array.isArray(n$2.languages)) {
  869 + // Starting from Chromium 86, there is only a single value in `window.navigator.language` in Incognito mode:
  870 + // the value of `window.navigator.language`. Therefore the value is ignored in this browser.
  871 + if (!(isChromium() && isChromium86OrNewer())) {
  872 + result.push(n$2.languages);
  873 + }
  874 + }
  875 + else if (typeof n$2.languages === 'string') {
  876 + var languages = n$2.languages;
  877 + if (languages) {
  878 + result.push(languages.split(','));
  879 + }
  880 + }
  881 + return result;
  882 + }
  883 +
  884 + function getColorDepth() {
  885 + return window.screen.colorDepth;
  886 + }
  887 +
  888 + function getDeviceMemory() {
  889 + return window.navigator.deviceMemory;
  890 + }
  891 +
  892 + var w$3 = window;
  893 + function getScreenResolution() {
  894 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  895 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  896 + var dimensions = [toInt(w$3.screen.width), toInt(w$3.screen.height)];
  897 + dimensions.sort().reverse();
  898 + return dimensions;
  899 + }
  900 +
  901 + var w$4 = window;
  902 + function getAvailableScreenResolution() {
  903 + if (w$4.screen.availWidth && w$4.screen.availHeight) {
  904 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  905 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  906 + var dimensions = [toInt(w$4.screen.availWidth), toInt(w$4.screen.availHeight)];
  907 + dimensions.sort().reverse();
  908 + return dimensions;
  909 + }
  910 + return undefined;
  911 + }
  912 +
  913 + function getHardwareConcurrency() {
  914 + try {
  915 + // sometimes hardware concurrency is a string
  916 + var concurrency = toInt(window.navigator.hardwareConcurrency);
  917 + return isNaN(concurrency) ? 1 : concurrency;
  918 + }
  919 + catch (e) {
  920 + return 1;
  921 + }
  922 + }
  923 +
  924 + function getTimezoneOffset() {
  925 + var currentYear = new Date().getFullYear();
  926 + // The timezone offset may change over time due to daylight saving time (DST) shifts.
  927 + // The non-DST timezone offset is used as the result timezone offset.
  928 + // Since the DST season differs in the northern and the southern hemispheres,
  929 + // both January and July timezones offsets are considered.
  930 + return Math.max(
  931 + // `getTimezoneOffset` returns a number as a string in some unidentified cases
  932 + toFloat(new Date(currentYear, 0, 1).getTimezoneOffset()), toFloat(new Date(currentYear, 6, 1).getTimezoneOffset()));
  933 + }
  934 +
  935 + var w$5 = window;
  936 + function getTimezone() {
  937 + var _a;
  938 + if ((_a = w$5.Intl) === null || _a === void 0 ? void 0 : _a.DateTimeFormat) {
  939 + return new w$5.Intl.DateTimeFormat().resolvedOptions().timeZone;
  940 + }
  941 + return undefined;
  942 + }
  943 +
  944 + function getSessionStorage() {
  945 + try {
  946 + return !!window.sessionStorage;
  947 + }
  948 + catch (error) {
  949 + /* SecurityError when referencing it means it exists */
  950 + return true;
  951 + }
  952 + }
  953 +
  954 + // https://bugzilla.mozilla.org/show_bug.cgi?id=781447
  955 + function getLocalStorage() {
  956 + try {
  957 + return !!window.localStorage;
  958 + }
  959 + catch (e) {
  960 + /* SecurityError when referencing it means it exists */
  961 + return true;
  962 + }
  963 + }
  964 +
  965 + function getIndexedDB() {
  966 + // IE and Edge don't allow accessing indexedDB in private mode, therefore IE and Edge will have different
  967 + // visitor identifier in normal and private modes.
  968 + if (isTrident() || isEdgeHTML()) {
  969 + return undefined;
  970 + }
  971 + try {
  972 + return !!window.indexedDB;
  973 + }
  974 + catch (e) {
  975 + /* SecurityError when referencing it means it exists */
  976 + return true;
  977 + }
  978 + }
  979 +
  980 + function getOpenDatabase() {
  981 + return !!window.openDatabase;
  982 + }
  983 +
  984 + function getCpuClass() {
  985 + return window.navigator.cpuClass;
  986 + }
  987 +
  988 + function getPlatform() {
  989 + return window.navigator.platform;
  990 + }
  991 +
  992 + function getPluginsSupport() {
  993 + return window.navigator.plugins !== undefined;
  994 + }
  995 +
  996 + function getProductSub() {
  997 + return window.navigator.productSub;
  998 + }
  999 +
  1000 + function getEmptyEvalLength() {
  1001 + return eval.toString().length;
  1002 + }
  1003 +
  1004 + function getErrorFF() {
  1005 + try {
  1006 + throw 'a';
  1007 + }
  1008 + catch (e) {
  1009 + try {
  1010 + e.toSource();
  1011 + return true;
  1012 + }
  1013 + catch (e2) {
  1014 + return false;
  1015 + }
  1016 + }
  1017 + }
  1018 +
  1019 + function getVendor() {
  1020 + return window.navigator.vendor;
  1021 + }
  1022 +
  1023 + function getChrome() {
  1024 + return window.chrome !== undefined;
  1025 + }
  1026 +
  1027 + var d$3 = window.document;
  1028 + /**
  1029 + * window.navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1030 + * cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past with
  1031 + * site-specific exceptions. Don't rely on it.
  1032 + *
  1033 + * @see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js Taken from here
  1034 + */
  1035 + function areCookiesEnabled() {
  1036 + // Taken from here: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js
  1037 + // window.navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1038 + // cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past
  1039 + // with site-specific exceptions. Don't rely on it.
  1040 + // try..catch because some in situations `window.document.cookie` is exposed but throws a
  1041 + // SecurityError if you try to access it; e.g. window.documents created from data URIs
  1042 + // or in sandboxed iframes (depending on flags/context)
  1043 + try {
  1044 + // Create cookie
  1045 + d$3.cookie = 'cookietest=1';
  1046 + var result = d$3.cookie.indexOf('cookietest=') !== -1;
  1047 + // Delete cookie
  1048 + d$3.cookie = 'cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT';
  1049 + return result;
  1050 + }
  1051 + catch (e) {
  1052 + return false;
  1053 + }
  1054 + }
  1055 +
  1056 + /**
  1057 + * The list of entropy sources used to make visitor identifiers.
  1058 + *
  1059 + * This value isn't restricted by Semantic Versioning, i.e. it may be changed without bumping minor or major version of
  1060 + * this package.
  1061 + */
  1062 + var sources = {
  1063 + // Expected errors and default values must be handled inside the functions. Unexpected errors must be thrown.
  1064 + osCpu: getOsCpu,
  1065 + languages: getLanguages,
  1066 + colorDepth: getColorDepth,
  1067 + deviceMemory: getDeviceMemory,
  1068 + screenResolution: getScreenResolution,
  1069 + availableScreenResolution: getAvailableScreenResolution,
  1070 + hardwareConcurrency: getHardwareConcurrency,
  1071 + timezoneOffset: getTimezoneOffset,
  1072 + timezone: getTimezone,
  1073 + sessionStorage: getSessionStorage,
  1074 + localStorage: getLocalStorage,
  1075 + indexedDB: getIndexedDB,
  1076 + openDatabase: getOpenDatabase,
  1077 + cpuClass: getCpuClass,
  1078 + // Maybe it should be excluded: https://github.com/fingerprintjs/fingerprintjs/issues/514#issuecomment-688754892
  1079 + platform: getPlatform,
  1080 + plugins: getPlugins,
  1081 + canvas: getCanvasFingerprint,
  1082 + // adBlock: isAdblockUsed, // https://github.com/fingerprintjs/fingerprintjs/issues/405
  1083 + touchSupport: getTouchSupport,
  1084 + fonts: getFonts,
  1085 + audio: getAudioFingerprint,
  1086 + pluginsSupport: getPluginsSupport,
  1087 + productSub: getProductSub,
  1088 + emptyEvalLength: getEmptyEvalLength,
  1089 + errorFF: getErrorFF,
  1090 + vendor: getVendor,
  1091 + chrome: getChrome,
  1092 + cookiesEnabled: areCookiesEnabled,
  1093 + };
  1094 + /**
  1095 + * Gets a components list from the given list of entropy sources.
  1096 + *
  1097 + * Warning for package users:
  1098 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  1099 + */
  1100 + function getComponents(sources, sourceOptions, excludeSources) {
  1101 + return tslib.__awaiter(this, void 0, void 0, function () {
  1102 + var timestamp, components, _i, _a, sourceKey, result, error_1, nextTimestamp;
  1103 + var _b;
  1104 + return tslib.__generator(this, function (_c) {
  1105 + switch (_c.label) {
  1106 + case 0:
  1107 + timestamp = Date.now();
  1108 + components = {};
  1109 + _i = 0, _a = Object.keys(sources);
  1110 + _c.label = 1;
  1111 + case 1:
  1112 + if (!(_i < _a.length)) return [3 /*break*/, 7];
  1113 + sourceKey = _a[_i];
  1114 + if (!excludes(excludeSources, sourceKey)) {
  1115 + return [3 /*break*/, 6];
  1116 + }
  1117 + result = void 0;
  1118 + _c.label = 2;
  1119 + case 2:
  1120 + _c.trys.push([2, 4, , 5]);
  1121 + _b = {};
  1122 + return [4 /*yield*/, sources[sourceKey](sourceOptions)];
  1123 + case 3:
  1124 + result = (_b.value = _c.sent(), _b);
  1125 + return [3 /*break*/, 5];
  1126 + case 4:
  1127 + error_1 = _c.sent();
  1128 + result = error_1 && typeof error_1 === 'object' && 'message' in error_1 ? { error: error_1 } : { error: { message: error_1 } };
  1129 + return [3 /*break*/, 5];
  1130 + case 5:
  1131 + nextTimestamp = Date.now();
  1132 + components[sourceKey] = tslib.__assign(tslib.__assign({}, result), { duration: nextTimestamp - timestamp }); // TypeScript has beaten me here
  1133 + timestamp = nextTimestamp;
  1134 + _c.label = 6;
  1135 + case 6:
  1136 + _i++;
  1137 + return [3 /*break*/, 1];
  1138 + case 7: return [2 /*return*/, components];
  1139 + }
  1140 + });
  1141 + });
  1142 + }
  1143 + /**
  1144 + * Collects entropy components from the built-in sources to make the visitor identifier.
  1145 + */
  1146 + function getBuiltinComponents() {
  1147 + return getComponents(sources, undefined, []);
  1148 + }
  1149 +
  1150 + function componentsToCanonicalString(components) {
  1151 + var result = '';
  1152 + for (var _i = 0, _a = Object.keys(components); _i < _a.length; _i++) {
  1153 + var componentKey = _a[_i];
  1154 + var component = components[componentKey];
  1155 + var value = component.error ? 'error' : JSON.stringify(component.value);
  1156 + result += "" + (result ? '|' : '') + componentKey.replace(/([:|\\])/g, '\\$1') + ":" + value;
  1157 + }
  1158 + return result;
  1159 + }
  1160 + function componentsToDebugString(components) {
  1161 + return JSON.stringify(components, function (_key, value) {
  1162 + var _a;
  1163 + if (value instanceof Error) {
  1164 + return tslib.__assign(tslib.__assign({}, value), { message: value.message, stack: (_a = value.stack) === null || _a === void 0 ? void 0 : _a.split('\n') });
  1165 + }
  1166 + return value;
  1167 + }, 2);
  1168 + }
  1169 + function hashComponents(components) {
  1170 + return x64hash128(componentsToCanonicalString(components));
  1171 + }
  1172 + /**
  1173 + * Makes a GetResult implementation that calculates the visitor id hash on demand.
  1174 + * Designed for optimisation.
  1175 + */
  1176 + function makeLazyGetResult(components) {
  1177 + var visitorIdCache;
  1178 + // A plain class isn't used because its getters and setters aren't enumerable.
  1179 + return {
  1180 + components: components,
  1181 + get visitorId() {
  1182 + if (visitorIdCache === undefined) {
  1183 + visitorIdCache = hashComponents(this.components);
  1184 + }
  1185 + return visitorIdCache;
  1186 + },
  1187 + set visitorId(visitorId) {
  1188 + visitorIdCache = visitorId;
  1189 + },
  1190 + };
  1191 + }
  1192 + /**
  1193 + * The class isn't exported from the index file to not expose the constructor.
  1194 + * The hiding gives more freedom for future non-breaking updates.
  1195 + */
  1196 + var OpenAgent = /** @class */ (function () {
  1197 + function OpenAgent() {
  1198 + }
  1199 + /**
  1200 + * @inheritDoc
  1201 + */
  1202 + OpenAgent.prototype.get = function (options) {
  1203 + if (options === void 0) { options = {}; }
  1204 + return tslib.__awaiter(this, void 0, void 0, function () {
  1205 + var components, result;
  1206 + return tslib.__generator(this, function (_a) {
  1207 + switch (_a.label) {
  1208 + case 0: return [4 /*yield*/, getBuiltinComponents()];
  1209 + case 1:
  1210 + components = _a.sent();
  1211 + result = makeLazyGetResult(components);
  1212 + if (options.debug) {
  1213 + // console.log is ok here because it's under a debug clause
  1214 + // eslint-disable-next-line no-console
  1215 + console.log("Copy the text below to get the debug data:\n\n```\nversion: " + version + "\nuserAgent: " + window.navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```");
  1216 + }
  1217 + return [2 /*return*/, result];
  1218 + }
  1219 + });
  1220 + });
  1221 + };
  1222 + return OpenAgent;
  1223 + }());
  1224 + /**
  1225 + * Builds an instance of Agent and waits a delay required for a proper operation.
  1226 + */
  1227 + function load(_a) {
  1228 + var _b = (_a === void 0 ? {} : _a).delayFallback, delayFallback = _b === void 0 ? 50 : _b;
  1229 + return tslib.__awaiter(this, void 0, void 0, function () {
  1230 + return tslib.__generator(this, function (_c) {
  1231 + switch (_c.label) {
  1232 + case 0:
  1233 + // A delay is required to ensure consistent entropy components.
  1234 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1235 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1236 + return [4 /*yield*/, requestIdleCallbackIfAvailable(delayFallback)];
  1237 + case 1:
  1238 + // A delay is required to ensure consistent entropy components.
  1239 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1240 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1241 + _c.sent();
  1242 + return [2 /*return*/, new OpenAgent()];
  1243 + }
  1244 + });
  1245 + });
  1246 + }
  1247 +
  1248 + // The default export is a syntax sugar (`import * as FP from '...' → import FP from '...'`).
  1249 + // It should contain all the public exported values.
  1250 + var index = { load: load, hashComponents: hashComponents, componentsToDebugString: componentsToDebugString };
  1251 + // The exports below are for private usage. They may change unexpectedly. Use them at your own risk.
  1252 + /** Not window.documented, out of Semantic Versioning, usage is at your own risk */
  1253 + var murmurX64Hash128 = x64hash128;
  1254 +
  1255 + exports.componentsToDebugString = componentsToDebugString;
  1256 + exports.default = index;
  1257 + exports.getComponents = getComponents;
  1258 + exports.hashComponents = hashComponents;
  1259 + exports.isChromium = isChromium;
  1260 + exports.isDesktopSafari = isDesktopSafari;
  1261 + exports.isEdgeHTML = isEdgeHTML;
  1262 + exports.isGecko = isGecko;
  1263 + exports.isTrident = isTrident;
  1264 + exports.isWebKit = isWebKit;
  1265 + exports.load = load;
  1266 + exports.murmurX64Hash128 = murmurX64Hash128;
  1267 +})(this)
\ No newline at end of file
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +declare function x64hash128(key: string, seed?: number): string;
  10 +
  11 +declare function getAudioFingerprint(): Promise<number>;
  12 +
  13 +declare function getFonts(): string[];
  14 +
  15 +interface PluginMimeTypeData {
  16 + type: string;
  17 + suffixes: string;
  18 +}
  19 +interface PluginData {
  20 + name: string;
  21 + description: string;
  22 + mimeTypes: PluginMimeTypeData[];
  23 +}
  24 +declare function getPlugins(): PluginData[] | undefined;
  25 +
  26 +interface CanvasFingerprint {
  27 + winding: boolean;
  28 + data: string;
  29 +}
  30 +declare function getCanvasFingerprint(): CanvasFingerprint;
  31 +
  32 +interface TouchSupport {
  33 + maxTouchPoints: number;
  34 + /** The success or failure of creating a TouchEvent */
  35 + touchEvent: boolean;
  36 + /** The availability of the "ontouchstart" property */
  37 + touchStart: boolean;
  38 +}
  39 +/**
  40 + * This is a crude and primitive touch screen detection. It's not possible to currently reliably detect the availability
  41 + * of a touch screen with a JS, without actually subscribing to a touch event.
  42 + *
  43 + * @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
  44 + * @see https://github.com/Modernizr/Modernizr/issues/548
  45 + */
  46 +declare function getTouchSupport(): TouchSupport;
  47 +
  48 +declare function getOsCpu(): string | undefined;
  49 +
  50 +declare function getLanguages(): string[][];
  51 +
  52 +declare function getColorDepth(): number;
  53 +
  54 +declare function getDeviceMemory(): number | undefined;
  55 +
  56 +declare function getScreenResolution(): [number, number];
  57 +
  58 +declare function getAvailableScreenResolution(): [number, number] | undefined;
  59 +
  60 +declare function getHardwareConcurrency(): number;
  61 +
  62 +declare function getTimezoneOffset(): number;
  63 +
  64 +declare function getTimezone(): string | undefined;
  65 +
  66 +declare function getSessionStorage(): boolean;
  67 +
  68 +declare function getLocalStorage(): boolean;
  69 +
  70 +declare function getIndexedDB(): boolean | undefined;
  71 +
  72 +declare function getOpenDatabase(): boolean;
  73 +
  74 +declare function getCpuClass(): string | undefined;
  75 +
  76 +declare function getPlatform(): string;
  77 +
  78 +declare function getPluginsSupport(): boolean;
  79 +
  80 +declare function getProductSub(): string;
  81 +
  82 +declare function getEmptyEvalLength(): number;
  83 +
  84 +declare function getErrorFF(): boolean;
  85 +
  86 +declare function getVendor(): string;
  87 +
  88 +declare function getChrome(): boolean;
  89 +
  90 +/**
  91 + * navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  92 + * cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past with
  93 + * site-specific exceptions. Don't rely on it.
  94 + *
  95 + * @see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js Taken from here
  96 + */
  97 +declare function areCookiesEnabled(): boolean;
  98 +
  99 +/**
  100 + * The list of entropy sources used to make visitor identifiers.
  101 + *
  102 + * This value isn't restricted by Semantic Versioning, i.e. it may be changed without bumping minor or major version of
  103 + * this package.
  104 + */
  105 +declare const sources: {
  106 + osCpu: typeof getOsCpu;
  107 + languages: typeof getLanguages;
  108 + colorDepth: typeof getColorDepth;
  109 + deviceMemory: typeof getDeviceMemory;
  110 + screenResolution: typeof getScreenResolution;
  111 + availableScreenResolution: typeof getAvailableScreenResolution;
  112 + hardwareConcurrency: typeof getHardwareConcurrency;
  113 + timezoneOffset: typeof getTimezoneOffset;
  114 + timezone: typeof getTimezone;
  115 + sessionStorage: typeof getSessionStorage;
  116 + localStorage: typeof getLocalStorage;
  117 + indexedDB: typeof getIndexedDB;
  118 + openDatabase: typeof getOpenDatabase;
  119 + cpuClass: typeof getCpuClass;
  120 + platform: typeof getPlatform;
  121 + plugins: typeof getPlugins;
  122 + canvas: typeof getCanvasFingerprint;
  123 + touchSupport: typeof getTouchSupport;
  124 + fonts: typeof getFonts;
  125 + audio: typeof getAudioFingerprint;
  126 + pluginsSupport: typeof getPluginsSupport;
  127 + productSub: typeof getProductSub;
  128 + emptyEvalLength: typeof getEmptyEvalLength;
  129 + errorFF: typeof getErrorFF;
  130 + vendor: typeof getVendor;
  131 + chrome: typeof getChrome;
  132 + cookiesEnabled: typeof areCookiesEnabled;
  133 +};
  134 +/**
  135 + * A functions that returns data with entropy to identify visitor.
  136 + * Source must handle expected errors by itself and turn them into entropy.
  137 + * The return value must be compatible with `JSON.stringify` or be undefined.
  138 + */
  139 +declare type Source<TOptions, TValue> = (options: TOptions) => Promise<TValue> | TValue;
  140 +/**
  141 + * Generic dictionary of unknown sources
  142 + */
  143 +declare type UnknownSources<TOptions> = Record<string, Source<TOptions, unknown>>;
  144 +/**
  145 + * Converts an entropy source type to the source return value type
  146 + */
  147 +declare type SourceValue<TSource extends Source<any, any>> = TSource extends Source<any, infer T> ? T : never;
  148 +/**
  149 + * Result of getting entropy data from a source
  150 + */
  151 +declare type Component<T> = ({
  152 + value: T;
  153 + error?: undefined;
  154 +} | {
  155 + value?: undefined;
  156 + error: Error | {
  157 + message: unknown;
  158 + };
  159 +}) & {
  160 + duration: number;
  161 +};
  162 +/**
  163 + * Generic dictionary of unknown components
  164 + */
  165 +declare type UnknownComponents = Record<string, Component<unknown>>;
  166 +/**
  167 + * Converts an entropy source list type to a corresponding component list type.
  168 + *
  169 + * Warning for package users:
  170 + * This type is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  171 + */
  172 +declare type SourcesToComponents<TSources extends UnknownSources<any>> = {
  173 + [K in keyof TSources]: Component<SourceValue<TSources[K]>>;
  174 +};
  175 +/**
  176 + * List of components from the built-in entropy sources.
  177 + *
  178 + * Warning! This type is out of Semantic Versioning, i.e. may have incompatible changes within a major version. If you
  179 + * want to avoid breaking changes, use `UnknownComponents` instead that is more generic but guarantees backward
  180 + * compatibility within a major version. This is because browsers change constantly and therefore entropy sources have
  181 + * to change too.
  182 + */
  183 +declare type BuiltinComponents = SourcesToComponents<typeof sources>;
  184 +/**
  185 + * Gets a components list from the given list of entropy sources.
  186 + *
  187 + * Warning for package users:
  188 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  189 + */
  190 +declare function getComponents<TSourceOptions, TSources extends UnknownSources<TSourceOptions>, TExclude extends string>(sources: TSources, sourceOptions: TSourceOptions, excludeSources: readonly TExclude[]): Promise<Omit<SourcesToComponents<TSources>, TExclude>>;
  191 +
  192 +/**
  193 + * Options for Fingerprint class loading
  194 + */
  195 +interface LoadOptions {
  196 + /**
  197 + * When browser doesn't support `requestIdleCallback` a `setTimeout` will be used. This number is only for Safari and
  198 + * old Edge, because Chrome/Blink based browsers support `requestIdleCallback`. The value is in milliseconds.
  199 + * @default 50
  200 + */
  201 + delayFallback?: number;
  202 +}
  203 +/**
  204 + * Options for getting visitor identifier
  205 + */
  206 +interface GetOptions {
  207 + /**
  208 + * Whether to print debug messages to the console.
  209 + * Required to ease investigations of problems.
  210 + */
  211 + debug?: boolean;
  212 +}
  213 +/**
  214 + * Result of getting a visitor identifier
  215 + */
  216 +interface GetResult {
  217 + /**
  218 + * The visitor identifier
  219 + */
  220 + visitorId: string;
  221 + /**
  222 + * List of components that has formed the visitor identifier.
  223 + *
  224 + * Warning! The type of this property is specific but out of Semantic Versioning, i.e. may have incompatible changes
  225 + * within a major version. If you want to avoid breaking changes, treat the property as having type
  226 + * `UnknownComponents` that is more generic but guarantees backward compatibility within a major version.
  227 + */
  228 + components: BuiltinComponents;
  229 +}
  230 +/**
  231 + * Agent object that can get visitor identifier
  232 + */
  233 +interface Agent {
  234 + /**
  235 + * Gets the visitor identifier
  236 + */
  237 + get(options?: Readonly<GetOptions>): Promise<GetResult>;
  238 +}
  239 +declare function componentsToDebugString(components: UnknownComponents): string;
  240 +declare function hashComponents(components: UnknownComponents): string;
  241 +/**
  242 + * Builds an instance of Agent and waits a delay required for a proper operation.
  243 + */
  244 +declare function load({ delayFallback }?: Readonly<LoadOptions>): Promise<Agent>;
  245 +
  246 +/**
  247 + * Checks whether the browser is based on Trident (the Internet Explorer engine) without using user-agent.
  248 + *
  249 + * Warning for package users:
  250 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  251 + */
  252 +declare function isTrident(): boolean;
  253 +/**
  254 + * Checks whether the browser is based on EdgeHTML (the pre-Chromium Edge engine) without using user-agent.
  255 + *
  256 + * Warning for package users:
  257 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  258 + */
  259 +declare function isEdgeHTML(): boolean;
  260 +/**
  261 + * Checks whether the browser is based on Chromium without using user-agent.
  262 + *
  263 + * Warning for package users:
  264 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  265 + */
  266 +declare function isChromium(): boolean;
  267 +/**
  268 + * Checks whether the browser is based on mobile or desktop Safari without using user-agent.
  269 + * All iOS browsers use WebKit (the Safari engine).
  270 + *
  271 + * Warning for package users:
  272 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  273 + */
  274 +declare function isWebKit(): boolean;
  275 +/**
  276 + * Checks whether the WebKit browser is a desktop Safari.
  277 + *
  278 + * Warning for package users:
  279 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  280 + */
  281 +declare function isDesktopSafari(): boolean;
  282 +/**
  283 + * Checks whether the browser is based on Gecko (Firefox engine) without using user-agent.
  284 + *
  285 + * Warning for package users:
  286 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  287 + */
  288 +declare function isGecko(): boolean;
  289 +
  290 +declare const _default: {
  291 + load: typeof load;
  292 + hashComponents: typeof hashComponents;
  293 + componentsToDebugString: typeof componentsToDebugString;
  294 +};
  295 +/** Not documented, out of Semantic Versioning, usage is at your own risk */
  296 +declare const murmurX64Hash128: typeof x64hash128;
  297 +
  298 +export default _default;
  299 +export { Agent, BuiltinComponents, Component, GetOptions, GetResult, LoadOptions, SourcesToComponents, UnknownComponents, componentsToDebugString, getComponents, hashComponents, isChromium, isDesktopSafari, isEdgeHTML, isGecko, isTrident, isWebKit, load, murmurX64Hash128 };
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +import { __awaiter, __generator, __assign } from 'tslib';
  10 +
  11 +/*
  12 + * Taken from https://github.com/karanlyons/murmurHash3.js/blob/a33d0723127e2e5415056c455f8aed2451ace208/murmurHash3.js
  13 + */
  14 +//
  15 +// Given two 64bit ints (as an array of two 32bit ints) returns the two
  16 +// added together as a 64bit int (as an array of two 32bit ints).
  17 +//
  18 +function x64Add(m, n) {
  19 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  20 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  21 + var o = [0, 0, 0, 0];
  22 + o[3] += m[3] + n[3];
  23 + o[2] += o[3] >>> 16;
  24 + o[3] &= 0xffff;
  25 + o[2] += m[2] + n[2];
  26 + o[1] += o[2] >>> 16;
  27 + o[2] &= 0xffff;
  28 + o[1] += m[1] + n[1];
  29 + o[0] += o[1] >>> 16;
  30 + o[1] &= 0xffff;
  31 + o[0] += m[0] + n[0];
  32 + o[0] &= 0xffff;
  33 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  34 +}
  35 +//
  36 +// Given two 64bit ints (as an array of two 32bit ints) returns the two
  37 +// multiplied together as a 64bit int (as an array of two 32bit ints).
  38 +//
  39 +function x64Multiply(m, n) {
  40 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  41 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  42 + var o = [0, 0, 0, 0];
  43 + o[3] += m[3] * n[3];
  44 + o[2] += o[3] >>> 16;
  45 + o[3] &= 0xffff;
  46 + o[2] += m[2] * n[3];
  47 + o[1] += o[2] >>> 16;
  48 + o[2] &= 0xffff;
  49 + o[2] += m[3] * n[2];
  50 + o[1] += o[2] >>> 16;
  51 + o[2] &= 0xffff;
  52 + o[1] += m[1] * n[3];
  53 + o[0] += o[1] >>> 16;
  54 + o[1] &= 0xffff;
  55 + o[1] += m[2] * n[2];
  56 + o[0] += o[1] >>> 16;
  57 + o[1] &= 0xffff;
  58 + o[1] += m[3] * n[1];
  59 + o[0] += o[1] >>> 16;
  60 + o[1] &= 0xffff;
  61 + o[0] += m[0] * n[3] + m[1] * n[2] + m[2] * n[1] + m[3] * n[0];
  62 + o[0] &= 0xffff;
  63 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  64 +}
  65 +//
  66 +// Given a 64bit int (as an array of two 32bit ints) and an int
  67 +// representing a number of bit positions, returns the 64bit int (as an
  68 +// array of two 32bit ints) rotated left by that number of positions.
  69 +//
  70 +function x64Rotl(m, n) {
  71 + n %= 64;
  72 + if (n === 32) {
  73 + return [m[1], m[0]];
  74 + }
  75 + else if (n < 32) {
  76 + return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))];
  77 + }
  78 + else {
  79 + n -= 32;
  80 + return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))];
  81 + }
  82 +}
  83 +//
  84 +// Given a 64bit int (as an array of two 32bit ints) and an int
  85 +// representing a number of bit positions, returns the 64bit int (as an
  86 +// array of two 32bit ints) shifted left by that number of positions.
  87 +//
  88 +function x64LeftShift(m, n) {
  89 + n %= 64;
  90 + if (n === 0) {
  91 + return m;
  92 + }
  93 + else if (n < 32) {
  94 + return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
  95 + }
  96 + else {
  97 + return [m[1] << (n - 32), 0];
  98 + }
  99 +}
  100 +//
  101 +// Given two 64bit ints (as an array of two 32bit ints) returns the two
  102 +// xored together as a 64bit int (as an array of two 32bit ints).
  103 +//
  104 +function x64Xor(m, n) {
  105 + return [m[0] ^ n[0], m[1] ^ n[1]];
  106 +}
  107 +//
  108 +// Given a block, returns murmurHash3's final x64 mix of that block.
  109 +// (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
  110 +// only place where we need to right shift 64bit ints.)
  111 +//
  112 +function x64Fmix(h) {
  113 + h = x64Xor(h, [0, h[0] >>> 1]);
  114 + h = x64Multiply(h, [0xff51afd7, 0xed558ccd]);
  115 + h = x64Xor(h, [0, h[0] >>> 1]);
  116 + h = x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
  117 + h = x64Xor(h, [0, h[0] >>> 1]);
  118 + return h;
  119 +}
  120 +//
  121 +// Given a string and an optional seed as an int, returns a 128 bit
  122 +// hash using the x64 flavor of MurmurHash3, as an unsigned hex.
  123 +//
  124 +function x64hash128(key, seed) {
  125 + key = key || '';
  126 + seed = seed || 0;
  127 + var remainder = key.length % 16;
  128 + var bytes = key.length - remainder;
  129 + var h1 = [0, seed];
  130 + var h2 = [0, seed];
  131 + var k1 = [0, 0];
  132 + var k2 = [0, 0];
  133 + var c1 = [0x87c37b91, 0x114253d5];
  134 + var c2 = [0x4cf5ad43, 0x2745937f];
  135 + var i;
  136 + for (i = 0; i < bytes; i = i + 16) {
  137 + k1 = [
  138 + (key.charCodeAt(i + 4) & 0xff) |
  139 + ((key.charCodeAt(i + 5) & 0xff) << 8) |
  140 + ((key.charCodeAt(i + 6) & 0xff) << 16) |
  141 + ((key.charCodeAt(i + 7) & 0xff) << 24),
  142 + (key.charCodeAt(i) & 0xff) |
  143 + ((key.charCodeAt(i + 1) & 0xff) << 8) |
  144 + ((key.charCodeAt(i + 2) & 0xff) << 16) |
  145 + ((key.charCodeAt(i + 3) & 0xff) << 24),
  146 + ];
  147 + k2 = [
  148 + (key.charCodeAt(i + 12) & 0xff) |
  149 + ((key.charCodeAt(i + 13) & 0xff) << 8) |
  150 + ((key.charCodeAt(i + 14) & 0xff) << 16) |
  151 + ((key.charCodeAt(i + 15) & 0xff) << 24),
  152 + (key.charCodeAt(i + 8) & 0xff) |
  153 + ((key.charCodeAt(i + 9) & 0xff) << 8) |
  154 + ((key.charCodeAt(i + 10) & 0xff) << 16) |
  155 + ((key.charCodeAt(i + 11) & 0xff) << 24),
  156 + ];
  157 + k1 = x64Multiply(k1, c1);
  158 + k1 = x64Rotl(k1, 31);
  159 + k1 = x64Multiply(k1, c2);
  160 + h1 = x64Xor(h1, k1);
  161 + h1 = x64Rotl(h1, 27);
  162 + h1 = x64Add(h1, h2);
  163 + h1 = x64Add(x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
  164 + k2 = x64Multiply(k2, c2);
  165 + k2 = x64Rotl(k2, 33);
  166 + k2 = x64Multiply(k2, c1);
  167 + h2 = x64Xor(h2, k2);
  168 + h2 = x64Rotl(h2, 31);
  169 + h2 = x64Add(h2, h1);
  170 + h2 = x64Add(x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
  171 + }
  172 + k1 = [0, 0];
  173 + k2 = [0, 0];
  174 + switch (remainder) {
  175 + case 15:
  176 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 14)], 48));
  177 + // fallthrough
  178 + case 14:
  179 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 13)], 40));
  180 + // fallthrough
  181 + case 13:
  182 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 12)], 32));
  183 + // fallthrough
  184 + case 12:
  185 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 11)], 24));
  186 + // fallthrough
  187 + case 11:
  188 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 10)], 16));
  189 + // fallthrough
  190 + case 10:
  191 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 9)], 8));
  192 + // fallthrough
  193 + case 9:
  194 + k2 = x64Xor(k2, [0, key.charCodeAt(i + 8)]);
  195 + k2 = x64Multiply(k2, c2);
  196 + k2 = x64Rotl(k2, 33);
  197 + k2 = x64Multiply(k2, c1);
  198 + h2 = x64Xor(h2, k2);
  199 + // fallthrough
  200 + case 8:
  201 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 7)], 56));
  202 + // fallthrough
  203 + case 7:
  204 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 6)], 48));
  205 + // fallthrough
  206 + case 6:
  207 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 5)], 40));
  208 + // fallthrough
  209 + case 5:
  210 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 4)], 32));
  211 + // fallthrough
  212 + case 4:
  213 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 3)], 24));
  214 + // fallthrough
  215 + case 3:
  216 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 2)], 16));
  217 + // fallthrough
  218 + case 2:
  219 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 1)], 8));
  220 + // fallthrough
  221 + case 1:
  222 + k1 = x64Xor(k1, [0, key.charCodeAt(i)]);
  223 + k1 = x64Multiply(k1, c1);
  224 + k1 = x64Rotl(k1, 31);
  225 + k1 = x64Multiply(k1, c2);
  226 + h1 = x64Xor(h1, k1);
  227 + // fallthrough
  228 + }
  229 + h1 = x64Xor(h1, [0, key.length]);
  230 + h2 = x64Xor(h2, [0, key.length]);
  231 + h1 = x64Add(h1, h2);
  232 + h2 = x64Add(h2, h1);
  233 + h1 = x64Fmix(h1);
  234 + h2 = x64Fmix(h2);
  235 + h1 = x64Add(h1, h2);
  236 + h2 = x64Add(h2, h1);
  237 + return (('00000000' + (h1[0] >>> 0).toString(16)).slice(-8) +
  238 + ('00000000' + (h1[1] >>> 0).toString(16)).slice(-8) +
  239 + ('00000000' + (h2[0] >>> 0).toString(16)).slice(-8) +
  240 + ('00000000' + (h2[1] >>> 0).toString(16)).slice(-8));
  241 +}
  242 +
  243 +var version = "3.0.3";
  244 +
  245 +function requestIdleCallbackIfAvailable(fallbackTimeout) {
  246 + return new Promise(function (resolve) {
  247 + if (window.requestIdleCallback) {
  248 + window.requestIdleCallback(function () { return resolve(); });
  249 + }
  250 + else {
  251 + setTimeout(resolve, fallbackTimeout);
  252 + }
  253 + });
  254 +}
  255 +
  256 +/*
  257 + * This file contains functions to work with pure data only (no browser features, DOM, side effects, etc).
  258 + */
  259 +/**
  260 + * Does the same as Array.prototype.includes but has better typing
  261 + */
  262 +function includes(haystack, needle) {
  263 + for (var i = 0, l = haystack.length; i < l; ++i) {
  264 + if (haystack[i] === needle) {
  265 + return true;
  266 + }
  267 + }
  268 + return false;
  269 +}
  270 +/**
  271 + * Like `!includes()` but with proper typing
  272 + */
  273 +function excludes(haystack, needle) {
  274 + return !includes(haystack, needle);
  275 +}
  276 +/**
  277 + * Be careful, NaN can return
  278 + */
  279 +function toInt(value) {
  280 + if (typeof value === 'number') {
  281 + return value | 0;
  282 + }
  283 + return parseInt(value);
  284 +}
  285 +/**
  286 + * Be careful, NaN can return
  287 + */
  288 +function toFloat(value) {
  289 + if (typeof value === 'number') {
  290 + return value;
  291 + }
  292 + return parseFloat(value);
  293 +}
  294 +function countTruthy(values) {
  295 + return values.reduce(function (sum, value) { return sum + (value ? 1 : 0); }, 0);
  296 +}
  297 +
  298 +/*
  299 + * Functions to help with browser features
  300 + */
  301 +var w = window;
  302 +var n = navigator;
  303 +var d = document;
  304 +/**
  305 + * Checks whether the browser is based on Trident (the Internet Explorer engine) without using user-agent.
  306 + *
  307 + * Warning for package users:
  308 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  309 + */
  310 +function isTrident() {
  311 + // The properties are checked to be in IE 10, IE 11 and not to be in other browsers in October 2020
  312 + return (countTruthy([
  313 + 'MSCSSMatrix' in w,
  314 + 'msSetImmediate' in w,
  315 + 'msIndexedDB' in w,
  316 + 'msMaxTouchPoints' in n,
  317 + 'msPointerEnabled' in n,
  318 + ]) >= 4);
  319 +}
  320 +/**
  321 + * Checks whether the browser is based on EdgeHTML (the pre-Chromium Edge engine) without using user-agent.
  322 + *
  323 + * Warning for package users:
  324 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  325 + */
  326 +function isEdgeHTML() {
  327 + // Based on research in October 2020
  328 + return (countTruthy(['msWriteProfilerMark' in w, 'MSStream' in w, 'msLaunchUri' in n, 'msSaveBlob' in n]) >= 3 &&
  329 + !isTrident());
  330 +}
  331 +/**
  332 + * Checks whether the browser is based on Chromium without using user-agent.
  333 + *
  334 + * Warning for package users:
  335 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  336 + */
  337 +function isChromium() {
  338 + // Based on research in October 2020. Tested to detect Chromium 42-86.
  339 + return (countTruthy([
  340 + 'webkitPersistentStorage' in n,
  341 + 'webkitTemporaryStorage' in n,
  342 + n.vendor.indexOf('Google') === 0,
  343 + 'webkitResolveLocalFileSystemURL' in w,
  344 + 'BatteryManager' in w,
  345 + 'webkitMediaStream' in w,
  346 + 'webkitSpeechGrammar' in w,
  347 + ]) >= 5);
  348 +}
  349 +/**
  350 + * Checks whether the browser is based on mobile or desktop Safari without using user-agent.
  351 + * All iOS browsers use WebKit (the Safari engine).
  352 + *
  353 + * Warning for package users:
  354 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  355 + */
  356 +function isWebKit() {
  357 + // Based on research in September 2020
  358 + return (countTruthy([
  359 + 'ApplePayError' in w,
  360 + 'CSSPrimitiveValue' in w,
  361 + 'Counter' in w,
  362 + n.vendor.indexOf('Apple') === 0,
  363 + 'getStorageUpdates' in n,
  364 + 'WebKitMediaKeys' in w,
  365 + ]) >= 4);
  366 +}
  367 +/**
  368 + * Checks whether the WebKit browser is a desktop Safari.
  369 + *
  370 + * Warning for package users:
  371 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  372 + */
  373 +function isDesktopSafari() {
  374 + return (countTruthy([
  375 + 'safari' in w,
  376 + !('DeviceMotionEvent' in w),
  377 + !('ongestureend' in w),
  378 + !('standalone' in n),
  379 + ]) >= 3);
  380 +}
  381 +/**
  382 + * Checks whether the browser is based on Gecko (Firefox engine) without using user-agent.
  383 + *
  384 + * Warning for package users:
  385 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  386 + */
  387 +function isGecko() {
  388 + var _a;
  389 + // Based on research in September 2020
  390 + return (countTruthy([
  391 + 'buildID' in n,
  392 + ((_a = d.documentElement) === null || _a === void 0 ? void 0 : _a.style) && 'MozAppearance' in d.documentElement.style,
  393 + 'MediaRecorderErrorEvent' in w,
  394 + 'mozInnerScreenX' in w,
  395 + 'CSSMozDocumentRule' in w,
  396 + 'CanvasCaptureMediaStream' in w,
  397 + ]) >= 4);
  398 +}
  399 +/**
  400 + * Checks whether the browser is based on Chromium version ≥86 without using user-agent.
  401 + * It doesn't check that the browser is based on Chromium, there is a separate function for this.
  402 + */
  403 +function isChromium86OrNewer() {
  404 + // Checked in Chrome 85 vs Chrome 86 both on desktop and Android
  405 + return (countTruthy([
  406 + !('MediaSettingsRange' in w),
  407 + 'RTCEncodedAudioFrame' in w,
  408 + '' + w.Intl === '[object Intl]',
  409 + '' + w.Reflect === '[object Reflect]',
  410 + ]) >= 3);
  411 +}
  412 +/**
  413 + * Checks whether the browser is based on WebKit version ≥606 (Safari ≥12) without using user-agent.
  414 + * It doesn't check that the browser is based on WebKit, there is a separate function for this.
  415 + *
  416 + * @link https://en.wikipedia.org/wiki/Safari_version_history#Release_history Safari-WebKit versions map
  417 + */
  418 +function isWebKit606OrNewer() {
  419 + // Checked in Safari 9–14
  420 + return (countTruthy([
  421 + 'DOMRectList' in w,
  422 + 'RTCPeerConnectionIceEvent' in w,
  423 + 'SVGGeometryElement' in w,
  424 + 'ontransitioncancel' in w,
  425 + ]) >= 3);
  426 +}
  427 +
  428 +var w$1 = window;
  429 +var d$1 = document;
  430 +// Inspired by and based on https://github.com/cozylife/audio-fingerprint
  431 +function getAudioFingerprint() {
  432 + return __awaiter(this, void 0, void 0, function () {
  433 + var AudioContext, context, oscillator, compressor, buffer, error_1;
  434 + return __generator(this, function (_a) {
  435 + switch (_a.label) {
  436 + case 0:
  437 + // In some browsers, audio context always stays suspended unless the context is started in response to a user action
  438 + // (e.g. a click or a tap). It prevents audio fingerprint from being taken at an arbitrary moment of time.
  439 + // Such browsers are old and unpopular, so the audio fingerprinting is just skipped in them.
  440 + // See a similar case explanation at https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088
  441 + if (doesCurrentBrowserSuspendAudioContext()) {
  442 + return [2 /*return*/, -1];
  443 + }
  444 + AudioContext = w$1.OfflineAudioContext || w$1.webkitOfflineAudioContext;
  445 + if (!AudioContext) {
  446 + return [2 /*return*/, -2];
  447 + }
  448 + context = new AudioContext(1, 44100, 44100);
  449 + oscillator = context.createOscillator();
  450 + oscillator.type = 'triangle';
  451 + setAudioParam(context, oscillator.frequency, 10000);
  452 + compressor = context.createDynamicsCompressor();
  453 + setAudioParam(context, compressor.threshold, -50);
  454 + setAudioParam(context, compressor.knee, 40);
  455 + setAudioParam(context, compressor.ratio, 12);
  456 + setAudioParam(context, compressor.reduction, -20);
  457 + setAudioParam(context, compressor.attack, 0);
  458 + setAudioParam(context, compressor.release, 0.25);
  459 + oscillator.connect(compressor);
  460 + compressor.connect(context.destination);
  461 + oscillator.start(0);
  462 + _a.label = 1;
  463 + case 1:
  464 + _a.trys.push([1, 3, 4, 5]);
  465 + return [4 /*yield*/, renderAudio(context)];
  466 + case 2:
  467 + buffer = _a.sent();
  468 + return [3 /*break*/, 5];
  469 + case 3:
  470 + error_1 = _a.sent();
  471 + if (error_1.name === "timeout" /* Timeout */ || error_1.name === "suspended" /* Suspended */) {
  472 + return [2 /*return*/, -3];
  473 + }
  474 + throw error_1;
  475 + case 4:
  476 + oscillator.disconnect();
  477 + compressor.disconnect();
  478 + return [7 /*endfinally*/];
  479 + case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))];
  480 + }
  481 + });
  482 + });
  483 +}
  484 +/**
  485 + * Checks if the current browser is known to always suspend audio context
  486 + */
  487 +function doesCurrentBrowserSuspendAudioContext() {
  488 + return isWebKit() && !isDesktopSafari() && !isWebKit606OrNewer();
  489 +}
  490 +function setAudioParam(context, param, value) {
  491 + var isAudioParam = function (value) {
  492 + return value && typeof value.setValueAtTime === 'function';
  493 + };
  494 + if (isAudioParam(param)) {
  495 + param.setValueAtTime(value, context.currentTime);
  496 + }
  497 +}
  498 +function renderAudio(context) {
  499 + var resumeTriesMaxCount = 3;
  500 + var resumeRetryDelay = 500;
  501 + var runningTimeout = 1000;
  502 + return new Promise(function (resolve, reject) {
  503 + context.oncomplete = function (event) { return resolve(event.renderedBuffer); };
  504 + var resumeTriesLeft = resumeTriesMaxCount;
  505 + var tryResume = function () {
  506 + context.startRendering();
  507 + switch (context.state) {
  508 + case 'running':
  509 + setTimeout(function () { return reject(makeInnerError("timeout" /* Timeout */)); }, runningTimeout);
  510 + break;
  511 + // Sometimes the audio context doesn't start after calling `startRendering` (in addition to the cases where
  512 + // audio context doesn't start at all). A known case is starting an audio context when the browser tab is in
  513 + // background on iPhone. Retries usually help in this case.
  514 + case 'suspended':
  515 + // The audio context can reject starting until the tab is in foreground. Long fingerprint duration
  516 + // in background isn't a problem, therefore the retry attempts don't count in background. It can lead to
  517 + // a situation when a fingerprint takes very long time and finishes successfully. FYI, the audio context
  518 + // can be suspended when `document.hidden === false` and start running after a retry.
  519 + if (!d$1.hidden) {
  520 + resumeTriesLeft--;
  521 + }
  522 + if (resumeTriesLeft > 0) {
  523 + setTimeout(tryResume, resumeRetryDelay);
  524 + }
  525 + else {
  526 + reject(makeInnerError("suspended" /* Suspended */));
  527 + }
  528 + break;
  529 + }
  530 + };
  531 + tryResume();
  532 + });
  533 +}
  534 +function getHash(signal) {
  535 + var hash = 0;
  536 + for (var i = 4500; i < 5000; ++i) {
  537 + hash += Math.abs(signal[i]);
  538 + }
  539 + return hash;
  540 +}
  541 +function makeInnerError(name) {
  542 + var error = new Error(name);
  543 + error.name = name;
  544 + return error;
  545 +}
  546 +
  547 +var d$2 = document;
  548 +// We use m or w because these two characters take up the maximum width.
  549 +// And we use a LLi so that the same matching fonts can get separated.
  550 +var testString = 'mmMwWLliI0O&1';
  551 +// We test using 48px font size, we may use any size. I guess larger the better.
  552 +var testSize = '48px';
  553 +// A font will be compared against all the three default fonts.
  554 +// And if it doesn't match all 3 then that font is not available.
  555 +var baseFonts = ['monospace', 'sans-serif', 'serif'];
  556 +var fontList = [
  557 + // This is android-specific font from "Roboto" family
  558 + 'sans-serif-thin',
  559 + 'ARNO PRO',
  560 + 'Agency FB',
  561 + 'Arabic Typesetting',
  562 + 'Arial Unicode MS',
  563 + 'AvantGarde Bk BT',
  564 + 'BankGothic Md BT',
  565 + 'Batang',
  566 + 'Bitstream Vera Sans Mono',
  567 + 'Calibri',
  568 + 'Century',
  569 + 'Century Gothic',
  570 + 'Clarendon',
  571 + 'EUROSTILE',
  572 + 'Franklin Gothic',
  573 + 'Futura Bk BT',
  574 + 'Futura Md BT',
  575 + 'GOTHAM',
  576 + 'Gill Sans',
  577 + 'HELV',
  578 + 'Haettenschweiler',
  579 + 'Helvetica Neue',
  580 + 'Humanst521 BT',
  581 + 'Leelawadee',
  582 + 'Letter Gothic',
  583 + 'Levenim MT',
  584 + 'Lucida Bright',
  585 + 'Lucida Sans',
  586 + 'Menlo',
  587 + 'MS Mincho',
  588 + 'MS Outlook',
  589 + 'MS Reference Specialty',
  590 + 'MS UI Gothic',
  591 + 'MT Extra',
  592 + 'MYRIAD PRO',
  593 + 'Marlett',
  594 + 'Meiryo UI',
  595 + 'Microsoft Uighur',
  596 + 'Minion Pro',
  597 + 'Monotype Corsiva',
  598 + 'PMingLiU',
  599 + 'Pristina',
  600 + 'SCRIPTINA',
  601 + 'Segoe UI Light',
  602 + 'Serifa',
  603 + 'SimHei',
  604 + 'Small Fonts',
  605 + 'Staccato222 BT',
  606 + 'TRAJAN PRO',
  607 + 'Univers CE 55 Medium',
  608 + 'Vrinda',
  609 + 'ZWAdobeF',
  610 +];
  611 +var fontSpanStyle = {
  612 + // CSS font reset to reset external styles
  613 + fontStyle: 'normal',
  614 + fontWeight: 'normal',
  615 + letterSpacing: 'normal',
  616 + lineBreak: 'auto',
  617 + lineHeight: 'normal',
  618 + textTransform: 'none',
  619 + textAlign: 'left',
  620 + textDecoration: 'none',
  621 + textShadow: 'none',
  622 + whiteSpace: 'normal',
  623 + wordBreak: 'normal',
  624 + wordSpacing: 'normal',
  625 + // We need this css as in some weird browser this span elements shows up for a microSec which creates
  626 + // a bad user experience
  627 + position: 'absolute',
  628 + left: '-9999px',
  629 + fontSize: testSize,
  630 +};
  631 +// kudos to http://www.lalit.org/lab/javascript-css-font-detect/
  632 +function getFonts() {
  633 + var h = d$2.body;
  634 + // div to load spans for the base fonts
  635 + var baseFontsDiv = d$2.createElement('div');
  636 + // div to load spans for the fonts to detect
  637 + var fontsDiv = d$2.createElement('div');
  638 + var defaultWidth = {};
  639 + var defaultHeight = {};
  640 + // creates a span where the fonts will be loaded
  641 + var createSpan = function () {
  642 + var span = d$2.createElement('span');
  643 + span.textContent = testString;
  644 + for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) {
  645 + var prop = _a[_i];
  646 + span.style[prop] = fontSpanStyle[prop];
  647 + }
  648 + return span;
  649 + };
  650 + // creates a span and load the font to detect and a base font for fallback
  651 + var createSpanWithFonts = function (fontToDetect, baseFont) {
  652 + var s = createSpan();
  653 + s.style.fontFamily = "'" + fontToDetect + "'," + baseFont;
  654 + return s;
  655 + };
  656 + // creates spans for the base fonts and adds them to baseFontsDiv
  657 + var initializeBaseFontsSpans = function () {
  658 + return baseFonts.map(function (baseFont) {
  659 + var s = createSpan();
  660 + s.style.fontFamily = baseFont;
  661 + baseFontsDiv.appendChild(s);
  662 + return s;
  663 + });
  664 + };
  665 + // creates spans for the fonts to detect and adds them to fontsDiv
  666 + var initializeFontsSpans = function () {
  667 + // Stores {fontName : [spans for that font]}
  668 + var spans = {};
  669 + var _loop_1 = function (font) {
  670 + spans[font] = baseFonts.map(function (baseFont) {
  671 + var s = createSpanWithFonts(font, baseFont);
  672 + fontsDiv.appendChild(s);
  673 + return s;
  674 + });
  675 + };
  676 + for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) {
  677 + var font = fontList_1[_i];
  678 + _loop_1(font);
  679 + }
  680 + return spans;
  681 + };
  682 + // checks if a font is available
  683 + var isFontAvailable = function (fontSpans) {
  684 + return baseFonts.some(function (baseFont, baseFontIndex) {
  685 + return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] ||
  686 + fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont];
  687 + });
  688 + };
  689 + // create spans for base fonts
  690 + var baseFontsSpans = initializeBaseFontsSpans();
  691 + // add the spans to the DOM
  692 + h.appendChild(baseFontsDiv);
  693 + // get the default width for the three base fonts
  694 + for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) {
  695 + defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font
  696 + defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font
  697 + }
  698 + // create spans for fonts to detect
  699 + var fontsSpans = initializeFontsSpans();
  700 + // add all the spans to the DOM
  701 + h.appendChild(fontsDiv);
  702 + // check available fonts
  703 + var available = [];
  704 + for (var i = 0, l = fontList.length; i < l; i++) {
  705 + if (isFontAvailable(fontsSpans[fontList[i]])) {
  706 + available.push(fontList[i]);
  707 + }
  708 + }
  709 + // remove spans from DOM
  710 + h.removeChild(fontsDiv);
  711 + h.removeChild(baseFontsDiv);
  712 + return available;
  713 +}
  714 +
  715 +function getPlugins() {
  716 + if (isTrident()) {
  717 + return [];
  718 + }
  719 + if (!navigator.plugins) {
  720 + return undefined;
  721 + }
  722 + var plugins = [];
  723 + // Safari 10 doesn't support iterating navigator.plugins with for...of
  724 + for (var i = 0; i < navigator.plugins.length; ++i) {
  725 + var plugin = navigator.plugins[i];
  726 + if (!plugin) {
  727 + continue;
  728 + }
  729 + var mimeTypes = [];
  730 + for (var j = 0; j < plugin.length; ++j) {
  731 + var mimeType = plugin[j];
  732 + mimeTypes.push({
  733 + type: mimeType.type,
  734 + suffixes: mimeType.suffixes,
  735 + });
  736 + }
  737 + plugins.push({
  738 + name: plugin.name,
  739 + description: plugin.description,
  740 + mimeTypes: mimeTypes,
  741 + });
  742 + }
  743 + return plugins;
  744 +}
  745 +
  746 +function makeCanvasContext() {
  747 + var canvas = document.createElement('canvas');
  748 + canvas.width = 240;
  749 + canvas.height = 140;
  750 + canvas.style.display = 'inline';
  751 + return [canvas, canvas.getContext('2d')];
  752 +}
  753 +function isSupported(canvas, context) {
  754 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  755 + return !!(context && canvas.toDataURL);
  756 +}
  757 +function save(canvas) {
  758 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  759 + return canvas.toDataURL();
  760 +}
  761 +// https://www.browserleaks.com/canvas#how-does-it-work
  762 +function getCanvasFingerprint() {
  763 + var _a = makeCanvasContext(), canvas = _a[0], context = _a[1];
  764 + if (!isSupported(canvas, context)) {
  765 + return { winding: false, data: '' };
  766 + }
  767 + // detect browser support of canvas winding
  768 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  769 + // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js
  770 + context.rect(0, 0, 10, 10);
  771 + context.rect(2, 2, 6, 6);
  772 + var winding = !context.isPointInPath(5, 5, 'evenodd');
  773 + context.textBaseline = 'alphabetic';
  774 + context.fillStyle = '#f60';
  775 + context.fillRect(125, 1, 62, 20);
  776 + context.fillStyle = '#069';
  777 + // https://github.com/Valve/fingerprintjs2/issues/66
  778 + // this can affect FP generation when applying different CSS on different websites
  779 + context.font = '11pt no-real-font-123';
  780 + // the choice of emojis has a gigantic impact on rendering performance (especially in FF)
  781 + // some newer emojis cause it to slow down 50-200 times
  782 + // context.fillText("Cw爨m fjordbank \ud83d\ude03 gly", 2, 15)
  783 + var printedText = 'Cwm fjordbank \ud83d\ude03 gly';
  784 + context.fillText(printedText, 2, 15);
  785 + context.fillStyle = 'rgba(102, 204, 0, 0.2)';
  786 + context.font = '18pt Arial';
  787 + context.fillText(printedText, 4, 45);
  788 + // canvas blending
  789 + // http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
  790 + // http://jsfiddle.net/NDYV8/16/
  791 + context.globalCompositeOperation = 'multiply';
  792 + context.fillStyle = 'rgb(255,0,255)';
  793 + context.beginPath();
  794 + context.arc(50, 50, 50, 0, Math.PI * 2, true);
  795 + context.closePath();
  796 + context.fill();
  797 + context.fillStyle = 'rgb(0,255,255)';
  798 + context.beginPath();
  799 + context.arc(100, 50, 50, 0, Math.PI * 2, true);
  800 + context.closePath();
  801 + context.fill();
  802 + context.fillStyle = 'rgb(255,255,0)';
  803 + context.beginPath();
  804 + context.arc(75, 100, 50, 0, Math.PI * 2, true);
  805 + context.closePath();
  806 + context.fill();
  807 + context.fillStyle = 'rgb(255,0,255)';
  808 + // canvas winding
  809 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  810 + // http://jsfiddle.net/NDYV8/19/
  811 + context.arc(75, 75, 75, 0, Math.PI * 2, true);
  812 + context.arc(75, 75, 25, 0, Math.PI * 2, true);
  813 + context.fill('evenodd');
  814 + return {
  815 + winding: winding,
  816 + data: save(canvas),
  817 + };
  818 +}
  819 +
  820 +var n$1 = navigator;
  821 +var w$2 = window;
  822 +/**
  823 + * This is a crude and primitive touch screen detection. It's not possible to currently reliably detect the availability
  824 + * of a touch screen with a JS, without actually subscribing to a touch event.
  825 + *
  826 + * @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
  827 + * @see https://github.com/Modernizr/Modernizr/issues/548
  828 + */
  829 +function getTouchSupport() {
  830 + var maxTouchPoints = 0;
  831 + var touchEvent;
  832 + if (n$1.maxTouchPoints !== undefined) {
  833 + maxTouchPoints = toInt(n$1.maxTouchPoints);
  834 + }
  835 + else if (n$1.msMaxTouchPoints !== undefined) {
  836 + maxTouchPoints = n$1.msMaxTouchPoints;
  837 + }
  838 + try {
  839 + document.createEvent('TouchEvent');
  840 + touchEvent = true;
  841 + }
  842 + catch (_) {
  843 + touchEvent = false;
  844 + }
  845 + var touchStart = 'ontouchstart' in w$2;
  846 + return {
  847 + maxTouchPoints: maxTouchPoints,
  848 + touchEvent: touchEvent,
  849 + touchStart: touchStart,
  850 + };
  851 +}
  852 +
  853 +function getOsCpu() {
  854 + return navigator.oscpu;
  855 +}
  856 +
  857 +var n$2 = navigator;
  858 +function getLanguages() {
  859 + var result = [];
  860 + var language = n$2.language || n$2.userLanguage || n$2.browserLanguage || n$2.systemLanguage;
  861 + if (language !== undefined) {
  862 + result.push([language]);
  863 + }
  864 + if (Array.isArray(n$2.languages)) {
  865 + // Starting from Chromium 86, there is only a single value in `navigator.language` in Incognito mode:
  866 + // the value of `navigator.language`. Therefore the value is ignored in this browser.
  867 + if (!(isChromium() && isChromium86OrNewer())) {
  868 + result.push(n$2.languages);
  869 + }
  870 + }
  871 + else if (typeof n$2.languages === 'string') {
  872 + var languages = n$2.languages;
  873 + if (languages) {
  874 + result.push(languages.split(','));
  875 + }
  876 + }
  877 + return result;
  878 +}
  879 +
  880 +function getColorDepth() {
  881 + return window.screen.colorDepth;
  882 +}
  883 +
  884 +function getDeviceMemory() {
  885 + return navigator.deviceMemory;
  886 +}
  887 +
  888 +var w$3 = window;
  889 +function getScreenResolution() {
  890 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  891 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  892 + var dimensions = [toInt(w$3.screen.width), toInt(w$3.screen.height)];
  893 + dimensions.sort().reverse();
  894 + return dimensions;
  895 +}
  896 +
  897 +var w$4 = window;
  898 +function getAvailableScreenResolution() {
  899 + if (w$4.screen.availWidth && w$4.screen.availHeight) {
  900 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  901 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  902 + var dimensions = [toInt(w$4.screen.availWidth), toInt(w$4.screen.availHeight)];
  903 + dimensions.sort().reverse();
  904 + return dimensions;
  905 + }
  906 + return undefined;
  907 +}
  908 +
  909 +function getHardwareConcurrency() {
  910 + try {
  911 + // sometimes hardware concurrency is a string
  912 + var concurrency = toInt(navigator.hardwareConcurrency);
  913 + return isNaN(concurrency) ? 1 : concurrency;
  914 + }
  915 + catch (e) {
  916 + return 1;
  917 + }
  918 +}
  919 +
  920 +function getTimezoneOffset() {
  921 + var currentYear = new Date().getFullYear();
  922 + // The timezone offset may change over time due to daylight saving time (DST) shifts.
  923 + // The non-DST timezone offset is used as the result timezone offset.
  924 + // Since the DST season differs in the northern and the southern hemispheres,
  925 + // both January and July timezones offsets are considered.
  926 + return Math.max(
  927 + // `getTimezoneOffset` returns a number as a string in some unidentified cases
  928 + toFloat(new Date(currentYear, 0, 1).getTimezoneOffset()), toFloat(new Date(currentYear, 6, 1).getTimezoneOffset()));
  929 +}
  930 +
  931 +var w$5 = window;
  932 +function getTimezone() {
  933 + var _a;
  934 + if ((_a = w$5.Intl) === null || _a === void 0 ? void 0 : _a.DateTimeFormat) {
  935 + return new w$5.Intl.DateTimeFormat().resolvedOptions().timeZone;
  936 + }
  937 + return undefined;
  938 +}
  939 +
  940 +function getSessionStorage() {
  941 + try {
  942 + return !!window.sessionStorage;
  943 + }
  944 + catch (error) {
  945 + /* SecurityError when referencing it means it exists */
  946 + return true;
  947 + }
  948 +}
  949 +
  950 +// https://bugzilla.mozilla.org/show_bug.cgi?id=781447
  951 +function getLocalStorage() {
  952 + try {
  953 + return !!window.localStorage;
  954 + }
  955 + catch (e) {
  956 + /* SecurityError when referencing it means it exists */
  957 + return true;
  958 + }
  959 +}
  960 +
  961 +function getIndexedDB() {
  962 + // IE and Edge don't allow accessing indexedDB in private mode, therefore IE and Edge will have different
  963 + // visitor identifier in normal and private modes.
  964 + if (isTrident() || isEdgeHTML()) {
  965 + return undefined;
  966 + }
  967 + try {
  968 + return !!window.indexedDB;
  969 + }
  970 + catch (e) {
  971 + /* SecurityError when referencing it means it exists */
  972 + return true;
  973 + }
  974 +}
  975 +
  976 +function getOpenDatabase() {
  977 + return !!window.openDatabase;
  978 +}
  979 +
  980 +function getCpuClass() {
  981 + return navigator.cpuClass;
  982 +}
  983 +
  984 +function getPlatform() {
  985 + return navigator.platform;
  986 +}
  987 +
  988 +function getPluginsSupport() {
  989 + return navigator.plugins !== undefined;
  990 +}
  991 +
  992 +function getProductSub() {
  993 + return navigator.productSub;
  994 +}
  995 +
  996 +function getEmptyEvalLength() {
  997 + return eval.toString().length;
  998 +}
  999 +
  1000 +function getErrorFF() {
  1001 + try {
  1002 + throw 'a';
  1003 + }
  1004 + catch (e) {
  1005 + try {
  1006 + e.toSource();
  1007 + return true;
  1008 + }
  1009 + catch (e2) {
  1010 + return false;
  1011 + }
  1012 + }
  1013 +}
  1014 +
  1015 +function getVendor() {
  1016 + return navigator.vendor;
  1017 +}
  1018 +
  1019 +function getChrome() {
  1020 + return window.chrome !== undefined;
  1021 +}
  1022 +
  1023 +var d$3 = document;
  1024 +/**
  1025 + * navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1026 + * cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past with
  1027 + * site-specific exceptions. Don't rely on it.
  1028 + *
  1029 + * @see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js Taken from here
  1030 + */
  1031 +function areCookiesEnabled() {
  1032 + // Taken from here: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js
  1033 + // navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1034 + // cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past
  1035 + // with site-specific exceptions. Don't rely on it.
  1036 + // try..catch because some in situations `document.cookie` is exposed but throws a
  1037 + // SecurityError if you try to access it; e.g. documents created from data URIs
  1038 + // or in sandboxed iframes (depending on flags/context)
  1039 + try {
  1040 + // Create cookie
  1041 + d$3.cookie = 'cookietest=1';
  1042 + var result = d$3.cookie.indexOf('cookietest=') !== -1;
  1043 + // Delete cookie
  1044 + d$3.cookie = 'cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT';
  1045 + return result;
  1046 + }
  1047 + catch (e) {
  1048 + return false;
  1049 + }
  1050 +}
  1051 +
  1052 +/**
  1053 + * The list of entropy sources used to make visitor identifiers.
  1054 + *
  1055 + * This value isn't restricted by Semantic Versioning, i.e. it may be changed without bumping minor or major version of
  1056 + * this package.
  1057 + */
  1058 +var sources = {
  1059 + // Expected errors and default values must be handled inside the functions. Unexpected errors must be thrown.
  1060 + osCpu: getOsCpu,
  1061 + languages: getLanguages,
  1062 + colorDepth: getColorDepth,
  1063 + deviceMemory: getDeviceMemory,
  1064 + screenResolution: getScreenResolution,
  1065 + availableScreenResolution: getAvailableScreenResolution,
  1066 + hardwareConcurrency: getHardwareConcurrency,
  1067 + timezoneOffset: getTimezoneOffset,
  1068 + timezone: getTimezone,
  1069 + sessionStorage: getSessionStorage,
  1070 + localStorage: getLocalStorage,
  1071 + indexedDB: getIndexedDB,
  1072 + openDatabase: getOpenDatabase,
  1073 + cpuClass: getCpuClass,
  1074 + // Maybe it should be excluded: https://github.com/fingerprintjs/fingerprintjs/issues/514#issuecomment-688754892
  1075 + platform: getPlatform,
  1076 + plugins: getPlugins,
  1077 + canvas: getCanvasFingerprint,
  1078 + // adBlock: isAdblockUsed, // https://github.com/fingerprintjs/fingerprintjs/issues/405
  1079 + touchSupport: getTouchSupport,
  1080 + fonts: getFonts,
  1081 + audio: getAudioFingerprint,
  1082 + pluginsSupport: getPluginsSupport,
  1083 + productSub: getProductSub,
  1084 + emptyEvalLength: getEmptyEvalLength,
  1085 + errorFF: getErrorFF,
  1086 + vendor: getVendor,
  1087 + chrome: getChrome,
  1088 + cookiesEnabled: areCookiesEnabled,
  1089 +};
  1090 +/**
  1091 + * Gets a components list from the given list of entropy sources.
  1092 + *
  1093 + * Warning for package users:
  1094 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  1095 + */
  1096 +function getComponents(sources, sourceOptions, excludeSources) {
  1097 + return __awaiter(this, void 0, void 0, function () {
  1098 + var timestamp, components, _i, _a, sourceKey, result, error_1, nextTimestamp;
  1099 + var _b;
  1100 + return __generator(this, function (_c) {
  1101 + switch (_c.label) {
  1102 + case 0:
  1103 + timestamp = Date.now();
  1104 + components = {};
  1105 + _i = 0, _a = Object.keys(sources);
  1106 + _c.label = 1;
  1107 + case 1:
  1108 + if (!(_i < _a.length)) return [3 /*break*/, 7];
  1109 + sourceKey = _a[_i];
  1110 + if (!excludes(excludeSources, sourceKey)) {
  1111 + return [3 /*break*/, 6];
  1112 + }
  1113 + result = void 0;
  1114 + _c.label = 2;
  1115 + case 2:
  1116 + _c.trys.push([2, 4, , 5]);
  1117 + _b = {};
  1118 + return [4 /*yield*/, sources[sourceKey](sourceOptions)];
  1119 + case 3:
  1120 + result = (_b.value = _c.sent(), _b);
  1121 + return [3 /*break*/, 5];
  1122 + case 4:
  1123 + error_1 = _c.sent();
  1124 + result = error_1 && typeof error_1 === 'object' && 'message' in error_1 ? { error: error_1 } : { error: { message: error_1 } };
  1125 + return [3 /*break*/, 5];
  1126 + case 5:
  1127 + nextTimestamp = Date.now();
  1128 + components[sourceKey] = __assign(__assign({}, result), { duration: nextTimestamp - timestamp }); // TypeScript has beaten me here
  1129 + timestamp = nextTimestamp;
  1130 + _c.label = 6;
  1131 + case 6:
  1132 + _i++;
  1133 + return [3 /*break*/, 1];
  1134 + case 7: return [2 /*return*/, components];
  1135 + }
  1136 + });
  1137 + });
  1138 +}
  1139 +/**
  1140 + * Collects entropy components from the built-in sources to make the visitor identifier.
  1141 + */
  1142 +function getBuiltinComponents() {
  1143 + return getComponents(sources, undefined, []);
  1144 +}
  1145 +
  1146 +function componentsToCanonicalString(components) {
  1147 + var result = '';
  1148 + for (var _i = 0, _a = Object.keys(components); _i < _a.length; _i++) {
  1149 + var componentKey = _a[_i];
  1150 + var component = components[componentKey];
  1151 + var value = component.error ? 'error' : JSON.stringify(component.value);
  1152 + result += "" + (result ? '|' : '') + componentKey.replace(/([:|\\])/g, '\\$1') + ":" + value;
  1153 + }
  1154 + return result;
  1155 +}
  1156 +function componentsToDebugString(components) {
  1157 + return JSON.stringify(components, function (_key, value) {
  1158 + var _a;
  1159 + if (value instanceof Error) {
  1160 + return __assign(__assign({}, value), { message: value.message, stack: (_a = value.stack) === null || _a === void 0 ? void 0 : _a.split('\n') });
  1161 + }
  1162 + return value;
  1163 + }, 2);
  1164 +}
  1165 +function hashComponents(components) {
  1166 + return x64hash128(componentsToCanonicalString(components));
  1167 +}
  1168 +/**
  1169 + * Makes a GetResult implementation that calculates the visitor id hash on demand.
  1170 + * Designed for optimisation.
  1171 + */
  1172 +function makeLazyGetResult(components) {
  1173 + var visitorIdCache;
  1174 + // A plain class isn't used because its getters and setters aren't enumerable.
  1175 + return {
  1176 + components: components,
  1177 + get visitorId() {
  1178 + if (visitorIdCache === undefined) {
  1179 + visitorIdCache = hashComponents(this.components);
  1180 + }
  1181 + return visitorIdCache;
  1182 + },
  1183 + set visitorId(visitorId) {
  1184 + visitorIdCache = visitorId;
  1185 + },
  1186 + };
  1187 +}
  1188 +/**
  1189 + * The class isn't exported from the index file to not expose the constructor.
  1190 + * The hiding gives more freedom for future non-breaking updates.
  1191 + */
  1192 +var OpenAgent = /** @class */ (function () {
  1193 + function OpenAgent() {
  1194 + }
  1195 + /**
  1196 + * @inheritDoc
  1197 + */
  1198 + OpenAgent.prototype.get = function (options) {
  1199 + if (options === void 0) { options = {}; }
  1200 + return __awaiter(this, void 0, void 0, function () {
  1201 + var components, result;
  1202 + return __generator(this, function (_a) {
  1203 + switch (_a.label) {
  1204 + case 0: return [4 /*yield*/, getBuiltinComponents()];
  1205 + case 1:
  1206 + components = _a.sent();
  1207 + result = makeLazyGetResult(components);
  1208 + if (options.debug) {
  1209 + // console.log is ok here because it's under a debug clause
  1210 + // eslint-disable-next-line no-console
  1211 + console.log("Copy the text below to get the debug data:\n\n```\nversion: " + version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```");
  1212 + }
  1213 + return [2 /*return*/, result];
  1214 + }
  1215 + });
  1216 + });
  1217 + };
  1218 + return OpenAgent;
  1219 +}());
  1220 +/**
  1221 + * Builds an instance of Agent and waits a delay required for a proper operation.
  1222 + */
  1223 +function load(_a) {
  1224 + var _b = (_a === void 0 ? {} : _a).delayFallback, delayFallback = _b === void 0 ? 50 : _b;
  1225 + return __awaiter(this, void 0, void 0, function () {
  1226 + return __generator(this, function (_c) {
  1227 + switch (_c.label) {
  1228 + case 0:
  1229 + // A delay is required to ensure consistent entropy components.
  1230 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1231 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1232 + return [4 /*yield*/, requestIdleCallbackIfAvailable(delayFallback)];
  1233 + case 1:
  1234 + // A delay is required to ensure consistent entropy components.
  1235 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1236 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1237 + _c.sent();
  1238 + return [2 /*return*/, new OpenAgent()];
  1239 + }
  1240 + });
  1241 + });
  1242 +}
  1243 +
  1244 +// The default export is a syntax sugar (`import * as FP from '...' → import FP from '...'`).
  1245 +// It should contain all the public exported values.
  1246 +var index = { load: load, hashComponents: hashComponents, componentsToDebugString: componentsToDebugString };
  1247 +// The exports below are for private usage. They may change unexpectedly. Use them at your own risk.
  1248 +/** Not documented, out of Semantic Versioning, usage is at your own risk */
  1249 +var murmurX64Hash128 = x64hash128;
  1250 +
  1251 +export default index;
  1252 +export { componentsToDebugString, getComponents, hashComponents, isChromium, isDesktopSafari, isEdgeHTML, isGecko, isTrident, isWebKit, load, murmurX64Hash128 };
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +var FingerprintJS = (function (exports) {
  10 + 'use strict';
  11 +
  12 + /*
  13 + * Taken from https://github.com/karanlyons/murmurHash3.js/blob/a33d0723127e2e5415056c455f8aed2451ace208/murmurHash3.js
  14 + */
  15 + //
  16 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  17 + // added together as a 64bit int (as an array of two 32bit ints).
  18 + //
  19 + function x64Add(m, n) {
  20 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  21 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  22 + var o = [0, 0, 0, 0];
  23 + o[3] += m[3] + n[3];
  24 + o[2] += o[3] >>> 16;
  25 + o[3] &= 0xffff;
  26 + o[2] += m[2] + n[2];
  27 + o[1] += o[2] >>> 16;
  28 + o[2] &= 0xffff;
  29 + o[1] += m[1] + n[1];
  30 + o[0] += o[1] >>> 16;
  31 + o[1] &= 0xffff;
  32 + o[0] += m[0] + n[0];
  33 + o[0] &= 0xffff;
  34 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  35 + }
  36 + //
  37 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  38 + // multiplied together as a 64bit int (as an array of two 32bit ints).
  39 + //
  40 + function x64Multiply(m, n) {
  41 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  42 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  43 + var o = [0, 0, 0, 0];
  44 + o[3] += m[3] * n[3];
  45 + o[2] += o[3] >>> 16;
  46 + o[3] &= 0xffff;
  47 + o[2] += m[2] * n[3];
  48 + o[1] += o[2] >>> 16;
  49 + o[2] &= 0xffff;
  50 + o[2] += m[3] * n[2];
  51 + o[1] += o[2] >>> 16;
  52 + o[2] &= 0xffff;
  53 + o[1] += m[1] * n[3];
  54 + o[0] += o[1] >>> 16;
  55 + o[1] &= 0xffff;
  56 + o[1] += m[2] * n[2];
  57 + o[0] += o[1] >>> 16;
  58 + o[1] &= 0xffff;
  59 + o[1] += m[3] * n[1];
  60 + o[0] += o[1] >>> 16;
  61 + o[1] &= 0xffff;
  62 + o[0] += m[0] * n[3] + m[1] * n[2] + m[2] * n[1] + m[3] * n[0];
  63 + o[0] &= 0xffff;
  64 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  65 + }
  66 + //
  67 + // Given a 64bit int (as an array of two 32bit ints) and an int
  68 + // representing a number of bit positions, returns the 64bit int (as an
  69 + // array of two 32bit ints) rotated left by that number of positions.
  70 + //
  71 + function x64Rotl(m, n) {
  72 + n %= 64;
  73 + if (n === 32) {
  74 + return [m[1], m[0]];
  75 + }
  76 + else if (n < 32) {
  77 + return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))];
  78 + }
  79 + else {
  80 + n -= 32;
  81 + return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))];
  82 + }
  83 + }
  84 + //
  85 + // Given a 64bit int (as an array of two 32bit ints) and an int
  86 + // representing a number of bit positions, returns the 64bit int (as an
  87 + // array of two 32bit ints) shifted left by that number of positions.
  88 + //
  89 + function x64LeftShift(m, n) {
  90 + n %= 64;
  91 + if (n === 0) {
  92 + return m;
  93 + }
  94 + else if (n < 32) {
  95 + return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
  96 + }
  97 + else {
  98 + return [m[1] << (n - 32), 0];
  99 + }
  100 + }
  101 + //
  102 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  103 + // xored together as a 64bit int (as an array of two 32bit ints).
  104 + //
  105 + function x64Xor(m, n) {
  106 + return [m[0] ^ n[0], m[1] ^ n[1]];
  107 + }
  108 + //
  109 + // Given a block, returns murmurHash3's final x64 mix of that block.
  110 + // (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
  111 + // only place where we need to right shift 64bit ints.)
  112 + //
  113 + function x64Fmix(h) {
  114 + h = x64Xor(h, [0, h[0] >>> 1]);
  115 + h = x64Multiply(h, [0xff51afd7, 0xed558ccd]);
  116 + h = x64Xor(h, [0, h[0] >>> 1]);
  117 + h = x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
  118 + h = x64Xor(h, [0, h[0] >>> 1]);
  119 + return h;
  120 + }
  121 + //
  122 + // Given a string and an optional seed as an int, returns a 128 bit
  123 + // hash using the x64 flavor of MurmurHash3, as an unsigned hex.
  124 + //
  125 + function x64hash128(key, seed) {
  126 + key = key || '';
  127 + seed = seed || 0;
  128 + var remainder = key.length % 16;
  129 + var bytes = key.length - remainder;
  130 + var h1 = [0, seed];
  131 + var h2 = [0, seed];
  132 + var k1 = [0, 0];
  133 + var k2 = [0, 0];
  134 + var c1 = [0x87c37b91, 0x114253d5];
  135 + var c2 = [0x4cf5ad43, 0x2745937f];
  136 + var i;
  137 + for (i = 0; i < bytes; i = i + 16) {
  138 + k1 = [
  139 + (key.charCodeAt(i + 4) & 0xff) |
  140 + ((key.charCodeAt(i + 5) & 0xff) << 8) |
  141 + ((key.charCodeAt(i + 6) & 0xff) << 16) |
  142 + ((key.charCodeAt(i + 7) & 0xff) << 24),
  143 + (key.charCodeAt(i) & 0xff) |
  144 + ((key.charCodeAt(i + 1) & 0xff) << 8) |
  145 + ((key.charCodeAt(i + 2) & 0xff) << 16) |
  146 + ((key.charCodeAt(i + 3) & 0xff) << 24),
  147 + ];
  148 + k2 = [
  149 + (key.charCodeAt(i + 12) & 0xff) |
  150 + ((key.charCodeAt(i + 13) & 0xff) << 8) |
  151 + ((key.charCodeAt(i + 14) & 0xff) << 16) |
  152 + ((key.charCodeAt(i + 15) & 0xff) << 24),
  153 + (key.charCodeAt(i + 8) & 0xff) |
  154 + ((key.charCodeAt(i + 9) & 0xff) << 8) |
  155 + ((key.charCodeAt(i + 10) & 0xff) << 16) |
  156 + ((key.charCodeAt(i + 11) & 0xff) << 24),
  157 + ];
  158 + k1 = x64Multiply(k1, c1);
  159 + k1 = x64Rotl(k1, 31);
  160 + k1 = x64Multiply(k1, c2);
  161 + h1 = x64Xor(h1, k1);
  162 + h1 = x64Rotl(h1, 27);
  163 + h1 = x64Add(h1, h2);
  164 + h1 = x64Add(x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
  165 + k2 = x64Multiply(k2, c2);
  166 + k2 = x64Rotl(k2, 33);
  167 + k2 = x64Multiply(k2, c1);
  168 + h2 = x64Xor(h2, k2);
  169 + h2 = x64Rotl(h2, 31);
  170 + h2 = x64Add(h2, h1);
  171 + h2 = x64Add(x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
  172 + }
  173 + k1 = [0, 0];
  174 + k2 = [0, 0];
  175 + switch (remainder) {
  176 + case 15:
  177 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 14)], 48));
  178 + // fallthrough
  179 + case 14:
  180 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 13)], 40));
  181 + // fallthrough
  182 + case 13:
  183 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 12)], 32));
  184 + // fallthrough
  185 + case 12:
  186 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 11)], 24));
  187 + // fallthrough
  188 + case 11:
  189 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 10)], 16));
  190 + // fallthrough
  191 + case 10:
  192 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 9)], 8));
  193 + // fallthrough
  194 + case 9:
  195 + k2 = x64Xor(k2, [0, key.charCodeAt(i + 8)]);
  196 + k2 = x64Multiply(k2, c2);
  197 + k2 = x64Rotl(k2, 33);
  198 + k2 = x64Multiply(k2, c1);
  199 + h2 = x64Xor(h2, k2);
  200 + // fallthrough
  201 + case 8:
  202 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 7)], 56));
  203 + // fallthrough
  204 + case 7:
  205 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 6)], 48));
  206 + // fallthrough
  207 + case 6:
  208 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 5)], 40));
  209 + // fallthrough
  210 + case 5:
  211 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 4)], 32));
  212 + // fallthrough
  213 + case 4:
  214 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 3)], 24));
  215 + // fallthrough
  216 + case 3:
  217 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 2)], 16));
  218 + // fallthrough
  219 + case 2:
  220 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 1)], 8));
  221 + // fallthrough
  222 + case 1:
  223 + k1 = x64Xor(k1, [0, key.charCodeAt(i)]);
  224 + k1 = x64Multiply(k1, c1);
  225 + k1 = x64Rotl(k1, 31);
  226 + k1 = x64Multiply(k1, c2);
  227 + h1 = x64Xor(h1, k1);
  228 + // fallthrough
  229 + }
  230 + h1 = x64Xor(h1, [0, key.length]);
  231 + h2 = x64Xor(h2, [0, key.length]);
  232 + h1 = x64Add(h1, h2);
  233 + h2 = x64Add(h2, h1);
  234 + h1 = x64Fmix(h1);
  235 + h2 = x64Fmix(h2);
  236 + h1 = x64Add(h1, h2);
  237 + h2 = x64Add(h2, h1);
  238 + return (('00000000' + (h1[0] >>> 0).toString(16)).slice(-8) +
  239 + ('00000000' + (h1[1] >>> 0).toString(16)).slice(-8) +
  240 + ('00000000' + (h2[0] >>> 0).toString(16)).slice(-8) +
  241 + ('00000000' + (h2[1] >>> 0).toString(16)).slice(-8));
  242 + }
  243 +
  244 + /*! *****************************************************************************
  245 + Copyright (c) Microsoft Corporation.
  246 +
  247 + Permission to use, copy, modify, and/or distribute this software for any
  248 + purpose with or without fee is hereby granted.
  249 +
  250 + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  251 + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  252 + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  253 + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  254 + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  255 + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  256 + PERFORMANCE OF THIS SOFTWARE.
  257 + ***************************************************************************** */
  258 +
  259 + var __assign = function() {
  260 + __assign = Object.assign || function __assign(t) {
  261 + for (var s, i = 1, n = arguments.length; i < n; i++) {
  262 + s = arguments[i];
  263 + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  264 + }
  265 + return t;
  266 + };
  267 + return __assign.apply(this, arguments);
  268 + };
  269 +
  270 + function __awaiter(thisArg, _arguments, P, generator) {
  271 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  272 + return new (P || (P = Promise))(function (resolve, reject) {
  273 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  274 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  275 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  276 + step((generator = generator.apply(thisArg, _arguments || [])).next());
  277 + });
  278 + }
  279 +
  280 + function __generator(thisArg, body) {
  281 + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  282 + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  283 + function verb(n) { return function (v) { return step([n, v]); }; }
  284 + function step(op) {
  285 + if (f) throw new TypeError("Generator is already executing.");
  286 + while (_) try {
  287 + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  288 + if (y = 0, t) op = [op[0] & 2, t.value];
  289 + switch (op[0]) {
  290 + case 0: case 1: t = op; break;
  291 + case 4: _.label++; return { value: op[1], done: false };
  292 + case 5: _.label++; y = op[1]; op = [0]; continue;
  293 + case 7: op = _.ops.pop(); _.trys.pop(); continue;
  294 + default:
  295 + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  296 + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  297 + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  298 + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  299 + if (t[2]) _.ops.pop();
  300 + _.trys.pop(); continue;
  301 + }
  302 + op = body.call(thisArg, _);
  303 + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  304 + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  305 + }
  306 + }
  307 +
  308 + var version = "3.0.3";
  309 +
  310 + function requestIdleCallbackIfAvailable(fallbackTimeout) {
  311 + return new Promise(function (resolve) {
  312 + if (window.requestIdleCallback) {
  313 + window.requestIdleCallback(function () { return resolve(); });
  314 + }
  315 + else {
  316 + setTimeout(resolve, fallbackTimeout);
  317 + }
  318 + });
  319 + }
  320 +
  321 + /*
  322 + * This file contains functions to work with pure data only (no browser features, DOM, side effects, etc).
  323 + */
  324 + /**
  325 + * Does the same as Array.prototype.includes but has better typing
  326 + */
  327 + function includes(haystack, needle) {
  328 + for (var i = 0, l = haystack.length; i < l; ++i) {
  329 + if (haystack[i] === needle) {
  330 + return true;
  331 + }
  332 + }
  333 + return false;
  334 + }
  335 + /**
  336 + * Like `!includes()` but with proper typing
  337 + */
  338 + function excludes(haystack, needle) {
  339 + return !includes(haystack, needle);
  340 + }
  341 + /**
  342 + * Be careful, NaN can return
  343 + */
  344 + function toInt(value) {
  345 + if (typeof value === 'number') {
  346 + return value | 0;
  347 + }
  348 + return parseInt(value);
  349 + }
  350 + /**
  351 + * Be careful, NaN can return
  352 + */
  353 + function toFloat(value) {
  354 + if (typeof value === 'number') {
  355 + return value;
  356 + }
  357 + return parseFloat(value);
  358 + }
  359 + function countTruthy(values) {
  360 + return values.reduce(function (sum, value) { return sum + (value ? 1 : 0); }, 0);
  361 + }
  362 +
  363 + /*
  364 + * Functions to help with browser features
  365 + */
  366 + var w = window;
  367 + var n = navigator;
  368 + var d = document;
  369 + /**
  370 + * Checks whether the browser is based on Trident (the Internet Explorer engine) without using user-agent.
  371 + *
  372 + * Warning for package users:
  373 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  374 + */
  375 + function isTrident() {
  376 + // The properties are checked to be in IE 10, IE 11 and not to be in other browsers in October 2020
  377 + return (countTruthy([
  378 + 'MSCSSMatrix' in w,
  379 + 'msSetImmediate' in w,
  380 + 'msIndexedDB' in w,
  381 + 'msMaxTouchPoints' in n,
  382 + 'msPointerEnabled' in n,
  383 + ]) >= 4);
  384 + }
  385 + /**
  386 + * Checks whether the browser is based on EdgeHTML (the pre-Chromium Edge engine) without using user-agent.
  387 + *
  388 + * Warning for package users:
  389 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  390 + */
  391 + function isEdgeHTML() {
  392 + // Based on research in October 2020
  393 + return (countTruthy(['msWriteProfilerMark' in w, 'MSStream' in w, 'msLaunchUri' in n, 'msSaveBlob' in n]) >= 3 &&
  394 + !isTrident());
  395 + }
  396 + /**
  397 + * Checks whether the browser is based on Chromium without using user-agent.
  398 + *
  399 + * Warning for package users:
  400 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  401 + */
  402 + function isChromium() {
  403 + // Based on research in October 2020. Tested to detect Chromium 42-86.
  404 + return (countTruthy([
  405 + 'webkitPersistentStorage' in n,
  406 + 'webkitTemporaryStorage' in n,
  407 + n.vendor.indexOf('Google') === 0,
  408 + 'webkitResolveLocalFileSystemURL' in w,
  409 + 'BatteryManager' in w,
  410 + 'webkitMediaStream' in w,
  411 + 'webkitSpeechGrammar' in w,
  412 + ]) >= 5);
  413 + }
  414 + /**
  415 + * Checks whether the browser is based on mobile or desktop Safari without using user-agent.
  416 + * All iOS browsers use WebKit (the Safari engine).
  417 + *
  418 + * Warning for package users:
  419 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  420 + */
  421 + function isWebKit() {
  422 + // Based on research in September 2020
  423 + return (countTruthy([
  424 + 'ApplePayError' in w,
  425 + 'CSSPrimitiveValue' in w,
  426 + 'Counter' in w,
  427 + n.vendor.indexOf('Apple') === 0,
  428 + 'getStorageUpdates' in n,
  429 + 'WebKitMediaKeys' in w,
  430 + ]) >= 4);
  431 + }
  432 + /**
  433 + * Checks whether the WebKit browser is a desktop Safari.
  434 + *
  435 + * Warning for package users:
  436 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  437 + */
  438 + function isDesktopSafari() {
  439 + return (countTruthy([
  440 + 'safari' in w,
  441 + !('DeviceMotionEvent' in w),
  442 + !('ongestureend' in w),
  443 + !('standalone' in n),
  444 + ]) >= 3);
  445 + }
  446 + /**
  447 + * Checks whether the browser is based on Gecko (Firefox engine) without using user-agent.
  448 + *
  449 + * Warning for package users:
  450 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  451 + */
  452 + function isGecko() {
  453 + var _a;
  454 + // Based on research in September 2020
  455 + return (countTruthy([
  456 + 'buildID' in n,
  457 + ((_a = d.documentElement) === null || _a === void 0 ? void 0 : _a.style) && 'MozAppearance' in d.documentElement.style,
  458 + 'MediaRecorderErrorEvent' in w,
  459 + 'mozInnerScreenX' in w,
  460 + 'CSSMozDocumentRule' in w,
  461 + 'CanvasCaptureMediaStream' in w,
  462 + ]) >= 4);
  463 + }
  464 + /**
  465 + * Checks whether the browser is based on Chromium version ≥86 without using user-agent.
  466 + * It doesn't check that the browser is based on Chromium, there is a separate function for this.
  467 + */
  468 + function isChromium86OrNewer() {
  469 + // Checked in Chrome 85 vs Chrome 86 both on desktop and Android
  470 + return (countTruthy([
  471 + !('MediaSettingsRange' in w),
  472 + 'RTCEncodedAudioFrame' in w,
  473 + '' + w.Intl === '[object Intl]',
  474 + '' + w.Reflect === '[object Reflect]',
  475 + ]) >= 3);
  476 + }
  477 + /**
  478 + * Checks whether the browser is based on WebKit version ≥606 (Safari ≥12) without using user-agent.
  479 + * It doesn't check that the browser is based on WebKit, there is a separate function for this.
  480 + *
  481 + * @link https://en.wikipedia.org/wiki/Safari_version_history#Release_history Safari-WebKit versions map
  482 + */
  483 + function isWebKit606OrNewer() {
  484 + // Checked in Safari 9–14
  485 + return (countTruthy([
  486 + 'DOMRectList' in w,
  487 + 'RTCPeerConnectionIceEvent' in w,
  488 + 'SVGGeometryElement' in w,
  489 + 'ontransitioncancel' in w,
  490 + ]) >= 3);
  491 + }
  492 +
  493 + var w$1 = window;
  494 + var d$1 = document;
  495 + // Inspired by and based on https://github.com/cozylife/audio-fingerprint
  496 + function getAudioFingerprint() {
  497 + return __awaiter(this, void 0, void 0, function () {
  498 + var AudioContext, context, oscillator, compressor, buffer, error_1;
  499 + return __generator(this, function (_a) {
  500 + switch (_a.label) {
  501 + case 0:
  502 + // In some browsers, audio context always stays suspended unless the context is started in response to a user action
  503 + // (e.g. a click or a tap). It prevents audio fingerprint from being taken at an arbitrary moment of time.
  504 + // Such browsers are old and unpopular, so the audio fingerprinting is just skipped in them.
  505 + // See a similar case explanation at https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088
  506 + if (doesCurrentBrowserSuspendAudioContext()) {
  507 + return [2 /*return*/, -1];
  508 + }
  509 + AudioContext = w$1.OfflineAudioContext || w$1.webkitOfflineAudioContext;
  510 + if (!AudioContext) {
  511 + return [2 /*return*/, -2];
  512 + }
  513 + context = new AudioContext(1, 44100, 44100);
  514 + oscillator = context.createOscillator();
  515 + oscillator.type = 'triangle';
  516 + setAudioParam(context, oscillator.frequency, 10000);
  517 + compressor = context.createDynamicsCompressor();
  518 + setAudioParam(context, compressor.threshold, -50);
  519 + setAudioParam(context, compressor.knee, 40);
  520 + setAudioParam(context, compressor.ratio, 12);
  521 + setAudioParam(context, compressor.reduction, -20);
  522 + setAudioParam(context, compressor.attack, 0);
  523 + setAudioParam(context, compressor.release, 0.25);
  524 + oscillator.connect(compressor);
  525 + compressor.connect(context.destination);
  526 + oscillator.start(0);
  527 + _a.label = 1;
  528 + case 1:
  529 + _a.trys.push([1, 3, 4, 5]);
  530 + return [4 /*yield*/, renderAudio(context)];
  531 + case 2:
  532 + buffer = _a.sent();
  533 + return [3 /*break*/, 5];
  534 + case 3:
  535 + error_1 = _a.sent();
  536 + if (error_1.name === "timeout" /* Timeout */ || error_1.name === "suspended" /* Suspended */) {
  537 + return [2 /*return*/, -3];
  538 + }
  539 + throw error_1;
  540 + case 4:
  541 + oscillator.disconnect();
  542 + compressor.disconnect();
  543 + return [7 /*endfinally*/];
  544 + case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))];
  545 + }
  546 + });
  547 + });
  548 + }
  549 + /**
  550 + * Checks if the current browser is known to always suspend audio context
  551 + */
  552 + function doesCurrentBrowserSuspendAudioContext() {
  553 + return isWebKit() && !isDesktopSafari() && !isWebKit606OrNewer();
  554 + }
  555 + function setAudioParam(context, param, value) {
  556 + var isAudioParam = function (value) {
  557 + return value && typeof value.setValueAtTime === 'function';
  558 + };
  559 + if (isAudioParam(param)) {
  560 + param.setValueAtTime(value, context.currentTime);
  561 + }
  562 + }
  563 + function renderAudio(context) {
  564 + var resumeTriesMaxCount = 3;
  565 + var resumeRetryDelay = 500;
  566 + var runningTimeout = 1000;
  567 + return new Promise(function (resolve, reject) {
  568 + context.oncomplete = function (event) { return resolve(event.renderedBuffer); };
  569 + var resumeTriesLeft = resumeTriesMaxCount;
  570 + var tryResume = function () {
  571 + context.startRendering();
  572 + switch (context.state) {
  573 + case 'running':
  574 + setTimeout(function () { return reject(makeInnerError("timeout" /* Timeout */)); }, runningTimeout);
  575 + break;
  576 + // Sometimes the audio context doesn't start after calling `startRendering` (in addition to the cases where
  577 + // audio context doesn't start at all). A known case is starting an audio context when the browser tab is in
  578 + // background on iPhone. Retries usually help in this case.
  579 + case 'suspended':
  580 + // The audio context can reject starting until the tab is in foreground. Long fingerprint duration
  581 + // in background isn't a problem, therefore the retry attempts don't count in background. It can lead to
  582 + // a situation when a fingerprint takes very long time and finishes successfully. FYI, the audio context
  583 + // can be suspended when `document.hidden === false` and start running after a retry.
  584 + if (!d$1.hidden) {
  585 + resumeTriesLeft--;
  586 + }
  587 + if (resumeTriesLeft > 0) {
  588 + setTimeout(tryResume, resumeRetryDelay);
  589 + }
  590 + else {
  591 + reject(makeInnerError("suspended" /* Suspended */));
  592 + }
  593 + break;
  594 + }
  595 + };
  596 + tryResume();
  597 + });
  598 + }
  599 + function getHash(signal) {
  600 + var hash = 0;
  601 + for (var i = 4500; i < 5000; ++i) {
  602 + hash += Math.abs(signal[i]);
  603 + }
  604 + return hash;
  605 + }
  606 + function makeInnerError(name) {
  607 + var error = new Error(name);
  608 + error.name = name;
  609 + return error;
  610 + }
  611 +
  612 + var d$2 = document;
  613 + // We use m or w because these two characters take up the maximum width.
  614 + // And we use a LLi so that the same matching fonts can get separated.
  615 + var testString = 'mmMwWLliI0O&1';
  616 + // We test using 48px font size, we may use any size. I guess larger the better.
  617 + var testSize = '48px';
  618 + // A font will be compared against all the three default fonts.
  619 + // And if it doesn't match all 3 then that font is not available.
  620 + var baseFonts = ['monospace', 'sans-serif', 'serif'];
  621 + var fontList = [
  622 + // This is android-specific font from "Roboto" family
  623 + 'sans-serif-thin',
  624 + 'ARNO PRO',
  625 + 'Agency FB',
  626 + 'Arabic Typesetting',
  627 + 'Arial Unicode MS',
  628 + 'AvantGarde Bk BT',
  629 + 'BankGothic Md BT',
  630 + 'Batang',
  631 + 'Bitstream Vera Sans Mono',
  632 + 'Calibri',
  633 + 'Century',
  634 + 'Century Gothic',
  635 + 'Clarendon',
  636 + 'EUROSTILE',
  637 + 'Franklin Gothic',
  638 + 'Futura Bk BT',
  639 + 'Futura Md BT',
  640 + 'GOTHAM',
  641 + 'Gill Sans',
  642 + 'HELV',
  643 + 'Haettenschweiler',
  644 + 'Helvetica Neue',
  645 + 'Humanst521 BT',
  646 + 'Leelawadee',
  647 + 'Letter Gothic',
  648 + 'Levenim MT',
  649 + 'Lucida Bright',
  650 + 'Lucida Sans',
  651 + 'Menlo',
  652 + 'MS Mincho',
  653 + 'MS Outlook',
  654 + 'MS Reference Specialty',
  655 + 'MS UI Gothic',
  656 + 'MT Extra',
  657 + 'MYRIAD PRO',
  658 + 'Marlett',
  659 + 'Meiryo UI',
  660 + 'Microsoft Uighur',
  661 + 'Minion Pro',
  662 + 'Monotype Corsiva',
  663 + 'PMingLiU',
  664 + 'Pristina',
  665 + 'SCRIPTINA',
  666 + 'Segoe UI Light',
  667 + 'Serifa',
  668 + 'SimHei',
  669 + 'Small Fonts',
  670 + 'Staccato222 BT',
  671 + 'TRAJAN PRO',
  672 + 'Univers CE 55 Medium',
  673 + 'Vrinda',
  674 + 'ZWAdobeF',
  675 + ];
  676 + var fontSpanStyle = {
  677 + // CSS font reset to reset external styles
  678 + fontStyle: 'normal',
  679 + fontWeight: 'normal',
  680 + letterSpacing: 'normal',
  681 + lineBreak: 'auto',
  682 + lineHeight: 'normal',
  683 + textTransform: 'none',
  684 + textAlign: 'left',
  685 + textDecoration: 'none',
  686 + textShadow: 'none',
  687 + whiteSpace: 'normal',
  688 + wordBreak: 'normal',
  689 + wordSpacing: 'normal',
  690 + // We need this css as in some weird browser this span elements shows up for a microSec which creates
  691 + // a bad user experience
  692 + position: 'absolute',
  693 + left: '-9999px',
  694 + fontSize: testSize,
  695 + };
  696 + // kudos to http://www.lalit.org/lab/javascript-css-font-detect/
  697 + function getFonts() {
  698 + var h = d$2.body;
  699 + // div to load spans for the base fonts
  700 + var baseFontsDiv = d$2.createElement('div');
  701 + // div to load spans for the fonts to detect
  702 + var fontsDiv = d$2.createElement('div');
  703 + var defaultWidth = {};
  704 + var defaultHeight = {};
  705 + // creates a span where the fonts will be loaded
  706 + var createSpan = function () {
  707 + var span = d$2.createElement('span');
  708 + span.textContent = testString;
  709 + for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) {
  710 + var prop = _a[_i];
  711 + span.style[prop] = fontSpanStyle[prop];
  712 + }
  713 + return span;
  714 + };
  715 + // creates a span and load the font to detect and a base font for fallback
  716 + var createSpanWithFonts = function (fontToDetect, baseFont) {
  717 + var s = createSpan();
  718 + s.style.fontFamily = "'" + fontToDetect + "'," + baseFont;
  719 + return s;
  720 + };
  721 + // creates spans for the base fonts and adds them to baseFontsDiv
  722 + var initializeBaseFontsSpans = function () {
  723 + return baseFonts.map(function (baseFont) {
  724 + var s = createSpan();
  725 + s.style.fontFamily = baseFont;
  726 + baseFontsDiv.appendChild(s);
  727 + return s;
  728 + });
  729 + };
  730 + // creates spans for the fonts to detect and adds them to fontsDiv
  731 + var initializeFontsSpans = function () {
  732 + // Stores {fontName : [spans for that font]}
  733 + var spans = {};
  734 + var _loop_1 = function (font) {
  735 + spans[font] = baseFonts.map(function (baseFont) {
  736 + var s = createSpanWithFonts(font, baseFont);
  737 + fontsDiv.appendChild(s);
  738 + return s;
  739 + });
  740 + };
  741 + for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) {
  742 + var font = fontList_1[_i];
  743 + _loop_1(font);
  744 + }
  745 + return spans;
  746 + };
  747 + // checks if a font is available
  748 + var isFontAvailable = function (fontSpans) {
  749 + return baseFonts.some(function (baseFont, baseFontIndex) {
  750 + return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] ||
  751 + fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont];
  752 + });
  753 + };
  754 + // create spans for base fonts
  755 + var baseFontsSpans = initializeBaseFontsSpans();
  756 + // add the spans to the DOM
  757 + h.appendChild(baseFontsDiv);
  758 + // get the default width for the three base fonts
  759 + for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) {
  760 + defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font
  761 + defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font
  762 + }
  763 + // create spans for fonts to detect
  764 + var fontsSpans = initializeFontsSpans();
  765 + // add all the spans to the DOM
  766 + h.appendChild(fontsDiv);
  767 + // check available fonts
  768 + var available = [];
  769 + for (var i = 0, l = fontList.length; i < l; i++) {
  770 + if (isFontAvailable(fontsSpans[fontList[i]])) {
  771 + available.push(fontList[i]);
  772 + }
  773 + }
  774 + // remove spans from DOM
  775 + h.removeChild(fontsDiv);
  776 + h.removeChild(baseFontsDiv);
  777 + return available;
  778 + }
  779 +
  780 + function getPlugins() {
  781 + if (isTrident()) {
  782 + return [];
  783 + }
  784 + if (!navigator.plugins) {
  785 + return undefined;
  786 + }
  787 + var plugins = [];
  788 + // Safari 10 doesn't support iterating navigator.plugins with for...of
  789 + for (var i = 0; i < navigator.plugins.length; ++i) {
  790 + var plugin = navigator.plugins[i];
  791 + if (!plugin) {
  792 + continue;
  793 + }
  794 + var mimeTypes = [];
  795 + for (var j = 0; j < plugin.length; ++j) {
  796 + var mimeType = plugin[j];
  797 + mimeTypes.push({
  798 + type: mimeType.type,
  799 + suffixes: mimeType.suffixes,
  800 + });
  801 + }
  802 + plugins.push({
  803 + name: plugin.name,
  804 + description: plugin.description,
  805 + mimeTypes: mimeTypes,
  806 + });
  807 + }
  808 + return plugins;
  809 + }
  810 +
  811 + function makeCanvasContext() {
  812 + var canvas = document.createElement('canvas');
  813 + canvas.width = 240;
  814 + canvas.height = 140;
  815 + canvas.style.display = 'inline';
  816 + return [canvas, canvas.getContext('2d')];
  817 + }
  818 + function isSupported(canvas, context) {
  819 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  820 + return !!(context && canvas.toDataURL);
  821 + }
  822 + function save(canvas) {
  823 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  824 + return canvas.toDataURL();
  825 + }
  826 + // https://www.browserleaks.com/canvas#how-does-it-work
  827 + function getCanvasFingerprint() {
  828 + var _a = makeCanvasContext(), canvas = _a[0], context = _a[1];
  829 + if (!isSupported(canvas, context)) {
  830 + return { winding: false, data: '' };
  831 + }
  832 + // detect browser support of canvas winding
  833 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  834 + // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js
  835 + context.rect(0, 0, 10, 10);
  836 + context.rect(2, 2, 6, 6);
  837 + var winding = !context.isPointInPath(5, 5, 'evenodd');
  838 + context.textBaseline = 'alphabetic';
  839 + context.fillStyle = '#f60';
  840 + context.fillRect(125, 1, 62, 20);
  841 + context.fillStyle = '#069';
  842 + // https://github.com/Valve/fingerprintjs2/issues/66
  843 + // this can affect FP generation when applying different CSS on different websites
  844 + context.font = '11pt no-real-font-123';
  845 + // the choice of emojis has a gigantic impact on rendering performance (especially in FF)
  846 + // some newer emojis cause it to slow down 50-200 times
  847 + // context.fillText("Cw爨m fjordbank \ud83d\ude03 gly", 2, 15)
  848 + var printedText = 'Cwm fjordbank \ud83d\ude03 gly';
  849 + context.fillText(printedText, 2, 15);
  850 + context.fillStyle = 'rgba(102, 204, 0, 0.2)';
  851 + context.font = '18pt Arial';
  852 + context.fillText(printedText, 4, 45);
  853 + // canvas blending
  854 + // http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
  855 + // http://jsfiddle.net/NDYV8/16/
  856 + context.globalCompositeOperation = 'multiply';
  857 + context.fillStyle = 'rgb(255,0,255)';
  858 + context.beginPath();
  859 + context.arc(50, 50, 50, 0, Math.PI * 2, true);
  860 + context.closePath();
  861 + context.fill();
  862 + context.fillStyle = 'rgb(0,255,255)';
  863 + context.beginPath();
  864 + context.arc(100, 50, 50, 0, Math.PI * 2, true);
  865 + context.closePath();
  866 + context.fill();
  867 + context.fillStyle = 'rgb(255,255,0)';
  868 + context.beginPath();
  869 + context.arc(75, 100, 50, 0, Math.PI * 2, true);
  870 + context.closePath();
  871 + context.fill();
  872 + context.fillStyle = 'rgb(255,0,255)';
  873 + // canvas winding
  874 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  875 + // http://jsfiddle.net/NDYV8/19/
  876 + context.arc(75, 75, 75, 0, Math.PI * 2, true);
  877 + context.arc(75, 75, 25, 0, Math.PI * 2, true);
  878 + context.fill('evenodd');
  879 + return {
  880 + winding: winding,
  881 + data: save(canvas),
  882 + };
  883 + }
  884 +
  885 + var n$1 = navigator;
  886 + var w$2 = window;
  887 + /**
  888 + * This is a crude and primitive touch screen detection. It's not possible to currently reliably detect the availability
  889 + * of a touch screen with a JS, without actually subscribing to a touch event.
  890 + *
  891 + * @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
  892 + * @see https://github.com/Modernizr/Modernizr/issues/548
  893 + */
  894 + function getTouchSupport() {
  895 + var maxTouchPoints = 0;
  896 + var touchEvent;
  897 + if (n$1.maxTouchPoints !== undefined) {
  898 + maxTouchPoints = toInt(n$1.maxTouchPoints);
  899 + }
  900 + else if (n$1.msMaxTouchPoints !== undefined) {
  901 + maxTouchPoints = n$1.msMaxTouchPoints;
  902 + }
  903 + try {
  904 + document.createEvent('TouchEvent');
  905 + touchEvent = true;
  906 + }
  907 + catch (_) {
  908 + touchEvent = false;
  909 + }
  910 + var touchStart = 'ontouchstart' in w$2;
  911 + return {
  912 + maxTouchPoints: maxTouchPoints,
  913 + touchEvent: touchEvent,
  914 + touchStart: touchStart,
  915 + };
  916 + }
  917 +
  918 + function getOsCpu() {
  919 + return navigator.oscpu;
  920 + }
  921 +
  922 + var n$2 = navigator;
  923 + function getLanguages() {
  924 + var result = [];
  925 + var language = n$2.language || n$2.userLanguage || n$2.browserLanguage || n$2.systemLanguage;
  926 + if (language !== undefined) {
  927 + result.push([language]);
  928 + }
  929 + if (Array.isArray(n$2.languages)) {
  930 + // Starting from Chromium 86, there is only a single value in `navigator.language` in Incognito mode:
  931 + // the value of `navigator.language`. Therefore the value is ignored in this browser.
  932 + if (!(isChromium() && isChromium86OrNewer())) {
  933 + result.push(n$2.languages);
  934 + }
  935 + }
  936 + else if (typeof n$2.languages === 'string') {
  937 + var languages = n$2.languages;
  938 + if (languages) {
  939 + result.push(languages.split(','));
  940 + }
  941 + }
  942 + return result;
  943 + }
  944 +
  945 + function getColorDepth() {
  946 + return window.screen.colorDepth;
  947 + }
  948 +
  949 + function getDeviceMemory() {
  950 + return navigator.deviceMemory;
  951 + }
  952 +
  953 + var w$3 = window;
  954 + function getScreenResolution() {
  955 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  956 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  957 + var dimensions = [toInt(w$3.screen.width), toInt(w$3.screen.height)];
  958 + dimensions.sort().reverse();
  959 + return dimensions;
  960 + }
  961 +
  962 + var w$4 = window;
  963 + function getAvailableScreenResolution() {
  964 + if (w$4.screen.availWidth && w$4.screen.availHeight) {
  965 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  966 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  967 + var dimensions = [toInt(w$4.screen.availWidth), toInt(w$4.screen.availHeight)];
  968 + dimensions.sort().reverse();
  969 + return dimensions;
  970 + }
  971 + return undefined;
  972 + }
  973 +
  974 + function getHardwareConcurrency() {
  975 + try {
  976 + // sometimes hardware concurrency is a string
  977 + var concurrency = toInt(navigator.hardwareConcurrency);
  978 + return isNaN(concurrency) ? 1 : concurrency;
  979 + }
  980 + catch (e) {
  981 + return 1;
  982 + }
  983 + }
  984 +
  985 + function getTimezoneOffset() {
  986 + var currentYear = new Date().getFullYear();
  987 + // The timezone offset may change over time due to daylight saving time (DST) shifts.
  988 + // The non-DST timezone offset is used as the result timezone offset.
  989 + // Since the DST season differs in the northern and the southern hemispheres,
  990 + // both January and July timezones offsets are considered.
  991 + return Math.max(
  992 + // `getTimezoneOffset` returns a number as a string in some unidentified cases
  993 + toFloat(new Date(currentYear, 0, 1).getTimezoneOffset()), toFloat(new Date(currentYear, 6, 1).getTimezoneOffset()));
  994 + }
  995 +
  996 + var w$5 = window;
  997 + function getTimezone() {
  998 + var _a;
  999 + if ((_a = w$5.Intl) === null || _a === void 0 ? void 0 : _a.DateTimeFormat) {
  1000 + return new w$5.Intl.DateTimeFormat().resolvedOptions().timeZone;
  1001 + }
  1002 + return undefined;
  1003 + }
  1004 +
  1005 + function getSessionStorage() {
  1006 + try {
  1007 + return !!window.sessionStorage;
  1008 + }
  1009 + catch (error) {
  1010 + /* SecurityError when referencing it means it exists */
  1011 + return true;
  1012 + }
  1013 + }
  1014 +
  1015 + // https://bugzilla.mozilla.org/show_bug.cgi?id=781447
  1016 + function getLocalStorage() {
  1017 + try {
  1018 + return !!window.localStorage;
  1019 + }
  1020 + catch (e) {
  1021 + /* SecurityError when referencing it means it exists */
  1022 + return true;
  1023 + }
  1024 + }
  1025 +
  1026 + function getIndexedDB() {
  1027 + // IE and Edge don't allow accessing indexedDB in private mode, therefore IE and Edge will have different
  1028 + // visitor identifier in normal and private modes.
  1029 + if (isTrident() || isEdgeHTML()) {
  1030 + return undefined;
  1031 + }
  1032 + try {
  1033 + return !!window.indexedDB;
  1034 + }
  1035 + catch (e) {
  1036 + /* SecurityError when referencing it means it exists */
  1037 + return true;
  1038 + }
  1039 + }
  1040 +
  1041 + function getOpenDatabase() {
  1042 + return !!window.openDatabase;
  1043 + }
  1044 +
  1045 + function getCpuClass() {
  1046 + return navigator.cpuClass;
  1047 + }
  1048 +
  1049 + function getPlatform() {
  1050 + return navigator.platform;
  1051 + }
  1052 +
  1053 + function getPluginsSupport() {
  1054 + return navigator.plugins !== undefined;
  1055 + }
  1056 +
  1057 + function getProductSub() {
  1058 + return navigator.productSub;
  1059 + }
  1060 +
  1061 + function getEmptyEvalLength() {
  1062 + return eval.toString().length;
  1063 + }
  1064 +
  1065 + function getErrorFF() {
  1066 + try {
  1067 + throw 'a';
  1068 + }
  1069 + catch (e) {
  1070 + try {
  1071 + e.toSource();
  1072 + return true;
  1073 + }
  1074 + catch (e2) {
  1075 + return false;
  1076 + }
  1077 + }
  1078 + }
  1079 +
  1080 + function getVendor() {
  1081 + return navigator.vendor;
  1082 + }
  1083 +
  1084 + function getChrome() {
  1085 + return window.chrome !== undefined;
  1086 + }
  1087 +
  1088 + var d$3 = document;
  1089 + /**
  1090 + * navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1091 + * cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past with
  1092 + * site-specific exceptions. Don't rely on it.
  1093 + *
  1094 + * @see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js Taken from here
  1095 + */
  1096 + function areCookiesEnabled() {
  1097 + // Taken from here: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js
  1098 + // navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1099 + // cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past
  1100 + // with site-specific exceptions. Don't rely on it.
  1101 + // try..catch because some in situations `document.cookie` is exposed but throws a
  1102 + // SecurityError if you try to access it; e.g. documents created from data URIs
  1103 + // or in sandboxed iframes (depending on flags/context)
  1104 + try {
  1105 + // Create cookie
  1106 + d$3.cookie = 'cookietest=1';
  1107 + var result = d$3.cookie.indexOf('cookietest=') !== -1;
  1108 + // Delete cookie
  1109 + d$3.cookie = 'cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT';
  1110 + return result;
  1111 + }
  1112 + catch (e) {
  1113 + return false;
  1114 + }
  1115 + }
  1116 +
  1117 + /**
  1118 + * The list of entropy sources used to make visitor identifiers.
  1119 + *
  1120 + * This value isn't restricted by Semantic Versioning, i.e. it may be changed without bumping minor or major version of
  1121 + * this package.
  1122 + */
  1123 + var sources = {
  1124 + // Expected errors and default values must be handled inside the functions. Unexpected errors must be thrown.
  1125 + osCpu: getOsCpu,
  1126 + languages: getLanguages,
  1127 + colorDepth: getColorDepth,
  1128 + deviceMemory: getDeviceMemory,
  1129 + screenResolution: getScreenResolution,
  1130 + availableScreenResolution: getAvailableScreenResolution,
  1131 + hardwareConcurrency: getHardwareConcurrency,
  1132 + timezoneOffset: getTimezoneOffset,
  1133 + timezone: getTimezone,
  1134 + sessionStorage: getSessionStorage,
  1135 + localStorage: getLocalStorage,
  1136 + indexedDB: getIndexedDB,
  1137 + openDatabase: getOpenDatabase,
  1138 + cpuClass: getCpuClass,
  1139 + // Maybe it should be excluded: https://github.com/fingerprintjs/fingerprintjs/issues/514#issuecomment-688754892
  1140 + platform: getPlatform,
  1141 + plugins: getPlugins,
  1142 + canvas: getCanvasFingerprint,
  1143 + // adBlock: isAdblockUsed, // https://github.com/fingerprintjs/fingerprintjs/issues/405
  1144 + touchSupport: getTouchSupport,
  1145 + fonts: getFonts,
  1146 + audio: getAudioFingerprint,
  1147 + pluginsSupport: getPluginsSupport,
  1148 + productSub: getProductSub,
  1149 + emptyEvalLength: getEmptyEvalLength,
  1150 + errorFF: getErrorFF,
  1151 + vendor: getVendor,
  1152 + chrome: getChrome,
  1153 + cookiesEnabled: areCookiesEnabled,
  1154 + };
  1155 + /**
  1156 + * Gets a components list from the given list of entropy sources.
  1157 + *
  1158 + * Warning for package users:
  1159 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  1160 + */
  1161 + function getComponents(sources, sourceOptions, excludeSources) {
  1162 + return __awaiter(this, void 0, void 0, function () {
  1163 + var timestamp, components, _i, _a, sourceKey, result, error_1, nextTimestamp;
  1164 + var _b;
  1165 + return __generator(this, function (_c) {
  1166 + switch (_c.label) {
  1167 + case 0:
  1168 + timestamp = Date.now();
  1169 + components = {};
  1170 + _i = 0, _a = Object.keys(sources);
  1171 + _c.label = 1;
  1172 + case 1:
  1173 + if (!(_i < _a.length)) return [3 /*break*/, 7];
  1174 + sourceKey = _a[_i];
  1175 + if (!excludes(excludeSources, sourceKey)) {
  1176 + return [3 /*break*/, 6];
  1177 + }
  1178 + result = void 0;
  1179 + _c.label = 2;
  1180 + case 2:
  1181 + _c.trys.push([2, 4, , 5]);
  1182 + _b = {};
  1183 + return [4 /*yield*/, sources[sourceKey](sourceOptions)];
  1184 + case 3:
  1185 + result = (_b.value = _c.sent(), _b);
  1186 + return [3 /*break*/, 5];
  1187 + case 4:
  1188 + error_1 = _c.sent();
  1189 + result = error_1 && typeof error_1 === 'object' && 'message' in error_1 ? { error: error_1 } : { error: { message: error_1 } };
  1190 + return [3 /*break*/, 5];
  1191 + case 5:
  1192 + nextTimestamp = Date.now();
  1193 + components[sourceKey] = __assign(__assign({}, result), { duration: nextTimestamp - timestamp }); // TypeScript has beaten me here
  1194 + timestamp = nextTimestamp;
  1195 + _c.label = 6;
  1196 + case 6:
  1197 + _i++;
  1198 + return [3 /*break*/, 1];
  1199 + case 7: return [2 /*return*/, components];
  1200 + }
  1201 + });
  1202 + });
  1203 + }
  1204 + /**
  1205 + * Collects entropy components from the built-in sources to make the visitor identifier.
  1206 + */
  1207 + function getBuiltinComponents() {
  1208 + return getComponents(sources, undefined, []);
  1209 + }
  1210 +
  1211 + function componentsToCanonicalString(components) {
  1212 + var result = '';
  1213 + for (var _i = 0, _a = Object.keys(components); _i < _a.length; _i++) {
  1214 + var componentKey = _a[_i];
  1215 + var component = components[componentKey];
  1216 + var value = component.error ? 'error' : JSON.stringify(component.value);
  1217 + result += "" + (result ? '|' : '') + componentKey.replace(/([:|\\])/g, '\\$1') + ":" + value;
  1218 + }
  1219 + return result;
  1220 + }
  1221 + function componentsToDebugString(components) {
  1222 + return JSON.stringify(components, function (_key, value) {
  1223 + var _a;
  1224 + if (value instanceof Error) {
  1225 + return __assign(__assign({}, value), { message: value.message, stack: (_a = value.stack) === null || _a === void 0 ? void 0 : _a.split('\n') });
  1226 + }
  1227 + return value;
  1228 + }, 2);
  1229 + }
  1230 + function hashComponents(components) {
  1231 + return x64hash128(componentsToCanonicalString(components));
  1232 + }
  1233 + /**
  1234 + * Makes a GetResult implementation that calculates the visitor id hash on demand.
  1235 + * Designed for optimisation.
  1236 + */
  1237 + function makeLazyGetResult(components) {
  1238 + var visitorIdCache;
  1239 + // A plain class isn't used because its getters and setters aren't enumerable.
  1240 + return {
  1241 + components: components,
  1242 + get visitorId() {
  1243 + if (visitorIdCache === undefined) {
  1244 + visitorIdCache = hashComponents(this.components);
  1245 + }
  1246 + return visitorIdCache;
  1247 + },
  1248 + set visitorId(visitorId) {
  1249 + visitorIdCache = visitorId;
  1250 + },
  1251 + };
  1252 + }
  1253 + /**
  1254 + * The class isn't exported from the index file to not expose the constructor.
  1255 + * The hiding gives more freedom for future non-breaking updates.
  1256 + */
  1257 + var OpenAgent = /** @class */ (function () {
  1258 + function OpenAgent() {
  1259 + }
  1260 + /**
  1261 + * @inheritDoc
  1262 + */
  1263 + OpenAgent.prototype.get = function (options) {
  1264 + if (options === void 0) { options = {}; }
  1265 + return __awaiter(this, void 0, void 0, function () {
  1266 + var components, result;
  1267 + return __generator(this, function (_a) {
  1268 + switch (_a.label) {
  1269 + case 0: return [4 /*yield*/, getBuiltinComponents()];
  1270 + case 1:
  1271 + components = _a.sent();
  1272 + result = makeLazyGetResult(components);
  1273 + if (options.debug) {
  1274 + // console.log is ok here because it's under a debug clause
  1275 + // eslint-disable-next-line no-console
  1276 + console.log("Copy the text below to get the debug data:\n\n```\nversion: " + version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```");
  1277 + }
  1278 + return [2 /*return*/, result];
  1279 + }
  1280 + });
  1281 + });
  1282 + };
  1283 + return OpenAgent;
  1284 + }());
  1285 + /**
  1286 + * Builds an instance of Agent and waits a delay required for a proper operation.
  1287 + */
  1288 + function load(_a) {
  1289 + var _b = (_a === void 0 ? {} : _a).delayFallback, delayFallback = _b === void 0 ? 50 : _b;
  1290 + return __awaiter(this, void 0, void 0, function () {
  1291 + return __generator(this, function (_c) {
  1292 + switch (_c.label) {
  1293 + case 0:
  1294 + // A delay is required to ensure consistent entropy components.
  1295 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1296 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1297 + return [4 /*yield*/, requestIdleCallbackIfAvailable(delayFallback)];
  1298 + case 1:
  1299 + // A delay is required to ensure consistent entropy components.
  1300 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1301 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1302 + _c.sent();
  1303 + return [2 /*return*/, new OpenAgent()];
  1304 + }
  1305 + });
  1306 + });
  1307 + }
  1308 +
  1309 + // The default export is a syntax sugar (`import * as FP from '...' → import FP from '...'`).
  1310 + // It should contain all the public exported values.
  1311 + var index = { load: load, hashComponents: hashComponents, componentsToDebugString: componentsToDebugString };
  1312 + // The exports below are for private usage. They may change unexpectedly. Use them at your own risk.
  1313 + /** Not documented, out of Semantic Versioning, usage is at your own risk */
  1314 + var murmurX64Hash128 = x64hash128;
  1315 +
  1316 + exports.componentsToDebugString = componentsToDebugString;
  1317 + exports.default = index;
  1318 + exports.getComponents = getComponents;
  1319 + exports.hashComponents = hashComponents;
  1320 + exports.isChromium = isChromium;
  1321 + exports.isDesktopSafari = isDesktopSafari;
  1322 + exports.isEdgeHTML = isEdgeHTML;
  1323 + exports.isGecko = isGecko;
  1324 + exports.isTrident = isTrident;
  1325 + exports.isWebKit = isWebKit;
  1326 + exports.load = load;
  1327 + exports.murmurX64Hash128 = murmurX64Hash128;
  1328 +
  1329 + return exports;
  1330 +
  1331 +}({}));
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +var FingerprintJS=function(e){"use strict";function t(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var n=[0,0,0,0];return n[3]+=e[3]+t[3],n[2]+=n[3]>>>16,n[3]&=65535,n[2]+=e[2]+t[2],n[1]+=n[2]>>>16,n[2]&=65535,n[1]+=e[1]+t[1],n[0]+=n[1]>>>16,n[1]&=65535,n[0]+=e[0]+t[0],n[0]&=65535,[n[0]<<16|n[1],n[2]<<16|n[3]]}function n(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var n=[0,0,0,0];return n[3]+=e[3]*t[3],n[2]+=n[3]>>>16,n[3]&=65535,n[2]+=e[2]*t[3],n[1]+=n[2]>>>16,n[2]&=65535,n[2]+=e[3]*t[2],n[1]+=n[2]>>>16,n[2]&=65535,n[1]+=e[1]*t[3],n[0]+=n[1]>>>16,n[1]&=65535,n[1]+=e[2]*t[2],n[0]+=n[1]>>>16,n[1]&=65535,n[1]+=e[3]*t[1],n[0]+=n[1]>>>16,n[1]&=65535,n[0]+=e[0]*t[3]+e[1]*t[2]+e[2]*t[1]+e[3]*t[0],n[0]&=65535,[n[0]<<16|n[1],n[2]<<16|n[3]]}function r(e,t){return 32===(t%=64)?[e[1],e[0]]:t<32?[e[0]<<t|e[1]>>>32-t,e[1]<<t|e[0]>>>32-t]:(t-=32,[e[1]<<t|e[0]>>>32-t,e[0]<<t|e[1]>>>32-t])}function o(e,t){return 0===(t%=64)?e:t<32?[e[0]<<t|e[1]>>>32-t,e[1]<<t]:[e[1]<<t-32,0]}function i(e,t){return[e[0]^t[0],e[1]^t[1]]}function a(e){return e=i(e,[0,e[0]>>>1]),e=i(e=n(e,[4283543511,3981806797]),[0,e[0]>>>1]),e=i(e=n(e,[3301882366,444984403]),[0,e[0]>>>1])}function c(e,c){c=c||0;var u,s=(e=e||"").length%16,l=e.length-s,f=[0,c],d=[0,c],h=[0,0],v=[0,0],g=[2277735313,289559509],p=[1291169091,658871167];for(u=0;u<l;u+=16)h=[255&e.charCodeAt(u+4)|(255&e.charCodeAt(u+5))<<8|(255&e.charCodeAt(u+6))<<16|(255&e.charCodeAt(u+7))<<24,255&e.charCodeAt(u)|(255&e.charCodeAt(u+1))<<8|(255&e.charCodeAt(u+2))<<16|(255&e.charCodeAt(u+3))<<24],v=[255&e.charCodeAt(u+12)|(255&e.charCodeAt(u+13))<<8|(255&e.charCodeAt(u+14))<<16|(255&e.charCodeAt(u+15))<<24,255&e.charCodeAt(u+8)|(255&e.charCodeAt(u+9))<<8|(255&e.charCodeAt(u+10))<<16|(255&e.charCodeAt(u+11))<<24],h=r(h=n(h,g),31),f=t(f=r(f=i(f,h=n(h,p)),27),d),f=t(n(f,[0,5]),[0,1390208809]),v=r(v=n(v,p),33),d=t(d=r(d=i(d,v=n(v,g)),31),f),d=t(n(d,[0,5]),[0,944331445]);switch(h=[0,0],v=[0,0],s){case 15:v=i(v,o([0,e.charCodeAt(u+14)],48));case 14:v=i(v,o([0,e.charCodeAt(u+13)],40));case 13:v=i(v,o([0,e.charCodeAt(u+12)],32));case 12:v=i(v,o([0,e.charCodeAt(u+11)],24));case 11:v=i(v,o([0,e.charCodeAt(u+10)],16));case 10:v=i(v,o([0,e.charCodeAt(u+9)],8));case 9:v=n(v=i(v,[0,e.charCodeAt(u+8)]),p),d=i(d,v=n(v=r(v,33),g));case 8:h=i(h,o([0,e.charCodeAt(u+7)],56));case 7:h=i(h,o([0,e.charCodeAt(u+6)],48));case 6:h=i(h,o([0,e.charCodeAt(u+5)],40));case 5:h=i(h,o([0,e.charCodeAt(u+4)],32));case 4:h=i(h,o([0,e.charCodeAt(u+3)],24));case 3:h=i(h,o([0,e.charCodeAt(u+2)],16));case 2:h=i(h,o([0,e.charCodeAt(u+1)],8));case 1:h=n(h=i(h,[0,e.charCodeAt(u)]),g),f=i(f,h=n(h=r(h,31),p))}return f=t(f=i(f,[0,e.length]),d=i(d,[0,e.length])),d=t(d,f),f=t(f=a(f),d=a(d)),d=t(d,f),("00000000"+(f[0]>>>0).toString(16)).slice(-8)+("00000000"+(f[1]>>>0).toString(16)).slice(-8)+("00000000"+(d[0]>>>0).toString(16)).slice(-8)+("00000000"+(d[1]>>>0).toString(16)).slice(-8)}var u=function(){return(u=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};function s(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(t){i(t)}}function c(e){try{u(r.throw(e))}catch(t){i(t)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,c)}u((r=r.apply(e,t||[])).next())}))}function l(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(c){i=[6,c],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}function f(e){return"number"==typeof e?0|e:parseInt(e)}function d(e){return"number"==typeof e?e:parseFloat(e)}function h(e){return e.reduce((function(e,t){return e+(t?1:0)}),0)}var v=window,g=navigator,p=document;function m(){return h(["MSCSSMatrix"in v,"msSetImmediate"in v,"msIndexedDB"in v,"msMaxTouchPoints"in g,"msPointerEnabled"in g])>=4}function y(){return h(["msWriteProfilerMark"in v,"MSStream"in v,"msLaunchUri"in g,"msSaveBlob"in g])>=3&&!m()}function w(){return h(["webkitPersistentStorage"in g,"webkitTemporaryStorage"in g,0===g.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in v,"BatteryManager"in v,"webkitMediaStream"in v,"webkitSpeechGrammar"in v])>=5}function b(){return h(["ApplePayError"in v,"CSSPrimitiveValue"in v,"Counter"in v,0===g.vendor.indexOf("Apple"),"getStorageUpdates"in g,"WebKitMediaKeys"in v])>=4}function S(){return h(["safari"in v,!("DeviceMotionEvent"in v),!("ongestureend"in v),!("standalone"in g)])>=3}var C=window,A=document;function M(e,t,n){(function(e){return e&&"function"==typeof e.setValueAtTime})(t)&&t.setValueAtTime(n,e.currentTime)}function T(e){return new Promise((function(t,n){e.oncomplete=function(e){return t(e.renderedBuffer)};var r=3,o=function(){switch(e.startRendering(),e.state){case"running":setTimeout((function(){return n(x("timeout"))}),1e3);break;case"suspended":A.hidden||r--,r>0?setTimeout(o,500):n(x("suspended"))}};o()}))}function k(e){for(var t=0,n=4500;n<5e3;++n)t+=Math.abs(e[n]);return t}function x(e){var t=new Error(e);return t.name=e,t}var P=document,I=["monospace","sans-serif","serif"],O=["sans-serif-thin","ARNO PRO","Agency FB","Arabic Typesetting","Arial Unicode MS","AvantGarde Bk BT","BankGothic Md BT","Batang","Bitstream Vera Sans Mono","Calibri","Century","Century Gothic","Clarendon","EUROSTILE","Franklin Gothic","Futura Bk BT","Futura Md BT","GOTHAM","Gill Sans","HELV","Haettenschweiler","Helvetica Neue","Humanst521 BT","Leelawadee","Letter Gothic","Levenim MT","Lucida Bright","Lucida Sans","Menlo","MS Mincho","MS Outlook","MS Reference Specialty","MS UI Gothic","MT Extra","MYRIAD PRO","Marlett","Meiryo UI","Microsoft Uighur","Minion Pro","Monotype Corsiva","PMingLiU","Pristina","SCRIPTINA","Segoe UI Light","Serifa","SimHei","Small Fonts","Staccato222 BT","TRAJAN PRO","Univers CE 55 Medium","Vrinda","ZWAdobeF"],E={fontStyle:"normal",fontWeight:"normal",letterSpacing:"normal",lineBreak:"auto",lineHeight:"normal",textTransform:"none",textAlign:"left",textDecoration:"none",textShadow:"none",whiteSpace:"normal",wordBreak:"normal",wordSpacing:"normal",position:"absolute",left:"-9999px",fontSize:"48px"};function D(e){return e.toDataURL()}var R=navigator,B=window;var L=navigator;var F=window;var G=window;var H=window;var U=document;var W={osCpu:function(){return navigator.oscpu},languages:function(){var e=[],t=L.language||L.userLanguage||L.browserLanguage||L.systemLanguage;if(void 0!==t&&e.push([t]),Array.isArray(L.languages))w()&&h([!("MediaSettingsRange"in v),"RTCEncodedAudioFrame"in v,""+v.Intl=="[object Intl]",""+v.Reflect=="[object Reflect]"])>=3||e.push(L.languages);else if("string"==typeof L.languages){var n=L.languages;n&&e.push(n.split(","))}return e},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return navigator.deviceMemory},screenResolution:function(){var e=[f(F.screen.width),f(F.screen.height)];return e.sort().reverse(),e},availableScreenResolution:function(){if(G.screen.availWidth&&G.screen.availHeight){var e=[f(G.screen.availWidth),f(G.screen.availHeight)];return e.sort().reverse(),e}},hardwareConcurrency:function(){try{var e=f(navigator.hardwareConcurrency);return isNaN(e)?1:e}catch(t){return 1}},timezoneOffset:function(){var e=(new Date).getFullYear();return Math.max(d(new Date(e,0,1).getTimezoneOffset()),d(new Date(e,6,1).getTimezoneOffset()))},timezone:function(){var e;if(null===(e=H.Intl)||void 0===e?void 0:e.DateTimeFormat)return(new H.Intl.DateTimeFormat).resolvedOptions().timeZone},sessionStorage:function(){try{return!!window.sessionStorage}catch(e){return!0}},localStorage:function(){try{return!!window.localStorage}catch(e){return!0}},indexedDB:function(){if(!m()&&!y())try{return!!window.indexedDB}catch(e){return!0}},openDatabase:function(){return!!window.openDatabase},cpuClass:function(){return navigator.cpuClass},platform:function(){return navigator.platform},plugins:function(){if(m())return[];if(navigator.plugins){for(var e=[],t=0;t<navigator.plugins.length;++t){var n=navigator.plugins[t];if(n){for(var r=[],o=0;o<n.length;++o){var i=n[o];r.push({type:i.type,suffixes:i.suffixes})}e.push({name:n.name,description:n.description,mimeTypes:r})}}return e}},canvas:function(){var e=function(){var e=document.createElement("canvas");return e.width=240,e.height=140,e.style.display="inline",[e,e.getContext("2d")]}(),t=e[0],n=e[1];if(!function(e,t){return!(!t||!e.toDataURL)}(t,n))return{winding:!1,data:""};n.rect(0,0,10,10),n.rect(2,2,6,6);var r=!n.isPointInPath(5,5,"evenodd");n.textBaseline="alphabetic",n.fillStyle="#f60",n.fillRect(125,1,62,20),n.fillStyle="#069",n.font="11pt no-real-font-123";var o="Cwm fjordbank 😃 gly";return n.fillText(o,2,15),n.fillStyle="rgba(102, 204, 0, 0.2)",n.font="18pt Arial",n.fillText(o,4,45),n.globalCompositeOperation="multiply",n.fillStyle="rgb(255,0,255)",n.beginPath(),n.arc(50,50,50,0,2*Math.PI,!0),n.closePath(),n.fill(),n.fillStyle="rgb(0,255,255)",n.beginPath(),n.arc(100,50,50,0,2*Math.PI,!0),n.closePath(),n.fill(),n.fillStyle="rgb(255,255,0)",n.beginPath(),n.arc(75,100,50,0,2*Math.PI,!0),n.closePath(),n.fill(),n.fillStyle="rgb(255,0,255)",n.arc(75,75,75,0,2*Math.PI,!0),n.arc(75,75,25,0,2*Math.PI,!0),n.fill("evenodd"),{winding:r,data:D(t)}},touchSupport:function(){var e,t=0;void 0!==R.maxTouchPoints?t=f(R.maxTouchPoints):void 0!==R.msMaxTouchPoints&&(t=R.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(n){e=!1}return{maxTouchPoints:t,touchEvent:e,touchStart:"ontouchstart"in B}},fonts:function(){var e=P.body,t=P.createElement("div"),n=P.createElement("div"),r={},o={},i=function(){var e=P.createElement("span");e.textContent="mmMwWLliI0O&1";for(var t=0,n=Object.keys(E);t<n.length;t++){var r=n[t];e.style[r]=E[r]}return e},a=function(e){return I.some((function(t,n){return e[n].offsetWidth!==r[t]||e[n].offsetHeight!==o[t]}))},c=I.map((function(e){var n=i();return n.style.fontFamily=e,t.appendChild(n),n}));e.appendChild(t);for(var u=0,s=I.length;u<s;u++)r[I[u]]=c[u].offsetWidth,o[I[u]]=c[u].offsetHeight;var l=function(){for(var e={},t=function(t){e[t]=I.map((function(e){var r=function(e,t){var n=i();return n.style.fontFamily="'"+e+"',"+t,n}(t,e);return n.appendChild(r),r}))},r=0,o=O;r<o.length;r++){t(o[r])}return e}();e.appendChild(n);for(var f=[],d=0,h=O.length;d<h;d++)a(l[O[d]])&&f.push(O[d]);return e.removeChild(n),e.removeChild(t),f},audio:function(){return s(this,void 0,void 0,(function(){var e,t,n,r,o,i;return l(this,(function(a){switch(a.label){case 0:if(b()&&!S()&&!(h(["DOMRectList"in v,"RTCPeerConnectionIceEvent"in v,"SVGGeometryElement"in v,"ontransitioncancel"in v])>=3))return[2,-1];if(!(e=C.OfflineAudioContext||C.webkitOfflineAudioContext))return[2,-2];t=new e(1,44100,44100),(n=t.createOscillator()).type="triangle",M(t,n.frequency,1e4),r=t.createDynamicsCompressor(),M(t,r.threshold,-50),M(t,r.knee,40),M(t,r.ratio,12),M(t,r.reduction,-20),M(t,r.attack,0),M(t,r.release,.25),n.connect(r),r.connect(t.destination),n.start(0),a.label=1;case 1:return a.trys.push([1,3,4,5]),[4,T(t)];case 2:return o=a.sent(),[3,5];case 3:if("timeout"===(i=a.sent()).name||"suspended"===i.name)return[2,-3];throw i;case 4:return n.disconnect(),r.disconnect(),[7];case 5:return[2,k(o.getChannelData(0))]}}))}))},pluginsSupport:function(){return void 0!==navigator.plugins},productSub:function(){return navigator.productSub},emptyEvalLength:function(){return eval.toString().length},errorFF:function(){try{throw"a"}catch(e){try{return e.toSource(),!0}catch(t){return!1}}},vendor:function(){return navigator.vendor},chrome:function(){return void 0!==window.chrome},cookiesEnabled:function(){try{U.cookie="cookietest=1";var e=-1!==U.cookie.indexOf("cookietest=");return U.cookie="cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT",e}catch(t){return!1}}};function j(e,t,n){return s(this,void 0,void 0,(function(){var r,o,i,a,c,s,f,d,h;return l(this,(function(l){switch(l.label){case 0:r=Date.now(),o={},i=0,a=Object.keys(e),l.label=1;case 1:if(!(i<a.length))return[3,7];if(c=a[i],function(e,t){for(var n=0,r=e.length;n<r;++n)if(e[n]===t)return!0;return!1}(n,c))return[3,6];s=void 0,l.label=2;case 2:return l.trys.push([2,4,,5]),h={},[4,e[c](t)];case 3:return h.value=l.sent(),s=h,[3,5];case 4:return f=l.sent(),s=f&&"object"==typeof f&&"message"in f?{error:f}:{error:{message:f}},[3,5];case 5:d=Date.now(),o[c]=u(u({},s),{duration:d-r}),r=d,l.label=6;case 6:return i++,[3,1];case 7:return[2,o]}}))}))}function N(e){return JSON.stringify(e,(function(e,t){var n;return t instanceof Error?u(u({},t),{message:t.message,stack:null===(n=t.stack)||void 0===n?void 0:n.split("\n")}):t}),2)}function z(e){return c(function(e){for(var t="",n=0,r=Object.keys(e);n<r.length;n++){var o=r[n],i=e[o],a=i.error?"error":JSON.stringify(i.value);t+=(t?"|":"")+o.replace(/([:|\\])/g,"\\$1")+":"+a}return t}(e))}var V=function(){function e(){}return e.prototype.get=function(e){return void 0===e&&(e={}),s(this,void 0,void 0,(function(){var t,n;return l(this,(function(r){switch(r.label){case 0:return[4,j(W,void 0,[])];case 1:return t=r.sent(),n=function(e){var t;return{components:e,get visitorId(){return void 0===t&&(t=z(this.components)),t},set visitorId(e){t=e}}}(t),e.debug&&console.log("Copy the text below to get the debug data:\n\n```\nversion: 3.0.3\nuserAgent: "+navigator.userAgent+"\ngetOptions: "+JSON.stringify(e,void 0,2)+"\nvisitorId: "+n.visitorId+"\ncomponents: "+N(t)+"\n```"),[2,n]}}))}))},e}();function J(e){var t=(void 0===e?{}:e).delayFallback,n=void 0===t?50:t;return s(this,void 0,void 0,(function(){return l(this,(function(e){switch(e.label){case 0:return[4,(t=n,new Promise((function(e){window.requestIdleCallback?window.requestIdleCallback((function(){return e()})):setTimeout(e,t)})))];case 1:return e.sent(),[2,new V]}var t}))}))}var q={load:J,hashComponents:z,componentsToDebugString:N},K=c;return e.componentsToDebugString=N,e.default=q,e.getComponents=j,e.hashComponents=z,e.isChromium=w,e.isDesktopSafari=S,e.isEdgeHTML=y,e.isGecko=function(){var e;return h(["buildID"in g,(null===(e=p.documentElement)||void 0===e?void 0:e.style)&&"MozAppearance"in p.documentElement.style,"MediaRecorderErrorEvent"in v,"mozInnerScreenX"in v,"CSSMozDocumentRule"in v,"CanvasCaptureMediaStream"in v])>=4},e.isTrident=m,e.isWebKit=b,e.load=J,e.murmurX64Hash128=K,e}({});
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +(function (global, factory) {
  10 + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  11 + typeof define === 'function' && define.amd ? define(['exports'], factory) :
  12 + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FingerprintJS = {}));
  13 +}(this, (function (exports) { 'use strict';
  14 +
  15 + /*
  16 + * Taken from https://github.com/karanlyons/murmurHash3.js/blob/a33d0723127e2e5415056c455f8aed2451ace208/murmurHash3.js
  17 + */
  18 + //
  19 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  20 + // added together as a 64bit int (as an array of two 32bit ints).
  21 + //
  22 + function x64Add(m, n) {
  23 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  24 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  25 + var o = [0, 0, 0, 0];
  26 + o[3] += m[3] + n[3];
  27 + o[2] += o[3] >>> 16;
  28 + o[3] &= 0xffff;
  29 + o[2] += m[2] + n[2];
  30 + o[1] += o[2] >>> 16;
  31 + o[2] &= 0xffff;
  32 + o[1] += m[1] + n[1];
  33 + o[0] += o[1] >>> 16;
  34 + o[1] &= 0xffff;
  35 + o[0] += m[0] + n[0];
  36 + o[0] &= 0xffff;
  37 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  38 + }
  39 + //
  40 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  41 + // multiplied together as a 64bit int (as an array of two 32bit ints).
  42 + //
  43 + function x64Multiply(m, n) {
  44 + m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
  45 + n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
  46 + var o = [0, 0, 0, 0];
  47 + o[3] += m[3] * n[3];
  48 + o[2] += o[3] >>> 16;
  49 + o[3] &= 0xffff;
  50 + o[2] += m[2] * n[3];
  51 + o[1] += o[2] >>> 16;
  52 + o[2] &= 0xffff;
  53 + o[2] += m[3] * n[2];
  54 + o[1] += o[2] >>> 16;
  55 + o[2] &= 0xffff;
  56 + o[1] += m[1] * n[3];
  57 + o[0] += o[1] >>> 16;
  58 + o[1] &= 0xffff;
  59 + o[1] += m[2] * n[2];
  60 + o[0] += o[1] >>> 16;
  61 + o[1] &= 0xffff;
  62 + o[1] += m[3] * n[1];
  63 + o[0] += o[1] >>> 16;
  64 + o[1] &= 0xffff;
  65 + o[0] += m[0] * n[3] + m[1] * n[2] + m[2] * n[1] + m[3] * n[0];
  66 + o[0] &= 0xffff;
  67 + return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
  68 + }
  69 + //
  70 + // Given a 64bit int (as an array of two 32bit ints) and an int
  71 + // representing a number of bit positions, returns the 64bit int (as an
  72 + // array of two 32bit ints) rotated left by that number of positions.
  73 + //
  74 + function x64Rotl(m, n) {
  75 + n %= 64;
  76 + if (n === 32) {
  77 + return [m[1], m[0]];
  78 + }
  79 + else if (n < 32) {
  80 + return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))];
  81 + }
  82 + else {
  83 + n -= 32;
  84 + return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))];
  85 + }
  86 + }
  87 + //
  88 + // Given a 64bit int (as an array of two 32bit ints) and an int
  89 + // representing a number of bit positions, returns the 64bit int (as an
  90 + // array of two 32bit ints) shifted left by that number of positions.
  91 + //
  92 + function x64LeftShift(m, n) {
  93 + n %= 64;
  94 + if (n === 0) {
  95 + return m;
  96 + }
  97 + else if (n < 32) {
  98 + return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
  99 + }
  100 + else {
  101 + return [m[1] << (n - 32), 0];
  102 + }
  103 + }
  104 + //
  105 + // Given two 64bit ints (as an array of two 32bit ints) returns the two
  106 + // xored together as a 64bit int (as an array of two 32bit ints).
  107 + //
  108 + function x64Xor(m, n) {
  109 + return [m[0] ^ n[0], m[1] ^ n[1]];
  110 + }
  111 + //
  112 + // Given a block, returns murmurHash3's final x64 mix of that block.
  113 + // (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
  114 + // only place where we need to right shift 64bit ints.)
  115 + //
  116 + function x64Fmix(h) {
  117 + h = x64Xor(h, [0, h[0] >>> 1]);
  118 + h = x64Multiply(h, [0xff51afd7, 0xed558ccd]);
  119 + h = x64Xor(h, [0, h[0] >>> 1]);
  120 + h = x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
  121 + h = x64Xor(h, [0, h[0] >>> 1]);
  122 + return h;
  123 + }
  124 + //
  125 + // Given a string and an optional seed as an int, returns a 128 bit
  126 + // hash using the x64 flavor of MurmurHash3, as an unsigned hex.
  127 + //
  128 + function x64hash128(key, seed) {
  129 + key = key || '';
  130 + seed = seed || 0;
  131 + var remainder = key.length % 16;
  132 + var bytes = key.length - remainder;
  133 + var h1 = [0, seed];
  134 + var h2 = [0, seed];
  135 + var k1 = [0, 0];
  136 + var k2 = [0, 0];
  137 + var c1 = [0x87c37b91, 0x114253d5];
  138 + var c2 = [0x4cf5ad43, 0x2745937f];
  139 + var i;
  140 + for (i = 0; i < bytes; i = i + 16) {
  141 + k1 = [
  142 + (key.charCodeAt(i + 4) & 0xff) |
  143 + ((key.charCodeAt(i + 5) & 0xff) << 8) |
  144 + ((key.charCodeAt(i + 6) & 0xff) << 16) |
  145 + ((key.charCodeAt(i + 7) & 0xff) << 24),
  146 + (key.charCodeAt(i) & 0xff) |
  147 + ((key.charCodeAt(i + 1) & 0xff) << 8) |
  148 + ((key.charCodeAt(i + 2) & 0xff) << 16) |
  149 + ((key.charCodeAt(i + 3) & 0xff) << 24),
  150 + ];
  151 + k2 = [
  152 + (key.charCodeAt(i + 12) & 0xff) |
  153 + ((key.charCodeAt(i + 13) & 0xff) << 8) |
  154 + ((key.charCodeAt(i + 14) & 0xff) << 16) |
  155 + ((key.charCodeAt(i + 15) & 0xff) << 24),
  156 + (key.charCodeAt(i + 8) & 0xff) |
  157 + ((key.charCodeAt(i + 9) & 0xff) << 8) |
  158 + ((key.charCodeAt(i + 10) & 0xff) << 16) |
  159 + ((key.charCodeAt(i + 11) & 0xff) << 24),
  160 + ];
  161 + k1 = x64Multiply(k1, c1);
  162 + k1 = x64Rotl(k1, 31);
  163 + k1 = x64Multiply(k1, c2);
  164 + h1 = x64Xor(h1, k1);
  165 + h1 = x64Rotl(h1, 27);
  166 + h1 = x64Add(h1, h2);
  167 + h1 = x64Add(x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
  168 + k2 = x64Multiply(k2, c2);
  169 + k2 = x64Rotl(k2, 33);
  170 + k2 = x64Multiply(k2, c1);
  171 + h2 = x64Xor(h2, k2);
  172 + h2 = x64Rotl(h2, 31);
  173 + h2 = x64Add(h2, h1);
  174 + h2 = x64Add(x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
  175 + }
  176 + k1 = [0, 0];
  177 + k2 = [0, 0];
  178 + switch (remainder) {
  179 + case 15:
  180 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 14)], 48));
  181 + // fallthrough
  182 + case 14:
  183 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 13)], 40));
  184 + // fallthrough
  185 + case 13:
  186 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 12)], 32));
  187 + // fallthrough
  188 + case 12:
  189 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 11)], 24));
  190 + // fallthrough
  191 + case 11:
  192 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 10)], 16));
  193 + // fallthrough
  194 + case 10:
  195 + k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 9)], 8));
  196 + // fallthrough
  197 + case 9:
  198 + k2 = x64Xor(k2, [0, key.charCodeAt(i + 8)]);
  199 + k2 = x64Multiply(k2, c2);
  200 + k2 = x64Rotl(k2, 33);
  201 + k2 = x64Multiply(k2, c1);
  202 + h2 = x64Xor(h2, k2);
  203 + // fallthrough
  204 + case 8:
  205 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 7)], 56));
  206 + // fallthrough
  207 + case 7:
  208 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 6)], 48));
  209 + // fallthrough
  210 + case 6:
  211 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 5)], 40));
  212 + // fallthrough
  213 + case 5:
  214 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 4)], 32));
  215 + // fallthrough
  216 + case 4:
  217 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 3)], 24));
  218 + // fallthrough
  219 + case 3:
  220 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 2)], 16));
  221 + // fallthrough
  222 + case 2:
  223 + k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 1)], 8));
  224 + // fallthrough
  225 + case 1:
  226 + k1 = x64Xor(k1, [0, key.charCodeAt(i)]);
  227 + k1 = x64Multiply(k1, c1);
  228 + k1 = x64Rotl(k1, 31);
  229 + k1 = x64Multiply(k1, c2);
  230 + h1 = x64Xor(h1, k1);
  231 + // fallthrough
  232 + }
  233 + h1 = x64Xor(h1, [0, key.length]);
  234 + h2 = x64Xor(h2, [0, key.length]);
  235 + h1 = x64Add(h1, h2);
  236 + h2 = x64Add(h2, h1);
  237 + h1 = x64Fmix(h1);
  238 + h2 = x64Fmix(h2);
  239 + h1 = x64Add(h1, h2);
  240 + h2 = x64Add(h2, h1);
  241 + return (('00000000' + (h1[0] >>> 0).toString(16)).slice(-8) +
  242 + ('00000000' + (h1[1] >>> 0).toString(16)).slice(-8) +
  243 + ('00000000' + (h2[0] >>> 0).toString(16)).slice(-8) +
  244 + ('00000000' + (h2[1] >>> 0).toString(16)).slice(-8));
  245 + }
  246 +
  247 + /*! *****************************************************************************
  248 + Copyright (c) Microsoft Corporation.
  249 +
  250 + Permission to use, copy, modify, and/or distribute this software for any
  251 + purpose with or without fee is hereby granted.
  252 +
  253 + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  254 + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  255 + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  256 + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  257 + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  258 + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  259 + PERFORMANCE OF THIS SOFTWARE.
  260 + ***************************************************************************** */
  261 +
  262 + var __assign = function() {
  263 + __assign = Object.assign || function __assign(t) {
  264 + for (var s, i = 1, n = arguments.length; i < n; i++) {
  265 + s = arguments[i];
  266 + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  267 + }
  268 + return t;
  269 + };
  270 + return __assign.apply(this, arguments);
  271 + };
  272 +
  273 + function __awaiter(thisArg, _arguments, P, generator) {
  274 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  275 + return new (P || (P = Promise))(function (resolve, reject) {
  276 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  277 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  278 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  279 + step((generator = generator.apply(thisArg, _arguments || [])).next());
  280 + });
  281 + }
  282 +
  283 + function __generator(thisArg, body) {
  284 + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  285 + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  286 + function verb(n) { return function (v) { return step([n, v]); }; }
  287 + function step(op) {
  288 + if (f) throw new TypeError("Generator is already executing.");
  289 + while (_) try {
  290 + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  291 + if (y = 0, t) op = [op[0] & 2, t.value];
  292 + switch (op[0]) {
  293 + case 0: case 1: t = op; break;
  294 + case 4: _.label++; return { value: op[1], done: false };
  295 + case 5: _.label++; y = op[1]; op = [0]; continue;
  296 + case 7: op = _.ops.pop(); _.trys.pop(); continue;
  297 + default:
  298 + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  299 + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  300 + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  301 + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  302 + if (t[2]) _.ops.pop();
  303 + _.trys.pop(); continue;
  304 + }
  305 + op = body.call(thisArg, _);
  306 + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  307 + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  308 + }
  309 + }
  310 +
  311 + var version = "3.0.3";
  312 +
  313 + function requestIdleCallbackIfAvailable(fallbackTimeout) {
  314 + return new Promise(function (resolve) {
  315 + if (window.requestIdleCallback) {
  316 + window.requestIdleCallback(function () { return resolve(); });
  317 + }
  318 + else {
  319 + setTimeout(resolve, fallbackTimeout);
  320 + }
  321 + });
  322 + }
  323 +
  324 + /*
  325 + * This file contains functions to work with pure data only (no browser features, DOM, side effects, etc).
  326 + */
  327 + /**
  328 + * Does the same as Array.prototype.includes but has better typing
  329 + */
  330 + function includes(haystack, needle) {
  331 + for (var i = 0, l = haystack.length; i < l; ++i) {
  332 + if (haystack[i] === needle) {
  333 + return true;
  334 + }
  335 + }
  336 + return false;
  337 + }
  338 + /**
  339 + * Like `!includes()` but with proper typing
  340 + */
  341 + function excludes(haystack, needle) {
  342 + return !includes(haystack, needle);
  343 + }
  344 + /**
  345 + * Be careful, NaN can return
  346 + */
  347 + function toInt(value) {
  348 + if (typeof value === 'number') {
  349 + return value | 0;
  350 + }
  351 + return parseInt(value);
  352 + }
  353 + /**
  354 + * Be careful, NaN can return
  355 + */
  356 + function toFloat(value) {
  357 + if (typeof value === 'number') {
  358 + return value;
  359 + }
  360 + return parseFloat(value);
  361 + }
  362 + function countTruthy(values) {
  363 + return values.reduce(function (sum, value) { return sum + (value ? 1 : 0); }, 0);
  364 + }
  365 +
  366 + /*
  367 + * Functions to help with browser features
  368 + */
  369 + var w = window;
  370 + var n = navigator;
  371 + var d = document;
  372 + /**
  373 + * Checks whether the browser is based on Trident (the Internet Explorer engine) without using user-agent.
  374 + *
  375 + * Warning for package users:
  376 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  377 + */
  378 + function isTrident() {
  379 + // The properties are checked to be in IE 10, IE 11 and not to be in other browsers in October 2020
  380 + return (countTruthy([
  381 + 'MSCSSMatrix' in w,
  382 + 'msSetImmediate' in w,
  383 + 'msIndexedDB' in w,
  384 + 'msMaxTouchPoints' in n,
  385 + 'msPointerEnabled' in n,
  386 + ]) >= 4);
  387 + }
  388 + /**
  389 + * Checks whether the browser is based on EdgeHTML (the pre-Chromium Edge engine) without using user-agent.
  390 + *
  391 + * Warning for package users:
  392 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  393 + */
  394 + function isEdgeHTML() {
  395 + // Based on research in October 2020
  396 + return (countTruthy(['msWriteProfilerMark' in w, 'MSStream' in w, 'msLaunchUri' in n, 'msSaveBlob' in n]) >= 3 &&
  397 + !isTrident());
  398 + }
  399 + /**
  400 + * Checks whether the browser is based on Chromium without using user-agent.
  401 + *
  402 + * Warning for package users:
  403 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  404 + */
  405 + function isChromium() {
  406 + // Based on research in October 2020. Tested to detect Chromium 42-86.
  407 + return (countTruthy([
  408 + 'webkitPersistentStorage' in n,
  409 + 'webkitTemporaryStorage' in n,
  410 + n.vendor.indexOf('Google') === 0,
  411 + 'webkitResolveLocalFileSystemURL' in w,
  412 + 'BatteryManager' in w,
  413 + 'webkitMediaStream' in w,
  414 + 'webkitSpeechGrammar' in w,
  415 + ]) >= 5);
  416 + }
  417 + /**
  418 + * Checks whether the browser is based on mobile or desktop Safari without using user-agent.
  419 + * All iOS browsers use WebKit (the Safari engine).
  420 + *
  421 + * Warning for package users:
  422 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  423 + */
  424 + function isWebKit() {
  425 + // Based on research in September 2020
  426 + return (countTruthy([
  427 + 'ApplePayError' in w,
  428 + 'CSSPrimitiveValue' in w,
  429 + 'Counter' in w,
  430 + n.vendor.indexOf('Apple') === 0,
  431 + 'getStorageUpdates' in n,
  432 + 'WebKitMediaKeys' in w,
  433 + ]) >= 4);
  434 + }
  435 + /**
  436 + * Checks whether the WebKit browser is a desktop Safari.
  437 + *
  438 + * Warning for package users:
  439 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  440 + */
  441 + function isDesktopSafari() {
  442 + return (countTruthy([
  443 + 'safari' in w,
  444 + !('DeviceMotionEvent' in w),
  445 + !('ongestureend' in w),
  446 + !('standalone' in n),
  447 + ]) >= 3);
  448 + }
  449 + /**
  450 + * Checks whether the browser is based on Gecko (Firefox engine) without using user-agent.
  451 + *
  452 + * Warning for package users:
  453 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  454 + */
  455 + function isGecko() {
  456 + var _a;
  457 + // Based on research in September 2020
  458 + return (countTruthy([
  459 + 'buildID' in n,
  460 + ((_a = d.documentElement) === null || _a === void 0 ? void 0 : _a.style) && 'MozAppearance' in d.documentElement.style,
  461 + 'MediaRecorderErrorEvent' in w,
  462 + 'mozInnerScreenX' in w,
  463 + 'CSSMozDocumentRule' in w,
  464 + 'CanvasCaptureMediaStream' in w,
  465 + ]) >= 4);
  466 + }
  467 + /**
  468 + * Checks whether the browser is based on Chromium version ≥86 without using user-agent.
  469 + * It doesn't check that the browser is based on Chromium, there is a separate function for this.
  470 + */
  471 + function isChromium86OrNewer() {
  472 + // Checked in Chrome 85 vs Chrome 86 both on desktop and Android
  473 + return (countTruthy([
  474 + !('MediaSettingsRange' in w),
  475 + 'RTCEncodedAudioFrame' in w,
  476 + '' + w.Intl === '[object Intl]',
  477 + '' + w.Reflect === '[object Reflect]',
  478 + ]) >= 3);
  479 + }
  480 + /**
  481 + * Checks whether the browser is based on WebKit version ≥606 (Safari ≥12) without using user-agent.
  482 + * It doesn't check that the browser is based on WebKit, there is a separate function for this.
  483 + *
  484 + * @link https://en.wikipedia.org/wiki/Safari_version_history#Release_history Safari-WebKit versions map
  485 + */
  486 + function isWebKit606OrNewer() {
  487 + // Checked in Safari 9–14
  488 + return (countTruthy([
  489 + 'DOMRectList' in w,
  490 + 'RTCPeerConnectionIceEvent' in w,
  491 + 'SVGGeometryElement' in w,
  492 + 'ontransitioncancel' in w,
  493 + ]) >= 3);
  494 + }
  495 +
  496 + var w$1 = window;
  497 + var d$1 = document;
  498 + // Inspired by and based on https://github.com/cozylife/audio-fingerprint
  499 + function getAudioFingerprint() {
  500 + return __awaiter(this, void 0, void 0, function () {
  501 + var AudioContext, context, oscillator, compressor, buffer, error_1;
  502 + return __generator(this, function (_a) {
  503 + switch (_a.label) {
  504 + case 0:
  505 + // In some browsers, audio context always stays suspended unless the context is started in response to a user action
  506 + // (e.g. a click or a tap). It prevents audio fingerprint from being taken at an arbitrary moment of time.
  507 + // Such browsers are old and unpopular, so the audio fingerprinting is just skipped in them.
  508 + // See a similar case explanation at https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088
  509 + if (doesCurrentBrowserSuspendAudioContext()) {
  510 + return [2 /*return*/, -1];
  511 + }
  512 + AudioContext = w$1.OfflineAudioContext || w$1.webkitOfflineAudioContext;
  513 + if (!AudioContext) {
  514 + return [2 /*return*/, -2];
  515 + }
  516 + context = new AudioContext(1, 44100, 44100);
  517 + oscillator = context.createOscillator();
  518 + oscillator.type = 'triangle';
  519 + setAudioParam(context, oscillator.frequency, 10000);
  520 + compressor = context.createDynamicsCompressor();
  521 + setAudioParam(context, compressor.threshold, -50);
  522 + setAudioParam(context, compressor.knee, 40);
  523 + setAudioParam(context, compressor.ratio, 12);
  524 + setAudioParam(context, compressor.reduction, -20);
  525 + setAudioParam(context, compressor.attack, 0);
  526 + setAudioParam(context, compressor.release, 0.25);
  527 + oscillator.connect(compressor);
  528 + compressor.connect(context.destination);
  529 + oscillator.start(0);
  530 + _a.label = 1;
  531 + case 1:
  532 + _a.trys.push([1, 3, 4, 5]);
  533 + return [4 /*yield*/, renderAudio(context)];
  534 + case 2:
  535 + buffer = _a.sent();
  536 + return [3 /*break*/, 5];
  537 + case 3:
  538 + error_1 = _a.sent();
  539 + if (error_1.name === "timeout" /* Timeout */ || error_1.name === "suspended" /* Suspended */) {
  540 + return [2 /*return*/, -3];
  541 + }
  542 + throw error_1;
  543 + case 4:
  544 + oscillator.disconnect();
  545 + compressor.disconnect();
  546 + return [7 /*endfinally*/];
  547 + case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))];
  548 + }
  549 + });
  550 + });
  551 + }
  552 + /**
  553 + * Checks if the current browser is known to always suspend audio context
  554 + */
  555 + function doesCurrentBrowserSuspendAudioContext() {
  556 + return isWebKit() && !isDesktopSafari() && !isWebKit606OrNewer();
  557 + }
  558 + function setAudioParam(context, param, value) {
  559 + var isAudioParam = function (value) {
  560 + return value && typeof value.setValueAtTime === 'function';
  561 + };
  562 + if (isAudioParam(param)) {
  563 + param.setValueAtTime(value, context.currentTime);
  564 + }
  565 + }
  566 + function renderAudio(context) {
  567 + var resumeTriesMaxCount = 3;
  568 + var resumeRetryDelay = 500;
  569 + var runningTimeout = 1000;
  570 + return new Promise(function (resolve, reject) {
  571 + context.oncomplete = function (event) { return resolve(event.renderedBuffer); };
  572 + var resumeTriesLeft = resumeTriesMaxCount;
  573 + var tryResume = function () {
  574 + context.startRendering();
  575 + switch (context.state) {
  576 + case 'running':
  577 + setTimeout(function () { return reject(makeInnerError("timeout" /* Timeout */)); }, runningTimeout);
  578 + break;
  579 + // Sometimes the audio context doesn't start after calling `startRendering` (in addition to the cases where
  580 + // audio context doesn't start at all). A known case is starting an audio context when the browser tab is in
  581 + // background on iPhone. Retries usually help in this case.
  582 + case 'suspended':
  583 + // The audio context can reject starting until the tab is in foreground. Long fingerprint duration
  584 + // in background isn't a problem, therefore the retry attempts don't count in background. It can lead to
  585 + // a situation when a fingerprint takes very long time and finishes successfully. FYI, the audio context
  586 + // can be suspended when `document.hidden === false` and start running after a retry.
  587 + if (!d$1.hidden) {
  588 + resumeTriesLeft--;
  589 + }
  590 + if (resumeTriesLeft > 0) {
  591 + setTimeout(tryResume, resumeRetryDelay);
  592 + }
  593 + else {
  594 + reject(makeInnerError("suspended" /* Suspended */));
  595 + }
  596 + break;
  597 + }
  598 + };
  599 + tryResume();
  600 + });
  601 + }
  602 + function getHash(signal) {
  603 + var hash = 0;
  604 + for (var i = 4500; i < 5000; ++i) {
  605 + hash += Math.abs(signal[i]);
  606 + }
  607 + return hash;
  608 + }
  609 + function makeInnerError(name) {
  610 + var error = new Error(name);
  611 + error.name = name;
  612 + return error;
  613 + }
  614 +
  615 + var d$2 = document;
  616 + // We use m or w because these two characters take up the maximum width.
  617 + // And we use a LLi so that the same matching fonts can get separated.
  618 + var testString = 'mmMwWLliI0O&1';
  619 + // We test using 48px font size, we may use any size. I guess larger the better.
  620 + var testSize = '48px';
  621 + // A font will be compared against all the three default fonts.
  622 + // And if it doesn't match all 3 then that font is not available.
  623 + var baseFonts = ['monospace', 'sans-serif', 'serif'];
  624 + var fontList = [
  625 + // This is android-specific font from "Roboto" family
  626 + 'sans-serif-thin',
  627 + 'ARNO PRO',
  628 + 'Agency FB',
  629 + 'Arabic Typesetting',
  630 + 'Arial Unicode MS',
  631 + 'AvantGarde Bk BT',
  632 + 'BankGothic Md BT',
  633 + 'Batang',
  634 + 'Bitstream Vera Sans Mono',
  635 + 'Calibri',
  636 + 'Century',
  637 + 'Century Gothic',
  638 + 'Clarendon',
  639 + 'EUROSTILE',
  640 + 'Franklin Gothic',
  641 + 'Futura Bk BT',
  642 + 'Futura Md BT',
  643 + 'GOTHAM',
  644 + 'Gill Sans',
  645 + 'HELV',
  646 + 'Haettenschweiler',
  647 + 'Helvetica Neue',
  648 + 'Humanst521 BT',
  649 + 'Leelawadee',
  650 + 'Letter Gothic',
  651 + 'Levenim MT',
  652 + 'Lucida Bright',
  653 + 'Lucida Sans',
  654 + 'Menlo',
  655 + 'MS Mincho',
  656 + 'MS Outlook',
  657 + 'MS Reference Specialty',
  658 + 'MS UI Gothic',
  659 + 'MT Extra',
  660 + 'MYRIAD PRO',
  661 + 'Marlett',
  662 + 'Meiryo UI',
  663 + 'Microsoft Uighur',
  664 + 'Minion Pro',
  665 + 'Monotype Corsiva',
  666 + 'PMingLiU',
  667 + 'Pristina',
  668 + 'SCRIPTINA',
  669 + 'Segoe UI Light',
  670 + 'Serifa',
  671 + 'SimHei',
  672 + 'Small Fonts',
  673 + 'Staccato222 BT',
  674 + 'TRAJAN PRO',
  675 + 'Univers CE 55 Medium',
  676 + 'Vrinda',
  677 + 'ZWAdobeF',
  678 + ];
  679 + var fontSpanStyle = {
  680 + // CSS font reset to reset external styles
  681 + fontStyle: 'normal',
  682 + fontWeight: 'normal',
  683 + letterSpacing: 'normal',
  684 + lineBreak: 'auto',
  685 + lineHeight: 'normal',
  686 + textTransform: 'none',
  687 + textAlign: 'left',
  688 + textDecoration: 'none',
  689 + textShadow: 'none',
  690 + whiteSpace: 'normal',
  691 + wordBreak: 'normal',
  692 + wordSpacing: 'normal',
  693 + // We need this css as in some weird browser this span elements shows up for a microSec which creates
  694 + // a bad user experience
  695 + position: 'absolute',
  696 + left: '-9999px',
  697 + fontSize: testSize,
  698 + };
  699 + // kudos to http://www.lalit.org/lab/javascript-css-font-detect/
  700 + function getFonts() {
  701 + var h = d$2.body;
  702 + // div to load spans for the base fonts
  703 + var baseFontsDiv = d$2.createElement('div');
  704 + // div to load spans for the fonts to detect
  705 + var fontsDiv = d$2.createElement('div');
  706 + var defaultWidth = {};
  707 + var defaultHeight = {};
  708 + // creates a span where the fonts will be loaded
  709 + var createSpan = function () {
  710 + var span = d$2.createElement('span');
  711 + span.textContent = testString;
  712 + for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) {
  713 + var prop = _a[_i];
  714 + span.style[prop] = fontSpanStyle[prop];
  715 + }
  716 + return span;
  717 + };
  718 + // creates a span and load the font to detect and a base font for fallback
  719 + var createSpanWithFonts = function (fontToDetect, baseFont) {
  720 + var s = createSpan();
  721 + s.style.fontFamily = "'" + fontToDetect + "'," + baseFont;
  722 + return s;
  723 + };
  724 + // creates spans for the base fonts and adds them to baseFontsDiv
  725 + var initializeBaseFontsSpans = function () {
  726 + return baseFonts.map(function (baseFont) {
  727 + var s = createSpan();
  728 + s.style.fontFamily = baseFont;
  729 + baseFontsDiv.appendChild(s);
  730 + return s;
  731 + });
  732 + };
  733 + // creates spans for the fonts to detect and adds them to fontsDiv
  734 + var initializeFontsSpans = function () {
  735 + // Stores {fontName : [spans for that font]}
  736 + var spans = {};
  737 + var _loop_1 = function (font) {
  738 + spans[font] = baseFonts.map(function (baseFont) {
  739 + var s = createSpanWithFonts(font, baseFont);
  740 + fontsDiv.appendChild(s);
  741 + return s;
  742 + });
  743 + };
  744 + for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) {
  745 + var font = fontList_1[_i];
  746 + _loop_1(font);
  747 + }
  748 + return spans;
  749 + };
  750 + // checks if a font is available
  751 + var isFontAvailable = function (fontSpans) {
  752 + return baseFonts.some(function (baseFont, baseFontIndex) {
  753 + return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] ||
  754 + fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont];
  755 + });
  756 + };
  757 + // create spans for base fonts
  758 + var baseFontsSpans = initializeBaseFontsSpans();
  759 + // add the spans to the DOM
  760 + h.appendChild(baseFontsDiv);
  761 + // get the default width for the three base fonts
  762 + for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) {
  763 + defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font
  764 + defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font
  765 + }
  766 + // create spans for fonts to detect
  767 + var fontsSpans = initializeFontsSpans();
  768 + // add all the spans to the DOM
  769 + h.appendChild(fontsDiv);
  770 + // check available fonts
  771 + var available = [];
  772 + for (var i = 0, l = fontList.length; i < l; i++) {
  773 + if (isFontAvailable(fontsSpans[fontList[i]])) {
  774 + available.push(fontList[i]);
  775 + }
  776 + }
  777 + // remove spans from DOM
  778 + h.removeChild(fontsDiv);
  779 + h.removeChild(baseFontsDiv);
  780 + return available;
  781 + }
  782 +
  783 + function getPlugins() {
  784 + if (isTrident()) {
  785 + return [];
  786 + }
  787 + if (!navigator.plugins) {
  788 + return undefined;
  789 + }
  790 + var plugins = [];
  791 + // Safari 10 doesn't support iterating navigator.plugins with for...of
  792 + for (var i = 0; i < navigator.plugins.length; ++i) {
  793 + var plugin = navigator.plugins[i];
  794 + if (!plugin) {
  795 + continue;
  796 + }
  797 + var mimeTypes = [];
  798 + for (var j = 0; j < plugin.length; ++j) {
  799 + var mimeType = plugin[j];
  800 + mimeTypes.push({
  801 + type: mimeType.type,
  802 + suffixes: mimeType.suffixes,
  803 + });
  804 + }
  805 + plugins.push({
  806 + name: plugin.name,
  807 + description: plugin.description,
  808 + mimeTypes: mimeTypes,
  809 + });
  810 + }
  811 + return plugins;
  812 + }
  813 +
  814 + function makeCanvasContext() {
  815 + var canvas = document.createElement('canvas');
  816 + canvas.width = 240;
  817 + canvas.height = 140;
  818 + canvas.style.display = 'inline';
  819 + return [canvas, canvas.getContext('2d')];
  820 + }
  821 + function isSupported(canvas, context) {
  822 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  823 + return !!(context && canvas.toDataURL);
  824 + }
  825 + function save(canvas) {
  826 + // TODO: look into: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
  827 + return canvas.toDataURL();
  828 + }
  829 + // https://www.browserleaks.com/canvas#how-does-it-work
  830 + function getCanvasFingerprint() {
  831 + var _a = makeCanvasContext(), canvas = _a[0], context = _a[1];
  832 + if (!isSupported(canvas, context)) {
  833 + return { winding: false, data: '' };
  834 + }
  835 + // detect browser support of canvas winding
  836 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  837 + // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js
  838 + context.rect(0, 0, 10, 10);
  839 + context.rect(2, 2, 6, 6);
  840 + var winding = !context.isPointInPath(5, 5, 'evenodd');
  841 + context.textBaseline = 'alphabetic';
  842 + context.fillStyle = '#f60';
  843 + context.fillRect(125, 1, 62, 20);
  844 + context.fillStyle = '#069';
  845 + // https://github.com/Valve/fingerprintjs2/issues/66
  846 + // this can affect FP generation when applying different CSS on different websites
  847 + context.font = '11pt no-real-font-123';
  848 + // the choice of emojis has a gigantic impact on rendering performance (especially in FF)
  849 + // some newer emojis cause it to slow down 50-200 times
  850 + // context.fillText("Cw爨m fjordbank \ud83d\ude03 gly", 2, 15)
  851 + var printedText = 'Cwm fjordbank \ud83d\ude03 gly';
  852 + context.fillText(printedText, 2, 15);
  853 + context.fillStyle = 'rgba(102, 204, 0, 0.2)';
  854 + context.font = '18pt Arial';
  855 + context.fillText(printedText, 4, 45);
  856 + // canvas blending
  857 + // http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
  858 + // http://jsfiddle.net/NDYV8/16/
  859 + context.globalCompositeOperation = 'multiply';
  860 + context.fillStyle = 'rgb(255,0,255)';
  861 + context.beginPath();
  862 + context.arc(50, 50, 50, 0, Math.PI * 2, true);
  863 + context.closePath();
  864 + context.fill();
  865 + context.fillStyle = 'rgb(0,255,255)';
  866 + context.beginPath();
  867 + context.arc(100, 50, 50, 0, Math.PI * 2, true);
  868 + context.closePath();
  869 + context.fill();
  870 + context.fillStyle = 'rgb(255,255,0)';
  871 + context.beginPath();
  872 + context.arc(75, 100, 50, 0, Math.PI * 2, true);
  873 + context.closePath();
  874 + context.fill();
  875 + context.fillStyle = 'rgb(255,0,255)';
  876 + // canvas winding
  877 + // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
  878 + // http://jsfiddle.net/NDYV8/19/
  879 + context.arc(75, 75, 75, 0, Math.PI * 2, true);
  880 + context.arc(75, 75, 25, 0, Math.PI * 2, true);
  881 + context.fill('evenodd');
  882 + return {
  883 + winding: winding,
  884 + data: save(canvas),
  885 + };
  886 + }
  887 +
  888 + var n$1 = navigator;
  889 + var w$2 = window;
  890 + /**
  891 + * This is a crude and primitive touch screen detection. It's not possible to currently reliably detect the availability
  892 + * of a touch screen with a JS, without actually subscribing to a touch event.
  893 + *
  894 + * @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
  895 + * @see https://github.com/Modernizr/Modernizr/issues/548
  896 + */
  897 + function getTouchSupport() {
  898 + var maxTouchPoints = 0;
  899 + var touchEvent;
  900 + if (n$1.maxTouchPoints !== undefined) {
  901 + maxTouchPoints = toInt(n$1.maxTouchPoints);
  902 + }
  903 + else if (n$1.msMaxTouchPoints !== undefined) {
  904 + maxTouchPoints = n$1.msMaxTouchPoints;
  905 + }
  906 + try {
  907 + document.createEvent('TouchEvent');
  908 + touchEvent = true;
  909 + }
  910 + catch (_) {
  911 + touchEvent = false;
  912 + }
  913 + var touchStart = 'ontouchstart' in w$2;
  914 + return {
  915 + maxTouchPoints: maxTouchPoints,
  916 + touchEvent: touchEvent,
  917 + touchStart: touchStart,
  918 + };
  919 + }
  920 +
  921 + function getOsCpu() {
  922 + return navigator.oscpu;
  923 + }
  924 +
  925 + var n$2 = navigator;
  926 + function getLanguages() {
  927 + var result = [];
  928 + var language = n$2.language || n$2.userLanguage || n$2.browserLanguage || n$2.systemLanguage;
  929 + if (language !== undefined) {
  930 + result.push([language]);
  931 + }
  932 + if (Array.isArray(n$2.languages)) {
  933 + // Starting from Chromium 86, there is only a single value in `navigator.language` in Incognito mode:
  934 + // the value of `navigator.language`. Therefore the value is ignored in this browser.
  935 + if (!(isChromium() && isChromium86OrNewer())) {
  936 + result.push(n$2.languages);
  937 + }
  938 + }
  939 + else if (typeof n$2.languages === 'string') {
  940 + var languages = n$2.languages;
  941 + if (languages) {
  942 + result.push(languages.split(','));
  943 + }
  944 + }
  945 + return result;
  946 + }
  947 +
  948 + function getColorDepth() {
  949 + return window.screen.colorDepth;
  950 + }
  951 +
  952 + function getDeviceMemory() {
  953 + return navigator.deviceMemory;
  954 + }
  955 +
  956 + var w$3 = window;
  957 + function getScreenResolution() {
  958 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  959 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  960 + var dimensions = [toInt(w$3.screen.width), toInt(w$3.screen.height)];
  961 + dimensions.sort().reverse();
  962 + return dimensions;
  963 + }
  964 +
  965 + var w$4 = window;
  966 + function getAvailableScreenResolution() {
  967 + if (w$4.screen.availWidth && w$4.screen.availHeight) {
  968 + // Some browsers return screen resolution as strings, e.g. "1200", instead of a number, e.g. 1200.
  969 + // I suspect it's done by certain plugins that randomize browser properties to prevent fingerprinting.
  970 + var dimensions = [toInt(w$4.screen.availWidth), toInt(w$4.screen.availHeight)];
  971 + dimensions.sort().reverse();
  972 + return dimensions;
  973 + }
  974 + return undefined;
  975 + }
  976 +
  977 + function getHardwareConcurrency() {
  978 + try {
  979 + // sometimes hardware concurrency is a string
  980 + var concurrency = toInt(navigator.hardwareConcurrency);
  981 + return isNaN(concurrency) ? 1 : concurrency;
  982 + }
  983 + catch (e) {
  984 + return 1;
  985 + }
  986 + }
  987 +
  988 + function getTimezoneOffset() {
  989 + var currentYear = new Date().getFullYear();
  990 + // The timezone offset may change over time due to daylight saving time (DST) shifts.
  991 + // The non-DST timezone offset is used as the result timezone offset.
  992 + // Since the DST season differs in the northern and the southern hemispheres,
  993 + // both January and July timezones offsets are considered.
  994 + return Math.max(
  995 + // `getTimezoneOffset` returns a number as a string in some unidentified cases
  996 + toFloat(new Date(currentYear, 0, 1).getTimezoneOffset()), toFloat(new Date(currentYear, 6, 1).getTimezoneOffset()));
  997 + }
  998 +
  999 + var w$5 = window;
  1000 + function getTimezone() {
  1001 + var _a;
  1002 + if ((_a = w$5.Intl) === null || _a === void 0 ? void 0 : _a.DateTimeFormat) {
  1003 + return new w$5.Intl.DateTimeFormat().resolvedOptions().timeZone;
  1004 + }
  1005 + return undefined;
  1006 + }
  1007 +
  1008 + function getSessionStorage() {
  1009 + try {
  1010 + return !!window.sessionStorage;
  1011 + }
  1012 + catch (error) {
  1013 + /* SecurityError when referencing it means it exists */
  1014 + return true;
  1015 + }
  1016 + }
  1017 +
  1018 + // https://bugzilla.mozilla.org/show_bug.cgi?id=781447
  1019 + function getLocalStorage() {
  1020 + try {
  1021 + return !!window.localStorage;
  1022 + }
  1023 + catch (e) {
  1024 + /* SecurityError when referencing it means it exists */
  1025 + return true;
  1026 + }
  1027 + }
  1028 +
  1029 + function getIndexedDB() {
  1030 + // IE and Edge don't allow accessing indexedDB in private mode, therefore IE and Edge will have different
  1031 + // visitor identifier in normal and private modes.
  1032 + if (isTrident() || isEdgeHTML()) {
  1033 + return undefined;
  1034 + }
  1035 + try {
  1036 + return !!window.indexedDB;
  1037 + }
  1038 + catch (e) {
  1039 + /* SecurityError when referencing it means it exists */
  1040 + return true;
  1041 + }
  1042 + }
  1043 +
  1044 + function getOpenDatabase() {
  1045 + return !!window.openDatabase;
  1046 + }
  1047 +
  1048 + function getCpuClass() {
  1049 + return navigator.cpuClass;
  1050 + }
  1051 +
  1052 + function getPlatform() {
  1053 + return navigator.platform;
  1054 + }
  1055 +
  1056 + function getPluginsSupport() {
  1057 + return navigator.plugins !== undefined;
  1058 + }
  1059 +
  1060 + function getProductSub() {
  1061 + return navigator.productSub;
  1062 + }
  1063 +
  1064 + function getEmptyEvalLength() {
  1065 + return eval.toString().length;
  1066 + }
  1067 +
  1068 + function getErrorFF() {
  1069 + try {
  1070 + throw 'a';
  1071 + }
  1072 + catch (e) {
  1073 + try {
  1074 + e.toSource();
  1075 + return true;
  1076 + }
  1077 + catch (e2) {
  1078 + return false;
  1079 + }
  1080 + }
  1081 + }
  1082 +
  1083 + function getVendor() {
  1084 + return navigator.vendor;
  1085 + }
  1086 +
  1087 + function getChrome() {
  1088 + return window.chrome !== undefined;
  1089 + }
  1090 +
  1091 + var d$3 = document;
  1092 + /**
  1093 + * navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1094 + * cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past with
  1095 + * site-specific exceptions. Don't rely on it.
  1096 + *
  1097 + * @see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js Taken from here
  1098 + */
  1099 + function areCookiesEnabled() {
  1100 + // Taken from here: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cookies.js
  1101 + // navigator.cookieEnabled cannot detect custom or nuanced cookie blocking configurations. For example, when blocking
  1102 + // cookies via the Advanced Privacy Settings in IE9, it always returns true. And there have been issues in the past
  1103 + // with site-specific exceptions. Don't rely on it.
  1104 + // try..catch because some in situations `document.cookie` is exposed but throws a
  1105 + // SecurityError if you try to access it; e.g. documents created from data URIs
  1106 + // or in sandboxed iframes (depending on flags/context)
  1107 + try {
  1108 + // Create cookie
  1109 + d$3.cookie = 'cookietest=1';
  1110 + var result = d$3.cookie.indexOf('cookietest=') !== -1;
  1111 + // Delete cookie
  1112 + d$3.cookie = 'cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT';
  1113 + return result;
  1114 + }
  1115 + catch (e) {
  1116 + return false;
  1117 + }
  1118 + }
  1119 +
  1120 + /**
  1121 + * The list of entropy sources used to make visitor identifiers.
  1122 + *
  1123 + * This value isn't restricted by Semantic Versioning, i.e. it may be changed without bumping minor or major version of
  1124 + * this package.
  1125 + */
  1126 + var sources = {
  1127 + // Expected errors and default values must be handled inside the functions. Unexpected errors must be thrown.
  1128 + osCpu: getOsCpu,
  1129 + languages: getLanguages,
  1130 + colorDepth: getColorDepth,
  1131 + deviceMemory: getDeviceMemory,
  1132 + screenResolution: getScreenResolution,
  1133 + availableScreenResolution: getAvailableScreenResolution,
  1134 + hardwareConcurrency: getHardwareConcurrency,
  1135 + timezoneOffset: getTimezoneOffset,
  1136 + timezone: getTimezone,
  1137 + sessionStorage: getSessionStorage,
  1138 + localStorage: getLocalStorage,
  1139 + indexedDB: getIndexedDB,
  1140 + openDatabase: getOpenDatabase,
  1141 + cpuClass: getCpuClass,
  1142 + // Maybe it should be excluded: https://github.com/fingerprintjs/fingerprintjs/issues/514#issuecomment-688754892
  1143 + platform: getPlatform,
  1144 + plugins: getPlugins,
  1145 + canvas: getCanvasFingerprint,
  1146 + // adBlock: isAdblockUsed, // https://github.com/fingerprintjs/fingerprintjs/issues/405
  1147 + touchSupport: getTouchSupport,
  1148 + fonts: getFonts,
  1149 + audio: getAudioFingerprint,
  1150 + pluginsSupport: getPluginsSupport,
  1151 + productSub: getProductSub,
  1152 + emptyEvalLength: getEmptyEvalLength,
  1153 + errorFF: getErrorFF,
  1154 + vendor: getVendor,
  1155 + chrome: getChrome,
  1156 + cookiesEnabled: areCookiesEnabled,
  1157 + };
  1158 + /**
  1159 + * Gets a components list from the given list of entropy sources.
  1160 + *
  1161 + * Warning for package users:
  1162 + * This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk.
  1163 + */
  1164 + function getComponents(sources, sourceOptions, excludeSources) {
  1165 + return __awaiter(this, void 0, void 0, function () {
  1166 + var timestamp, components, _i, _a, sourceKey, result, error_1, nextTimestamp;
  1167 + var _b;
  1168 + return __generator(this, function (_c) {
  1169 + switch (_c.label) {
  1170 + case 0:
  1171 + timestamp = Date.now();
  1172 + components = {};
  1173 + _i = 0, _a = Object.keys(sources);
  1174 + _c.label = 1;
  1175 + case 1:
  1176 + if (!(_i < _a.length)) return [3 /*break*/, 7];
  1177 + sourceKey = _a[_i];
  1178 + if (!excludes(excludeSources, sourceKey)) {
  1179 + return [3 /*break*/, 6];
  1180 + }
  1181 + result = void 0;
  1182 + _c.label = 2;
  1183 + case 2:
  1184 + _c.trys.push([2, 4, , 5]);
  1185 + _b = {};
  1186 + return [4 /*yield*/, sources[sourceKey](sourceOptions)];
  1187 + case 3:
  1188 + result = (_b.value = _c.sent(), _b);
  1189 + return [3 /*break*/, 5];
  1190 + case 4:
  1191 + error_1 = _c.sent();
  1192 + result = error_1 && typeof error_1 === 'object' && 'message' in error_1 ? { error: error_1 } : { error: { message: error_1 } };
  1193 + return [3 /*break*/, 5];
  1194 + case 5:
  1195 + nextTimestamp = Date.now();
  1196 + components[sourceKey] = __assign(__assign({}, result), { duration: nextTimestamp - timestamp }); // TypeScript has beaten me here
  1197 + timestamp = nextTimestamp;
  1198 + _c.label = 6;
  1199 + case 6:
  1200 + _i++;
  1201 + return [3 /*break*/, 1];
  1202 + case 7: return [2 /*return*/, components];
  1203 + }
  1204 + });
  1205 + });
  1206 + }
  1207 + /**
  1208 + * Collects entropy components from the built-in sources to make the visitor identifier.
  1209 + */
  1210 + function getBuiltinComponents() {
  1211 + return getComponents(sources, undefined, []);
  1212 + }
  1213 +
  1214 + function componentsToCanonicalString(components) {
  1215 + var result = '';
  1216 + for (var _i = 0, _a = Object.keys(components); _i < _a.length; _i++) {
  1217 + var componentKey = _a[_i];
  1218 + var component = components[componentKey];
  1219 + var value = component.error ? 'error' : JSON.stringify(component.value);
  1220 + result += "" + (result ? '|' : '') + componentKey.replace(/([:|\\])/g, '\\$1') + ":" + value;
  1221 + }
  1222 + return result;
  1223 + }
  1224 + function componentsToDebugString(components) {
  1225 + return JSON.stringify(components, function (_key, value) {
  1226 + var _a;
  1227 + if (value instanceof Error) {
  1228 + return __assign(__assign({}, value), { message: value.message, stack: (_a = value.stack) === null || _a === void 0 ? void 0 : _a.split('\n') });
  1229 + }
  1230 + return value;
  1231 + }, 2);
  1232 + }
  1233 + function hashComponents(components) {
  1234 + return x64hash128(componentsToCanonicalString(components));
  1235 + }
  1236 + /**
  1237 + * Makes a GetResult implementation that calculates the visitor id hash on demand.
  1238 + * Designed for optimisation.
  1239 + */
  1240 + function makeLazyGetResult(components) {
  1241 + var visitorIdCache;
  1242 + // A plain class isn't used because its getters and setters aren't enumerable.
  1243 + return {
  1244 + components: components,
  1245 + get visitorId() {
  1246 + if (visitorIdCache === undefined) {
  1247 + visitorIdCache = hashComponents(this.components);
  1248 + }
  1249 + return visitorIdCache;
  1250 + },
  1251 + set visitorId(visitorId) {
  1252 + visitorIdCache = visitorId;
  1253 + },
  1254 + };
  1255 + }
  1256 + /**
  1257 + * The class isn't exported from the index file to not expose the constructor.
  1258 + * The hiding gives more freedom for future non-breaking updates.
  1259 + */
  1260 + var OpenAgent = /** @class */ (function () {
  1261 + function OpenAgent() {
  1262 + }
  1263 + /**
  1264 + * @inheritDoc
  1265 + */
  1266 + OpenAgent.prototype.get = function (options) {
  1267 + if (options === void 0) { options = {}; }
  1268 + return __awaiter(this, void 0, void 0, function () {
  1269 + var components, result;
  1270 + return __generator(this, function (_a) {
  1271 + switch (_a.label) {
  1272 + case 0: return [4 /*yield*/, getBuiltinComponents()];
  1273 + case 1:
  1274 + components = _a.sent();
  1275 + result = makeLazyGetResult(components);
  1276 + if (options.debug) {
  1277 + // console.log is ok here because it's under a debug clause
  1278 + // eslint-disable-next-line no-console
  1279 + console.log("Copy the text below to get the debug data:\n\n```\nversion: " + version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```");
  1280 + }
  1281 + return [2 /*return*/, result];
  1282 + }
  1283 + });
  1284 + });
  1285 + };
  1286 + return OpenAgent;
  1287 + }());
  1288 + /**
  1289 + * Builds an instance of Agent and waits a delay required for a proper operation.
  1290 + */
  1291 + function load(_a) {
  1292 + var _b = (_a === void 0 ? {} : _a).delayFallback, delayFallback = _b === void 0 ? 50 : _b;
  1293 + return __awaiter(this, void 0, void 0, function () {
  1294 + return __generator(this, function (_c) {
  1295 + switch (_c.label) {
  1296 + case 0:
  1297 + // A delay is required to ensure consistent entropy components.
  1298 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1299 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1300 + return [4 /*yield*/, requestIdleCallbackIfAvailable(delayFallback)];
  1301 + case 1:
  1302 + // A delay is required to ensure consistent entropy components.
  1303 + // See https://github.com/fingerprintjs/fingerprintjs/issues/254
  1304 + // and https://github.com/fingerprintjs/fingerprintjs/issues/307
  1305 + _c.sent();
  1306 + return [2 /*return*/, new OpenAgent()];
  1307 + }
  1308 + });
  1309 + });
  1310 + }
  1311 +
  1312 + // The default export is a syntax sugar (`import * as FP from '...' → import FP from '...'`).
  1313 + // It should contain all the public exported values.
  1314 + var index = { load: load, hashComponents: hashComponents, componentsToDebugString: componentsToDebugString };
  1315 + // The exports below are for private usage. They may change unexpectedly. Use them at your own risk.
  1316 + /** Not documented, out of Semantic Versioning, usage is at your own risk */
  1317 + var murmurX64Hash128 = x64hash128;
  1318 +
  1319 + exports.componentsToDebugString = componentsToDebugString;
  1320 + exports.default = index;
  1321 + exports.getComponents = getComponents;
  1322 + exports.hashComponents = hashComponents;
  1323 + exports.isChromium = isChromium;
  1324 + exports.isDesktopSafari = isDesktopSafari;
  1325 + exports.isEdgeHTML = isEdgeHTML;
  1326 + exports.isGecko = isGecko;
  1327 + exports.isTrident = isTrident;
  1328 + exports.isWebKit = isWebKit;
  1329 + exports.load = load;
  1330 + exports.murmurX64Hash128 = murmurX64Hash128;
  1331 +
  1332 + Object.defineProperty(exports, '__esModule', { value: true });
  1333 +
  1334 +})));
... ...
  1 +/**
  2 + * FingerprintJS v3.0.3 - Copyright (c) FingerprintJS, Inc, 2020 (https://fingerprintjs.com)
  3 + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  4 + *
  5 + * This software contains code from open-source projects:
  6 + * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
  7 + */
  8 +
  9 +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FingerprintJS={})}(this,(function(e){"use strict";function t(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var n=[0,0,0,0];return n[3]+=e[3]+t[3],n[2]+=n[3]>>>16,n[3]&=65535,n[2]+=e[2]+t[2],n[1]+=n[2]>>>16,n[2]&=65535,n[1]+=e[1]+t[1],n[0]+=n[1]>>>16,n[1]&=65535,n[0]+=e[0]+t[0],n[0]&=65535,[n[0]<<16|n[1],n[2]<<16|n[3]]}function n(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var n=[0,0,0,0];return n[3]+=e[3]*t[3],n[2]+=n[3]>>>16,n[3]&=65535,n[2]+=e[2]*t[3],n[1]+=n[2]>>>16,n[2]&=65535,n[2]+=e[3]*t[2],n[1]+=n[2]>>>16,n[2]&=65535,n[1]+=e[1]*t[3],n[0]+=n[1]>>>16,n[1]&=65535,n[1]+=e[2]*t[2],n[0]+=n[1]>>>16,n[1]&=65535,n[1]+=e[3]*t[1],n[0]+=n[1]>>>16,n[1]&=65535,n[0]+=e[0]*t[3]+e[1]*t[2]+e[2]*t[1]+e[3]*t[0],n[0]&=65535,[n[0]<<16|n[1],n[2]<<16|n[3]]}function r(e,t){return 32===(t%=64)?[e[1],e[0]]:t<32?[e[0]<<t|e[1]>>>32-t,e[1]<<t|e[0]>>>32-t]:(t-=32,[e[1]<<t|e[0]>>>32-t,e[0]<<t|e[1]>>>32-t])}function o(e,t){return 0===(t%=64)?e:t<32?[e[0]<<t|e[1]>>>32-t,e[1]<<t]:[e[1]<<t-32,0]}function i(e,t){return[e[0]^t[0],e[1]^t[1]]}function a(e){return e=i(e,[0,e[0]>>>1]),e=i(e=n(e,[4283543511,3981806797]),[0,e[0]>>>1]),e=i(e=n(e,[3301882366,444984403]),[0,e[0]>>>1])}function c(e,c){c=c||0;var u,s=(e=e||"").length%16,l=e.length-s,f=[0,c],d=[0,c],h=[0,0],v=[0,0],g=[2277735313,289559509],p=[1291169091,658871167];for(u=0;u<l;u+=16)h=[255&e.charCodeAt(u+4)|(255&e.charCodeAt(u+5))<<8|(255&e.charCodeAt(u+6))<<16|(255&e.charCodeAt(u+7))<<24,255&e.charCodeAt(u)|(255&e.charCodeAt(u+1))<<8|(255&e.charCodeAt(u+2))<<16|(255&e.charCodeAt(u+3))<<24],v=[255&e.charCodeAt(u+12)|(255&e.charCodeAt(u+13))<<8|(255&e.charCodeAt(u+14))<<16|(255&e.charCodeAt(u+15))<<24,255&e.charCodeAt(u+8)|(255&e.charCodeAt(u+9))<<8|(255&e.charCodeAt(u+10))<<16|(255&e.charCodeAt(u+11))<<24],h=r(h=n(h,g),31),f=t(f=r(f=i(f,h=n(h,p)),27),d),f=t(n(f,[0,5]),[0,1390208809]),v=r(v=n(v,p),33),d=t(d=r(d=i(d,v=n(v,g)),31),f),d=t(n(d,[0,5]),[0,944331445]);switch(h=[0,0],v=[0,0],s){case 15:v=i(v,o([0,e.charCodeAt(u+14)],48));case 14:v=i(v,o([0,e.charCodeAt(u+13)],40));case 13:v=i(v,o([0,e.charCodeAt(u+12)],32));case 12:v=i(v,o([0,e.charCodeAt(u+11)],24));case 11:v=i(v,o([0,e.charCodeAt(u+10)],16));case 10:v=i(v,o([0,e.charCodeAt(u+9)],8));case 9:v=n(v=i(v,[0,e.charCodeAt(u+8)]),p),d=i(d,v=n(v=r(v,33),g));case 8:h=i(h,o([0,e.charCodeAt(u+7)],56));case 7:h=i(h,o([0,e.charCodeAt(u+6)],48));case 6:h=i(h,o([0,e.charCodeAt(u+5)],40));case 5:h=i(h,o([0,e.charCodeAt(u+4)],32));case 4:h=i(h,o([0,e.charCodeAt(u+3)],24));case 3:h=i(h,o([0,e.charCodeAt(u+2)],16));case 2:h=i(h,o([0,e.charCodeAt(u+1)],8));case 1:h=n(h=i(h,[0,e.charCodeAt(u)]),g),f=i(f,h=n(h=r(h,31),p))}return f=t(f=i(f,[0,e.length]),d=i(d,[0,e.length])),d=t(d,f),f=t(f=a(f),d=a(d)),d=t(d,f),("00000000"+(f[0]>>>0).toString(16)).slice(-8)+("00000000"+(f[1]>>>0).toString(16)).slice(-8)+("00000000"+(d[0]>>>0).toString(16)).slice(-8)+("00000000"+(d[1]>>>0).toString(16)).slice(-8)}var u=function(){return(u=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};function s(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(t){i(t)}}function c(e){try{u(r.throw(e))}catch(t){i(t)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,c)}u((r=r.apply(e,t||[])).next())}))}function l(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}catch(c){i=[6,c],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}function f(e){return"number"==typeof e?0|e:parseInt(e)}function d(e){return"number"==typeof e?e:parseFloat(e)}function h(e){return e.reduce((function(e,t){return e+(t?1:0)}),0)}var v=window,g=navigator,p=document;function m(){return h(["MSCSSMatrix"in v,"msSetImmediate"in v,"msIndexedDB"in v,"msMaxTouchPoints"in g,"msPointerEnabled"in g])>=4}function y(){return h(["msWriteProfilerMark"in v,"MSStream"in v,"msLaunchUri"in g,"msSaveBlob"in g])>=3&&!m()}function b(){return h(["webkitPersistentStorage"in g,"webkitTemporaryStorage"in g,0===g.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in v,"BatteryManager"in v,"webkitMediaStream"in v,"webkitSpeechGrammar"in v])>=5}function w(){return h(["ApplePayError"in v,"CSSPrimitiveValue"in v,"Counter"in v,0===g.vendor.indexOf("Apple"),"getStorageUpdates"in g,"WebKitMediaKeys"in v])>=4}function S(){return h(["safari"in v,!("DeviceMotionEvent"in v),!("ongestureend"in v),!("standalone"in g)])>=3}var C=window,A=document;function M(e,t,n){(function(e){return e&&"function"==typeof e.setValueAtTime})(t)&&t.setValueAtTime(n,e.currentTime)}function T(e){return new Promise((function(t,n){e.oncomplete=function(e){return t(e.renderedBuffer)};var r=3,o=function(){switch(e.startRendering(),e.state){case"running":setTimeout((function(){return n(k("timeout"))}),1e3);break;case"suspended":A.hidden||r--,r>0?setTimeout(o,500):n(k("suspended"))}};o()}))}function x(e){for(var t=0,n=4500;n<5e3;++n)t+=Math.abs(e[n]);return t}function k(e){var t=new Error(e);return t.name=e,t}var P=document,O=["monospace","sans-serif","serif"],I=["sans-serif-thin","ARNO PRO","Agency FB","Arabic Typesetting","Arial Unicode MS","AvantGarde Bk BT","BankGothic Md BT","Batang","Bitstream Vera Sans Mono","Calibri","Century","Century Gothic","Clarendon","EUROSTILE","Franklin Gothic","Futura Bk BT","Futura Md BT","GOTHAM","Gill Sans","HELV","Haettenschweiler","Helvetica Neue","Humanst521 BT","Leelawadee","Letter Gothic","Levenim MT","Lucida Bright","Lucida Sans","Menlo","MS Mincho","MS Outlook","MS Reference Specialty","MS UI Gothic","MT Extra","MYRIAD PRO","Marlett","Meiryo UI","Microsoft Uighur","Minion Pro","Monotype Corsiva","PMingLiU","Pristina","SCRIPTINA","Segoe UI Light","Serifa","SimHei","Small Fonts","Staccato222 BT","TRAJAN PRO","Univers CE 55 Medium","Vrinda","ZWAdobeF"],E={fontStyle:"normal",fontWeight:"normal",letterSpacing:"normal",lineBreak:"auto",lineHeight:"normal",textTransform:"none",textAlign:"left",textDecoration:"none",textShadow:"none",whiteSpace:"normal",wordBreak:"normal",wordSpacing:"normal",position:"absolute",left:"-9999px",fontSize:"48px"};function D(e){return e.toDataURL()}var R=navigator,B=window;var L=navigator;var F=window;var G=window;var H=window;var U=document;var j={osCpu:function(){return navigator.oscpu},languages:function(){var e=[],t=L.language||L.userLanguage||L.browserLanguage||L.systemLanguage;if(void 0!==t&&e.push([t]),Array.isArray(L.languages))b()&&h([!("MediaSettingsRange"in v),"RTCEncodedAudioFrame"in v,""+v.Intl=="[object Intl]",""+v.Reflect=="[object Reflect]"])>=3||e.push(L.languages);else if("string"==typeof L.languages){var n=L.languages;n&&e.push(n.split(","))}return e},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return navigator.deviceMemory},screenResolution:function(){var e=[f(F.screen.width),f(F.screen.height)];return e.sort().reverse(),e},availableScreenResolution:function(){if(G.screen.availWidth&&G.screen.availHeight){var e=[f(G.screen.availWidth),f(G.screen.availHeight)];return e.sort().reverse(),e}},hardwareConcurrency:function(){try{var e=f(navigator.hardwareConcurrency);return isNaN(e)?1:e}catch(t){return 1}},timezoneOffset:function(){var e=(new Date).getFullYear();return Math.max(d(new Date(e,0,1).getTimezoneOffset()),d(new Date(e,6,1).getTimezoneOffset()))},timezone:function(){var e;if(null===(e=H.Intl)||void 0===e?void 0:e.DateTimeFormat)return(new H.Intl.DateTimeFormat).resolvedOptions().timeZone},sessionStorage:function(){try{return!!window.sessionStorage}catch(e){return!0}},localStorage:function(){try{return!!window.localStorage}catch(e){return!0}},indexedDB:function(){if(!m()&&!y())try{return!!window.indexedDB}catch(e){return!0}},openDatabase:function(){return!!window.openDatabase},cpuClass:function(){return navigator.cpuClass},platform:function(){return navigator.platform},plugins:function(){if(m())return[];if(navigator.plugins){for(var e=[],t=0;t<navigator.plugins.length;++t){var n=navigator.plugins[t];if(n){for(var r=[],o=0;o<n.length;++o){var i=n[o];r.push({type:i.type,suffixes:i.suffixes})}e.push({name:n.name,description:n.description,mimeTypes:r})}}return e}},canvas:function(){var e=function(){var e=document.createElement("canvas");return e.width=240,e.height=140,e.style.display="inline",[e,e.getContext("2d")]}(),t=e[0],n=e[1];if(!function(e,t){return!(!t||!e.toDataURL)}(t,n))return{winding:!1,data:""};n.rect(0,0,10,10),n.rect(2,2,6,6);var r=!n.isPointInPath(5,5,"evenodd");n.textBaseline="alphabetic",n.fillStyle="#f60",n.fillRect(125,1,62,20),n.fillStyle="#069",n.font="11pt no-real-font-123";var o="Cwm fjordbank 😃 gly";return n.fillText(o,2,15),n.fillStyle="rgba(102, 204, 0, 0.2)",n.font="18pt Arial",n.fillText(o,4,45),n.globalCompositeOperation="multiply",n.fillStyle="rgb(255,0,255)",n.beginPath(),n.arc(50,50,50,0,2*Math.PI,!0),n.closePath(),n.fill(),n.fillStyle="rgb(0,255,255)",n.beginPath(),n.arc(100,50,50,0,2*Math.PI,!0),n.closePath(),n.fill(),n.fillStyle="rgb(255,255,0)",n.beginPath(),n.arc(75,100,50,0,2*Math.PI,!0),n.closePath(),n.fill(),n.fillStyle="rgb(255,0,255)",n.arc(75,75,75,0,2*Math.PI,!0),n.arc(75,75,25,0,2*Math.PI,!0),n.fill("evenodd"),{winding:r,data:D(t)}},touchSupport:function(){var e,t=0;void 0!==R.maxTouchPoints?t=f(R.maxTouchPoints):void 0!==R.msMaxTouchPoints&&(t=R.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(n){e=!1}return{maxTouchPoints:t,touchEvent:e,touchStart:"ontouchstart"in B}},fonts:function(){var e=P.body,t=P.createElement("div"),n=P.createElement("div"),r={},o={},i=function(){var e=P.createElement("span");e.textContent="mmMwWLliI0O&1";for(var t=0,n=Object.keys(E);t<n.length;t++){var r=n[t];e.style[r]=E[r]}return e},a=function(e){return O.some((function(t,n){return e[n].offsetWidth!==r[t]||e[n].offsetHeight!==o[t]}))},c=O.map((function(e){var n=i();return n.style.fontFamily=e,t.appendChild(n),n}));e.appendChild(t);for(var u=0,s=O.length;u<s;u++)r[O[u]]=c[u].offsetWidth,o[O[u]]=c[u].offsetHeight;var l=function(){for(var e={},t=function(t){e[t]=O.map((function(e){var r=function(e,t){var n=i();return n.style.fontFamily="'"+e+"',"+t,n}(t,e);return n.appendChild(r),r}))},r=0,o=I;r<o.length;r++){t(o[r])}return e}();e.appendChild(n);for(var f=[],d=0,h=I.length;d<h;d++)a(l[I[d]])&&f.push(I[d]);return e.removeChild(n),e.removeChild(t),f},audio:function(){return s(this,void 0,void 0,(function(){var e,t,n,r,o,i;return l(this,(function(a){switch(a.label){case 0:if(w()&&!S()&&!(h(["DOMRectList"in v,"RTCPeerConnectionIceEvent"in v,"SVGGeometryElement"in v,"ontransitioncancel"in v])>=3))return[2,-1];if(!(e=C.OfflineAudioContext||C.webkitOfflineAudioContext))return[2,-2];t=new e(1,44100,44100),(n=t.createOscillator()).type="triangle",M(t,n.frequency,1e4),r=t.createDynamicsCompressor(),M(t,r.threshold,-50),M(t,r.knee,40),M(t,r.ratio,12),M(t,r.reduction,-20),M(t,r.attack,0),M(t,r.release,.25),n.connect(r),r.connect(t.destination),n.start(0),a.label=1;case 1:return a.trys.push([1,3,4,5]),[4,T(t)];case 2:return o=a.sent(),[3,5];case 3:if("timeout"===(i=a.sent()).name||"suspended"===i.name)return[2,-3];throw i;case 4:return n.disconnect(),r.disconnect(),[7];case 5:return[2,x(o.getChannelData(0))]}}))}))},pluginsSupport:function(){return void 0!==navigator.plugins},productSub:function(){return navigator.productSub},emptyEvalLength:function(){return eval.toString().length},errorFF:function(){try{throw"a"}catch(e){try{return e.toSource(),!0}catch(t){return!1}}},vendor:function(){return navigator.vendor},chrome:function(){return void 0!==window.chrome},cookiesEnabled:function(){try{U.cookie="cookietest=1";var e=-1!==U.cookie.indexOf("cookietest=");return U.cookie="cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT",e}catch(t){return!1}}};function W(e,t,n){return s(this,void 0,void 0,(function(){var r,o,i,a,c,s,f,d,h;return l(this,(function(l){switch(l.label){case 0:r=Date.now(),o={},i=0,a=Object.keys(e),l.label=1;case 1:if(!(i<a.length))return[3,7];if(c=a[i],function(e,t){for(var n=0,r=e.length;n<r;++n)if(e[n]===t)return!0;return!1}(n,c))return[3,6];s=void 0,l.label=2;case 2:return l.trys.push([2,4,,5]),h={},[4,e[c](t)];case 3:return h.value=l.sent(),s=h,[3,5];case 4:return f=l.sent(),s=f&&"object"==typeof f&&"message"in f?{error:f}:{error:{message:f}},[3,5];case 5:d=Date.now(),o[c]=u(u({},s),{duration:d-r}),r=d,l.label=6;case 6:return i++,[3,1];case 7:return[2,o]}}))}))}function N(e){return JSON.stringify(e,(function(e,t){var n;return t instanceof Error?u(u({},t),{message:t.message,stack:null===(n=t.stack)||void 0===n?void 0:n.split("\n")}):t}),2)}function z(e){return c(function(e){for(var t="",n=0,r=Object.keys(e);n<r.length;n++){var o=r[n],i=e[o],a=i.error?"error":JSON.stringify(i.value);t+=(t?"|":"")+o.replace(/([:|\\])/g,"\\$1")+":"+a}return t}(e))}var V=function(){function e(){}return e.prototype.get=function(e){return void 0===e&&(e={}),s(this,void 0,void 0,(function(){var t,n;return l(this,(function(r){switch(r.label){case 0:return[4,W(j,void 0,[])];case 1:return t=r.sent(),n=function(e){var t;return{components:e,get visitorId(){return void 0===t&&(t=z(this.components)),t},set visitorId(e){t=e}}}(t),e.debug&&console.log("Copy the text below to get the debug data:\n\n```\nversion: 3.0.3\nuserAgent: "+navigator.userAgent+"\ngetOptions: "+JSON.stringify(e,void 0,2)+"\nvisitorId: "+n.visitorId+"\ncomponents: "+N(t)+"\n```"),[2,n]}}))}))},e}();function J(e){var t=(void 0===e?{}:e).delayFallback,n=void 0===t?50:t;return s(this,void 0,void 0,(function(){return l(this,(function(e){switch(e.label){case 0:return[4,(t=n,new Promise((function(e){window.requestIdleCallback?window.requestIdleCallback((function(){return e()})):setTimeout(e,t)})))];case 1:return e.sent(),[2,new V]}var t}))}))}var q={load:J,hashComponents:z,componentsToDebugString:N},K=c;e.componentsToDebugString=N,e.default=q,e.getComponents=W,e.hashComponents=z,e.isChromium=b,e.isDesktopSafari=S,e.isEdgeHTML=y,e.isGecko=function(){var e;return h(["buildID"in g,(null===(e=p.documentElement)||void 0===e?void 0:e.style)&&"MozAppearance"in p.documentElement.style,"MediaRecorderErrorEvent"in v,"mozInnerScreenX"in v,"CSSMozDocumentRule"in v,"CanvasCaptureMediaStream"in v])>=4},e.isTrident=m,e.isWebKit=w,e.load=J,e.murmurX64Hash128=K,Object.defineProperty(e,"__esModule",{value:!0})}));
... ...
  1 +{
  2 + "name": "@fingerprintjs/fingerprintjs",
  3 + "description": "Modern & flexible browser fingerprinting library",
  4 + "version": "3.0.3",
  5 + "keywords": [
  6 + "fraud",
  7 + "fraud detection",
  8 + "fraud prevention",
  9 + "browser",
  10 + "identification",
  11 + "fingerprint",
  12 + "fingerprinting",
  13 + "browser fingerprint",
  14 + "device fingerprint",
  15 + "privacy"
  16 + ],
  17 + "author": "FingerprintJS, Inc (https://fingerprintjs.com)",
  18 + "license": "MIT",
  19 + "repository": {
  20 + "type": "git",
  21 + "url": "https://github.com/fingerprintjs/fingerprintjs.git"
  22 + },
  23 + "bugs": {
  24 + "url": "https://github.com/fingerprintjs/fingerprintjs/issues"
  25 + },
  26 + "homepage": "https://github.com/fingerprintjs/fingerprintjs",
  27 + "main": "dist/fp.cjs.js",
  28 + "module": "dist/fp.esm.js",
  29 + "types": "dist/fp.d.ts",
  30 + "sideEffects": false,
  31 + "files": [
  32 + "dist"
  33 + ],
  34 + "scripts": {
  35 + "build": "rimraf dist && rollup -c",
  36 + "build:watch": "yarn build --watch",
  37 + "playground:start": "cd playground && webpack-dev-server --mode development",
  38 + "playground:build": "cd playground && webpack --mode production",
  39 + "lint": "eslint --ext .js,.ts --ignore-path .gitignore --max-warnings 0 .",
  40 + "lint:fix": "yarn lint --fix",
  41 + "test:local": "karma start tests/karma.local.config.js --single-run",
  42 + "test:browserstack": "karma start tests/karma.browserstack.config.js --single-run",
  43 + "test:dts": "tsc --noEmit dist/fp.d.ts"
  44 + },
  45 + "dependencies": {
  46 + "tslib": "^2.0.1"
  47 + },
  48 + "devDependencies": {
  49 + "@rollup/plugin-json": "^4.1.0",
  50 + "@rollup/plugin-node-resolve": "^9.0.0",
  51 + "@rollup/plugin-typescript": "^6.0.0",
  52 + "@types/jasmine": "^3.5.14",
  53 + "@types/ua-parser-js": "^0.7.33",
  54 + "@typescript-eslint/eslint-plugin": "^4.4.1",
  55 + "@typescript-eslint/parser": "^4.4.1",
  56 + "clean-webpack-plugin": "^3.0.0",
  57 + "eslint": "^7.11.0",
  58 + "eslint-config-prettier": "^6.13.0",
  59 + "eslint-plugin-prettier": "^3.1.4",
  60 + "file-loader": "^6.2.0",
  61 + "html-webpack-plugin": "^4.5.0",
  62 + "karma": "^5.2.3",
  63 + "karma-browserstack-launcher": "^1.6.0",
  64 + "karma-chrome-launcher": "^3.1.0",
  65 + "karma-firefox-launcher": "^1.3.0",
  66 + "karma-jasmine": "^4.0.1",
  67 + "karma-spec-reporter": "^0.0.32",
  68 + "karma-summary-reporter": "^1.9.0",
  69 + "karma-typescript": "^5.2.0",
  70 + "prettier": "^2.1.2",
  71 + "promise-polyfill": "^8.2.0",
  72 + "rimraf": "^3.0.2",
  73 + "rollup": "^2.28.2",
  74 + "rollup-plugin-dts": "^1.4.13",
  75 + "rollup-plugin-license": "^2.2.0",
  76 + "rollup-plugin-terser": "^7.0.2",
  77 + "terser-webpack-plugin": "^4.2.3",
  78 + "ts-loader": "^8.0.7",
  79 + "typescript": "^4.0.3",
  80 + "ua-parser-js": "^0.7.22",
  81 + "webpack": "^4.44.2",
  82 + "webpack-cli": "^3.3.12",
  83 + "webpack-dev-server": "^3.11.0"
  84 + }
  85 +}
... ...
  1 +<p align="center">
  2 + <a href="https://fingerprintjs.com">
  3 + <img src="resources/logo.svg" alt="FingerprintJS" width="300px" />
  4 + </a>
  5 +</p>
  6 +<p align="center">
  7 + <a href="https://github.com/fingerprintjs/fingerprintjs/actions?workflow=Lint%20and%20test">
  8 + <img src="https://github.com/fingerprintjs/fingerprintjs/workflows/Lint%20and%20test/badge.svg" alt="Build status">
  9 + </a>
  10 + <a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs">
  11 + <img src="https://img.shields.io/npm/dt/fingerprintjs2.svg" alt="Total downloads from NPM">
  12 + </a>
  13 + <a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs">
  14 + <img src="https://img.shields.io/npm/v/@fingerprintjs/fingerprintjs.svg" alt="Current NPM version">
  15 + </a>
  16 +</p>
  17 +
  18 +Makes a website visitor identifier from a browser fingerprint.
  19 +Unlike cookies and local storage, fingerprint stays the same in incognito/private mode and even when browser data is purged.
  20 +[Demo](https://fingerprintjs.github.io/fingerprintjs/).
  21 +
  22 +## Quick start
  23 +
  24 +### Install from CDN
  25 +
  26 +```html
  27 +<script>
  28 + function initFingerprintJS() {
  29 + FingerprintJS.load().then(fp => {
  30 + // The FingerprintJS agent is ready.
  31 + // Get a visitor identifier when you'd like to.
  32 + fp.get().then(result => {
  33 + // This is the visitor identifier:
  34 + const visitorId = result.visitorId;
  35 + console.log(visitorId);
  36 + });
  37 + });
  38 + }
  39 +</script>
  40 +<script
  41 + async
  42 + src="//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.min.js"
  43 + onload="initFingerprintJS()"
  44 +></script>
  45 +```
  46 +
  47 +### Alternatively you can install from NPM to use with Webpack/Rollup/Browserify
  48 +
  49 +```bash
  50 +npm i @fingerprintjs/fingerprintjs
  51 +# or
  52 +yarn add @fingerprintjs/fingerprintjs
  53 +```
  54 +
  55 +```js
  56 +import FingerprintJS from '@fingerprintjs/fingerprintjs';
  57 +
  58 +(async () => {
  59 + // We recommend to call `load` at application startup.
  60 + const fp = await FingerprintJS.load();
  61 +
  62 + // The FingerprintJS agent is ready.
  63 + // Get a visitor identifier when you'd like to.
  64 + const result = await fp.get();
  65 +
  66 + // This is the visitor identifier:
  67 + const visitorId = result.visitorId;
  68 + console.log(visitorId);
  69 +})();
  70 +```
  71 +
  72 +📕 [Full documentation](#open-source-version-reference)
  73 +
  74 +## Upgrade to [Pro version](https://fingerprintjs.com) to get 99.5% identification accuracy
  75 +
  76 +<p align="center">
  77 + <a href="https://fingerprintjs.com">
  78 + <img src="resources/pro_screenshot.png" alt="Pro screenshot" width="697px" />
  79 + </a>
  80 +</p>
  81 +
  82 +<table>
  83 + <thead>
  84 + <tr>
  85 + <th></th>
  86 + <!-- The <img>s are to make the table take the full width -->
  87 + <th align="center"><img width="350" height="0"> <p>Open Source version</p></th>
  88 + <th align="center"><img width="350" height="0"> <p>Pro version</p></th>
  89 + </tr>
  90 + </thead>
  91 + <tbody>
  92 + <tr><td>Identification accuracy</td><td align="center">60%</td><td align="center">99.5%</td></tr>
  93 + <tr><td>Bot detection</td><td align="center"></td><td align="center"></td></tr>
  94 + <tr><td>Incognito / Private mode detection</td><td align="center"></td><td align="center"></td></tr>
  95 + <tr><td>Geolocation</td><td align="center"></td><td align="center"></td></tr>
  96 + <tr><td>Security</td><td align="center"></td><td align="center"></td></tr>
  97 + <tr><td>Server API</td><td align="center"></td><td align="center"></td></tr>
  98 + <tr><td>Webhooks</td><td align="center"></td><td align="center"></td></tr>
  99 + <tr><td>Stable identifier between versions</td><td align="center"></td><td align="center"></td></tr>
  100 + </tbody>
  101 +</table>
  102 +
  103 +Pro result example:
  104 +
  105 +```js
  106 +{
  107 + "requestId": "HFMlljrzKEiZmhUNDx7Z",
  108 + "visitorId": "kHqPGWS1Mj18sZFsP8Wl",
  109 + "visitorFound": true,
  110 + "incognito": false,
  111 + "bot": { "probability": 0.96 },
  112 + "browserName": "Chrome",
  113 + "browserVersion": "85.0.4183",
  114 + "os": "Mac OS X",
  115 + "osVersion": "10.15.6",
  116 + "device": "Other",
  117 + "ip": "192.65.67.131",
  118 + "ipLocation": {
  119 + "accuracyRadius": 100,
  120 + "latitude": 37.409657,
  121 + "longitude": -121.965467
  122 + // ...
  123 + }
  124 +}
  125 +```
  126 +
  127 +🍿 [Live demo](https://fingerprintjs.com/demo)
  128 +
  129 +[How to upgrade from Open Source to Pro in 30 seconds](https://dev.fingerprintjs.com/v3/docs/migrating-from-previous-versions#from-fingerprintjs-open-source-version-3)
  130 +
  131 +📕 [FingerprintJS Pro documentation](https://dev.fingerprintjs.com)
  132 +
  133 +## Open-source version reference
  134 +
  135 +### Installation
  136 +
  137 +The library is shipped in various formats:
  138 +
  139 +- Global variable
  140 + ```html
  141 + <script>
  142 + function initFingerprintJS() {
  143 + // Start loading FingerprintJS here
  144 + }
  145 + </script>
  146 + <script
  147 + async
  148 + src="//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.min.js"
  149 + onload="initFingerprintJS()"
  150 + ></script>
  151 + ```
  152 +- UMD
  153 + ```js
  154 + require(
  155 + ['//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.umd.min.js'],
  156 + (FingerprintJS) => {
  157 + // Start loading FingerprintJS here
  158 + }
  159 + );
  160 + ```
  161 +- ECMAScript module
  162 + ```bash
  163 + # Install the package first:
  164 + npm i @fingerprintjs/fingerprintjs
  165 + # or
  166 + yarn add @fingerprintjs/fingerprintjs
  167 + ```
  168 +
  169 + ```js
  170 + import FingerprintJS from '@fingerprintjs/fingerprintjs';
  171 +
  172 + // Start loading FingerprintJS here
  173 + ```
  174 +- CommonJS
  175 + ```bash
  176 + # Install the package first:
  177 + npm i @fingerprintjs/fingerprintjs
  178 + # or
  179 + yarn add @fingerprintjs/fingerprintjs
  180 + ```
  181 +
  182 + ```js
  183 + const FingerprintJS = require('@fingerprintjs/fingerprintjs');
  184 +
  185 + // Start loading FingerprintJS here
  186 + ```
  187 +
  188 +### API
  189 +
  190 +- `FingerprintJS.load({ delayFallback?: number }): Promise<Agent>`
  191 +
  192 + Builds an instance of Agent and waits a delay required for a proper operation.
  193 + `delayFallback` is an optional parameter that sets duration (milliseconds) of the fallback for browsers that don't support [requestIdleCallback](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback);
  194 + it has a good default value which we don't recommend to change.
  195 +
  196 +- `agent.get({ debug?: boolean }): Promise<{ visitorId: string, components: {/* ... */} }>`
  197 +
  198 + Gets the visitor identifier.
  199 + `debug: true` prints debug messages to the console.
  200 + `visitorId` is the visitor identifier.
  201 + `components` is a dictionary of components that have formed the identifier;
  202 + each value is an object like `{ value: any, duration: number }` in case of success
  203 + and `{ error: object, duration: number }` in case of an unexpected error during getting the component.
  204 +
  205 +- `FingerprintJS.hashComponents(components: object): string`
  206 +
  207 + Converts a dictionary of components (described above) into a short hash string a.k.a. a visitor identifier.
  208 + Designed for extending the library with your own components.
  209 +
  210 +- `FingerprintJS.componentsToDebugString(components: object): string`
  211 +
  212 + Converts a dictionary of components (described above) into human-friendly format.
  213 +
  214 +## Migrating from v2
  215 +
  216 +- [Migration guide](docs/migrating_v2_v3.md)
  217 +- [V2 documentation](https://github.com/fingerprintjs/fingerprintjs/tree/v2)
  218 +
  219 +## Version policy
  220 +
  221 +The OSS version doesn't guarantee the same visitor identifier between versions,
  222 +but will try to keep them the same as much as possible.
  223 +To get identifiers that remain stable up to 1 year, please consider [upgrading to pro.](https://dashboard.fingerprintjs.com)
  224 +
  225 +The documented JS API follows [Semantic Versioning](https://semver.org).
  226 +Use undocumented features at your own risk.
  227 +
  228 +## Browser support
  229 +
  230 +```bash
  231 +npx browserslist "cover 95% in us, not IE < 10"
  232 +```
  233 +
  234 +See more details and learn how to run the library in old browsers in the [documentation article](docs/browser_support.md).
  235 +
  236 +## Contributing
  237 +
  238 +See the [contributing guidelines](contributing.md) to learn how to start a playground, test and build.
... ...
注册登录 后发表评论