@fingerprintjs/fingerprintjs
Advanced tools
Comparing version 3.0.6 to 3.0.7
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -247,15 +247,16 @@ * | ||
var version = "3.0.6"; | ||
var version = "3.0.7"; | ||
function wait(durationMs, resolveWith) { | ||
return new Promise(function (resolve) { return setTimeout(resolve, durationMs, resolveWith); }); | ||
} | ||
function requestIdleCallbackIfAvailable(fallbackTimeout, deadlineTimeout) { | ||
if (deadlineTimeout === void 0) { deadlineTimeout = Infinity; } | ||
return new Promise(function (resolve) { | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); | ||
} | ||
else { | ||
setTimeout(resolve, Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
}); | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
return new Promise(function (resolve) { return requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); }); | ||
} | ||
else { | ||
return wait(Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
} | ||
@@ -453,3 +454,3 @@ | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var w, AudioContext, context, oscillator, compressor, buffer, error_1; | ||
var w, AudioContext, hashFromIndex, hashToIndex, context, oscillator, compressor, buffer, error_1; | ||
return tslib.__generator(this, function (_a) { | ||
@@ -470,13 +471,14 @@ switch (_a.label) { | ||
} | ||
context = new AudioContext(1, 44100, 44100); | ||
hashFromIndex = 4500; | ||
hashToIndex = 5000; | ||
context = new AudioContext(1, hashToIndex, 44100); | ||
oscillator = context.createOscillator(); | ||
oscillator.type = 'triangle'; | ||
setAudioParam(context, oscillator.frequency, 10000); | ||
oscillator.frequency.value = 10000; | ||
compressor = context.createDynamicsCompressor(); | ||
setAudioParam(context, compressor.threshold, -50); | ||
setAudioParam(context, compressor.knee, 40); | ||
setAudioParam(context, compressor.ratio, 12); | ||
setAudioParam(context, compressor.reduction, -20); | ||
setAudioParam(context, compressor.attack, 0); | ||
setAudioParam(context, compressor.release, 0.25); | ||
compressor.threshold.value = -50; | ||
compressor.knee.value = 40; | ||
compressor.ratio.value = 12; | ||
compressor.attack.value = 0; | ||
compressor.release.value = 0.25; | ||
oscillator.connect(compressor); | ||
@@ -487,7 +489,7 @@ compressor.connect(context.destination); | ||
case 1: | ||
_a.trys.push([1, 3, 4, 5]); | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, renderAudio(context)]; | ||
case 2: | ||
buffer = _a.sent(); | ||
return [3 /*break*/, 5]; | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
@@ -499,7 +501,3 @@ error_1 = _a.sent(); | ||
throw error_1; | ||
case 4: | ||
oscillator.disconnect(); | ||
compressor.disconnect(); | ||
return [7 /*endfinally*/]; | ||
case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))]; | ||
case 4: return [2 /*return*/, getHash(buffer.getChannelData(0).subarray(hashFromIndex))]; | ||
} | ||
@@ -515,10 +513,2 @@ }); | ||
} | ||
function setAudioParam(context, param, value) { | ||
var isAudioParam = function (value) { | ||
return value && typeof value.setValueAtTime === 'function'; | ||
}; | ||
if (isAudioParam(param)) { | ||
param.setValueAtTime(value, context.currentTime); | ||
} | ||
} | ||
function renderAudio(context) { | ||
@@ -562,3 +552,3 @@ var resumeTriesMaxCount = 3; | ||
var hash = 0; | ||
for (var i = 4500; i < 5000; ++i) { | ||
for (var i = 0; i < signal.length; ++i) { | ||
hash += Math.abs(signal[i]); | ||
@@ -574,2 +564,70 @@ } | ||
/** | ||
* Creates and keeps an invisible iframe while the given function runs. | ||
* The given function is called when the iframe is loaded and has a body. | ||
* The iframe allows to measure DOM sizes inside itself. | ||
* | ||
* Notice: passing an initial HTML code doesn't work in IE. | ||
* | ||
* Warning for package users: | ||
* This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk. | ||
*/ | ||
function withIframe(action, initialHtml, domPollInterval) { | ||
var _a, _b; | ||
if (domPollInterval === void 0) { domPollInterval = 50; } | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var d, iframe; | ||
return tslib.__generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
d = document; | ||
_c.label = 1; | ||
case 1: | ||
if (!!d.body) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 2: | ||
_c.sent(); | ||
return [3 /*break*/, 1]; | ||
case 3: | ||
iframe = d.createElement('iframe'); | ||
_c.label = 4; | ||
case 4: | ||
_c.trys.push([4, , 10, 11]); | ||
return [4 /*yield*/, new Promise(function (resolve, reject) { | ||
iframe.onload = resolve; | ||
iframe.onerror = reject; | ||
var style = iframe.style; | ||
style.setProperty('display', 'block', 'important'); // Required for browsers to calculate the layout | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.visibility = 'hidden'; | ||
if (initialHtml && 'srcdoc' in iframe) { | ||
iframe.srcdoc = initialHtml; | ||
} | ||
else { | ||
iframe.src = 'about:blank'; | ||
} | ||
d.body.appendChild(iframe); | ||
})]; | ||
case 5: | ||
_c.sent(); | ||
_c.label = 6; | ||
case 6: | ||
if (!!((_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document.body)) return [3 /*break*/, 8]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 7: | ||
_c.sent(); | ||
return [3 /*break*/, 6]; | ||
case 8: return [4 /*yield*/, action(iframe, iframe.contentWindow)]; | ||
case 9: return [2 /*return*/, _c.sent()]; | ||
case 10: | ||
(_b = iframe.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(iframe); | ||
return [7 /*endfinally*/]; | ||
case 11: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
// We use m or w because these two characters take up the maximum width. | ||
@@ -579,3 +637,3 @@ // And we use a LLi so that the same matching fonts can get separated. | ||
// We test using 48px font size, we may use any size. I guess larger the better. | ||
var testSize = '48px'; | ||
var textSize = '48px'; | ||
// A font will be compared against all the three default fonts. | ||
@@ -639,105 +697,69 @@ // And if it doesn't match all 3 then that font is not available. | ||
]; | ||
var fontSpanStyle = { | ||
// CSS font reset to reset external styles | ||
fontStyle: 'normal', | ||
fontWeight: 'normal', | ||
letterSpacing: 'normal', | ||
lineBreak: 'auto', | ||
lineHeight: 'normal', | ||
textTransform: 'none', | ||
textAlign: 'left', | ||
textDecoration: 'none', | ||
textShadow: 'none', | ||
whiteSpace: 'normal', | ||
wordBreak: 'normal', | ||
wordSpacing: 'normal', | ||
// We need this css as in some weird browser this span elements shows up for a microSec which creates | ||
// a bad user experience | ||
position: 'absolute', | ||
left: '-9999px', | ||
fontSize: testSize, | ||
}; | ||
// kudos to http://www.lalit.org/lab/javascript-css-font-detect/ | ||
function getFonts() { | ||
var d = document; | ||
var holder = d.body; | ||
// div to load spans for the base fonts | ||
var baseFontsDiv = d.createElement('div'); | ||
// div to load spans for the fonts to detect | ||
var fontsDiv = d.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function () { | ||
var span = d.createElement('span'); | ||
span.textContent = testString; | ||
for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) { | ||
var prop = _a[_i]; | ||
span.style[prop] = fontSpanStyle[prop]; | ||
} | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = "'" + fontToDetect + "'," + baseFont; | ||
return s; | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(function (baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = baseFont; | ||
baseFontsDiv.appendChild(s); | ||
return s; | ||
}); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { | ||
var s = createSpanWithFonts(font, baseFont); | ||
fontsDiv.appendChild(s); | ||
return s; | ||
function getFontsIframe() { | ||
// Running the script in an iframe makes it not affect the page look and not be affected by the page CSS. See: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/592 | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/628 | ||
return withIframe(function (_, _a) { | ||
var document = _a.document; | ||
var holder = document.body; | ||
holder.style.fontSize = textSize; | ||
// div to load spans for the default fonts and the fonts to detect | ||
var spansContainer = document.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function (fontFamily) { | ||
var span = document.createElement('span'); | ||
var style = span.style; | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.fontFamily = fontFamily; | ||
span.textContent = testString; | ||
spansContainer.appendChild(span); | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
return createSpan("'" + fontToDetect + "'," + baseFont); | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(createSpan); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { return createSpanWithFonts(font, baseFont); }); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(spansContainer); | ||
// get the default width for the three base fonts | ||
for (var index = 0; index < baseFonts.length; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// add the spans to the DOM | ||
holder.appendChild(baseFontsDiv); | ||
// get the default width for the three base fonts | ||
for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(fontsDiv); | ||
// check available fonts | ||
var available = []; | ||
for (var i = 0, l = fontList.length; i < l; i++) { | ||
if (isFontAvailable(fontsSpans[fontList[i]])) { | ||
available.push(fontList[i]); | ||
} | ||
} | ||
// remove spans from DOM | ||
holder.removeChild(fontsDiv); | ||
holder.removeChild(baseFontsDiv); | ||
return available; | ||
// check available fonts | ||
return fontList.filter(function (font) { return isFontAvailable(fontsSpans[font]); }); | ||
}); | ||
} | ||
@@ -797,4 +819,4 @@ | ||
} | ||
// detect browser support of canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// Detect browser support of canvas winding | ||
// https://web.archive.org/web/20170825024655/http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js | ||
@@ -808,9 +830,11 @@ context.rect(0, 0, 10, 10); | ||
context.fillStyle = '#069'; | ||
// https://github.com/Valve/fingerprintjs2/issues/66 | ||
// this can affect FP generation when applying different CSS on different websites | ||
// This can affect FP generation when applying different CSS on different websites: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
context.font = '11pt no-real-font-123'; | ||
// the choice of emojis has a gigantic impact on rendering performance (especially in FF) | ||
// some newer emojis cause it to slow down 50-200 times | ||
// context.fillText("CwēØm fjordbank \ud83d\ude03 gly", 2, 15) | ||
var printedText = 'Cwm fjordbank \ud83d\ude03 gly'; | ||
// The choice of emojis has a gigantic impact on rendering performance (especially in FF). | ||
// Some newer emojis cause it to slow down 50-200 times. | ||
// A bare emoji shouldn't be used because the canvas will change depending on the script encoding: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
// Escape sequence shouldn't be used too because Terser will turn it into a bare unicode. | ||
var printedText = "Cwm fjordbank " + String.fromCharCode(55357, 56835) /* š */ + " gly"; | ||
context.fillText(printedText, 2, 15); | ||
@@ -820,25 +844,22 @@ context.fillStyle = 'rgba(102, 204, 0, 0.2)'; | ||
context.fillText(printedText, 4, 45); | ||
// canvas blending | ||
// http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// Canvas blending | ||
// https://web.archive.org/web/20170826194121/http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/16/ | ||
context.globalCompositeOperation = 'multiply'; | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
context.beginPath(); | ||
context.arc(50, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(0,255,255)'; | ||
context.beginPath(); | ||
context.arc(100, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,255,0)'; | ||
context.beginPath(); | ||
context.arc(75, 100, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
// canvas winding | ||
for (var _i = 0, _b = [ | ||
['#f0f', 50, 50], | ||
['#0ff', 100, 50], | ||
['#ff0', 75, 100], | ||
]; _i < _b.length; _i++) { | ||
var _c = _b[_i], color = _c[0], x = _c[1], y = _c[2]; | ||
context.fillStyle = color; | ||
context.beginPath(); | ||
context.arc(x, y, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
} | ||
// Canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/19/ | ||
context.fillStyle = '#f0f'; | ||
context.arc(75, 75, 75, 0, Math.PI * 2, true); | ||
@@ -1116,3 +1137,3 @@ context.arc(75, 75, 25, 0, Math.PI * 2, true); | ||
touchSupport: getTouchSupport, | ||
fonts: getFonts, | ||
fonts: getFontsIframe, | ||
audio: getAudioFingerprint, | ||
@@ -1222,2 +1243,3 @@ pluginsSupport: getPluginsSupport, | ||
}, | ||
version: version, | ||
}; | ||
@@ -1248,3 +1270,3 @@ } | ||
// eslint-disable-next-line no-console | ||
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```"); | ||
console.log("Copy the text below to get the debug data:\n\n```\nversion: " + result.version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```"); | ||
} | ||
@@ -1251,0 +1273,0 @@ return [2 /*return*/, result]; |
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -13,3 +13,3 @@ * | ||
declare function getFonts(): string[]; | ||
declare function getFontsIframe(): Promise<string[]>; | ||
@@ -129,3 +129,3 @@ interface PluginMimeTypeData { | ||
touchSupport: typeof getTouchSupport; | ||
fonts: typeof getFonts; | ||
fonts: typeof getFontsIframe; | ||
audio: typeof getAudioFingerprint; | ||
@@ -235,2 +235,8 @@ pluginsSupport: typeof getPluginsSupport; | ||
components: BuiltinComponents; | ||
/** | ||
* The fingerprinting algorithm version | ||
* | ||
* @see https://github.com/fingerprintjs/fingerprintjs#version-policy For more details | ||
*/ | ||
version: string; | ||
} | ||
@@ -237,0 +243,0 @@ /** |
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -243,15 +243,16 @@ * | ||
var version = "3.0.6"; | ||
var version = "3.0.7"; | ||
function wait(durationMs, resolveWith) { | ||
return new Promise(function (resolve) { return setTimeout(resolve, durationMs, resolveWith); }); | ||
} | ||
function requestIdleCallbackIfAvailable(fallbackTimeout, deadlineTimeout) { | ||
if (deadlineTimeout === void 0) { deadlineTimeout = Infinity; } | ||
return new Promise(function (resolve) { | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); | ||
} | ||
else { | ||
setTimeout(resolve, Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
}); | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
return new Promise(function (resolve) { return requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); }); | ||
} | ||
else { | ||
return wait(Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
} | ||
@@ -449,3 +450,3 @@ | ||
return __awaiter(this, void 0, void 0, function () { | ||
var w, AudioContext, context, oscillator, compressor, buffer, error_1; | ||
var w, AudioContext, hashFromIndex, hashToIndex, context, oscillator, compressor, buffer, error_1; | ||
return __generator(this, function (_a) { | ||
@@ -466,13 +467,14 @@ switch (_a.label) { | ||
} | ||
context = new AudioContext(1, 44100, 44100); | ||
hashFromIndex = 4500; | ||
hashToIndex = 5000; | ||
context = new AudioContext(1, hashToIndex, 44100); | ||
oscillator = context.createOscillator(); | ||
oscillator.type = 'triangle'; | ||
setAudioParam(context, oscillator.frequency, 10000); | ||
oscillator.frequency.value = 10000; | ||
compressor = context.createDynamicsCompressor(); | ||
setAudioParam(context, compressor.threshold, -50); | ||
setAudioParam(context, compressor.knee, 40); | ||
setAudioParam(context, compressor.ratio, 12); | ||
setAudioParam(context, compressor.reduction, -20); | ||
setAudioParam(context, compressor.attack, 0); | ||
setAudioParam(context, compressor.release, 0.25); | ||
compressor.threshold.value = -50; | ||
compressor.knee.value = 40; | ||
compressor.ratio.value = 12; | ||
compressor.attack.value = 0; | ||
compressor.release.value = 0.25; | ||
oscillator.connect(compressor); | ||
@@ -483,7 +485,7 @@ compressor.connect(context.destination); | ||
case 1: | ||
_a.trys.push([1, 3, 4, 5]); | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, renderAudio(context)]; | ||
case 2: | ||
buffer = _a.sent(); | ||
return [3 /*break*/, 5]; | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
@@ -495,7 +497,3 @@ error_1 = _a.sent(); | ||
throw error_1; | ||
case 4: | ||
oscillator.disconnect(); | ||
compressor.disconnect(); | ||
return [7 /*endfinally*/]; | ||
case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))]; | ||
case 4: return [2 /*return*/, getHash(buffer.getChannelData(0).subarray(hashFromIndex))]; | ||
} | ||
@@ -511,10 +509,2 @@ }); | ||
} | ||
function setAudioParam(context, param, value) { | ||
var isAudioParam = function (value) { | ||
return value && typeof value.setValueAtTime === 'function'; | ||
}; | ||
if (isAudioParam(param)) { | ||
param.setValueAtTime(value, context.currentTime); | ||
} | ||
} | ||
function renderAudio(context) { | ||
@@ -558,3 +548,3 @@ var resumeTriesMaxCount = 3; | ||
var hash = 0; | ||
for (var i = 4500; i < 5000; ++i) { | ||
for (var i = 0; i < signal.length; ++i) { | ||
hash += Math.abs(signal[i]); | ||
@@ -570,2 +560,70 @@ } | ||
/** | ||
* Creates and keeps an invisible iframe while the given function runs. | ||
* The given function is called when the iframe is loaded and has a body. | ||
* The iframe allows to measure DOM sizes inside itself. | ||
* | ||
* Notice: passing an initial HTML code doesn't work in IE. | ||
* | ||
* Warning for package users: | ||
* This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk. | ||
*/ | ||
function withIframe(action, initialHtml, domPollInterval) { | ||
var _a, _b; | ||
if (domPollInterval === void 0) { domPollInterval = 50; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var d, iframe; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
d = document; | ||
_c.label = 1; | ||
case 1: | ||
if (!!d.body) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 2: | ||
_c.sent(); | ||
return [3 /*break*/, 1]; | ||
case 3: | ||
iframe = d.createElement('iframe'); | ||
_c.label = 4; | ||
case 4: | ||
_c.trys.push([4, , 10, 11]); | ||
return [4 /*yield*/, new Promise(function (resolve, reject) { | ||
iframe.onload = resolve; | ||
iframe.onerror = reject; | ||
var style = iframe.style; | ||
style.setProperty('display', 'block', 'important'); // Required for browsers to calculate the layout | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.visibility = 'hidden'; | ||
if (initialHtml && 'srcdoc' in iframe) { | ||
iframe.srcdoc = initialHtml; | ||
} | ||
else { | ||
iframe.src = 'about:blank'; | ||
} | ||
d.body.appendChild(iframe); | ||
})]; | ||
case 5: | ||
_c.sent(); | ||
_c.label = 6; | ||
case 6: | ||
if (!!((_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document.body)) return [3 /*break*/, 8]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 7: | ||
_c.sent(); | ||
return [3 /*break*/, 6]; | ||
case 8: return [4 /*yield*/, action(iframe, iframe.contentWindow)]; | ||
case 9: return [2 /*return*/, _c.sent()]; | ||
case 10: | ||
(_b = iframe.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(iframe); | ||
return [7 /*endfinally*/]; | ||
case 11: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
// We use m or w because these two characters take up the maximum width. | ||
@@ -575,3 +633,3 @@ // And we use a LLi so that the same matching fonts can get separated. | ||
// We test using 48px font size, we may use any size. I guess larger the better. | ||
var testSize = '48px'; | ||
var textSize = '48px'; | ||
// A font will be compared against all the three default fonts. | ||
@@ -635,105 +693,69 @@ // And if it doesn't match all 3 then that font is not available. | ||
]; | ||
var fontSpanStyle = { | ||
// CSS font reset to reset external styles | ||
fontStyle: 'normal', | ||
fontWeight: 'normal', | ||
letterSpacing: 'normal', | ||
lineBreak: 'auto', | ||
lineHeight: 'normal', | ||
textTransform: 'none', | ||
textAlign: 'left', | ||
textDecoration: 'none', | ||
textShadow: 'none', | ||
whiteSpace: 'normal', | ||
wordBreak: 'normal', | ||
wordSpacing: 'normal', | ||
// We need this css as in some weird browser this span elements shows up for a microSec which creates | ||
// a bad user experience | ||
position: 'absolute', | ||
left: '-9999px', | ||
fontSize: testSize, | ||
}; | ||
// kudos to http://www.lalit.org/lab/javascript-css-font-detect/ | ||
function getFonts() { | ||
var d = document; | ||
var holder = d.body; | ||
// div to load spans for the base fonts | ||
var baseFontsDiv = d.createElement('div'); | ||
// div to load spans for the fonts to detect | ||
var fontsDiv = d.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function () { | ||
var span = d.createElement('span'); | ||
span.textContent = testString; | ||
for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) { | ||
var prop = _a[_i]; | ||
span.style[prop] = fontSpanStyle[prop]; | ||
} | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = "'" + fontToDetect + "'," + baseFont; | ||
return s; | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(function (baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = baseFont; | ||
baseFontsDiv.appendChild(s); | ||
return s; | ||
}); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { | ||
var s = createSpanWithFonts(font, baseFont); | ||
fontsDiv.appendChild(s); | ||
return s; | ||
function getFontsIframe() { | ||
// Running the script in an iframe makes it not affect the page look and not be affected by the page CSS. See: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/592 | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/628 | ||
return withIframe(function (_, _a) { | ||
var document = _a.document; | ||
var holder = document.body; | ||
holder.style.fontSize = textSize; | ||
// div to load spans for the default fonts and the fonts to detect | ||
var spansContainer = document.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function (fontFamily) { | ||
var span = document.createElement('span'); | ||
var style = span.style; | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.fontFamily = fontFamily; | ||
span.textContent = testString; | ||
spansContainer.appendChild(span); | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
return createSpan("'" + fontToDetect + "'," + baseFont); | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(createSpan); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { return createSpanWithFonts(font, baseFont); }); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(spansContainer); | ||
// get the default width for the three base fonts | ||
for (var index = 0; index < baseFonts.length; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// add the spans to the DOM | ||
holder.appendChild(baseFontsDiv); | ||
// get the default width for the three base fonts | ||
for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(fontsDiv); | ||
// check available fonts | ||
var available = []; | ||
for (var i = 0, l = fontList.length; i < l; i++) { | ||
if (isFontAvailable(fontsSpans[fontList[i]])) { | ||
available.push(fontList[i]); | ||
} | ||
} | ||
// remove spans from DOM | ||
holder.removeChild(fontsDiv); | ||
holder.removeChild(baseFontsDiv); | ||
return available; | ||
// check available fonts | ||
return fontList.filter(function (font) { return isFontAvailable(fontsSpans[font]); }); | ||
}); | ||
} | ||
@@ -793,4 +815,4 @@ | ||
} | ||
// detect browser support of canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// Detect browser support of canvas winding | ||
// https://web.archive.org/web/20170825024655/http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js | ||
@@ -804,9 +826,11 @@ context.rect(0, 0, 10, 10); | ||
context.fillStyle = '#069'; | ||
// https://github.com/Valve/fingerprintjs2/issues/66 | ||
// this can affect FP generation when applying different CSS on different websites | ||
// This can affect FP generation when applying different CSS on different websites: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
context.font = '11pt no-real-font-123'; | ||
// the choice of emojis has a gigantic impact on rendering performance (especially in FF) | ||
// some newer emojis cause it to slow down 50-200 times | ||
// context.fillText("CwēØm fjordbank \ud83d\ude03 gly", 2, 15) | ||
var printedText = 'Cwm fjordbank \ud83d\ude03 gly'; | ||
// The choice of emojis has a gigantic impact on rendering performance (especially in FF). | ||
// Some newer emojis cause it to slow down 50-200 times. | ||
// A bare emoji shouldn't be used because the canvas will change depending on the script encoding: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
// Escape sequence shouldn't be used too because Terser will turn it into a bare unicode. | ||
var printedText = "Cwm fjordbank " + String.fromCharCode(55357, 56835) /* š */ + " gly"; | ||
context.fillText(printedText, 2, 15); | ||
@@ -816,25 +840,22 @@ context.fillStyle = 'rgba(102, 204, 0, 0.2)'; | ||
context.fillText(printedText, 4, 45); | ||
// canvas blending | ||
// http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// Canvas blending | ||
// https://web.archive.org/web/20170826194121/http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/16/ | ||
context.globalCompositeOperation = 'multiply'; | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
context.beginPath(); | ||
context.arc(50, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(0,255,255)'; | ||
context.beginPath(); | ||
context.arc(100, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,255,0)'; | ||
context.beginPath(); | ||
context.arc(75, 100, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
// canvas winding | ||
for (var _i = 0, _b = [ | ||
['#f0f', 50, 50], | ||
['#0ff', 100, 50], | ||
['#ff0', 75, 100], | ||
]; _i < _b.length; _i++) { | ||
var _c = _b[_i], color = _c[0], x = _c[1], y = _c[2]; | ||
context.fillStyle = color; | ||
context.beginPath(); | ||
context.arc(x, y, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
} | ||
// Canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/19/ | ||
context.fillStyle = '#f0f'; | ||
context.arc(75, 75, 75, 0, Math.PI * 2, true); | ||
@@ -1112,3 +1133,3 @@ context.arc(75, 75, 25, 0, Math.PI * 2, true); | ||
touchSupport: getTouchSupport, | ||
fonts: getFonts, | ||
fonts: getFontsIframe, | ||
audio: getAudioFingerprint, | ||
@@ -1218,2 +1239,3 @@ pluginsSupport: getPluginsSupport, | ||
}, | ||
version: version, | ||
}; | ||
@@ -1244,3 +1266,3 @@ } | ||
// eslint-disable-next-line no-console | ||
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```"); | ||
console.log("Copy the text below to get the debug data:\n\n```\nversion: " + result.version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```"); | ||
} | ||
@@ -1247,0 +1269,0 @@ return [2 /*return*/, result]; |
352
dist/fp.js
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -308,15 +308,16 @@ * | ||
var version = "3.0.6"; | ||
var version = "3.0.7"; | ||
function wait(durationMs, resolveWith) { | ||
return new Promise(function (resolve) { return setTimeout(resolve, durationMs, resolveWith); }); | ||
} | ||
function requestIdleCallbackIfAvailable(fallbackTimeout, deadlineTimeout) { | ||
if (deadlineTimeout === void 0) { deadlineTimeout = Infinity; } | ||
return new Promise(function (resolve) { | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); | ||
} | ||
else { | ||
setTimeout(resolve, Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
}); | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
return new Promise(function (resolve) { return requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); }); | ||
} | ||
else { | ||
return wait(Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
} | ||
@@ -514,3 +515,3 @@ | ||
return __awaiter(this, void 0, void 0, function () { | ||
var w, AudioContext, context, oscillator, compressor, buffer, error_1; | ||
var w, AudioContext, hashFromIndex, hashToIndex, context, oscillator, compressor, buffer, error_1; | ||
return __generator(this, function (_a) { | ||
@@ -531,13 +532,14 @@ switch (_a.label) { | ||
} | ||
context = new AudioContext(1, 44100, 44100); | ||
hashFromIndex = 4500; | ||
hashToIndex = 5000; | ||
context = new AudioContext(1, hashToIndex, 44100); | ||
oscillator = context.createOscillator(); | ||
oscillator.type = 'triangle'; | ||
setAudioParam(context, oscillator.frequency, 10000); | ||
oscillator.frequency.value = 10000; | ||
compressor = context.createDynamicsCompressor(); | ||
setAudioParam(context, compressor.threshold, -50); | ||
setAudioParam(context, compressor.knee, 40); | ||
setAudioParam(context, compressor.ratio, 12); | ||
setAudioParam(context, compressor.reduction, -20); | ||
setAudioParam(context, compressor.attack, 0); | ||
setAudioParam(context, compressor.release, 0.25); | ||
compressor.threshold.value = -50; | ||
compressor.knee.value = 40; | ||
compressor.ratio.value = 12; | ||
compressor.attack.value = 0; | ||
compressor.release.value = 0.25; | ||
oscillator.connect(compressor); | ||
@@ -548,7 +550,7 @@ compressor.connect(context.destination); | ||
case 1: | ||
_a.trys.push([1, 3, 4, 5]); | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, renderAudio(context)]; | ||
case 2: | ||
buffer = _a.sent(); | ||
return [3 /*break*/, 5]; | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
@@ -560,7 +562,3 @@ error_1 = _a.sent(); | ||
throw error_1; | ||
case 4: | ||
oscillator.disconnect(); | ||
compressor.disconnect(); | ||
return [7 /*endfinally*/]; | ||
case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))]; | ||
case 4: return [2 /*return*/, getHash(buffer.getChannelData(0).subarray(hashFromIndex))]; | ||
} | ||
@@ -576,10 +574,2 @@ }); | ||
} | ||
function setAudioParam(context, param, value) { | ||
var isAudioParam = function (value) { | ||
return value && typeof value.setValueAtTime === 'function'; | ||
}; | ||
if (isAudioParam(param)) { | ||
param.setValueAtTime(value, context.currentTime); | ||
} | ||
} | ||
function renderAudio(context) { | ||
@@ -623,3 +613,3 @@ var resumeTriesMaxCount = 3; | ||
var hash = 0; | ||
for (var i = 4500; i < 5000; ++i) { | ||
for (var i = 0; i < signal.length; ++i) { | ||
hash += Math.abs(signal[i]); | ||
@@ -635,2 +625,70 @@ } | ||
/** | ||
* Creates and keeps an invisible iframe while the given function runs. | ||
* The given function is called when the iframe is loaded and has a body. | ||
* The iframe allows to measure DOM sizes inside itself. | ||
* | ||
* Notice: passing an initial HTML code doesn't work in IE. | ||
* | ||
* Warning for package users: | ||
* This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk. | ||
*/ | ||
function withIframe(action, initialHtml, domPollInterval) { | ||
var _a, _b; | ||
if (domPollInterval === void 0) { domPollInterval = 50; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var d, iframe; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
d = document; | ||
_c.label = 1; | ||
case 1: | ||
if (!!d.body) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 2: | ||
_c.sent(); | ||
return [3 /*break*/, 1]; | ||
case 3: | ||
iframe = d.createElement('iframe'); | ||
_c.label = 4; | ||
case 4: | ||
_c.trys.push([4, , 10, 11]); | ||
return [4 /*yield*/, new Promise(function (resolve, reject) { | ||
iframe.onload = resolve; | ||
iframe.onerror = reject; | ||
var style = iframe.style; | ||
style.setProperty('display', 'block', 'important'); // Required for browsers to calculate the layout | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.visibility = 'hidden'; | ||
if (initialHtml && 'srcdoc' in iframe) { | ||
iframe.srcdoc = initialHtml; | ||
} | ||
else { | ||
iframe.src = 'about:blank'; | ||
} | ||
d.body.appendChild(iframe); | ||
})]; | ||
case 5: | ||
_c.sent(); | ||
_c.label = 6; | ||
case 6: | ||
if (!!((_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document.body)) return [3 /*break*/, 8]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 7: | ||
_c.sent(); | ||
return [3 /*break*/, 6]; | ||
case 8: return [4 /*yield*/, action(iframe, iframe.contentWindow)]; | ||
case 9: return [2 /*return*/, _c.sent()]; | ||
case 10: | ||
(_b = iframe.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(iframe); | ||
return [7 /*endfinally*/]; | ||
case 11: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
// We use m or w because these two characters take up the maximum width. | ||
@@ -640,3 +698,3 @@ // And we use a LLi so that the same matching fonts can get separated. | ||
// We test using 48px font size, we may use any size. I guess larger the better. | ||
var testSize = '48px'; | ||
var textSize = '48px'; | ||
// A font will be compared against all the three default fonts. | ||
@@ -700,105 +758,69 @@ // And if it doesn't match all 3 then that font is not available. | ||
]; | ||
var fontSpanStyle = { | ||
// CSS font reset to reset external styles | ||
fontStyle: 'normal', | ||
fontWeight: 'normal', | ||
letterSpacing: 'normal', | ||
lineBreak: 'auto', | ||
lineHeight: 'normal', | ||
textTransform: 'none', | ||
textAlign: 'left', | ||
textDecoration: 'none', | ||
textShadow: 'none', | ||
whiteSpace: 'normal', | ||
wordBreak: 'normal', | ||
wordSpacing: 'normal', | ||
// We need this css as in some weird browser this span elements shows up for a microSec which creates | ||
// a bad user experience | ||
position: 'absolute', | ||
left: '-9999px', | ||
fontSize: testSize, | ||
}; | ||
// kudos to http://www.lalit.org/lab/javascript-css-font-detect/ | ||
function getFonts() { | ||
var d = document; | ||
var holder = d.body; | ||
// div to load spans for the base fonts | ||
var baseFontsDiv = d.createElement('div'); | ||
// div to load spans for the fonts to detect | ||
var fontsDiv = d.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function () { | ||
var span = d.createElement('span'); | ||
span.textContent = testString; | ||
for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) { | ||
var prop = _a[_i]; | ||
span.style[prop] = fontSpanStyle[prop]; | ||
} | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = "'" + fontToDetect + "'," + baseFont; | ||
return s; | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(function (baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = baseFont; | ||
baseFontsDiv.appendChild(s); | ||
return s; | ||
}); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { | ||
var s = createSpanWithFonts(font, baseFont); | ||
fontsDiv.appendChild(s); | ||
return s; | ||
function getFontsIframe() { | ||
// Running the script in an iframe makes it not affect the page look and not be affected by the page CSS. See: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/592 | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/628 | ||
return withIframe(function (_, _a) { | ||
var document = _a.document; | ||
var holder = document.body; | ||
holder.style.fontSize = textSize; | ||
// div to load spans for the default fonts and the fonts to detect | ||
var spansContainer = document.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function (fontFamily) { | ||
var span = document.createElement('span'); | ||
var style = span.style; | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.fontFamily = fontFamily; | ||
span.textContent = testString; | ||
spansContainer.appendChild(span); | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
return createSpan("'" + fontToDetect + "'," + baseFont); | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(createSpan); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { return createSpanWithFonts(font, baseFont); }); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(spansContainer); | ||
// get the default width for the three base fonts | ||
for (var index = 0; index < baseFonts.length; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// add the spans to the DOM | ||
holder.appendChild(baseFontsDiv); | ||
// get the default width for the three base fonts | ||
for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(fontsDiv); | ||
// check available fonts | ||
var available = []; | ||
for (var i = 0, l = fontList.length; i < l; i++) { | ||
if (isFontAvailable(fontsSpans[fontList[i]])) { | ||
available.push(fontList[i]); | ||
} | ||
} | ||
// remove spans from DOM | ||
holder.removeChild(fontsDiv); | ||
holder.removeChild(baseFontsDiv); | ||
return available; | ||
// check available fonts | ||
return fontList.filter(function (font) { return isFontAvailable(fontsSpans[font]); }); | ||
}); | ||
} | ||
@@ -858,4 +880,4 @@ | ||
} | ||
// detect browser support of canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// Detect browser support of canvas winding | ||
// https://web.archive.org/web/20170825024655/http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js | ||
@@ -869,9 +891,11 @@ context.rect(0, 0, 10, 10); | ||
context.fillStyle = '#069'; | ||
// https://github.com/Valve/fingerprintjs2/issues/66 | ||
// this can affect FP generation when applying different CSS on different websites | ||
// This can affect FP generation when applying different CSS on different websites: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
context.font = '11pt no-real-font-123'; | ||
// the choice of emojis has a gigantic impact on rendering performance (especially in FF) | ||
// some newer emojis cause it to slow down 50-200 times | ||
// context.fillText("CwēØm fjordbank \ud83d\ude03 gly", 2, 15) | ||
var printedText = 'Cwm fjordbank \ud83d\ude03 gly'; | ||
// The choice of emojis has a gigantic impact on rendering performance (especially in FF). | ||
// Some newer emojis cause it to slow down 50-200 times. | ||
// A bare emoji shouldn't be used because the canvas will change depending on the script encoding: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
// Escape sequence shouldn't be used too because Terser will turn it into a bare unicode. | ||
var printedText = "Cwm fjordbank " + String.fromCharCode(55357, 56835) /* š */ + " gly"; | ||
context.fillText(printedText, 2, 15); | ||
@@ -881,25 +905,22 @@ context.fillStyle = 'rgba(102, 204, 0, 0.2)'; | ||
context.fillText(printedText, 4, 45); | ||
// canvas blending | ||
// http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// Canvas blending | ||
// https://web.archive.org/web/20170826194121/http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/16/ | ||
context.globalCompositeOperation = 'multiply'; | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
context.beginPath(); | ||
context.arc(50, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(0,255,255)'; | ||
context.beginPath(); | ||
context.arc(100, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,255,0)'; | ||
context.beginPath(); | ||
context.arc(75, 100, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
// canvas winding | ||
for (var _i = 0, _b = [ | ||
['#f0f', 50, 50], | ||
['#0ff', 100, 50], | ||
['#ff0', 75, 100], | ||
]; _i < _b.length; _i++) { | ||
var _c = _b[_i], color = _c[0], x = _c[1], y = _c[2]; | ||
context.fillStyle = color; | ||
context.beginPath(); | ||
context.arc(x, y, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
} | ||
// Canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/19/ | ||
context.fillStyle = '#f0f'; | ||
context.arc(75, 75, 75, 0, Math.PI * 2, true); | ||
@@ -1177,3 +1198,3 @@ context.arc(75, 75, 25, 0, Math.PI * 2, true); | ||
touchSupport: getTouchSupport, | ||
fonts: getFonts, | ||
fonts: getFontsIframe, | ||
audio: getAudioFingerprint, | ||
@@ -1283,2 +1304,3 @@ pluginsSupport: getPluginsSupport, | ||
}, | ||
version: version, | ||
}; | ||
@@ -1309,3 +1331,3 @@ } | ||
// eslint-disable-next-line no-console | ||
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```"); | ||
console.log("Copy the text below to get the debug data:\n\n```\nversion: " + result.version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```"); | ||
} | ||
@@ -1312,0 +1334,0 @@ return [2 /*return*/, result]; |
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -9,2 +9,2 @@ * | ||
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],m=[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,m)),27),d),f=t(n(f,[0,5]),[0,1390208809]),v=r(v=n(v,m),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)]),m),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),m))}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 parseInt(e)}function d(e){return parseFloat(e)}function h(e){return e.reduce((function(e,t){return e+(t?1:0)}),0)}function v(){var e=window,t=navigator;return h(["MSCSSMatrix"in e,"msSetImmediate"in e,"msIndexedDB"in e,"msMaxTouchPoints"in t,"msPointerEnabled"in t])>=4}function g(){var e=window,t=navigator;return h(["msWriteProfilerMark"in e,"MSStream"in e,"msLaunchUri"in t,"msSaveBlob"in t])>=3&&!v()}function m(){var e=window,t=navigator;return h(["webkitPersistentStorage"in t,"webkitTemporaryStorage"in t,0===t.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in e,"BatteryManager"in e,"webkitMediaStream"in e,"webkitSpeechGrammar"in e])>=5}function p(){var e=window,t=navigator;return h(["ApplePayError"in e,"CSSPrimitiveValue"in e,"Counter"in e,0===t.vendor.indexOf("Apple"),"getStorageUpdates"in t,"WebKitMediaKeys"in e])>=4}function w(){var e=window;return h(["safari"in e,!("DeviceMotionEvent"in e),!("ongestureend"in e),!("standalone"in navigator)])>=3}function y(e,t,n){(function(e){return e&&"function"==typeof e.setValueAtTime})(t)&&t.setValueAtTime(n,e.currentTime)}function S(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(C("timeout"))}),1e3);break;case"suspended":document.hidden||r--,r>0?setTimeout(o,500):n(C("suspended"))}};o()}))}function b(e){for(var t=0,n=4500;n<5e3;++n)t+=Math.abs(e[n]);return t}function C(e){var t=new Error(e);return t.name=e,t}var A=["monospace","sans-serif","serif"],M=["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"],T={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 k(e){return e.toDataURL()}var x={osCpu:function(){return navigator.oscpu},languages:function(){var e,t=navigator,n=[],r=t.language||t.userLanguage||t.browserLanguage||t.systemLanguage;if(void 0!==r&&n.push([r]),Array.isArray(t.languages))m()&&h([!("MediaSettingsRange"in(e=window)),"RTCEncodedAudioFrame"in e,""+e.Intl=="[object Intl]",""+e.Reflect=="[object Reflect]"])>=3||n.push(t.languages);else if("string"==typeof t.languages){var o=t.languages;o&&n.push(o.split(","))}return n},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return e=d(navigator.deviceMemory),t=void 0,"number"==typeof e&&isNaN(e)?t:e;var e,t},screenResolution:function(){var e=screen,t=[f(e.width),f(e.height)];return t.sort().reverse(),t},availableScreenResolution:function(){var e=screen;if(e.availWidth&&e.availHeight){var t=[f(e.availWidth),f(e.availHeight)];return t.sort().reverse(),t}},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,t=null===(e=window.Intl)||void 0===e?void 0:e.DateTimeFormat;if(t)return(new t).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(!v()&&!g())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(v())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:k(t)}},touchSupport:function(){var e,t=navigator,n=0;void 0!==t.maxTouchPoints?n=f(t.maxTouchPoints):void 0!==t.msMaxTouchPoints&&(n=t.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(r){e=!1}return{maxTouchPoints:n,touchEvent:e,touchStart:"ontouchstart"in window}},fonts:function(){var e=document,t=e.body,n=e.createElement("div"),r=e.createElement("div"),o={},i={},a=function(){var t=e.createElement("span");t.textContent="mmMwWLliI0O&1";for(var n=0,r=Object.keys(T);n<r.length;n++){var o=r[n];t.style[o]=T[o]}return t},c=function(e){return A.some((function(t,n){return e[n].offsetWidth!==o[t]||e[n].offsetHeight!==i[t]}))},u=A.map((function(e){var t=a();return t.style.fontFamily=e,n.appendChild(t),t}));t.appendChild(n);for(var s=0,l=A.length;s<l;s++)o[A[s]]=u[s].offsetWidth,i[A[s]]=u[s].offsetHeight;var f=function(){for(var e={},t=function(t){e[t]=A.map((function(e){var n=function(e,t){var n=a();return n.style.fontFamily="'"+e+"',"+t,n}(t,e);return r.appendChild(n),n}))},n=0,o=M;n<o.length;n++){t(o[n])}return e}();t.appendChild(r);for(var d=[],h=0,v=M.length;h<v;h++)c(f[M[h]])&&d.push(M[h]);return t.removeChild(r),t.removeChild(n),d},audio:function(){return s(this,void 0,void 0,(function(){var e,t,n,r,o,i,a;return l(this,(function(c){switch(c.label){case 0:if(e=window,!(t=e.OfflineAudioContext||e.webkitOfflineAudioContext))return[2,-2];if(p()&&!w()&&!function(){var e=window;return h(["DOMRectList"in e,"RTCPeerConnectionIceEvent"in e,"SVGGeometryElement"in e,"ontransitioncancel"in e])>=3}())return[2,-1];n=new t(1,44100,44100),(r=n.createOscillator()).type="triangle",y(n,r.frequency,1e4),o=n.createDynamicsCompressor(),y(n,o.threshold,-50),y(n,o.knee,40),y(n,o.ratio,12),y(n,o.reduction,-20),y(n,o.attack,0),y(n,o.release,.25),r.connect(o),o.connect(n.destination),r.start(0),c.label=1;case 1:return c.trys.push([1,3,4,5]),[4,S(n)];case 2:return i=c.sent(),[3,5];case 3:if("timeout"===(a=c.sent()).name||"suspended"===a.name)return[2,-3];throw a;case 4:return r.disconnect(),o.disconnect(),[7];case 5:return[2,b(i.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(){var e=document;try{e.cookie="cookietest=1; SameSite=Strict;";var t=-1!==e.cookie.indexOf("cookietest=");return e.cookie="cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT",t}catch(n){return!1}}};function P(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 O(e){return JSON.stringify(e,(function(e,t){return t instanceof Error?u({name:(n=t).name,message:n.message,stack:null===(r=n.stack)||void 0===r?void 0:r.split("\n")},n):t;var n,r}),2)}function I(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 E=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,P(x,void 0,[])];case 1:return t=r.sent(),n=function(e){var t;return{components:e,get visitorId(){return void 0===t&&(t=I(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.6\nuserAgent: "+navigator.userAgent+"\ngetOptions: "+JSON.stringify(e,void 0,2)+"\nvisitorId: "+n.visitorId+"\ncomponents: "+O(t)+"\n```"),[2,n]}}))}))},e}();function D(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,r=2*n,void 0===r&&(r=1/0),new Promise((function(e){var n=window.requestIdleCallback;n?n((function(){return e()}),{timeout:r}):setTimeout(e,Math.min(t,r))})))];case 1:return e.sent(),[2,new E]}var t,r}))}))}var R={load:D,hashComponents:I,componentsToDebugString:O},B=c;return e.componentsToDebugString=O,e.default=R,e.getComponents=P,e.hashComponents=I,e.isChromium=m,e.isDesktopSafari=w,e.isEdgeHTML=g,e.isGecko=function(){var e,t,n=window;return h(["buildID"in navigator,"MozAppearance"in(null!==(t=null===(e=document.documentElement)||void 0===e?void 0:e.style)&&void 0!==t?t:{}),"MediaRecorderErrorEvent"in n,"mozInnerScreenX"in n,"CSSMozDocumentRule"in n,"CanvasCaptureMediaStream"in n])>=4},e.isTrident=v,e.isWebKit=p,e.load=D,e.murmurX64Hash128=B,e}({}); | ||
var FingerprintJS=function(e){"use strict";function n(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]+n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]+n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]+n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]+n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function t(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]*n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]*n[3],t[1]+=t[2]>>>16,t[2]&=65535,t[2]+=e[3]*n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]*n[3],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[2]*n[2],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[3]*n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]*n[3]+e[1]*n[2]+e[2]*n[1]+e[3]*n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function r(e,n){return 32===(n%=64)?[e[1],e[0]]:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n|e[0]>>>32-n]:(n-=32,[e[1]<<n|e[0]>>>32-n,e[0]<<n|e[1]>>>32-n])}function o(e,n){return 0===(n%=64)?e:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n]:[e[1]<<n-32,0]}function i(e,n){return[e[0]^n[0],e[1]^n[1]]}function a(e){return e=i(e,[0,e[0]>>>1]),e=i(e=t(e,[4283543511,3981806797]),[0,e[0]>>>1]),e=i(e=t(e,[3301882366,444984403]),[0,e[0]>>>1])}function u(e,u){u=u||0;var c,s=(e=e||"").length%16,l=e.length-s,f=[0,u],d=[0,u],v=[0,0],h=[0,0],g=[2277735313,289559509],p=[1291169091,658871167];for(c=0;c<l;c+=16)v=[255&e.charCodeAt(c+4)|(255&e.charCodeAt(c+5))<<8|(255&e.charCodeAt(c+6))<<16|(255&e.charCodeAt(c+7))<<24,255&e.charCodeAt(c)|(255&e.charCodeAt(c+1))<<8|(255&e.charCodeAt(c+2))<<16|(255&e.charCodeAt(c+3))<<24],h=[255&e.charCodeAt(c+12)|(255&e.charCodeAt(c+13))<<8|(255&e.charCodeAt(c+14))<<16|(255&e.charCodeAt(c+15))<<24,255&e.charCodeAt(c+8)|(255&e.charCodeAt(c+9))<<8|(255&e.charCodeAt(c+10))<<16|(255&e.charCodeAt(c+11))<<24],v=r(v=t(v,g),31),f=n(f=r(f=i(f,v=t(v,p)),27),d),f=n(t(f,[0,5]),[0,1390208809]),h=r(h=t(h,p),33),d=n(d=r(d=i(d,h=t(h,g)),31),f),d=n(t(d,[0,5]),[0,944331445]);switch(v=[0,0],h=[0,0],s){case 15:h=i(h,o([0,e.charCodeAt(c+14)],48));case 14:h=i(h,o([0,e.charCodeAt(c+13)],40));case 13:h=i(h,o([0,e.charCodeAt(c+12)],32));case 12:h=i(h,o([0,e.charCodeAt(c+11)],24));case 11:h=i(h,o([0,e.charCodeAt(c+10)],16));case 10:h=i(h,o([0,e.charCodeAt(c+9)],8));case 9:h=t(h=i(h,[0,e.charCodeAt(c+8)]),p),d=i(d,h=t(h=r(h,33),g));case 8:v=i(v,o([0,e.charCodeAt(c+7)],56));case 7:v=i(v,o([0,e.charCodeAt(c+6)],48));case 6:v=i(v,o([0,e.charCodeAt(c+5)],40));case 5:v=i(v,o([0,e.charCodeAt(c+4)],32));case 4:v=i(v,o([0,e.charCodeAt(c+3)],24));case 3:v=i(v,o([0,e.charCodeAt(c+2)],16));case 2:v=i(v,o([0,e.charCodeAt(c+1)],8));case 1:v=t(v=i(v,[0,e.charCodeAt(c)]),g),f=i(f,v=t(v=r(v,31),p))}return f=n(f=i(f,[0,e.length]),d=i(d,[0,e.length])),d=n(d,f),f=n(f=a(f),d=a(d)),d=n(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 c=function(){return(c=Object.assign||function(e){for(var n,t=1,r=arguments.length;t<r;t++)for(var o in n=arguments[t])Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o]);return e}).apply(this,arguments)};function s(e,n,t,r){return new(t||(t=Promise))((function(o,i){function a(e){try{c(r.next(e))}catch(n){i(n)}}function u(e){try{c(r.throw(e))}catch(n){i(n)}}function c(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(a,u)}c((r=r.apply(e,n||[])).next())}))}function l(e,n){var t,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=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=n.call(e,a)}catch(u){i=[6,u],r=0}finally{t=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,u])}}}function f(e,n){return new Promise((function(t){return setTimeout(t,e,n)}))}function d(e,n){void 0===n&&(n=1/0);var t=window.requestIdleCallback;return t?new Promise((function(e){return t((function(){return e()}),{timeout:n})})):f(Math.min(e,n))}function v(e){return parseInt(e)}function h(e){return parseFloat(e)}function g(e){return e.reduce((function(e,n){return e+(n?1:0)}),0)}function p(){var e=window,n=navigator;return g(["MSCSSMatrix"in e,"msSetImmediate"in e,"msIndexedDB"in e,"msMaxTouchPoints"in n,"msPointerEnabled"in n])>=4}function m(){var e=window,n=navigator;return g(["msWriteProfilerMark"in e,"MSStream"in e,"msLaunchUri"in n,"msSaveBlob"in n])>=3&&!p()}function w(){var e=window,n=navigator;return g(["webkitPersistentStorage"in n,"webkitTemporaryStorage"in n,0===n.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in e,"BatteryManager"in e,"webkitMediaStream"in e,"webkitSpeechGrammar"in e])>=5}function y(){var e=window,n=navigator;return g(["ApplePayError"in e,"CSSPrimitiveValue"in e,"Counter"in e,0===n.vendor.indexOf("Apple"),"getStorageUpdates"in n,"WebKitMediaKeys"in e])>=4}function b(){var e=window;return g(["safari"in e,!("DeviceMotionEvent"in e),!("ongestureend"in e),!("standalone"in navigator)])>=3}function S(e){return new Promise((function(n,t){e.oncomplete=function(e){return n(e.renderedBuffer)};var r=3,o=function(){switch(e.startRendering(),e.state){case"running":setTimeout((function(){return t(A("timeout"))}),1e3);break;case"suspended":document.hidden||r--,r>0?setTimeout(o,500):t(A("suspended"))}};o()}))}function C(e){for(var n=0,t=0;t<e.length;++t)n+=Math.abs(e[t]);return n}function A(e){var n=new Error(e);return n.name=e,n}var M=["monospace","sans-serif","serif"],T=["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"];function k(e){return e.toDataURL()}var P={osCpu:function(){return navigator.oscpu},languages:function(){var e,n=navigator,t=[],r=n.language||n.userLanguage||n.browserLanguage||n.systemLanguage;if(void 0!==r&&t.push([r]),Array.isArray(n.languages))w()&&g([!("MediaSettingsRange"in(e=window)),"RTCEncodedAudioFrame"in e,""+e.Intl=="[object Intl]",""+e.Reflect=="[object Reflect]"])>=3||t.push(n.languages);else if("string"==typeof n.languages){var o=n.languages;o&&t.push(o.split(","))}return t},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return e=h(navigator.deviceMemory),n=void 0,"number"==typeof e&&isNaN(e)?n:e;var e,n},screenResolution:function(){var e=screen,n=[v(e.width),v(e.height)];return n.sort().reverse(),n},availableScreenResolution:function(){var e=screen;if(e.availWidth&&e.availHeight){var n=[v(e.availWidth),v(e.availHeight)];return n.sort().reverse(),n}},hardwareConcurrency:function(){try{var e=v(navigator.hardwareConcurrency);return isNaN(e)?1:e}catch(n){return 1}},timezoneOffset:function(){var e=(new Date).getFullYear();return Math.max(h(new Date(e,0,1).getTimezoneOffset()),h(new Date(e,6,1).getTimezoneOffset()))},timezone:function(){var e,n=null===(e=window.Intl)||void 0===e?void 0:e.DateTimeFormat;if(n)return(new n).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(!p()&&!m())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(p())return[];if(navigator.plugins){for(var e=[],n=0;n<navigator.plugins.length;++n){var t=navigator.plugins[n];if(t){for(var r=[],o=0;o<t.length;++o){var i=t[o];r.push({type:i.type,suffixes:i.suffixes})}e.push({name:t.name,description:t.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")]}(),n=e[0],t=e[1];if(!function(e,n){return!(!n||!e.toDataURL)}(n,t))return{winding:!1,data:""};t.rect(0,0,10,10),t.rect(2,2,6,6);var r=!t.isPointInPath(5,5,"evenodd");t.textBaseline="alphabetic",t.fillStyle="#f60",t.fillRect(125,1,62,20),t.fillStyle="#069",t.font="11pt no-real-font-123";var o="Cwm fjordbank "+String.fromCharCode(55357,56835)+" gly";t.fillText(o,2,15),t.fillStyle="rgba(102, 204, 0, 0.2)",t.font="18pt Arial",t.fillText(o,4,45),t.globalCompositeOperation="multiply";for(var i=0,a=[["#f0f",50,50],["#0ff",100,50],["#ff0",75,100]];i<a.length;i++){var u=a[i],c=u[0],s=u[1],l=u[2];t.fillStyle=c,t.beginPath(),t.arc(s,l,50,0,2*Math.PI,!0),t.closePath(),t.fill()}return t.fillStyle="#f0f",t.arc(75,75,75,0,2*Math.PI,!0),t.arc(75,75,25,0,2*Math.PI,!0),t.fill("evenodd"),{winding:r,data:k(n)}},touchSupport:function(){var e,n=navigator,t=0;void 0!==n.maxTouchPoints?t=v(n.maxTouchPoints):void 0!==n.msMaxTouchPoints&&(t=n.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(r){e=!1}return{maxTouchPoints:t,touchEvent:e,touchStart:"ontouchstart"in window}},fonts:function(){return function(e,n,t){var r,o;return void 0===t&&(t=50),s(this,void 0,void 0,(function(){var i,a;return l(this,(function(u){switch(u.label){case 0:i=document,u.label=1;case 1:return i.body?[3,3]:[4,f(t)];case 2:return u.sent(),[3,1];case 3:a=i.createElement("iframe"),u.label=4;case 4:return u.trys.push([4,,10,11]),[4,new Promise((function(e,t){a.onload=e,a.onerror=t;var r=a.style;r.setProperty("display","block","important"),r.position="absolute",r.top="0",r.left="0",r.visibility="hidden",n&&"srcdoc"in a?a.srcdoc=n:a.src="about:blank",i.body.appendChild(a)}))];case 5:u.sent(),u.label=6;case 6:return(null===(r=a.contentWindow)||void 0===r?void 0:r.document.body)?[3,8]:[4,f(t)];case 7:return u.sent(),[3,6];case 8:return[4,e(a,a.contentWindow)];case 9:return[2,u.sent()];case 10:return null===(o=a.parentNode)||void 0===o||o.removeChild(a),[7];case 11:return[2]}}))}))}((function(e,n){var t=n.document,r=t.body;r.style.fontSize="48px";var o=t.createElement("div"),i={},a={},u=function(e){var n=t.createElement("span"),r=n.style;return r.position="absolute",r.top="0",r.left="0",r.fontFamily=e,n.textContent="mmMwWLliI0O&1",o.appendChild(n),n},c=M.map(u),s=function(){for(var e={},n=function(n){e[n]=M.map((function(e){return function(e,n){return u("'"+e+"',"+n)}(n,e)}))},t=0,r=T;t<r.length;t++){n(r[t])}return e}();r.appendChild(o);for(var l=0;l<M.length;l++)i[M[l]]=c[l].offsetWidth,a[M[l]]=c[l].offsetHeight;return T.filter((function(e){return n=s[e],M.some((function(e,t){return n[t].offsetWidth!==i[e]||n[t].offsetHeight!==a[e]}));var n}))}))},audio:function(){return s(this,void 0,void 0,(function(){var e,n,t,r,o,i,a,u;return l(this,(function(c){switch(c.label){case 0:if(e=window,!(n=e.OfflineAudioContext||e.webkitOfflineAudioContext))return[2,-2];if(y()&&!b()&&!function(){var e=window;return g(["DOMRectList"in e,"RTCPeerConnectionIceEvent"in e,"SVGGeometryElement"in e,"ontransitioncancel"in e])>=3}())return[2,-1];t=4500,5e3,r=new n(1,5e3,44100),(o=r.createOscillator()).type="triangle",o.frequency.value=1e4,(i=r.createDynamicsCompressor()).threshold.value=-50,i.knee.value=40,i.ratio.value=12,i.attack.value=0,i.release.value=.25,o.connect(i),i.connect(r.destination),o.start(0),c.label=1;case 1:return c.trys.push([1,3,,4]),[4,S(r)];case 2:return a=c.sent(),[3,4];case 3:if("timeout"===(u=c.sent()).name||"suspended"===u.name)return[2,-3];throw u;case 4:return[2,C(a.getChannelData(0).subarray(t))]}}))}))},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(n){return!1}}},vendor:function(){return navigator.vendor},chrome:function(){return void 0!==window.chrome},cookiesEnabled:function(){var e=document;try{e.cookie="cookietest=1; SameSite=Strict;";var n=-1!==e.cookie.indexOf("cookietest=");return e.cookie="cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT",n}catch(t){return!1}}};function x(e,n,t){return s(this,void 0,void 0,(function(){var r,o,i,a,u,s,f,d,v;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(u=a[i],function(e,n){for(var t=0,r=e.length;t<r;++t)if(e[t]===n)return!0;return!1}(t,u))return[3,6];s=void 0,l.label=2;case 2:return l.trys.push([2,4,,5]),v={},[4,e[u](n)];case 3:return v.value=l.sent(),s=v,[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[u]=c(c({},s),{duration:d-r}),r=d,l.label=6;case 6:return i++,[3,1];case 7:return[2,o]}}))}))}function O(e){return JSON.stringify(e,(function(e,n){return n instanceof Error?c({name:(t=n).name,message:t.message,stack:null===(r=t.stack)||void 0===r?void 0:r.split("\n")},t):n;var t,r}),2)}function E(e){return u(function(e){for(var n="",t=0,r=Object.keys(e);t<r.length;t++){var o=r[t],i=e[o],a=i.error?"error":JSON.stringify(i.value);n+=(n?"|":"")+o.replace(/([:|\\])/g,"\\$1")+":"+a}return n}(e))}var I=function(){function e(){}return e.prototype.get=function(e){return void 0===e&&(e={}),s(this,void 0,void 0,(function(){var n,t;return l(this,(function(r){switch(r.label){case 0:return[4,x(P,void 0,[])];case 1:return n=r.sent(),t=function(e){var n;return{components:e,get visitorId(){return void 0===n&&(n=E(this.components)),n},set visitorId(e){n=e},version:"3.0.7"}}(n),e.debug&&console.log("Copy the text below to get the debug data:\n\n```\nversion: "+t.version+"\nuserAgent: "+navigator.userAgent+"\ngetOptions: "+JSON.stringify(e,void 0,2)+"\nvisitorId: "+t.visitorId+"\ncomponents: "+O(n)+"\n```"),[2,t]}}))}))},e}();function D(e){var n=(void 0===e?{}:e).delayFallback,t=void 0===n?50:n;return s(this,void 0,void 0,(function(){return l(this,(function(e){switch(e.label){case 0:return[4,d(t,2*t)];case 1:return e.sent(),[2,new I]}}))}))}var R={load:D,hashComponents:E,componentsToDebugString:O},L=u;return e.componentsToDebugString=O,e.default=R,e.getComponents=x,e.hashComponents=E,e.isChromium=w,e.isDesktopSafari=b,e.isEdgeHTML=m,e.isGecko=function(){var e,n,t=window;return g(["buildID"in navigator,"MozAppearance"in(null!==(n=null===(e=document.documentElement)||void 0===e?void 0:e.style)&&void 0!==n?n:{}),"MediaRecorderErrorEvent"in t,"mozInnerScreenX"in t,"CSSMozDocumentRule"in t,"CanvasCaptureMediaStream"in t])>=4},e.isTrident=p,e.isWebKit=y,e.load=D,e.murmurX64Hash128=L,e}({}); |
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -311,15 +311,16 @@ * | ||
var version = "3.0.6"; | ||
var version = "3.0.7"; | ||
function wait(durationMs, resolveWith) { | ||
return new Promise(function (resolve) { return setTimeout(resolve, durationMs, resolveWith); }); | ||
} | ||
function requestIdleCallbackIfAvailable(fallbackTimeout, deadlineTimeout) { | ||
if (deadlineTimeout === void 0) { deadlineTimeout = Infinity; } | ||
return new Promise(function (resolve) { | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); | ||
} | ||
else { | ||
setTimeout(resolve, Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
}); | ||
var requestIdleCallback = window.requestIdleCallback; | ||
if (requestIdleCallback) { | ||
return new Promise(function (resolve) { return requestIdleCallback(function () { return resolve(); }, { timeout: deadlineTimeout }); }); | ||
} | ||
else { | ||
return wait(Math.min(fallbackTimeout, deadlineTimeout)); | ||
} | ||
} | ||
@@ -517,3 +518,3 @@ | ||
return __awaiter(this, void 0, void 0, function () { | ||
var w, AudioContext, context, oscillator, compressor, buffer, error_1; | ||
var w, AudioContext, hashFromIndex, hashToIndex, context, oscillator, compressor, buffer, error_1; | ||
return __generator(this, function (_a) { | ||
@@ -534,13 +535,14 @@ switch (_a.label) { | ||
} | ||
context = new AudioContext(1, 44100, 44100); | ||
hashFromIndex = 4500; | ||
hashToIndex = 5000; | ||
context = new AudioContext(1, hashToIndex, 44100); | ||
oscillator = context.createOscillator(); | ||
oscillator.type = 'triangle'; | ||
setAudioParam(context, oscillator.frequency, 10000); | ||
oscillator.frequency.value = 10000; | ||
compressor = context.createDynamicsCompressor(); | ||
setAudioParam(context, compressor.threshold, -50); | ||
setAudioParam(context, compressor.knee, 40); | ||
setAudioParam(context, compressor.ratio, 12); | ||
setAudioParam(context, compressor.reduction, -20); | ||
setAudioParam(context, compressor.attack, 0); | ||
setAudioParam(context, compressor.release, 0.25); | ||
compressor.threshold.value = -50; | ||
compressor.knee.value = 40; | ||
compressor.ratio.value = 12; | ||
compressor.attack.value = 0; | ||
compressor.release.value = 0.25; | ||
oscillator.connect(compressor); | ||
@@ -551,7 +553,7 @@ compressor.connect(context.destination); | ||
case 1: | ||
_a.trys.push([1, 3, 4, 5]); | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, renderAudio(context)]; | ||
case 2: | ||
buffer = _a.sent(); | ||
return [3 /*break*/, 5]; | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
@@ -563,7 +565,3 @@ error_1 = _a.sent(); | ||
throw error_1; | ||
case 4: | ||
oscillator.disconnect(); | ||
compressor.disconnect(); | ||
return [7 /*endfinally*/]; | ||
case 5: return [2 /*return*/, getHash(buffer.getChannelData(0))]; | ||
case 4: return [2 /*return*/, getHash(buffer.getChannelData(0).subarray(hashFromIndex))]; | ||
} | ||
@@ -579,10 +577,2 @@ }); | ||
} | ||
function setAudioParam(context, param, value) { | ||
var isAudioParam = function (value) { | ||
return value && typeof value.setValueAtTime === 'function'; | ||
}; | ||
if (isAudioParam(param)) { | ||
param.setValueAtTime(value, context.currentTime); | ||
} | ||
} | ||
function renderAudio(context) { | ||
@@ -626,3 +616,3 @@ var resumeTriesMaxCount = 3; | ||
var hash = 0; | ||
for (var i = 4500; i < 5000; ++i) { | ||
for (var i = 0; i < signal.length; ++i) { | ||
hash += Math.abs(signal[i]); | ||
@@ -638,2 +628,70 @@ } | ||
/** | ||
* Creates and keeps an invisible iframe while the given function runs. | ||
* The given function is called when the iframe is loaded and has a body. | ||
* The iframe allows to measure DOM sizes inside itself. | ||
* | ||
* Notice: passing an initial HTML code doesn't work in IE. | ||
* | ||
* Warning for package users: | ||
* This function is out of Semantic Versioning, i.e. can change unexpectedly. Usage is at your own risk. | ||
*/ | ||
function withIframe(action, initialHtml, domPollInterval) { | ||
var _a, _b; | ||
if (domPollInterval === void 0) { domPollInterval = 50; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var d, iframe; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
d = document; | ||
_c.label = 1; | ||
case 1: | ||
if (!!d.body) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 2: | ||
_c.sent(); | ||
return [3 /*break*/, 1]; | ||
case 3: | ||
iframe = d.createElement('iframe'); | ||
_c.label = 4; | ||
case 4: | ||
_c.trys.push([4, , 10, 11]); | ||
return [4 /*yield*/, new Promise(function (resolve, reject) { | ||
iframe.onload = resolve; | ||
iframe.onerror = reject; | ||
var style = iframe.style; | ||
style.setProperty('display', 'block', 'important'); // Required for browsers to calculate the layout | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.visibility = 'hidden'; | ||
if (initialHtml && 'srcdoc' in iframe) { | ||
iframe.srcdoc = initialHtml; | ||
} | ||
else { | ||
iframe.src = 'about:blank'; | ||
} | ||
d.body.appendChild(iframe); | ||
})]; | ||
case 5: | ||
_c.sent(); | ||
_c.label = 6; | ||
case 6: | ||
if (!!((_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document.body)) return [3 /*break*/, 8]; | ||
return [4 /*yield*/, wait(domPollInterval)]; | ||
case 7: | ||
_c.sent(); | ||
return [3 /*break*/, 6]; | ||
case 8: return [4 /*yield*/, action(iframe, iframe.contentWindow)]; | ||
case 9: return [2 /*return*/, _c.sent()]; | ||
case 10: | ||
(_b = iframe.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(iframe); | ||
return [7 /*endfinally*/]; | ||
case 11: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
// We use m or w because these two characters take up the maximum width. | ||
@@ -643,3 +701,3 @@ // And we use a LLi so that the same matching fonts can get separated. | ||
// We test using 48px font size, we may use any size. I guess larger the better. | ||
var testSize = '48px'; | ||
var textSize = '48px'; | ||
// A font will be compared against all the three default fonts. | ||
@@ -703,105 +761,69 @@ // And if it doesn't match all 3 then that font is not available. | ||
]; | ||
var fontSpanStyle = { | ||
// CSS font reset to reset external styles | ||
fontStyle: 'normal', | ||
fontWeight: 'normal', | ||
letterSpacing: 'normal', | ||
lineBreak: 'auto', | ||
lineHeight: 'normal', | ||
textTransform: 'none', | ||
textAlign: 'left', | ||
textDecoration: 'none', | ||
textShadow: 'none', | ||
whiteSpace: 'normal', | ||
wordBreak: 'normal', | ||
wordSpacing: 'normal', | ||
// We need this css as in some weird browser this span elements shows up for a microSec which creates | ||
// a bad user experience | ||
position: 'absolute', | ||
left: '-9999px', | ||
fontSize: testSize, | ||
}; | ||
// kudos to http://www.lalit.org/lab/javascript-css-font-detect/ | ||
function getFonts() { | ||
var d = document; | ||
var holder = d.body; | ||
// div to load spans for the base fonts | ||
var baseFontsDiv = d.createElement('div'); | ||
// div to load spans for the fonts to detect | ||
var fontsDiv = d.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function () { | ||
var span = d.createElement('span'); | ||
span.textContent = testString; | ||
for (var _i = 0, _a = Object.keys(fontSpanStyle); _i < _a.length; _i++) { | ||
var prop = _a[_i]; | ||
span.style[prop] = fontSpanStyle[prop]; | ||
} | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = "'" + fontToDetect + "'," + baseFont; | ||
return s; | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(function (baseFont) { | ||
var s = createSpan(); | ||
s.style.fontFamily = baseFont; | ||
baseFontsDiv.appendChild(s); | ||
return s; | ||
}); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { | ||
var s = createSpanWithFonts(font, baseFont); | ||
fontsDiv.appendChild(s); | ||
return s; | ||
function getFontsIframe() { | ||
// Running the script in an iframe makes it not affect the page look and not be affected by the page CSS. See: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/592 | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/628 | ||
return withIframe(function (_, _a) { | ||
var document = _a.document; | ||
var holder = document.body; | ||
holder.style.fontSize = textSize; | ||
// div to load spans for the default fonts and the fonts to detect | ||
var spansContainer = document.createElement('div'); | ||
var defaultWidth = {}; | ||
var defaultHeight = {}; | ||
// creates a span where the fonts will be loaded | ||
var createSpan = function (fontFamily) { | ||
var span = document.createElement('span'); | ||
var style = span.style; | ||
style.position = 'absolute'; | ||
style.top = '0'; | ||
style.left = '0'; | ||
style.fontFamily = fontFamily; | ||
span.textContent = testString; | ||
spansContainer.appendChild(span); | ||
return span; | ||
}; | ||
// creates a span and load the font to detect and a base font for fallback | ||
var createSpanWithFonts = function (fontToDetect, baseFont) { | ||
return createSpan("'" + fontToDetect + "'," + baseFont); | ||
}; | ||
// creates spans for the base fonts and adds them to baseFontsDiv | ||
var initializeBaseFontsSpans = function () { | ||
return baseFonts.map(createSpan); | ||
}; | ||
// creates spans for the fonts to detect and adds them to fontsDiv | ||
var initializeFontsSpans = function () { | ||
// Stores {fontName : [spans for that font]} | ||
var spans = {}; | ||
var _loop_1 = function (font) { | ||
spans[font] = baseFonts.map(function (baseFont) { return createSpanWithFonts(font, baseFont); }); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
for (var _i = 0, fontList_1 = fontList; _i < fontList_1.length; _i++) { | ||
var font = fontList_1[_i]; | ||
_loop_1(font); | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(spansContainer); | ||
// get the default width for the three base fonts | ||
for (var index = 0; index < baseFonts.length; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
return spans; | ||
}; | ||
// checks if a font is available | ||
var isFontAvailable = function (fontSpans) { | ||
return baseFonts.some(function (baseFont, baseFontIndex) { | ||
return fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || | ||
fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]; | ||
}); | ||
}; | ||
// create spans for base fonts | ||
var baseFontsSpans = initializeBaseFontsSpans(); | ||
// add the spans to the DOM | ||
holder.appendChild(baseFontsDiv); | ||
// get the default width for the three base fonts | ||
for (var index = 0, length_1 = baseFonts.length; index < length_1; index++) { | ||
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font | ||
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font | ||
} | ||
// create spans for fonts to detect | ||
var fontsSpans = initializeFontsSpans(); | ||
// add all the spans to the DOM | ||
holder.appendChild(fontsDiv); | ||
// check available fonts | ||
var available = []; | ||
for (var i = 0, l = fontList.length; i < l; i++) { | ||
if (isFontAvailable(fontsSpans[fontList[i]])) { | ||
available.push(fontList[i]); | ||
} | ||
} | ||
// remove spans from DOM | ||
holder.removeChild(fontsDiv); | ||
holder.removeChild(baseFontsDiv); | ||
return available; | ||
// check available fonts | ||
return fontList.filter(function (font) { return isFontAvailable(fontsSpans[font]); }); | ||
}); | ||
} | ||
@@ -861,4 +883,4 @@ | ||
} | ||
// detect browser support of canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// Detect browser support of canvas winding | ||
// https://web.archive.org/web/20170825024655/http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js | ||
@@ -872,9 +894,11 @@ context.rect(0, 0, 10, 10); | ||
context.fillStyle = '#069'; | ||
// https://github.com/Valve/fingerprintjs2/issues/66 | ||
// this can affect FP generation when applying different CSS on different websites | ||
// This can affect FP generation when applying different CSS on different websites: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
context.font = '11pt no-real-font-123'; | ||
// the choice of emojis has a gigantic impact on rendering performance (especially in FF) | ||
// some newer emojis cause it to slow down 50-200 times | ||
// context.fillText("CwēØm fjordbank \ud83d\ude03 gly", 2, 15) | ||
var printedText = 'Cwm fjordbank \ud83d\ude03 gly'; | ||
// The choice of emojis has a gigantic impact on rendering performance (especially in FF). | ||
// Some newer emojis cause it to slow down 50-200 times. | ||
// A bare emoji shouldn't be used because the canvas will change depending on the script encoding: | ||
// https://github.com/fingerprintjs/fingerprintjs/issues/66 | ||
// Escape sequence shouldn't be used too because Terser will turn it into a bare unicode. | ||
var printedText = "Cwm fjordbank " + String.fromCharCode(55357, 56835) /* š */ + " gly"; | ||
context.fillText(printedText, 2, 15); | ||
@@ -884,25 +908,22 @@ context.fillStyle = 'rgba(102, 204, 0, 0.2)'; | ||
context.fillText(printedText, 4, 45); | ||
// canvas blending | ||
// http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// Canvas blending | ||
// https://web.archive.org/web/20170826194121/http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/16/ | ||
context.globalCompositeOperation = 'multiply'; | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
context.beginPath(); | ||
context.arc(50, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(0,255,255)'; | ||
context.beginPath(); | ||
context.arc(100, 50, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,255,0)'; | ||
context.beginPath(); | ||
context.arc(75, 100, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
context.fillStyle = 'rgb(255,0,255)'; | ||
// canvas winding | ||
for (var _i = 0, _b = [ | ||
['#f0f', 50, 50], | ||
['#0ff', 100, 50], | ||
['#ff0', 75, 100], | ||
]; _i < _b.length; _i++) { | ||
var _c = _b[_i], color = _c[0], x = _c[1], y = _c[2]; | ||
context.fillStyle = color; | ||
context.beginPath(); | ||
context.arc(x, y, 50, 0, Math.PI * 2, true); | ||
context.closePath(); | ||
context.fill(); | ||
} | ||
// Canvas winding | ||
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ | ||
// http://jsfiddle.net/NDYV8/19/ | ||
context.fillStyle = '#f0f'; | ||
context.arc(75, 75, 75, 0, Math.PI * 2, true); | ||
@@ -1180,3 +1201,3 @@ context.arc(75, 75, 25, 0, Math.PI * 2, true); | ||
touchSupport: getTouchSupport, | ||
fonts: getFonts, | ||
fonts: getFontsIframe, | ||
audio: getAudioFingerprint, | ||
@@ -1286,2 +1307,3 @@ pluginsSupport: getPluginsSupport, | ||
}, | ||
version: version, | ||
}; | ||
@@ -1312,3 +1334,3 @@ } | ||
// eslint-disable-next-line no-console | ||
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```"); | ||
console.log("Copy the text below to get the debug data:\n\n```\nversion: " + result.version + "\nuserAgent: " + navigator.userAgent + "\ngetOptions: " + JSON.stringify(options, undefined, 2) + "\nvisitorId: " + result.visitorId + "\ncomponents: " + componentsToDebugString(components) + "\n```"); | ||
} | ||
@@ -1315,0 +1337,0 @@ return [2 /*return*/, result]; |
/** | ||
* FingerprintJS v3.0.6 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* FingerprintJS v3.0.7 - Copyright (c) FingerprintJS, Inc, 2021 (https://fingerprintjs.com) | ||
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. | ||
@@ -9,2 +9,2 @@ * | ||
!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 parseInt(e)}function d(e){return parseFloat(e)}function h(e){return e.reduce((function(e,t){return e+(t?1:0)}),0)}function v(){var e=window,t=navigator;return h(["MSCSSMatrix"in e,"msSetImmediate"in e,"msIndexedDB"in e,"msMaxTouchPoints"in t,"msPointerEnabled"in t])>=4}function g(){var e=window,t=navigator;return h(["msWriteProfilerMark"in e,"MSStream"in e,"msLaunchUri"in t,"msSaveBlob"in t])>=3&&!v()}function p(){var e=window,t=navigator;return h(["webkitPersistentStorage"in t,"webkitTemporaryStorage"in t,0===t.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in e,"BatteryManager"in e,"webkitMediaStream"in e,"webkitSpeechGrammar"in e])>=5}function m(){var e=window,t=navigator;return h(["ApplePayError"in e,"CSSPrimitiveValue"in e,"Counter"in e,0===t.vendor.indexOf("Apple"),"getStorageUpdates"in t,"WebKitMediaKeys"in e])>=4}function y(){var e=window;return h(["safari"in e,!("DeviceMotionEvent"in e),!("ongestureend"in e),!("standalone"in navigator)])>=3}function w(e,t,n){(function(e){return e&&"function"==typeof e.setValueAtTime})(t)&&t.setValueAtTime(n,e.currentTime)}function S(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(C("timeout"))}),1e3);break;case"suspended":document.hidden||r--,r>0?setTimeout(o,500):n(C("suspended"))}};o()}))}function b(e){for(var t=0,n=4500;n<5e3;++n)t+=Math.abs(e[n]);return t}function C(e){var t=new Error(e);return t.name=e,t}var A=["monospace","sans-serif","serif"],M=["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"],T={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 x(e){return e.toDataURL()}var k={osCpu:function(){return navigator.oscpu},languages:function(){var e,t=navigator,n=[],r=t.language||t.userLanguage||t.browserLanguage||t.systemLanguage;if(void 0!==r&&n.push([r]),Array.isArray(t.languages))p()&&h([!("MediaSettingsRange"in(e=window)),"RTCEncodedAudioFrame"in e,""+e.Intl=="[object Intl]",""+e.Reflect=="[object Reflect]"])>=3||n.push(t.languages);else if("string"==typeof t.languages){var o=t.languages;o&&n.push(o.split(","))}return n},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return e=d(navigator.deviceMemory),t=void 0,"number"==typeof e&&isNaN(e)?t:e;var e,t},screenResolution:function(){var e=screen,t=[f(e.width),f(e.height)];return t.sort().reverse(),t},availableScreenResolution:function(){var e=screen;if(e.availWidth&&e.availHeight){var t=[f(e.availWidth),f(e.availHeight)];return t.sort().reverse(),t}},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,t=null===(e=window.Intl)||void 0===e?void 0:e.DateTimeFormat;if(t)return(new t).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(!v()&&!g())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(v())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:x(t)}},touchSupport:function(){var e,t=navigator,n=0;void 0!==t.maxTouchPoints?n=f(t.maxTouchPoints):void 0!==t.msMaxTouchPoints&&(n=t.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(r){e=!1}return{maxTouchPoints:n,touchEvent:e,touchStart:"ontouchstart"in window}},fonts:function(){var e=document,t=e.body,n=e.createElement("div"),r=e.createElement("div"),o={},i={},a=function(){var t=e.createElement("span");t.textContent="mmMwWLliI0O&1";for(var n=0,r=Object.keys(T);n<r.length;n++){var o=r[n];t.style[o]=T[o]}return t},c=function(e){return A.some((function(t,n){return e[n].offsetWidth!==o[t]||e[n].offsetHeight!==i[t]}))},u=A.map((function(e){var t=a();return t.style.fontFamily=e,n.appendChild(t),t}));t.appendChild(n);for(var s=0,l=A.length;s<l;s++)o[A[s]]=u[s].offsetWidth,i[A[s]]=u[s].offsetHeight;var f=function(){for(var e={},t=function(t){e[t]=A.map((function(e){var n=function(e,t){var n=a();return n.style.fontFamily="'"+e+"',"+t,n}(t,e);return r.appendChild(n),n}))},n=0,o=M;n<o.length;n++){t(o[n])}return e}();t.appendChild(r);for(var d=[],h=0,v=M.length;h<v;h++)c(f[M[h]])&&d.push(M[h]);return t.removeChild(r),t.removeChild(n),d},audio:function(){return s(this,void 0,void 0,(function(){var e,t,n,r,o,i,a;return l(this,(function(c){switch(c.label){case 0:if(e=window,!(t=e.OfflineAudioContext||e.webkitOfflineAudioContext))return[2,-2];if(m()&&!y()&&!function(){var e=window;return h(["DOMRectList"in e,"RTCPeerConnectionIceEvent"in e,"SVGGeometryElement"in e,"ontransitioncancel"in e])>=3}())return[2,-1];n=new t(1,44100,44100),(r=n.createOscillator()).type="triangle",w(n,r.frequency,1e4),o=n.createDynamicsCompressor(),w(n,o.threshold,-50),w(n,o.knee,40),w(n,o.ratio,12),w(n,o.reduction,-20),w(n,o.attack,0),w(n,o.release,.25),r.connect(o),o.connect(n.destination),r.start(0),c.label=1;case 1:return c.trys.push([1,3,4,5]),[4,S(n)];case 2:return i=c.sent(),[3,5];case 3:if("timeout"===(a=c.sent()).name||"suspended"===a.name)return[2,-3];throw a;case 4:return r.disconnect(),o.disconnect(),[7];case 5:return[2,b(i.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(){var e=document;try{e.cookie="cookietest=1; SameSite=Strict;";var t=-1!==e.cookie.indexOf("cookietest=");return e.cookie="cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT",t}catch(n){return!1}}};function P(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 O(e){return JSON.stringify(e,(function(e,t){return t instanceof Error?u({name:(n=t).name,message:n.message,stack:null===(r=n.stack)||void 0===r?void 0:r.split("\n")},n):t;var n,r}),2)}function I(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 E=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,P(k,void 0,[])];case 1:return t=r.sent(),n=function(e){var t;return{components:e,get visitorId(){return void 0===t&&(t=I(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.6\nuserAgent: "+navigator.userAgent+"\ngetOptions: "+JSON.stringify(e,void 0,2)+"\nvisitorId: "+n.visitorId+"\ncomponents: "+O(t)+"\n```"),[2,n]}}))}))},e}();function D(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,r=2*n,void 0===r&&(r=1/0),new Promise((function(e){var n=window.requestIdleCallback;n?n((function(){return e()}),{timeout:r}):setTimeout(e,Math.min(t,r))})))];case 1:return e.sent(),[2,new E]}var t,r}))}))}var R={load:D,hashComponents:I,componentsToDebugString:O},B=c;e.componentsToDebugString=O,e.default=R,e.getComponents=P,e.hashComponents=I,e.isChromium=p,e.isDesktopSafari=y,e.isEdgeHTML=g,e.isGecko=function(){var e,t,n=window;return h(["buildID"in navigator,"MozAppearance"in(null!==(t=null===(e=document.documentElement)||void 0===e?void 0:e.style)&&void 0!==t?t:{}),"MediaRecorderErrorEvent"in n,"mozInnerScreenX"in n,"CSSMozDocumentRule"in n,"CanvasCaptureMediaStream"in n])>=4},e.isTrident=v,e.isWebKit=m,e.load=D,e.murmurX64Hash128=B,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).FingerprintJS={})}(this,(function(e){"use strict";function n(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]+n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]+n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]+n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]+n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function t(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]*n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]*n[3],t[1]+=t[2]>>>16,t[2]&=65535,t[2]+=e[3]*n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]*n[3],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[2]*n[2],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[3]*n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]*n[3]+e[1]*n[2]+e[2]*n[1]+e[3]*n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function r(e,n){return 32===(n%=64)?[e[1],e[0]]:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n|e[0]>>>32-n]:(n-=32,[e[1]<<n|e[0]>>>32-n,e[0]<<n|e[1]>>>32-n])}function o(e,n){return 0===(n%=64)?e:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n]:[e[1]<<n-32,0]}function i(e,n){return[e[0]^n[0],e[1]^n[1]]}function a(e){return e=i(e,[0,e[0]>>>1]),e=i(e=t(e,[4283543511,3981806797]),[0,e[0]>>>1]),e=i(e=t(e,[3301882366,444984403]),[0,e[0]>>>1])}function u(e,u){u=u||0;var c,s=(e=e||"").length%16,l=e.length-s,f=[0,u],d=[0,u],v=[0,0],h=[0,0],g=[2277735313,289559509],p=[1291169091,658871167];for(c=0;c<l;c+=16)v=[255&e.charCodeAt(c+4)|(255&e.charCodeAt(c+5))<<8|(255&e.charCodeAt(c+6))<<16|(255&e.charCodeAt(c+7))<<24,255&e.charCodeAt(c)|(255&e.charCodeAt(c+1))<<8|(255&e.charCodeAt(c+2))<<16|(255&e.charCodeAt(c+3))<<24],h=[255&e.charCodeAt(c+12)|(255&e.charCodeAt(c+13))<<8|(255&e.charCodeAt(c+14))<<16|(255&e.charCodeAt(c+15))<<24,255&e.charCodeAt(c+8)|(255&e.charCodeAt(c+9))<<8|(255&e.charCodeAt(c+10))<<16|(255&e.charCodeAt(c+11))<<24],v=r(v=t(v,g),31),f=n(f=r(f=i(f,v=t(v,p)),27),d),f=n(t(f,[0,5]),[0,1390208809]),h=r(h=t(h,p),33),d=n(d=r(d=i(d,h=t(h,g)),31),f),d=n(t(d,[0,5]),[0,944331445]);switch(v=[0,0],h=[0,0],s){case 15:h=i(h,o([0,e.charCodeAt(c+14)],48));case 14:h=i(h,o([0,e.charCodeAt(c+13)],40));case 13:h=i(h,o([0,e.charCodeAt(c+12)],32));case 12:h=i(h,o([0,e.charCodeAt(c+11)],24));case 11:h=i(h,o([0,e.charCodeAt(c+10)],16));case 10:h=i(h,o([0,e.charCodeAt(c+9)],8));case 9:h=t(h=i(h,[0,e.charCodeAt(c+8)]),p),d=i(d,h=t(h=r(h,33),g));case 8:v=i(v,o([0,e.charCodeAt(c+7)],56));case 7:v=i(v,o([0,e.charCodeAt(c+6)],48));case 6:v=i(v,o([0,e.charCodeAt(c+5)],40));case 5:v=i(v,o([0,e.charCodeAt(c+4)],32));case 4:v=i(v,o([0,e.charCodeAt(c+3)],24));case 3:v=i(v,o([0,e.charCodeAt(c+2)],16));case 2:v=i(v,o([0,e.charCodeAt(c+1)],8));case 1:v=t(v=i(v,[0,e.charCodeAt(c)]),g),f=i(f,v=t(v=r(v,31),p))}return f=n(f=i(f,[0,e.length]),d=i(d,[0,e.length])),d=n(d,f),f=n(f=a(f),d=a(d)),d=n(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 c=function(){return(c=Object.assign||function(e){for(var n,t=1,r=arguments.length;t<r;t++)for(var o in n=arguments[t])Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o]);return e}).apply(this,arguments)};function s(e,n,t,r){return new(t||(t=Promise))((function(o,i){function a(e){try{c(r.next(e))}catch(n){i(n)}}function u(e){try{c(r.throw(e))}catch(n){i(n)}}function c(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(a,u)}c((r=r.apply(e,n||[])).next())}))}function l(e,n){var t,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=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=n.call(e,a)}catch(u){i=[6,u],r=0}finally{t=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,u])}}}function f(e,n){return new Promise((function(t){return setTimeout(t,e,n)}))}function d(e,n){void 0===n&&(n=1/0);var t=window.requestIdleCallback;return t?new Promise((function(e){return t((function(){return e()}),{timeout:n})})):f(Math.min(e,n))}function v(e){return parseInt(e)}function h(e){return parseFloat(e)}function g(e){return e.reduce((function(e,n){return e+(n?1:0)}),0)}function p(){var e=window,n=navigator;return g(["MSCSSMatrix"in e,"msSetImmediate"in e,"msIndexedDB"in e,"msMaxTouchPoints"in n,"msPointerEnabled"in n])>=4}function m(){var e=window,n=navigator;return g(["msWriteProfilerMark"in e,"MSStream"in e,"msLaunchUri"in n,"msSaveBlob"in n])>=3&&!p()}function y(){var e=window,n=navigator;return g(["webkitPersistentStorage"in n,"webkitTemporaryStorage"in n,0===n.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in e,"BatteryManager"in e,"webkitMediaStream"in e,"webkitSpeechGrammar"in e])>=5}function w(){var e=window,n=navigator;return g(["ApplePayError"in e,"CSSPrimitiveValue"in e,"Counter"in e,0===n.vendor.indexOf("Apple"),"getStorageUpdates"in n,"WebKitMediaKeys"in e])>=4}function b(){var e=window;return g(["safari"in e,!("DeviceMotionEvent"in e),!("ongestureend"in e),!("standalone"in navigator)])>=3}function S(e){return new Promise((function(n,t){e.oncomplete=function(e){return n(e.renderedBuffer)};var r=3,o=function(){switch(e.startRendering(),e.state){case"running":setTimeout((function(){return t(A("timeout"))}),1e3);break;case"suspended":document.hidden||r--,r>0?setTimeout(o,500):t(A("suspended"))}};o()}))}function C(e){for(var n=0,t=0;t<e.length;++t)n+=Math.abs(e[t]);return n}function A(e){var n=new Error(e);return n.name=e,n}var M=["monospace","sans-serif","serif"],T=["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"];function k(e){return e.toDataURL()}var x={osCpu:function(){return navigator.oscpu},languages:function(){var e,n=navigator,t=[],r=n.language||n.userLanguage||n.browserLanguage||n.systemLanguage;if(void 0!==r&&t.push([r]),Array.isArray(n.languages))y()&&g([!("MediaSettingsRange"in(e=window)),"RTCEncodedAudioFrame"in e,""+e.Intl=="[object Intl]",""+e.Reflect=="[object Reflect]"])>=3||t.push(n.languages);else if("string"==typeof n.languages){var o=n.languages;o&&t.push(o.split(","))}return t},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return e=h(navigator.deviceMemory),n=void 0,"number"==typeof e&&isNaN(e)?n:e;var e,n},screenResolution:function(){var e=screen,n=[v(e.width),v(e.height)];return n.sort().reverse(),n},availableScreenResolution:function(){var e=screen;if(e.availWidth&&e.availHeight){var n=[v(e.availWidth),v(e.availHeight)];return n.sort().reverse(),n}},hardwareConcurrency:function(){try{var e=v(navigator.hardwareConcurrency);return isNaN(e)?1:e}catch(n){return 1}},timezoneOffset:function(){var e=(new Date).getFullYear();return Math.max(h(new Date(e,0,1).getTimezoneOffset()),h(new Date(e,6,1).getTimezoneOffset()))},timezone:function(){var e,n=null===(e=window.Intl)||void 0===e?void 0:e.DateTimeFormat;if(n)return(new n).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(!p()&&!m())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(p())return[];if(navigator.plugins){for(var e=[],n=0;n<navigator.plugins.length;++n){var t=navigator.plugins[n];if(t){for(var r=[],o=0;o<t.length;++o){var i=t[o];r.push({type:i.type,suffixes:i.suffixes})}e.push({name:t.name,description:t.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")]}(),n=e[0],t=e[1];if(!function(e,n){return!(!n||!e.toDataURL)}(n,t))return{winding:!1,data:""};t.rect(0,0,10,10),t.rect(2,2,6,6);var r=!t.isPointInPath(5,5,"evenodd");t.textBaseline="alphabetic",t.fillStyle="#f60",t.fillRect(125,1,62,20),t.fillStyle="#069",t.font="11pt no-real-font-123";var o="Cwm fjordbank "+String.fromCharCode(55357,56835)+" gly";t.fillText(o,2,15),t.fillStyle="rgba(102, 204, 0, 0.2)",t.font="18pt Arial",t.fillText(o,4,45),t.globalCompositeOperation="multiply";for(var i=0,a=[["#f0f",50,50],["#0ff",100,50],["#ff0",75,100]];i<a.length;i++){var u=a[i],c=u[0],s=u[1],l=u[2];t.fillStyle=c,t.beginPath(),t.arc(s,l,50,0,2*Math.PI,!0),t.closePath(),t.fill()}return t.fillStyle="#f0f",t.arc(75,75,75,0,2*Math.PI,!0),t.arc(75,75,25,0,2*Math.PI,!0),t.fill("evenodd"),{winding:r,data:k(n)}},touchSupport:function(){var e,n=navigator,t=0;void 0!==n.maxTouchPoints?t=v(n.maxTouchPoints):void 0!==n.msMaxTouchPoints&&(t=n.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(r){e=!1}return{maxTouchPoints:t,touchEvent:e,touchStart:"ontouchstart"in window}},fonts:function(){return function(e,n,t){var r,o;return void 0===t&&(t=50),s(this,void 0,void 0,(function(){var i,a;return l(this,(function(u){switch(u.label){case 0:i=document,u.label=1;case 1:return i.body?[3,3]:[4,f(t)];case 2:return u.sent(),[3,1];case 3:a=i.createElement("iframe"),u.label=4;case 4:return u.trys.push([4,,10,11]),[4,new Promise((function(e,t){a.onload=e,a.onerror=t;var r=a.style;r.setProperty("display","block","important"),r.position="absolute",r.top="0",r.left="0",r.visibility="hidden",n&&"srcdoc"in a?a.srcdoc=n:a.src="about:blank",i.body.appendChild(a)}))];case 5:u.sent(),u.label=6;case 6:return(null===(r=a.contentWindow)||void 0===r?void 0:r.document.body)?[3,8]:[4,f(t)];case 7:return u.sent(),[3,6];case 8:return[4,e(a,a.contentWindow)];case 9:return[2,u.sent()];case 10:return null===(o=a.parentNode)||void 0===o||o.removeChild(a),[7];case 11:return[2]}}))}))}((function(e,n){var t=n.document,r=t.body;r.style.fontSize="48px";var o=t.createElement("div"),i={},a={},u=function(e){var n=t.createElement("span"),r=n.style;return r.position="absolute",r.top="0",r.left="0",r.fontFamily=e,n.textContent="mmMwWLliI0O&1",o.appendChild(n),n},c=M.map(u),s=function(){for(var e={},n=function(n){e[n]=M.map((function(e){return function(e,n){return u("'"+e+"',"+n)}(n,e)}))},t=0,r=T;t<r.length;t++){n(r[t])}return e}();r.appendChild(o);for(var l=0;l<M.length;l++)i[M[l]]=c[l].offsetWidth,a[M[l]]=c[l].offsetHeight;return T.filter((function(e){return n=s[e],M.some((function(e,t){return n[t].offsetWidth!==i[e]||n[t].offsetHeight!==a[e]}));var n}))}))},audio:function(){return s(this,void 0,void 0,(function(){var e,n,t,r,o,i,a,u;return l(this,(function(c){switch(c.label){case 0:if(e=window,!(n=e.OfflineAudioContext||e.webkitOfflineAudioContext))return[2,-2];if(w()&&!b()&&!function(){var e=window;return g(["DOMRectList"in e,"RTCPeerConnectionIceEvent"in e,"SVGGeometryElement"in e,"ontransitioncancel"in e])>=3}())return[2,-1];t=4500,5e3,r=new n(1,5e3,44100),(o=r.createOscillator()).type="triangle",o.frequency.value=1e4,(i=r.createDynamicsCompressor()).threshold.value=-50,i.knee.value=40,i.ratio.value=12,i.attack.value=0,i.release.value=.25,o.connect(i),i.connect(r.destination),o.start(0),c.label=1;case 1:return c.trys.push([1,3,,4]),[4,S(r)];case 2:return a=c.sent(),[3,4];case 3:if("timeout"===(u=c.sent()).name||"suspended"===u.name)return[2,-3];throw u;case 4:return[2,C(a.getChannelData(0).subarray(t))]}}))}))},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(n){return!1}}},vendor:function(){return navigator.vendor},chrome:function(){return void 0!==window.chrome},cookiesEnabled:function(){var e=document;try{e.cookie="cookietest=1; SameSite=Strict;";var n=-1!==e.cookie.indexOf("cookietest=");return e.cookie="cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT",n}catch(t){return!1}}};function P(e,n,t){return s(this,void 0,void 0,(function(){var r,o,i,a,u,s,f,d,v;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(u=a[i],function(e,n){for(var t=0,r=e.length;t<r;++t)if(e[t]===n)return!0;return!1}(t,u))return[3,6];s=void 0,l.label=2;case 2:return l.trys.push([2,4,,5]),v={},[4,e[u](n)];case 3:return v.value=l.sent(),s=v,[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[u]=c(c({},s),{duration:d-r}),r=d,l.label=6;case 6:return i++,[3,1];case 7:return[2,o]}}))}))}function O(e){return JSON.stringify(e,(function(e,n){return n instanceof Error?c({name:(t=n).name,message:t.message,stack:null===(r=t.stack)||void 0===r?void 0:r.split("\n")},t):n;var t,r}),2)}function E(e){return u(function(e){for(var n="",t=0,r=Object.keys(e);t<r.length;t++){var o=r[t],i=e[o],a=i.error?"error":JSON.stringify(i.value);n+=(n?"|":"")+o.replace(/([:|\\])/g,"\\$1")+":"+a}return n}(e))}var I=function(){function e(){}return e.prototype.get=function(e){return void 0===e&&(e={}),s(this,void 0,void 0,(function(){var n,t;return l(this,(function(r){switch(r.label){case 0:return[4,P(x,void 0,[])];case 1:return n=r.sent(),t=function(e){var n;return{components:e,get visitorId(){return void 0===n&&(n=E(this.components)),n},set visitorId(e){n=e},version:"3.0.7"}}(n),e.debug&&console.log("Copy the text below to get the debug data:\n\n```\nversion: "+t.version+"\nuserAgent: "+navigator.userAgent+"\ngetOptions: "+JSON.stringify(e,void 0,2)+"\nvisitorId: "+t.visitorId+"\ncomponents: "+O(n)+"\n```"),[2,t]}}))}))},e}();function D(e){var n=(void 0===e?{}:e).delayFallback,t=void 0===n?50:n;return s(this,void 0,void 0,(function(){return l(this,(function(e){switch(e.label){case 0:return[4,d(t,2*t)];case 1:return e.sent(),[2,new I]}}))}))}var R={load:D,hashComponents:E,componentsToDebugString:O},L=u;e.componentsToDebugString=O,e.default=R,e.getComponents=P,e.hashComponents=E,e.isChromium=y,e.isDesktopSafari=b,e.isEdgeHTML=m,e.isGecko=function(){var e,n,t=window;return g(["buildID"in navigator,"MozAppearance"in(null!==(n=null===(e=document.documentElement)||void 0===e?void 0:e.style)&&void 0!==n?n:{}),"MediaRecorderErrorEvent"in t,"mozInnerScreenX"in t,"CSSMozDocumentRule"in t,"CanvasCaptureMediaStream"in t])>=4},e.isTrident=p,e.isWebKit=w,e.load=D,e.murmurX64Hash128=L,Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "@fingerprintjs/fingerprintjs", | ||
"description": "Browser fingerprinting library with the highest accuracy and stability", | ||
"version": "3.0.6", | ||
"version": "3.0.7", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "fraud", |
175
readme.md
@@ -7,17 +7,20 @@ <p align="center"> | ||
<p align="center"> | ||
<a href="https://github.com/fingerprintjs/fingerprintjs/actions?workflow=Lint%20and%20test"> | ||
<img src="https://github.com/fingerprintjs/fingerprintjs/workflows/Lint%20and%20test/badge.svg" alt="Build status"> | ||
<a href="https://github.com/fingerprintjs/fingerprintjs/actions/workflows/test.yml"> | ||
<img src="https://github.com/fingerprintjs/fingerprintjs/actions/workflows/test.yml/badge.svg?branch=v2" alt="Build status"> | ||
</a> | ||
<a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs"> | ||
<img src="https://img.shields.io/npm/dt/fingerprintjs2.svg" alt="Total downloads from NPM"> | ||
<img src="https://img.shields.io/npm/v/@fingerprintjs/fingerprintjs.svg" alt="Current NPM version"> | ||
</a> | ||
<a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs"> | ||
<img src="https://img.shields.io/npm/v/@fingerprintjs/fingerprintjs.svg" alt="Current NPM version"> | ||
<img src="https://img.shields.io/npm/dm/@fingerprintjs/fingerprintjs.svg" alt="Monthly downloads from NPM"> | ||
</a> | ||
<a href="https://www.jsdelivr.com/package/npm/@fingerprintjs/fingerprintjs"> | ||
<img src="https://img.shields.io/jsdelivr/npm/hm/@fingerprintjs/fingerprintjs.svg" alt="Monthly downloads from jsDelivr"> | ||
</a> | ||
</p> | ||
Makes a website visitor identifier from a browser fingerprint. | ||
Unlike cookies and local storage, fingerprint stays the same in incognito/private mode and even when browser data is purged. | ||
[Demo](https://fingerprintjs.github.io/fingerprintjs/). | ||
FingerprintJS is a browser fingerprinting library that queries browser attributes and computes a hashed visitor identifier from them. Unlike cookies and local storage, a fingerprint stays the same in incognito/private mode and even when browser data is purged. | ||
[View Our Demo](https://fingerprintjs.github.io/fingerprintjs/). | ||
## Quick start | ||
@@ -75,4 +78,10 @@ | ||
## Upgrade to [Pro version](https://fingerprintjs.com) to get 99.5% identification accuracy | ||
## Upgrade to [Pro version](https://pro.fingerprintjs.com/github/) to get 99.5% identification accuracy | ||
FingerprintJS Pro is a professional visitor identification service that processes all information server-side and transmits it securely to your servers using server-to-server APIs. | ||
Pro combines browser fingerprinting with vast amounts of auxiliary data (IP addresses, time of visit patterns, URL changes and more) to be able to reliably deduplicate different users that have identical devices, resulting in 99.5% identification accuracy. | ||
See our [full product comparison](https://pro.fingerprintjs.com/github/) for more information on the differences between open source and Pro. | ||
<p align="center"> | ||
@@ -141,77 +150,90 @@ <a href="https://fingerprintjs.com"> | ||
- Global variable | ||
```html | ||
<script> | ||
function initFingerprintJS() { | ||
// Start loading FingerprintJS here | ||
} | ||
</script> | ||
<script | ||
async | ||
src="//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.min.js" | ||
onload="initFingerprintJS()" | ||
></script> | ||
``` | ||
- UMD | ||
```js | ||
require( | ||
['//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.umd.min.js'], | ||
(FingerprintJS) => { | ||
// Start loading FingerprintJS here | ||
} | ||
); | ||
``` | ||
- ECMAScript module | ||
```bash | ||
# Install the package first: | ||
npm i @fingerprintjs/fingerprintjs | ||
# or | ||
yarn add @fingerprintjs/fingerprintjs | ||
``` | ||
#### Global variable | ||
```js | ||
import FingerprintJS from '@fingerprintjs/fingerprintjs'; | ||
```html | ||
<script> | ||
function initFingerprintJS() { | ||
// Start loading FingerprintJS here | ||
``` | ||
- CommonJS | ||
```bash | ||
# Install the package first: | ||
npm i @fingerprintjs/fingerprintjs | ||
# or | ||
yarn add @fingerprintjs/fingerprintjs | ||
``` | ||
} | ||
</script> | ||
<script | ||
async | ||
src="//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.min.js" | ||
onload="initFingerprintJS()" | ||
></script> | ||
``` | ||
```js | ||
const FingerprintJS = require('@fingerprintjs/fingerprintjs'); | ||
#### UMD | ||
```js | ||
require( | ||
['//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.umd.min.js'], | ||
(FingerprintJS) => { | ||
// Start loading FingerprintJS here | ||
``` | ||
} | ||
); | ||
``` | ||
#### ECMAScript module | ||
```bash | ||
# Install the package first: | ||
npm i @fingerprintjs/fingerprintjs | ||
# or | ||
yarn add @fingerprintjs/fingerprintjs | ||
``` | ||
```js | ||
import FingerprintJS from '@fingerprintjs/fingerprintjs'; | ||
// Start loading FingerprintJS here | ||
``` | ||
#### CommonJS | ||
```bash | ||
# Install the package first: | ||
npm i @fingerprintjs/fingerprintjs | ||
# or | ||
yarn add @fingerprintjs/fingerprintjs | ||
``` | ||
```js | ||
const FingerprintJS = require('@fingerprintjs/fingerprintjs'); | ||
// Start loading FingerprintJS here | ||
``` | ||
### API | ||
- `FingerprintJS.load({ delayFallback?: number }): Promise<Agent>` | ||
#### `FingerprintJS.load({ delayFallback?: number }): Promise<Agent>` | ||
Builds an instance of Agent and waits a delay required for a proper operation. | ||
`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); | ||
it has a good default value which we don't recommend to change. | ||
Builds an instance of Agent and waits a delay required for a proper operation. | ||
`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); | ||
it has a good default value which we don't recommend to change. | ||
- `agent.get({ debug?: boolean }): Promise<{ visitorId: string, components: {/* ... */} }>` | ||
#### `agent.get({ debug?: boolean }): Promise<object>` | ||
Gets the visitor identifier. | ||
`debug: true` prints debug messages to the console. | ||
`visitorId` is the visitor identifier. | ||
`components` is a dictionary of components that have formed the identifier; | ||
each value is an object like `{ value: any, duration: number }` in case of success | ||
Gets the visitor identifier. | ||
`debug: true` prints debug messages to the console. | ||
Result object fields: | ||
- `visitorId` The visitor identifier | ||
- `components` A dictionary of components that have formed the identifier. | ||
Each value is an object like `{ value: any, duration: number }` in case of success | ||
and `{ error: object, duration: number }` in case of an unexpected error during getting the component. | ||
- `version` The fingerprinting algorithm version which is equal to the library version. | ||
See [the version policy section](#version-policy) for more details. | ||
- `FingerprintJS.hashComponents(components: object): string` | ||
See the [extending guide](docs/extending.md) to learn how to remove and add entropy components. | ||
Converts a dictionary of components (described above) into a short hash string a.k.a. a visitor identifier. | ||
Designed for extending the library with your own components. | ||
#### `FingerprintJS.hashComponents(components: object): string` | ||
- `FingerprintJS.componentsToDebugString(components: object): string` | ||
Converts a dictionary of components (described above) into a short hash string a.k.a. a visitor identifier. | ||
Designed for [extending the library](docs/extending.md) with your own components. | ||
Converts a dictionary of components (described above) into human-friendly format. | ||
#### `FingerprintJS.componentsToDebugString(components: object): string` | ||
Converts a dictionary of components (described above) into human-friendly format. | ||
## Migrating from v2 | ||
@@ -224,6 +246,21 @@ | ||
The OSS version doesn't guarantee the same visitor identifier between versions, | ||
but will try to keep them the same as much as possible. | ||
To get identifiers that remain stable up to 1 year, please consider [upgrading to pro.](https://dashboard.fingerprintjs.com) | ||
The library tries to keep visitor identifiers the same within a minor version (i.e. when the first 2 numbers of the version don't change). | ||
Some visitor identifiers may change within a minor version due to stability fixes. | ||
To get identifiers that remain stable up to 1 year, please consider [upgrading to pro](https://dashboard.fingerprintjs.com). | ||
Agent `get()` function returns the version together with the visitor identifier. | ||
You can use it to decide whether a couple of identifiers can be matched together. | ||
Example: | ||
```js | ||
if ( | ||
result1.version.split('.').slice(0, 2).join('.') === | ||
result2.version.split('.').slice(0, 2).join('.') | ||
) { | ||
return result1.visitorId === result2.visitorId ? 'same' : 'different'; | ||
} else { | ||
return 'unknown'; | ||
} | ||
``` | ||
The documented JS API follows [Semantic Versioning](https://semver.org). | ||
@@ -230,0 +267,0 @@ Use undocumented features at your own risk. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
267144
5600
276